From 0a08828476080ea37e155665e97af0cfbad6cdde Mon Sep 17 00:00:00 2001 From: MonkSoul Date: Mon, 5 Sep 2022 15:54:50 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=98=8A=20=E5=8F=91=E5=B8=83=20Furion=20v4?= =?UTF-8?q?.4.0=20=E7=89=88=E6=9C=AC=EF=BC=8C=E6=94=B9=E8=BF=9B=E8=BF=9C?= =?UTF-8?q?=E7=A8=8B=E8=AF=B7=E6=B1=82=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 含 #I5PPKE:📝 支持 `JWTEncryption` 无注册使用 功能发布 - 含 #I5POLZ:web项目token生成 功能发布 - 含 #I5PMS5:📝 新增 `HttpFile` 类,针对远程请求上传文件封装 功能发布 - 含 #I5PIYI:http post BodyBytes("键","文件名") 文件名只能写死固定吗 功能发布 - 含 #I5PKJH:📝 友好异常支持控制是否输出日志 功能发布 - 更新示例项目 samples 依赖至 v4.4.0 版本 - 发布 v4.4.0 版本文档 - Replit 网站 Furion 案例同步到 v4.4.0 版本 - Gitee 和 Github 发布 Release 版本 - 同步更新日志 --- ...ion.Extras.Authentication.JwtBearer.csproj | 2 +- ...rion.Extras.DatabaseAccessor.Dapper.csproj | 2 +- ...ion.Extras.DatabaseAccessor.MongoDB.csproj | 2 +- ...on.Extras.DatabaseAccessor.SqlSugar.csproj | 2 +- ...Extras.DependencyModel.CodeAnalysis.csproj | 2 +- .../Furion.Extras.Logging.Serilog.csproj | 2 +- .../Furion.Extras.ObjectMapper.Mapster.csproj | 2 +- ...Extras.DependencyModel.CodeAnalysis.csproj | 2 +- .../Furion.Pure.Xunit.csproj | 4 ++-- framework/Furion.Pure/Furion.Pure.csproj | 8 ++++---- framework/Furion.Xunit/Furion.Xunit.csproj | 4 ++-- framework/Furion/Furion.csproj | 8 ++++---- handbook/build/404.html | 17 ++++++++--------- ...tyles.adf4a870.css => styles.5c4d70d3.css} | 2 +- handbook/build/assets/js/000e798f.49cd0fb3.js | 1 - handbook/build/assets/js/000e798f.a0d354b5.js | 1 + handbook/build/assets/js/00cf5050.0557c5ee.js | 1 + handbook/build/assets/js/00cf5050.edbd97d1.js | 1 - handbook/build/assets/js/00ee0bc9.807ce380.js | 1 - handbook/build/assets/js/00ee0bc9.e5d0b018.js | 1 + ...85c17.a0e539b3.js => 01a85c17.4b3a9f27.js} | 2 +- handbook/build/assets/js/0249e0f1.8dca2318.js | 1 - handbook/build/assets/js/0249e0f1.b04f4642.js | 1 + handbook/build/assets/js/02a99512.6353effe.js | 1 - handbook/build/assets/js/02a99512.76dc891f.js | 1 + handbook/build/assets/js/0482bd9e.8e52c7b9.js | 1 - handbook/build/assets/js/0482bd9e.b11beeab.js | 1 + handbook/build/assets/js/04b9380e.66397e23.js | 1 + handbook/build/assets/js/04b9380e.d0d2173b.js | 1 - ...4f6af.2029e147.js => 06c1d953.73a63479.js} | 2 +- handbook/build/assets/js/083979a2.2e037b98.js | 1 - handbook/build/assets/js/083979a2.ef6110f4.js | 1 + handbook/build/assets/js/093b1cf0.d0ea6525.js | 1 - handbook/build/assets/js/093b1cf0.f242526e.js | 1 + handbook/build/assets/js/09bd0aa2.79620765.js | 1 - handbook/build/assets/js/09bd0aa2.bf2ee55f.js | 1 + handbook/build/assets/js/0baa6b13.47423144.js | 1 + handbook/build/assets/js/0baa6b13.7c1d3edb.js | 1 - handbook/build/assets/js/0f2c6659.8eedeb7a.js | 1 - handbook/build/assets/js/0f2c6659.e5dc8f58.js | 1 + handbook/build/assets/js/0ff68343.1e411abb.js | 1 + handbook/build/assets/js/0ff68343.9f62d4ed.js | 1 - handbook/build/assets/js/12829a06.3d723eb4.js | 1 - handbook/build/assets/js/12829a06.759cbd37.js | 1 + handbook/build/assets/js/14cdac51.abde07cc.js | 1 - handbook/build/assets/js/14cdac51.d9d040de.js | 1 + handbook/build/assets/js/17896441.08aa0b1c.js | 1 - handbook/build/assets/js/17896441.d648632e.js | 1 + handbook/build/assets/js/1a4e3797.b4a26642.js | 2 -- handbook/build/assets/js/1a4e3797.f48b4242.js | 2 ++ ...E.txt => 1a4e3797.f48b4242.js.LICENSE.txt} | 0 handbook/build/assets/js/1be78505.2600d13c.js | 1 - handbook/build/assets/js/1be78505.9ee37fe4.js | 1 + handbook/build/assets/js/1c2c7d62.7e20de84.js | 1 - handbook/build/assets/js/1c2c7d62.92594d0c.js | 1 + ...dbfc1.fc56613a.js => 22bdbfc1.363d2198.js} | 2 +- handbook/build/assets/js/22f09a41.39655112.js | 1 + handbook/build/assets/js/22f09a41.a8df2925.js | 1 - handbook/build/assets/js/2397d9c0.a16e91c1.js | 1 - handbook/build/assets/js/2397d9c0.bcd55237.js | 1 + handbook/build/assets/js/2529.ad701460.js | 1 + handbook/build/assets/js/26682ccc.1fee17ed.js | 1 + handbook/build/assets/js/26682ccc.23223d4d.js | 1 - handbook/build/assets/js/2729f1a8.1400fa7d.js | 1 - handbook/build/assets/js/2729f1a8.475bacf0.js | 1 + handbook/build/assets/js/2b75607b.4ea221d8.js | 1 + handbook/build/assets/js/2b75607b.87fde087.js | 1 - handbook/build/assets/js/2b85edf2.95aa392d.js | 1 - handbook/build/assets/js/2b85edf2.acdd7bc5.js | 1 + handbook/build/assets/js/3427cf63.5efd64d8.js | 1 - handbook/build/assets/js/3427cf63.fdc09969.js | 1 + handbook/build/assets/js/3594fad8.6b7f470d.js | 1 - handbook/build/assets/js/3594fad8.970f9fe1.js | 1 + handbook/build/assets/js/3653278d.7b1f8f0c.js | 1 + handbook/build/assets/js/3653278d.8bc48f2c.js | 1 - ...adb68.48b6d44a.js => 39c6bc14.291e8779.js} | 2 +- handbook/build/assets/js/3a136e85.a5517a61.js | 1 + handbook/build/assets/js/3a136e85.cdf57f74.js | 1 - handbook/build/assets/js/3d66e15d.357081f9.js | 1 + handbook/build/assets/js/3d66e15d.dfbcc1cc.js | 1 - handbook/build/assets/js/3d72d16d.45bf21c4.js | 1 - handbook/build/assets/js/3d72d16d.a4f56d9b.js | 1 + handbook/build/assets/js/3eb8904d.9ae5fa04.js | 1 + handbook/build/assets/js/3eb8904d.f4f55df5.js | 1 - handbook/build/assets/js/40a433d4.38e4030f.js | 1 + handbook/build/assets/js/40a433d4.66306be6.js | 1 - handbook/build/assets/js/42806b0f.6cb69319.js | 1 - handbook/build/assets/js/42806b0f.bdadccb7.js | 1 + handbook/build/assets/js/4972.006d6232.js | 1 + handbook/build/assets/js/4ad72136.3768d2a2.js | 1 + handbook/build/assets/js/4ad72136.61d6cae6.js | 1 - handbook/build/assets/js/4b6c538b.0b1661d7.js | 1 + handbook/build/assets/js/4b6c538b.d9f39463.js | 1 - handbook/build/assets/js/4c19669a.8044c709.js | 1 + handbook/build/assets/js/4c19669a.b0ff1dc3.js | 1 - handbook/build/assets/js/4c79e569.433ccd43.js | 1 - handbook/build/assets/js/4c79e569.57384544.js | 1 + handbook/build/assets/js/4d87bc8d.4aafd3e2.js | 1 - handbook/build/assets/js/4d87bc8d.c1c6d8c6.js | 1 + handbook/build/assets/js/51c11da7.6ea72f85.js | 1 - handbook/build/assets/js/51c11da7.bb370a81.js | 1 + handbook/build/assets/js/51c14d7f.062a1d65.js | 1 - handbook/build/assets/js/51c14d7f.ff396dd7.js | 1 + handbook/build/assets/js/52821183.1a0f0bc7.js | 1 - handbook/build/assets/js/52821183.73e65fc1.js | 1 + handbook/build/assets/js/5672fbad.7a2a2240.js | 1 - handbook/build/assets/js/5672fbad.ea02e960.js | 1 + handbook/build/assets/js/5792.06bee9e5.js | 1 - handbook/build/assets/js/57da61d5.7fa28076.js | 1 - handbook/build/assets/js/57da61d5.c16ad6d6.js | 1 + handbook/build/assets/js/58624d73.7c550d93.js | 1 - handbook/build/assets/js/58624d73.bd06e57a.js | 1 + ...f7d91.d4ca715b.js => 5b1379ef.a9febb22.js} | 2 +- handbook/build/assets/js/5edfa151.0fad3db0.js | 1 - handbook/build/assets/js/5edfa151.b3508620.js | 1 + handbook/build/assets/js/5edfff3a.4b55c402.js | 1 - handbook/build/assets/js/5edfff3a.8528a756.js | 1 + handbook/build/assets/js/5f6c9278.c0cb49de.js | 1 - handbook/build/assets/js/5f6c9278.fc06fa9b.js | 1 + handbook/build/assets/js/612f2d9e.5cb6d11d.js | 1 + handbook/build/assets/js/612f2d9e.86459e08.js | 1 - .../js/{9363.30f6f0bd.js => 617.ddf33500.js} | 2 +- handbook/build/assets/js/62d444b9.1c24496f.js | 1 - handbook/build/assets/js/62d444b9.aee53dfa.js | 1 + handbook/build/assets/js/633e39ed.ca94d7aa.js | 1 + handbook/build/assets/js/633e39ed.f316c012.js | 1 - handbook/build/assets/js/64e66f0d.17bc1018.js | 1 + handbook/build/assets/js/64e66f0d.d611c4b2.js | 1 - handbook/build/assets/js/64ece2db.1dd6422a.js | 1 - handbook/build/assets/js/64ece2db.fc8d0233.js | 1 + handbook/build/assets/js/6875c492.9175ef0f.js | 1 + handbook/build/assets/js/6875c492.d10d6e87.js | 1 - handbook/build/assets/js/68ec177d.96ded009.js | 1 - handbook/build/assets/js/68ec177d.fe841cfd.js | 1 + handbook/build/assets/js/698c3fb7.49c7b7fe.js | 1 - handbook/build/assets/js/698c3fb7.f4c008bc.js | 1 + handbook/build/assets/js/69b28fcd.6676266a.js | 1 - handbook/build/assets/js/69b28fcd.da1662d4.js | 1 + handbook/build/assets/js/6b7b862c.ac22c3a5.js | 1 - handbook/build/assets/js/6b7b862c.dd7ce31a.js | 1 + handbook/build/assets/js/6eaa010c.a430e57a.js | 1 + handbook/build/assets/js/6eaa010c.e6f407eb.js | 1 - handbook/build/assets/js/6fa9a93a.ae659217.js | 1 - handbook/build/assets/js/6fa9a93a.fc03db49.js | 1 + handbook/build/assets/js/711b45e3.398f241d.js | 1 - handbook/build/assets/js/711b45e3.ec13726e.js | 1 + handbook/build/assets/js/713.e2d721b5.js | 1 - handbook/build/assets/js/713be7bb.0b389d71.js | 1 - handbook/build/assets/js/713be7bb.8ab7df69.js | 1 + handbook/build/assets/js/73d3b1ea.3825ed12.js | 1 + handbook/build/assets/js/73d3b1ea.db30f856.js | 1 - handbook/build/assets/js/757fb418.b628ed3a.js | 1 - handbook/build/assets/js/757fb418.d19ffcfd.js | 1 + handbook/build/assets/js/76437093.b81a4f82.js | 1 + handbook/build/assets/js/76437093.ce2a8922.js | 1 - handbook/build/assets/js/76b00148.7abbab6c.js | 1 - handbook/build/assets/js/76b00148.eb20b8a7.js | 1 + handbook/build/assets/js/78e5e8dd.0f59ff26.js | 1 - handbook/build/assets/js/78e5e8dd.5277f06b.js | 1 + handbook/build/assets/js/7c5dd5ef.9634009c.js | 1 - handbook/build/assets/js/7c5dd5ef.b86dde09.js | 1 + handbook/build/assets/js/7c6b08dc.85addf76.js | 1 + handbook/build/assets/js/7c6b08dc.897bee85.js | 1 - handbook/build/assets/js/7d1915d2.08fd2c20.js | 1 + handbook/build/assets/js/7d1915d2.c1af54c4.js | 1 - handbook/build/assets/js/7dd08b1c.7d4cd667.js | 1 + handbook/build/assets/js/7dd08b1c.cbbe1161.js | 1 - handbook/build/assets/js/800036d7.0f729a1e.js | 1 + handbook/build/assets/js/800036d7.c5090b95.js | 1 - handbook/build/assets/js/84a61a3c.255a77ab.js | 1 - handbook/build/assets/js/84a61a3c.58c2675f.js | 1 + handbook/build/assets/js/84b6e574.53077f68.js | 1 - handbook/build/assets/js/84b6e574.b4dbdcc8.js | 1 + handbook/build/assets/js/861b6d56.82136f7f.js | 1 + handbook/build/assets/js/861b6d56.f4a2fc6e.js | 1 - handbook/build/assets/js/88486ef5.8256c724.js | 1 - handbook/build/assets/js/88486ef5.c02a6a2a.js | 1 + handbook/build/assets/js/8968961d.e90ecda8.js | 1 - handbook/build/assets/js/8968961d.edbe173e.js | 1 + handbook/build/assets/js/8a0794d9.a10e91de.js | 1 + handbook/build/assets/js/8a0794d9.ccc96964.js | 1 - handbook/build/assets/js/8b7511b6.56851f0a.js | 1 - handbook/build/assets/js/8b7511b6.b153f625.js | 1 + ...5ae1b.6981b7a2.js => 8d45ae1b.d16db555.js} | 2 +- handbook/build/assets/js/8dcbe064.ecefcb93.js | 1 - handbook/build/assets/js/8dcbe064.f2e594d6.js | 1 + handbook/build/assets/js/8f2f6685.0c1801d5.js | 1 + handbook/build/assets/js/8f2f6685.a829fdbc.js | 1 - handbook/build/assets/js/9055.186ea641.js | 1 + handbook/build/assets/js/914e87db.437727ef.js | 1 - handbook/build/assets/js/914e87db.856f476f.js | 1 + handbook/build/assets/js/934e2055.4d5ac78b.js | 1 + handbook/build/assets/js/934e2055.c48809ce.js | 1 - handbook/build/assets/js/935f2afb.57011e9b.js | 1 - handbook/build/assets/js/935f2afb.ccba3080.js | 1 + handbook/build/assets/js/937eda02.a37f00fa.js | 1 - handbook/build/assets/js/937eda02.db68586a.js | 1 + handbook/build/assets/js/9888.c11ad302.js | 1 - handbook/build/assets/js/9b04aa07.559eaa5c.js | 1 + handbook/build/assets/js/9b04aa07.e9458336.js | 1 - handbook/build/assets/js/9bd20b97.a160a0db.js | 1 + handbook/build/assets/js/9bd20b97.e8922b01.js | 1 - handbook/build/assets/js/9c854613.317925eb.js | 1 - handbook/build/assets/js/9c854613.45824898.js | 1 + handbook/build/assets/js/9ce2543b.78443ed4.js | 1 + handbook/build/assets/js/9ce2543b.f74974a7.js | 1 - ...087bc.7950f9cb.js => 9e4087bc.7202a43f.js} | 2 +- handbook/build/assets/js/9e7ef9fa.c0b774f3.js | 1 + handbook/build/assets/js/9e7ef9fa.d9a3ef03.js | 1 - handbook/build/assets/js/a0a8cac6.7a8e93e6.js | 1 - handbook/build/assets/js/a0a8cac6.ef8fa4bd.js | 1 + handbook/build/assets/js/a125e20e.21aa56b6.js | 1 + handbook/build/assets/js/a125e20e.6c234aa6.js | 1 - handbook/build/assets/js/a19656d0.05ba8fe6.js | 1 - handbook/build/assets/js/a19656d0.1eb0420c.js | 1 + handbook/build/assets/js/a2d62645.f029c5ed.js | 1 + handbook/build/assets/js/a2d62645.fcb746f2.js | 1 - handbook/build/assets/js/a4688235.1134e6e2.js | 1 + handbook/build/assets/js/a4688235.2d20d46b.js | 1 - handbook/build/assets/js/a4c09e9b.91ba7bb3.js | 1 - handbook/build/assets/js/a4c09e9b.f29c947c.js | 1 + handbook/build/assets/js/a6aa9e1f.4482c8b9.js | 1 + handbook/build/assets/js/a6aa9e1f.e5d8d377.js | 1 - handbook/build/assets/js/a71f9f93.20230c19.js | 1 + handbook/build/assets/js/a71f9f93.2db4ebc2.js | 1 - handbook/build/assets/js/a8677dec.ad1235ff.js | 1 + handbook/build/assets/js/a8677dec.d6c71cca.js | 1 - handbook/build/assets/js/aa7bdd74.02dd36a3.js | 1 + handbook/build/assets/js/aa7bdd74.3b76ce8d.js | 1 - handbook/build/assets/js/ab4c4f37.5ee20dfb.js | 1 - handbook/build/assets/js/ab4c4f37.f827e34a.js | 1 + handbook/build/assets/js/ab6beea0.0f966ba6.js | 1 - handbook/build/assets/js/ab6beea0.48e0088f.js | 1 + handbook/build/assets/js/ace43ec3.2e7195f2.js | 1 - handbook/build/assets/js/ace43ec3.53d29fea.js | 1 + handbook/build/assets/js/adf0697d.8c4636c6.js | 1 - handbook/build/assets/js/adf0697d.ebd6554a.js | 1 + handbook/build/assets/js/afaad682.373f32f8.js | 1 - handbook/build/assets/js/afaad682.47fac500.js | 1 + handbook/build/assets/js/b0352e4c.7b695c42.js | 1 + handbook/build/assets/js/b0352e4c.fb0c2a88.js | 1 - handbook/build/assets/js/b40312ef.0517251e.js | 1 - handbook/build/assets/js/b40312ef.4b4dbccc.js | 1 + handbook/build/assets/js/b4685f05.0886951d.js | 1 - handbook/build/assets/js/b4685f05.e7416c4a.js | 1 + handbook/build/assets/js/b6492972.05854844.js | 1 + handbook/build/assets/js/b6492972.9d788011.js | 1 - handbook/build/assets/js/b753a5b5.69498779.js | 1 - handbook/build/assets/js/b753a5b5.d41da7d4.js | 1 + handbook/build/assets/js/b7a8adf4.7cf903ff.js | 1 - handbook/build/assets/js/b7a8adf4.c57c32da.js | 1 + handbook/build/assets/js/b89c6849.645c0b5e.js | 1 + handbook/build/assets/js/b89c6849.8c07483c.js | 1 - ...fd1af.8ef10849.js => b96ebcf3.889835bb.js} | 2 +- handbook/build/assets/js/bb3cf766.c474c445.js | 1 - handbook/build/assets/js/bb3cf766.d974ec94.js | 1 + ...bce29.16934f75.js => bc8bce29.c61c20b8.js} | 2 +- handbook/build/assets/js/bfaddb57.09d1fbeb.js | 1 - handbook/build/assets/js/bfaddb57.9256bc68.js | 1 + handbook/build/assets/js/c0812ddb.233de97c.js | 1 + handbook/build/assets/js/c0812ddb.48ff70af.js | 1 - handbook/build/assets/js/c4b1c400.45a327f8.js | 1 - handbook/build/assets/js/c4b1c400.cb4c5d0b.js | 1 + handbook/build/assets/js/c4f5d8e4.05ac18fa.js | 1 + handbook/build/assets/js/c4f5d8e4.8fac2b97.js | 1 - handbook/build/assets/js/c601aa1c.2e50a800.js | 1 - handbook/build/assets/js/c601aa1c.93b6fd4c.js | 1 + handbook/build/assets/js/c76f8c40.baae6566.js | 1 - handbook/build/assets/js/c76f8c40.eb7a2876.js | 1 + handbook/build/assets/js/c7a9ad89.8cfb38a9.js | 1 + handbook/build/assets/js/c7a9ad89.bb0b3826.js | 1 - handbook/build/assets/js/cbb899e4.4636e3f3.js | 1 - handbook/build/assets/js/cbb899e4.9428b656.js | 1 + handbook/build/assets/js/ccc2287e.0846b13c.js | 1 - handbook/build/assets/js/ccc2287e.dc8a82fc.js | 1 + handbook/build/assets/js/ccc49370.c96ce516.js | 1 - handbook/build/assets/js/ccc49370.e75da32b.js | 1 + handbook/build/assets/js/cd54e801.026c4cdc.js | 1 + handbook/build/assets/js/cd54e801.b72d8366.js | 1 - handbook/build/assets/js/d0a6dadf.21d6e0e6.js | 1 + handbook/build/assets/js/d0a6dadf.325cec41.js | 1 - handbook/build/assets/js/d22033f9.7ff99e41.js | 1 - handbook/build/assets/js/d22033f9.dad18b96.js | 1 + handbook/build/assets/js/d444ce62.b29f9de5.js | 1 + handbook/build/assets/js/d444ce62.e73386cd.js | 1 - handbook/build/assets/js/d47dc5e2.626f9e2b.js | 1 + handbook/build/assets/js/d47dc5e2.8ae7c236.js | 1 - handbook/build/assets/js/d71de838.15badbc1.js | 1 - handbook/build/assets/js/d71de838.7a4dbb10.js | 1 + handbook/build/assets/js/d8865cb1.38525976.js | 1 + handbook/build/assets/js/d8865cb1.a7e0b5b2.js | 1 - handbook/build/assets/js/d894cce0.d59716c1.js | 1 + handbook/build/assets/js/d894cce0.f09011f2.js | 1 - handbook/build/assets/js/da6c7707.2bc08084.js | 1 - handbook/build/assets/js/da6c7707.4d1a9809.js | 1 + handbook/build/assets/js/da88eb6b.0ddeca6c.js | 1 - handbook/build/assets/js/da88eb6b.33e09cab.js | 1 + handbook/build/assets/js/db5a72a0.1542f7d4.js | 1 + handbook/build/assets/js/db5a72a0.43da0f36.js | 1 - handbook/build/assets/js/dc235550.371e1288.js | 1 - handbook/build/assets/js/dc235550.fe340f9e.js | 1 + handbook/build/assets/js/e17ba759.3ac9b836.js | 1 - handbook/build/assets/js/e17ba759.4237f9ec.js | 1 + handbook/build/assets/js/e60cf3ee.298f2c0b.js | 1 - handbook/build/assets/js/e60cf3ee.42322920.js | 1 + handbook/build/assets/js/e7929401.4f3d7915.js | 1 - handbook/build/assets/js/e7929401.c8528a6c.js | 1 + handbook/build/assets/js/e829a4ba.3998cd6e.js | 1 + handbook/build/assets/js/e829a4ba.832473ff.js | 1 - handbook/build/assets/js/ea36d85d.6fd1562f.js | 1 + handbook/build/assets/js/ea36d85d.f439dd72.js | 1 - handbook/build/assets/js/ea50195b.15d8a67e.js | 1 - handbook/build/assets/js/ea50195b.729b23eb.js | 1 + handbook/build/assets/js/edb1f2eb.0c47b5d4.js | 1 - handbook/build/assets/js/edb1f2eb.34dd0faa.js | 1 + handbook/build/assets/js/efaef7c6.66b19c69.js | 1 + handbook/build/assets/js/efaef7c6.d3c76c73.js | 1 - handbook/build/assets/js/f1c506f3.7d70aff2.js | 1 + handbook/build/assets/js/f1c506f3.a0f8c0c5.js | 1 - handbook/build/assets/js/f2131000.2bc2eabe.js | 1 - handbook/build/assets/js/f2131000.2d4ce8ce.js | 1 + handbook/build/assets/js/f60abd31.36261204.js | 1 + handbook/build/assets/js/f60abd31.f36fe3d8.js | 1 - handbook/build/assets/js/f7db4844.580da9fb.js | 1 + handbook/build/assets/js/f7db4844.c41090e8.js | 1 - handbook/build/assets/js/fc508b36.671e2aec.js | 1 - handbook/build/assets/js/fc508b36.e1b88d0f.js | 1 + handbook/build/assets/js/fd6801a9.506dbbb7.js | 1 + handbook/build/assets/js/fd6801a9.9b58e88b.js | 1 - handbook/build/assets/js/fd885aa1.391bbc3a.js | 1 - handbook/build/assets/js/fd885aa1.76cfb01e.js | 1 + handbook/build/assets/js/fe38d63c.22f6af76.js | 1 - handbook/build/assets/js/fe38d63c.fe1ab479.js | 1 + handbook/build/assets/js/fe3b2968.5499402c.js | 1 + handbook/build/assets/js/fe3b2968.588dbe92.js | 1 - handbook/build/assets/js/main.930b2221.js | 2 -- handbook/build/assets/js/main.e0f2178f.js | 2 ++ ...CENSE.txt => main.e0f2178f.js.LICENSE.txt} | 0 .../build/assets/js/runtime~main.a62e617c.js | 1 + .../build/assets/js/runtime~main.e0dbf6bc.js | 1 - handbook/build/blog/archive/index.html | 17 ++++++++--------- handbook/build/blog/console/index.html | 17 ++++++++--------- .../build/blog/fileupload-download/index.html | 17 ++++++++--------- handbook/build/blog/global-usings/index.html | 17 ++++++++--------- handbook/build/blog/httpcontext/index.html | 17 ++++++++--------- handbook/build/blog/index.html | 17 ++++++++--------- handbook/build/blog/net6-preview5/index.html | 17 ++++++++--------- handbook/build/blog/net6-preview6/index.html | 17 ++++++++--------- handbook/build/blog/net6-preview7/index.html | 17 ++++++++--------- handbook/build/blog/tags/download/index.html | 17 ++++++++--------- handbook/build/blog/tags/furion/index.html | 17 ++++++++--------- handbook/build/blog/tags/furos/index.html | 17 ++++++++--------- .../build/blog/tags/httpcontext/index.html | 17 ++++++++--------- handbook/build/blog/tags/index.html | 17 ++++++++--------- handbook/build/blog/tags/net-5/index.html | 17 ++++++++--------- handbook/build/blog/tags/net-6/index.html | 17 ++++++++--------- handbook/build/blog/tags/net/index.html | 17 ++++++++--------- handbook/build/blog/tags/netcore/index.html | 17 ++++++++--------- handbook/build/blog/tags/upload/index.html | 17 ++++++++--------- handbook/build/docs/appstartup/index.html | 17 ++++++++--------- handbook/build/docs/audit/index.html | 17 ++++++++--------- handbook/build/docs/auth-control/index.html | 17 ++++++++--------- handbook/build/docs/author/index.html | 17 ++++++++--------- handbook/build/docs/benchmark/index.html | 17 ++++++++--------- handbook/build/docs/bingfa/index.html | 17 ++++++++--------- handbook/build/docs/cache/index.html | 17 ++++++++--------- handbook/build/docs/case/index.html | 17 ++++++++--------- handbook/build/docs/clayobj/index.html | 17 ++++++++--------- handbook/build/docs/clientapi/index.html | 17 ++++++++--------- handbook/build/docs/component/index.html | 17 ++++++++--------- handbook/build/docs/configuration/index.html | 17 ++++++++--------- handbook/build/docs/contribute/index.html | 17 ++++++++--------- handbook/build/docs/cors/index.html | 17 ++++++++--------- handbook/build/docs/course/index.html | 17 ++++++++--------- handbook/build/docs/dapper/index.html | 17 ++++++++--------- .../build/docs/data-validation/index.html | 17 ++++++++--------- .../docs/dbcontext-Interceptor/index.html | 17 ++++++++--------- .../docs/dbcontext-add-or-update/index.html | 17 ++++++++--------- handbook/build/docs/dbcontext-add/index.html | 17 ++++++++--------- .../build/docs/dbcontext-audit/index.html | 17 ++++++++--------- .../build/docs/dbcontext-batch/index.html | 17 ++++++++--------- .../docs/dbcontext-code-first/index.html | 17 ++++++++--------- .../build/docs/dbcontext-db-first/index.html | 17 ++++++++--------- .../build/docs/dbcontext-delete/index.html | 17 ++++++++--------- .../docs/dbcontext-entitytrigger/index.html | 17 ++++++++--------- .../build/docs/dbcontext-filter/index.html | 17 ++++++++--------- .../build/docs/dbcontext-function/index.html | 17 ++++++++--------- .../docs/dbcontext-hight-query/index.html | 17 ++++++++--------- .../build/docs/dbcontext-locator/index.html | 17 ++++++++--------- .../docs/dbcontext-multi-database/index.html | 17 ++++++++--------- handbook/build/docs/dbcontext-proc/index.html | 17 ++++++++--------- .../build/docs/dbcontext-query/index.html | 17 ++++++++--------- .../docs/dbcontext-read-write/index.html | 17 ++++++++--------- .../docs/dbcontext-repository/index.html | 17 ++++++++--------- .../build/docs/dbcontext-seed-data/index.html | 17 ++++++++--------- .../build/docs/dbcontext-sql-proxy/index.html | 17 ++++++++--------- .../docs/dbcontext-sql-template/index.html | 17 ++++++++--------- handbook/build/docs/dbcontext-sql/index.html | 17 ++++++++--------- .../build/docs/dbcontext-start/index.html | 17 ++++++++--------- .../build/docs/dbcontext-update/index.html | 17 ++++++++--------- handbook/build/docs/dbcontext-view/index.html | 17 ++++++++--------- handbook/build/docs/dbcontext/index.html | 17 ++++++++--------- .../docs/dependency-injection/index.html | 17 ++++++++--------- .../build/docs/deploy-docker-auto/index.html | 17 ++++++++--------- handbook/build/docs/deploy-docker/index.html | 17 ++++++++--------- handbook/build/docs/deploy-iis/index.html | 17 ++++++++--------- handbook/build/docs/deploy-nginx/index.html | 17 ++++++++--------- handbook/build/docs/devops/index.html | 17 ++++++++--------- handbook/build/docs/donate/index.html | 17 ++++++++--------- handbook/build/docs/dotnet-tools/index.html | 17 ++++++++--------- .../docs/dynamic-api-controller/index.html | 17 ++++++++--------- .../build/docs/efcore-recommend/index.html | 17 ++++++++--------- handbook/build/docs/encryption/index.html | 17 ++++++++--------- handbook/build/docs/entity/index.html | 17 ++++++++--------- handbook/build/docs/event-bus-old/index.html | 17 ++++++++--------- handbook/build/docs/event-bus/index.html | 17 ++++++++--------- handbook/build/docs/file-provider/index.html | 17 ++++++++--------- handbook/build/docs/filter/index.html | 17 ++++++++--------- .../build/docs/friendly-exception/index.html | 17 ++++++++--------- handbook/build/docs/get-start-net6/index.html | 17 ++++++++--------- handbook/build/docs/get-start/index.html | 17 ++++++++--------- handbook/build/docs/global/app/index.html | 17 ++++++++--------- .../docs/global/datavalidator/index.html | 17 ++++++++--------- handbook/build/docs/global/db/index.html | 17 ++++++++--------- handbook/build/docs/global/fs/index.html | 17 ++++++++--------- handbook/build/docs/global/json/index.html | 17 ++++++++--------- .../docs/global/jsonserializer/index.html | 17 ++++++++--------- handbook/build/docs/global/jwt/index.html | 17 ++++++++--------- handbook/build/docs/global/l/index.html | 17 ++++++++--------- .../docs/global/linqexpression/index.html | 17 ++++++++--------- .../docs/global/messagecenter/index.html | 17 ++++++++--------- handbook/build/docs/global/oops/index.html | 17 ++++++++--------- handbook/build/docs/global/scoped/index.html | 17 ++++++++--------- handbook/build/docs/global/shttp/index.html | 17 ++++++++--------- .../build/docs/global/sparetime/index.html | 17 ++++++++--------- handbook/build/docs/global/tp/index.html | 17 ++++++++--------- handbook/build/docs/globalusing/index.html | 17 ++++++++--------- handbook/build/docs/http/index.html | 19 +++++++++---------- handbook/build/docs/httpcontext/index.html | 17 ++++++++--------- handbook/build/docs/idgenerator/index.html | 17 ++++++++--------- handbook/build/docs/index.html | 17 ++++++++--------- handbook/build/docs/inject/index.html | 17 ++++++++--------- handbook/build/docs/ipc/index.html | 17 ++++++++--------- handbook/build/docs/job/index.html | 17 ++++++++--------- .../build/docs/json-serialization/index.html | 17 ++++++++--------- handbook/build/docs/jsonschema/index.html | 17 ++++++++--------- handbook/build/docs/local-language/index.html | 17 ++++++++--------- handbook/build/docs/logging/index.html | 17 ++++++++--------- handbook/build/docs/middleware/index.html | 17 ++++++++--------- handbook/build/docs/module-dev/index.html | 17 ++++++++--------- handbook/build/docs/mongodb/index.html | 17 ++++++++--------- handbook/build/docs/net5-to-net6/index.html | 19 +++++++++---------- handbook/build/docs/nuget-local/index.html | 17 ++++++++--------- handbook/build/docs/object-mapper/index.html | 17 ++++++++--------- handbook/build/docs/options/index.html | 17 ++++++++--------- handbook/build/docs/performance/index.html | 17 ++++++++--------- .../docs/pillar-of-humiliation/index.html | 17 ++++++++--------- handbook/build/docs/pm2/index.html | 17 ++++++++--------- .../build/docs/process-service/index.html | 17 ++++++++--------- handbook/build/docs/reference/index.html | 17 ++++++++--------- handbook/build/docs/saas/index.html | 17 ++++++++--------- .../build/docs/sensitive-detection/index.html | 17 ++++++++--------- handbook/build/docs/serverun/index.html | 17 ++++++++--------- handbook/build/docs/sesssion-state/index.html | 17 ++++++++--------- .../docs/settings/appsettings/index.html | 17 ++++++++--------- .../settings/corsaccessorsettings/index.html | 17 ++++++++--------- .../dependencyinjectionsettings/index.html | 17 ++++++++--------- .../dynamicapicontrollersettings/index.html | 17 ++++++++--------- .../friendlyexceptionsettings/index.html | 17 ++++++++--------- .../docs/settings/jwtsettings/index.html | 17 ++++++++--------- .../settings/localizationsettings/index.html | 17 ++++++++--------- .../specificationdocumentsettings/index.html | 17 ++++++++--------- .../settings/unifyresultsettings/index.html | 17 ++++++++--------- .../validationTypemessagesettings/index.html | 17 ++++++++--------- handbook/build/docs/signalr/index.html | 17 ++++++++--------- handbook/build/docs/singlefile/index.html | 17 ++++++++--------- handbook/build/docs/source/index.html | 17 ++++++++--------- .../docs/specification-document/index.html | 17 ++++++++--------- handbook/build/docs/split-db/index.html | 17 ++++++++--------- handbook/build/docs/sqlsugar-old/index.html | 17 ++++++++--------- handbook/build/docs/sqlsugar/index.html | 17 ++++++++--------- handbook/build/docs/template/index.html | 17 ++++++++--------- handbook/build/docs/tran/index.html | 17 ++++++++--------- handbook/build/docs/unittest/index.html | 17 ++++++++--------- handbook/build/docs/upgrade/index.html | 19 +++++++++---------- handbook/build/docs/view-engine/index.html | 17 ++++++++--------- handbook/build/docs/virtual-deploy/index.html | 17 ++++++++--------- handbook/build/docs/vsfast/index.html | 17 ++++++++--------- handbook/build/index.html | 17 ++++++++--------- handbook/build/search/index.html | 17 ++++++++--------- handbook/docs/net5-to-net6.mdx | 2 +- handbook/docs/template.mdx | 4 ++-- handbook/docs/upgrade.mdx | 12 ++++++++---- handbook/package.json | 2 +- handbook/src/pages/index.js | 4 ++-- samples/Furion.Core/Furion.Core.csproj | 4 ++-- .../Furion.Template.Api.nuspec | 2 +- .../src/FurionApi.Core/FurionApi.Core.csproj | 6 +++--- .../Furion.Template.App.nuspec | 2 +- .../src/FurionApp.Core/FurionApp.Core.csproj | 6 +++--- .../Furion.Template.Blazor.nuspec | 2 +- .../FurionBlazor.Core.csproj | 4 ++-- .../Furion.Template.BlazorWithWebApi.nuspec | 2 +- .../FurionBlazorApi.Core.csproj | 6 +++--- .../Furion.Template.Mvc.nuspec | 2 +- .../src/FurionMvc.Core/FurionMvc.Core.csproj | 4 ++-- .../Furion.Template.Razor.nuspec | 2 +- .../FurionRazor.Core/FurionRazor.Core.csproj | 4 ++-- .../Furion.Template.RazorWithWebApi.nuspec | 2 +- .../FurionRazorApi.Core.csproj | 6 +++--- .../Furion.Template.Api.nuspec | 2 +- .../src/FurionApi.Core/FurionApi.Core.csproj | 6 +++--- .../Furion.Template.App.nuspec | 2 +- .../src/FurionApp.Core/FurionApp.Core.csproj | 6 +++--- .../Furion.Template.Blazor.nuspec | 2 +- .../FurionBlazor.Core.csproj | 4 ++-- .../Furion.Template.BlazorWithWebApi.nuspec | 2 +- .../FurionBlazorApi.Core.csproj | 6 +++--- .../Furion.Template.Mvc.nuspec | 2 +- .../src/FurionMvc.Core/FurionMvc.Core.csproj | 4 ++-- .../Furion.Template.Razor.nuspec | 2 +- .../FurionRazor.Core/FurionRazor.Core.csproj | 4 ++-- .../Furion.Template.RazorWithWebApi.nuspec | 2 +- .../FurionRazorApi.Core.csproj | 6 +++--- .../Furion.Tools.CommandLine.csproj | 2 +- .../Furion.Tools/Furion.Tools.csproj | 4 ++-- tools/cli.ps1 | 2 +- 527 files changed, 1471 insertions(+), 1618 deletions(-) rename handbook/build/assets/css/{styles.adf4a870.css => styles.5c4d70d3.css} (41%) delete mode 100644 handbook/build/assets/js/000e798f.49cd0fb3.js create mode 100644 handbook/build/assets/js/000e798f.a0d354b5.js create mode 100644 handbook/build/assets/js/00cf5050.0557c5ee.js delete mode 100644 handbook/build/assets/js/00cf5050.edbd97d1.js delete mode 100644 handbook/build/assets/js/00ee0bc9.807ce380.js create mode 100644 handbook/build/assets/js/00ee0bc9.e5d0b018.js rename handbook/build/assets/js/{01a85c17.a0e539b3.js => 01a85c17.4b3a9f27.js} (46%) delete mode 100644 handbook/build/assets/js/0249e0f1.8dca2318.js create mode 100644 handbook/build/assets/js/0249e0f1.b04f4642.js delete mode 100644 handbook/build/assets/js/02a99512.6353effe.js create mode 100644 handbook/build/assets/js/02a99512.76dc891f.js delete mode 100644 handbook/build/assets/js/0482bd9e.8e52c7b9.js create mode 100644 handbook/build/assets/js/0482bd9e.b11beeab.js create mode 100644 handbook/build/assets/js/04b9380e.66397e23.js delete mode 100644 handbook/build/assets/js/04b9380e.d0d2173b.js rename handbook/build/assets/js/{5d34f6af.2029e147.js => 06c1d953.73a63479.js} (65%) delete mode 100644 handbook/build/assets/js/083979a2.2e037b98.js create mode 100644 handbook/build/assets/js/083979a2.ef6110f4.js delete mode 100644 handbook/build/assets/js/093b1cf0.d0ea6525.js create mode 100644 handbook/build/assets/js/093b1cf0.f242526e.js delete mode 100644 handbook/build/assets/js/09bd0aa2.79620765.js create mode 100644 handbook/build/assets/js/09bd0aa2.bf2ee55f.js create mode 100644 handbook/build/assets/js/0baa6b13.47423144.js delete mode 100644 handbook/build/assets/js/0baa6b13.7c1d3edb.js delete mode 100644 handbook/build/assets/js/0f2c6659.8eedeb7a.js create mode 100644 handbook/build/assets/js/0f2c6659.e5dc8f58.js create mode 100644 handbook/build/assets/js/0ff68343.1e411abb.js delete mode 100644 handbook/build/assets/js/0ff68343.9f62d4ed.js delete mode 100644 handbook/build/assets/js/12829a06.3d723eb4.js create mode 100644 handbook/build/assets/js/12829a06.759cbd37.js delete mode 100644 handbook/build/assets/js/14cdac51.abde07cc.js create mode 100644 handbook/build/assets/js/14cdac51.d9d040de.js delete mode 100644 handbook/build/assets/js/17896441.08aa0b1c.js create mode 100644 handbook/build/assets/js/17896441.d648632e.js delete mode 100644 handbook/build/assets/js/1a4e3797.b4a26642.js create mode 100644 handbook/build/assets/js/1a4e3797.f48b4242.js rename handbook/build/assets/js/{1a4e3797.b4a26642.js.LICENSE.txt => 1a4e3797.f48b4242.js.LICENSE.txt} (100%) delete mode 100644 handbook/build/assets/js/1be78505.2600d13c.js create mode 100644 handbook/build/assets/js/1be78505.9ee37fe4.js delete mode 100644 handbook/build/assets/js/1c2c7d62.7e20de84.js create mode 100644 handbook/build/assets/js/1c2c7d62.92594d0c.js rename handbook/build/assets/js/{22bdbfc1.fc56613a.js => 22bdbfc1.363d2198.js} (72%) create mode 100644 handbook/build/assets/js/22f09a41.39655112.js delete mode 100644 handbook/build/assets/js/22f09a41.a8df2925.js delete mode 100644 handbook/build/assets/js/2397d9c0.a16e91c1.js create mode 100644 handbook/build/assets/js/2397d9c0.bcd55237.js create mode 100644 handbook/build/assets/js/2529.ad701460.js create mode 100644 handbook/build/assets/js/26682ccc.1fee17ed.js delete mode 100644 handbook/build/assets/js/26682ccc.23223d4d.js delete mode 100644 handbook/build/assets/js/2729f1a8.1400fa7d.js create mode 100644 handbook/build/assets/js/2729f1a8.475bacf0.js create mode 100644 handbook/build/assets/js/2b75607b.4ea221d8.js delete mode 100644 handbook/build/assets/js/2b75607b.87fde087.js delete mode 100644 handbook/build/assets/js/2b85edf2.95aa392d.js create mode 100644 handbook/build/assets/js/2b85edf2.acdd7bc5.js delete mode 100644 handbook/build/assets/js/3427cf63.5efd64d8.js create mode 100644 handbook/build/assets/js/3427cf63.fdc09969.js delete mode 100644 handbook/build/assets/js/3594fad8.6b7f470d.js create mode 100644 handbook/build/assets/js/3594fad8.970f9fe1.js create mode 100644 handbook/build/assets/js/3653278d.7b1f8f0c.js delete mode 100644 handbook/build/assets/js/3653278d.8bc48f2c.js rename handbook/build/assets/js/{2b0adb68.48b6d44a.js => 39c6bc14.291e8779.js} (65%) create mode 100644 handbook/build/assets/js/3a136e85.a5517a61.js delete mode 100644 handbook/build/assets/js/3a136e85.cdf57f74.js create mode 100644 handbook/build/assets/js/3d66e15d.357081f9.js delete mode 100644 handbook/build/assets/js/3d66e15d.dfbcc1cc.js delete mode 100644 handbook/build/assets/js/3d72d16d.45bf21c4.js create mode 100644 handbook/build/assets/js/3d72d16d.a4f56d9b.js create mode 100644 handbook/build/assets/js/3eb8904d.9ae5fa04.js delete mode 100644 handbook/build/assets/js/3eb8904d.f4f55df5.js create mode 100644 handbook/build/assets/js/40a433d4.38e4030f.js delete mode 100644 handbook/build/assets/js/40a433d4.66306be6.js delete mode 100644 handbook/build/assets/js/42806b0f.6cb69319.js create mode 100644 handbook/build/assets/js/42806b0f.bdadccb7.js create mode 100644 handbook/build/assets/js/4972.006d6232.js create mode 100644 handbook/build/assets/js/4ad72136.3768d2a2.js delete mode 100644 handbook/build/assets/js/4ad72136.61d6cae6.js create mode 100644 handbook/build/assets/js/4b6c538b.0b1661d7.js delete mode 100644 handbook/build/assets/js/4b6c538b.d9f39463.js create mode 100644 handbook/build/assets/js/4c19669a.8044c709.js delete mode 100644 handbook/build/assets/js/4c19669a.b0ff1dc3.js delete mode 100644 handbook/build/assets/js/4c79e569.433ccd43.js create mode 100644 handbook/build/assets/js/4c79e569.57384544.js delete mode 100644 handbook/build/assets/js/4d87bc8d.4aafd3e2.js create mode 100644 handbook/build/assets/js/4d87bc8d.c1c6d8c6.js delete mode 100644 handbook/build/assets/js/51c11da7.6ea72f85.js create mode 100644 handbook/build/assets/js/51c11da7.bb370a81.js delete mode 100644 handbook/build/assets/js/51c14d7f.062a1d65.js create mode 100644 handbook/build/assets/js/51c14d7f.ff396dd7.js delete mode 100644 handbook/build/assets/js/52821183.1a0f0bc7.js create mode 100644 handbook/build/assets/js/52821183.73e65fc1.js delete mode 100644 handbook/build/assets/js/5672fbad.7a2a2240.js create mode 100644 handbook/build/assets/js/5672fbad.ea02e960.js delete mode 100644 handbook/build/assets/js/5792.06bee9e5.js delete mode 100644 handbook/build/assets/js/57da61d5.7fa28076.js create mode 100644 handbook/build/assets/js/57da61d5.c16ad6d6.js delete mode 100644 handbook/build/assets/js/58624d73.7c550d93.js create mode 100644 handbook/build/assets/js/58624d73.bd06e57a.js rename handbook/build/assets/js/{afff7d91.d4ca715b.js => 5b1379ef.a9febb22.js} (34%) delete mode 100644 handbook/build/assets/js/5edfa151.0fad3db0.js create mode 100644 handbook/build/assets/js/5edfa151.b3508620.js delete mode 100644 handbook/build/assets/js/5edfff3a.4b55c402.js create mode 100644 handbook/build/assets/js/5edfff3a.8528a756.js delete mode 100644 handbook/build/assets/js/5f6c9278.c0cb49de.js create mode 100644 handbook/build/assets/js/5f6c9278.fc06fa9b.js create mode 100644 handbook/build/assets/js/612f2d9e.5cb6d11d.js delete mode 100644 handbook/build/assets/js/612f2d9e.86459e08.js rename handbook/build/assets/js/{9363.30f6f0bd.js => 617.ddf33500.js} (94%) delete mode 100644 handbook/build/assets/js/62d444b9.1c24496f.js create mode 100644 handbook/build/assets/js/62d444b9.aee53dfa.js create mode 100644 handbook/build/assets/js/633e39ed.ca94d7aa.js delete mode 100644 handbook/build/assets/js/633e39ed.f316c012.js create mode 100644 handbook/build/assets/js/64e66f0d.17bc1018.js delete mode 100644 handbook/build/assets/js/64e66f0d.d611c4b2.js delete mode 100644 handbook/build/assets/js/64ece2db.1dd6422a.js create mode 100644 handbook/build/assets/js/64ece2db.fc8d0233.js create mode 100644 handbook/build/assets/js/6875c492.9175ef0f.js delete mode 100644 handbook/build/assets/js/6875c492.d10d6e87.js delete mode 100644 handbook/build/assets/js/68ec177d.96ded009.js create mode 100644 handbook/build/assets/js/68ec177d.fe841cfd.js delete mode 100644 handbook/build/assets/js/698c3fb7.49c7b7fe.js create mode 100644 handbook/build/assets/js/698c3fb7.f4c008bc.js delete mode 100644 handbook/build/assets/js/69b28fcd.6676266a.js create mode 100644 handbook/build/assets/js/69b28fcd.da1662d4.js delete mode 100644 handbook/build/assets/js/6b7b862c.ac22c3a5.js create mode 100644 handbook/build/assets/js/6b7b862c.dd7ce31a.js create mode 100644 handbook/build/assets/js/6eaa010c.a430e57a.js delete mode 100644 handbook/build/assets/js/6eaa010c.e6f407eb.js delete mode 100644 handbook/build/assets/js/6fa9a93a.ae659217.js create mode 100644 handbook/build/assets/js/6fa9a93a.fc03db49.js delete mode 100644 handbook/build/assets/js/711b45e3.398f241d.js create mode 100644 handbook/build/assets/js/711b45e3.ec13726e.js delete mode 100644 handbook/build/assets/js/713.e2d721b5.js delete mode 100644 handbook/build/assets/js/713be7bb.0b389d71.js create mode 100644 handbook/build/assets/js/713be7bb.8ab7df69.js create mode 100644 handbook/build/assets/js/73d3b1ea.3825ed12.js delete mode 100644 handbook/build/assets/js/73d3b1ea.db30f856.js delete mode 100644 handbook/build/assets/js/757fb418.b628ed3a.js create mode 100644 handbook/build/assets/js/757fb418.d19ffcfd.js create mode 100644 handbook/build/assets/js/76437093.b81a4f82.js delete mode 100644 handbook/build/assets/js/76437093.ce2a8922.js delete mode 100644 handbook/build/assets/js/76b00148.7abbab6c.js create mode 100644 handbook/build/assets/js/76b00148.eb20b8a7.js delete mode 100644 handbook/build/assets/js/78e5e8dd.0f59ff26.js create mode 100644 handbook/build/assets/js/78e5e8dd.5277f06b.js delete mode 100644 handbook/build/assets/js/7c5dd5ef.9634009c.js create mode 100644 handbook/build/assets/js/7c5dd5ef.b86dde09.js create mode 100644 handbook/build/assets/js/7c6b08dc.85addf76.js delete mode 100644 handbook/build/assets/js/7c6b08dc.897bee85.js create mode 100644 handbook/build/assets/js/7d1915d2.08fd2c20.js delete mode 100644 handbook/build/assets/js/7d1915d2.c1af54c4.js create mode 100644 handbook/build/assets/js/7dd08b1c.7d4cd667.js delete mode 100644 handbook/build/assets/js/7dd08b1c.cbbe1161.js create mode 100644 handbook/build/assets/js/800036d7.0f729a1e.js delete mode 100644 handbook/build/assets/js/800036d7.c5090b95.js delete mode 100644 handbook/build/assets/js/84a61a3c.255a77ab.js create mode 100644 handbook/build/assets/js/84a61a3c.58c2675f.js delete mode 100644 handbook/build/assets/js/84b6e574.53077f68.js create mode 100644 handbook/build/assets/js/84b6e574.b4dbdcc8.js create mode 100644 handbook/build/assets/js/861b6d56.82136f7f.js delete mode 100644 handbook/build/assets/js/861b6d56.f4a2fc6e.js delete mode 100644 handbook/build/assets/js/88486ef5.8256c724.js create mode 100644 handbook/build/assets/js/88486ef5.c02a6a2a.js delete mode 100644 handbook/build/assets/js/8968961d.e90ecda8.js create mode 100644 handbook/build/assets/js/8968961d.edbe173e.js create mode 100644 handbook/build/assets/js/8a0794d9.a10e91de.js delete mode 100644 handbook/build/assets/js/8a0794d9.ccc96964.js delete mode 100644 handbook/build/assets/js/8b7511b6.56851f0a.js create mode 100644 handbook/build/assets/js/8b7511b6.b153f625.js rename handbook/build/assets/js/{8d45ae1b.6981b7a2.js => 8d45ae1b.d16db555.js} (71%) delete mode 100644 handbook/build/assets/js/8dcbe064.ecefcb93.js create mode 100644 handbook/build/assets/js/8dcbe064.f2e594d6.js create mode 100644 handbook/build/assets/js/8f2f6685.0c1801d5.js delete mode 100644 handbook/build/assets/js/8f2f6685.a829fdbc.js create mode 100644 handbook/build/assets/js/9055.186ea641.js delete mode 100644 handbook/build/assets/js/914e87db.437727ef.js create mode 100644 handbook/build/assets/js/914e87db.856f476f.js create mode 100644 handbook/build/assets/js/934e2055.4d5ac78b.js delete mode 100644 handbook/build/assets/js/934e2055.c48809ce.js delete mode 100644 handbook/build/assets/js/935f2afb.57011e9b.js create mode 100644 handbook/build/assets/js/935f2afb.ccba3080.js delete mode 100644 handbook/build/assets/js/937eda02.a37f00fa.js create mode 100644 handbook/build/assets/js/937eda02.db68586a.js delete mode 100644 handbook/build/assets/js/9888.c11ad302.js create mode 100644 handbook/build/assets/js/9b04aa07.559eaa5c.js delete mode 100644 handbook/build/assets/js/9b04aa07.e9458336.js create mode 100644 handbook/build/assets/js/9bd20b97.a160a0db.js delete mode 100644 handbook/build/assets/js/9bd20b97.e8922b01.js delete mode 100644 handbook/build/assets/js/9c854613.317925eb.js create mode 100644 handbook/build/assets/js/9c854613.45824898.js create mode 100644 handbook/build/assets/js/9ce2543b.78443ed4.js delete mode 100644 handbook/build/assets/js/9ce2543b.f74974a7.js rename handbook/build/assets/js/{9e4087bc.7950f9cb.js => 9e4087bc.7202a43f.js} (88%) create mode 100644 handbook/build/assets/js/9e7ef9fa.c0b774f3.js delete mode 100644 handbook/build/assets/js/9e7ef9fa.d9a3ef03.js delete mode 100644 handbook/build/assets/js/a0a8cac6.7a8e93e6.js create mode 100644 handbook/build/assets/js/a0a8cac6.ef8fa4bd.js create mode 100644 handbook/build/assets/js/a125e20e.21aa56b6.js delete mode 100644 handbook/build/assets/js/a125e20e.6c234aa6.js delete mode 100644 handbook/build/assets/js/a19656d0.05ba8fe6.js create mode 100644 handbook/build/assets/js/a19656d0.1eb0420c.js create mode 100644 handbook/build/assets/js/a2d62645.f029c5ed.js delete mode 100644 handbook/build/assets/js/a2d62645.fcb746f2.js create mode 100644 handbook/build/assets/js/a4688235.1134e6e2.js delete mode 100644 handbook/build/assets/js/a4688235.2d20d46b.js delete mode 100644 handbook/build/assets/js/a4c09e9b.91ba7bb3.js create mode 100644 handbook/build/assets/js/a4c09e9b.f29c947c.js create mode 100644 handbook/build/assets/js/a6aa9e1f.4482c8b9.js delete mode 100644 handbook/build/assets/js/a6aa9e1f.e5d8d377.js create mode 100644 handbook/build/assets/js/a71f9f93.20230c19.js delete mode 100644 handbook/build/assets/js/a71f9f93.2db4ebc2.js create mode 100644 handbook/build/assets/js/a8677dec.ad1235ff.js delete mode 100644 handbook/build/assets/js/a8677dec.d6c71cca.js create mode 100644 handbook/build/assets/js/aa7bdd74.02dd36a3.js delete mode 100644 handbook/build/assets/js/aa7bdd74.3b76ce8d.js delete mode 100644 handbook/build/assets/js/ab4c4f37.5ee20dfb.js create mode 100644 handbook/build/assets/js/ab4c4f37.f827e34a.js delete mode 100644 handbook/build/assets/js/ab6beea0.0f966ba6.js create mode 100644 handbook/build/assets/js/ab6beea0.48e0088f.js delete mode 100644 handbook/build/assets/js/ace43ec3.2e7195f2.js create mode 100644 handbook/build/assets/js/ace43ec3.53d29fea.js delete mode 100644 handbook/build/assets/js/adf0697d.8c4636c6.js create mode 100644 handbook/build/assets/js/adf0697d.ebd6554a.js delete mode 100644 handbook/build/assets/js/afaad682.373f32f8.js create mode 100644 handbook/build/assets/js/afaad682.47fac500.js create mode 100644 handbook/build/assets/js/b0352e4c.7b695c42.js delete mode 100644 handbook/build/assets/js/b0352e4c.fb0c2a88.js delete mode 100644 handbook/build/assets/js/b40312ef.0517251e.js create mode 100644 handbook/build/assets/js/b40312ef.4b4dbccc.js delete mode 100644 handbook/build/assets/js/b4685f05.0886951d.js create mode 100644 handbook/build/assets/js/b4685f05.e7416c4a.js create mode 100644 handbook/build/assets/js/b6492972.05854844.js delete mode 100644 handbook/build/assets/js/b6492972.9d788011.js delete mode 100644 handbook/build/assets/js/b753a5b5.69498779.js create mode 100644 handbook/build/assets/js/b753a5b5.d41da7d4.js delete mode 100644 handbook/build/assets/js/b7a8adf4.7cf903ff.js create mode 100644 handbook/build/assets/js/b7a8adf4.c57c32da.js create mode 100644 handbook/build/assets/js/b89c6849.645c0b5e.js delete mode 100644 handbook/build/assets/js/b89c6849.8c07483c.js rename handbook/build/assets/js/{f70fd1af.8ef10849.js => b96ebcf3.889835bb.js} (65%) delete mode 100644 handbook/build/assets/js/bb3cf766.c474c445.js create mode 100644 handbook/build/assets/js/bb3cf766.d974ec94.js rename handbook/build/assets/js/{bc8bce29.16934f75.js => bc8bce29.c61c20b8.js} (76%) delete mode 100644 handbook/build/assets/js/bfaddb57.09d1fbeb.js create mode 100644 handbook/build/assets/js/bfaddb57.9256bc68.js create mode 100644 handbook/build/assets/js/c0812ddb.233de97c.js delete mode 100644 handbook/build/assets/js/c0812ddb.48ff70af.js delete mode 100644 handbook/build/assets/js/c4b1c400.45a327f8.js create mode 100644 handbook/build/assets/js/c4b1c400.cb4c5d0b.js create mode 100644 handbook/build/assets/js/c4f5d8e4.05ac18fa.js delete mode 100644 handbook/build/assets/js/c4f5d8e4.8fac2b97.js delete mode 100644 handbook/build/assets/js/c601aa1c.2e50a800.js create mode 100644 handbook/build/assets/js/c601aa1c.93b6fd4c.js delete mode 100644 handbook/build/assets/js/c76f8c40.baae6566.js create mode 100644 handbook/build/assets/js/c76f8c40.eb7a2876.js create mode 100644 handbook/build/assets/js/c7a9ad89.8cfb38a9.js delete mode 100644 handbook/build/assets/js/c7a9ad89.bb0b3826.js delete mode 100644 handbook/build/assets/js/cbb899e4.4636e3f3.js create mode 100644 handbook/build/assets/js/cbb899e4.9428b656.js delete mode 100644 handbook/build/assets/js/ccc2287e.0846b13c.js create mode 100644 handbook/build/assets/js/ccc2287e.dc8a82fc.js delete mode 100644 handbook/build/assets/js/ccc49370.c96ce516.js create mode 100644 handbook/build/assets/js/ccc49370.e75da32b.js create mode 100644 handbook/build/assets/js/cd54e801.026c4cdc.js delete mode 100644 handbook/build/assets/js/cd54e801.b72d8366.js create mode 100644 handbook/build/assets/js/d0a6dadf.21d6e0e6.js delete mode 100644 handbook/build/assets/js/d0a6dadf.325cec41.js delete mode 100644 handbook/build/assets/js/d22033f9.7ff99e41.js create mode 100644 handbook/build/assets/js/d22033f9.dad18b96.js create mode 100644 handbook/build/assets/js/d444ce62.b29f9de5.js delete mode 100644 handbook/build/assets/js/d444ce62.e73386cd.js create mode 100644 handbook/build/assets/js/d47dc5e2.626f9e2b.js delete mode 100644 handbook/build/assets/js/d47dc5e2.8ae7c236.js delete mode 100644 handbook/build/assets/js/d71de838.15badbc1.js create mode 100644 handbook/build/assets/js/d71de838.7a4dbb10.js create mode 100644 handbook/build/assets/js/d8865cb1.38525976.js delete mode 100644 handbook/build/assets/js/d8865cb1.a7e0b5b2.js create mode 100644 handbook/build/assets/js/d894cce0.d59716c1.js delete mode 100644 handbook/build/assets/js/d894cce0.f09011f2.js delete mode 100644 handbook/build/assets/js/da6c7707.2bc08084.js create mode 100644 handbook/build/assets/js/da6c7707.4d1a9809.js delete mode 100644 handbook/build/assets/js/da88eb6b.0ddeca6c.js create mode 100644 handbook/build/assets/js/da88eb6b.33e09cab.js create mode 100644 handbook/build/assets/js/db5a72a0.1542f7d4.js delete mode 100644 handbook/build/assets/js/db5a72a0.43da0f36.js delete mode 100644 handbook/build/assets/js/dc235550.371e1288.js create mode 100644 handbook/build/assets/js/dc235550.fe340f9e.js delete mode 100644 handbook/build/assets/js/e17ba759.3ac9b836.js create mode 100644 handbook/build/assets/js/e17ba759.4237f9ec.js delete mode 100644 handbook/build/assets/js/e60cf3ee.298f2c0b.js create mode 100644 handbook/build/assets/js/e60cf3ee.42322920.js delete mode 100644 handbook/build/assets/js/e7929401.4f3d7915.js create mode 100644 handbook/build/assets/js/e7929401.c8528a6c.js create mode 100644 handbook/build/assets/js/e829a4ba.3998cd6e.js delete mode 100644 handbook/build/assets/js/e829a4ba.832473ff.js create mode 100644 handbook/build/assets/js/ea36d85d.6fd1562f.js delete mode 100644 handbook/build/assets/js/ea36d85d.f439dd72.js delete mode 100644 handbook/build/assets/js/ea50195b.15d8a67e.js create mode 100644 handbook/build/assets/js/ea50195b.729b23eb.js delete mode 100644 handbook/build/assets/js/edb1f2eb.0c47b5d4.js create mode 100644 handbook/build/assets/js/edb1f2eb.34dd0faa.js create mode 100644 handbook/build/assets/js/efaef7c6.66b19c69.js delete mode 100644 handbook/build/assets/js/efaef7c6.d3c76c73.js create mode 100644 handbook/build/assets/js/f1c506f3.7d70aff2.js delete mode 100644 handbook/build/assets/js/f1c506f3.a0f8c0c5.js delete mode 100644 handbook/build/assets/js/f2131000.2bc2eabe.js create mode 100644 handbook/build/assets/js/f2131000.2d4ce8ce.js create mode 100644 handbook/build/assets/js/f60abd31.36261204.js delete mode 100644 handbook/build/assets/js/f60abd31.f36fe3d8.js create mode 100644 handbook/build/assets/js/f7db4844.580da9fb.js delete mode 100644 handbook/build/assets/js/f7db4844.c41090e8.js delete mode 100644 handbook/build/assets/js/fc508b36.671e2aec.js create mode 100644 handbook/build/assets/js/fc508b36.e1b88d0f.js create mode 100644 handbook/build/assets/js/fd6801a9.506dbbb7.js delete mode 100644 handbook/build/assets/js/fd6801a9.9b58e88b.js delete mode 100644 handbook/build/assets/js/fd885aa1.391bbc3a.js create mode 100644 handbook/build/assets/js/fd885aa1.76cfb01e.js delete mode 100644 handbook/build/assets/js/fe38d63c.22f6af76.js create mode 100644 handbook/build/assets/js/fe38d63c.fe1ab479.js create mode 100644 handbook/build/assets/js/fe3b2968.5499402c.js delete mode 100644 handbook/build/assets/js/fe3b2968.588dbe92.js delete mode 100644 handbook/build/assets/js/main.930b2221.js create mode 100644 handbook/build/assets/js/main.e0f2178f.js rename handbook/build/assets/js/{main.930b2221.js.LICENSE.txt => main.e0f2178f.js.LICENSE.txt} (100%) create mode 100644 handbook/build/assets/js/runtime~main.a62e617c.js delete mode 100644 handbook/build/assets/js/runtime~main.e0dbf6bc.js diff --git a/framework/Furion.Extras.Authentication.JwtBearer/Furion.Extras.Authentication.JwtBearer.csproj b/framework/Furion.Extras.Authentication.JwtBearer/Furion.Extras.Authentication.JwtBearer.csproj index 5080d5d0d9..275a5388a5 100644 --- a/framework/Furion.Extras.Authentication.JwtBearer/Furion.Extras.Authentication.JwtBearer.csproj +++ b/framework/Furion.Extras.Authentication.JwtBearer/Furion.Extras.Authentication.JwtBearer.csproj @@ -2,7 +2,7 @@ net5.0;net6.0;net7.0 - 4.3.9 + 4.4.0 Furion Jwt 授权验证拓展插件。 enable diff --git a/framework/Furion.Extras.DatabaseAccessor.Dapper/Furion.Extras.DatabaseAccessor.Dapper.csproj b/framework/Furion.Extras.DatabaseAccessor.Dapper/Furion.Extras.DatabaseAccessor.Dapper.csproj index 51e63b8496..23e7c549c1 100644 --- a/framework/Furion.Extras.DatabaseAccessor.Dapper/Furion.Extras.DatabaseAccessor.Dapper.csproj +++ b/framework/Furion.Extras.DatabaseAccessor.Dapper/Furion.Extras.DatabaseAccessor.Dapper.csproj @@ -2,7 +2,7 @@ net5.0;net6.0;net7.0 - 4.3.9 + 4.4.0 Furion 数据库访问器 Dapper 插件。 enable diff --git a/framework/Furion.Extras.DatabaseAccessor.MongoDB/Furion.Extras.DatabaseAccessor.MongoDB.csproj b/framework/Furion.Extras.DatabaseAccessor.MongoDB/Furion.Extras.DatabaseAccessor.MongoDB.csproj index 7d59bac1a5..9ebb83b979 100644 --- a/framework/Furion.Extras.DatabaseAccessor.MongoDB/Furion.Extras.DatabaseAccessor.MongoDB.csproj +++ b/framework/Furion.Extras.DatabaseAccessor.MongoDB/Furion.Extras.DatabaseAccessor.MongoDB.csproj @@ -2,7 +2,7 @@ net5.0;net6.0;net7.0 - 4.3.9 + 4.4.0 Furion 数据库访问器 MongoDB 插件。 enable diff --git a/framework/Furion.Extras.DatabaseAccessor.SqlSugar/Furion.Extras.DatabaseAccessor.SqlSugar.csproj b/framework/Furion.Extras.DatabaseAccessor.SqlSugar/Furion.Extras.DatabaseAccessor.SqlSugar.csproj index 7275d7a784..7dd9c8cbd2 100644 --- a/framework/Furion.Extras.DatabaseAccessor.SqlSugar/Furion.Extras.DatabaseAccessor.SqlSugar.csproj +++ b/framework/Furion.Extras.DatabaseAccessor.SqlSugar/Furion.Extras.DatabaseAccessor.SqlSugar.csproj @@ -2,7 +2,7 @@ net5.0;net6.0;net7.0 - 4.3.9 + 4.4.0 Furion 数据库访问器 SqlSugar 插件。 enable diff --git a/framework/Furion.Extras.DependencyModel.CodeAnalysis/Furion.Extras.DependencyModel.CodeAnalysis.csproj b/framework/Furion.Extras.DependencyModel.CodeAnalysis/Furion.Extras.DependencyModel.CodeAnalysis.csproj index c5876ac39e..d1f71b484d 100644 --- a/framework/Furion.Extras.DependencyModel.CodeAnalysis/Furion.Extras.DependencyModel.CodeAnalysis.csproj +++ b/framework/Furion.Extras.DependencyModel.CodeAnalysis/Furion.Extras.DependencyModel.CodeAnalysis.csproj @@ -2,7 +2,7 @@ net5.0;net6.0;net7.0 - 4.3.9 + 4.4.0 Furion 程序集扫描和代码分析拓展插件。 enable diff --git a/framework/Furion.Extras.Logging.Serilog/Furion.Extras.Logging.Serilog.csproj b/framework/Furion.Extras.Logging.Serilog/Furion.Extras.Logging.Serilog.csproj index 502ad01dbe..9aa6466761 100644 --- a/framework/Furion.Extras.Logging.Serilog/Furion.Extras.Logging.Serilog.csproj +++ b/framework/Furion.Extras.Logging.Serilog/Furion.Extras.Logging.Serilog.csproj @@ -2,7 +2,7 @@ net5.0;net6.0;net7.0 - 4.3.9 + 4.4.0 Furion 日志记录 Serilog 插件。 enable 0618 diff --git a/framework/Furion.Extras.ObjectMapper.Mapster/Furion.Extras.ObjectMapper.Mapster.csproj b/framework/Furion.Extras.ObjectMapper.Mapster/Furion.Extras.ObjectMapper.Mapster.csproj index 55ea9a9a41..29a4ee5e7f 100644 --- a/framework/Furion.Extras.ObjectMapper.Mapster/Furion.Extras.ObjectMapper.Mapster.csproj +++ b/framework/Furion.Extras.ObjectMapper.Mapster/Furion.Extras.ObjectMapper.Mapster.csproj @@ -2,7 +2,7 @@ net5.0;net6.0;net7.0 - 4.3.9 + 4.4.0 Furion 对象映射 Mapster 插件。 enable diff --git a/framework/Furion.Pure.Extras.DependencyModel.CodeAnalysis/Furion.Pure.Extras.DependencyModel.CodeAnalysis.csproj b/framework/Furion.Pure.Extras.DependencyModel.CodeAnalysis/Furion.Pure.Extras.DependencyModel.CodeAnalysis.csproj index 369d38f90b..66257fe283 100644 --- a/framework/Furion.Pure.Extras.DependencyModel.CodeAnalysis/Furion.Pure.Extras.DependencyModel.CodeAnalysis.csproj +++ b/framework/Furion.Pure.Extras.DependencyModel.CodeAnalysis/Furion.Pure.Extras.DependencyModel.CodeAnalysis.csproj @@ -2,7 +2,7 @@ net5.0;net6.0;net7.0 - 4.3.9 + 4.4.0 Furion 程序集扫描和代码分析拓展插件。 enable diff --git a/framework/Furion.Pure.Xunit/Furion.Pure.Xunit.csproj b/framework/Furion.Pure.Xunit/Furion.Pure.Xunit.csproj index 8af2871c0d..e4a5182def 100644 --- a/framework/Furion.Pure.Xunit/Furion.Pure.Xunit.csproj +++ b/framework/Furion.Pure.Xunit/Furion.Pure.Xunit.csproj @@ -2,13 +2,13 @@ net5.0;net6.0;net7.0 - 4.3.9 + 4.4.0 Furion 纯净版 Xunit 单元测试拓展插件。 enable - + diff --git a/framework/Furion.Pure/Furion.Pure.csproj b/framework/Furion.Pure/Furion.Pure.csproj index 304a58ba9e..7ca7d21163 100644 --- a/framework/Furion.Pure/Furion.Pure.csproj +++ b/framework/Furion.Pure/Furion.Pure.csproj @@ -2,7 +2,7 @@ net5.0;net6.0;net7.0 - 4.3.9 + 4.4.0 让 .NET 开发更简单,更通用,更流行。 true enable @@ -26,19 +26,19 @@ - + - + - + diff --git a/framework/Furion.Xunit/Furion.Xunit.csproj b/framework/Furion.Xunit/Furion.Xunit.csproj index 0b4c7c5bfc..ecd754a4d2 100644 --- a/framework/Furion.Xunit/Furion.Xunit.csproj +++ b/framework/Furion.Xunit/Furion.Xunit.csproj @@ -2,13 +2,13 @@ net5.0;net6.0;net7.0 - 4.3.9 + 4.4.0 Furion Xunit 单元测试拓展插件。 enable - + diff --git a/framework/Furion/Furion.csproj b/framework/Furion/Furion.csproj index a17e3f77d5..341c9f9382 100644 --- a/framework/Furion/Furion.csproj +++ b/framework/Furion/Furion.csproj @@ -2,7 +2,7 @@ net5.0;net6.0;net7.0 - 4.3.9 + 4.4.0 让 .NET 开发更简单,更通用,更流行。 true enable @@ -26,19 +26,19 @@ - + - + - + diff --git a/handbook/build/404.html b/handbook/build/404.html index c2686b28e6..0430627ba1 100644 --- a/handbook/build/404.html +++ b/handbook/build/404.html @@ -2,22 +2,21 @@ - - - + +Page Not Found | Furion -Page Not Found | Furion - - + + +
-

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

演练场
- - +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

演练场
+ + \ No newline at end of file diff --git a/handbook/build/assets/css/styles.adf4a870.css b/handbook/build/assets/css/styles.5c4d70d3.css similarity index 41% rename from handbook/build/assets/css/styles.adf4a870.css rename to handbook/build/assets/css/styles.5c4d70d3.css index 9c0080630c..e2de838eeb 100644 --- a/handbook/build/assets/css/styles.adf4a870.css +++ b/handbook/build/assets/css/styles.5c4d70d3.css @@ -1 +1 @@ -@charset "UTF-8";.col,.container{padding:0 var(--ifm-spacing-horizontal);width:100%}.markdown li,body{word-wrap:break-word}body,ol ol,ol ul,ul ol,ul ul{margin:0}pre,table{overflow:auto}blockquote,pre{margin:0 0 var(--ifm-spacing-vertical)}.breadcrumbs__link,.button{transition-timing-function:var(--ifm-transition-timing-default)}.button,code{vertical-align:middle}.button--outline.button--active,.button--outline:active,.button--outline:hover,:root{--ifm-button-color:var(--ifm-font-color-base-inverse)}.menu__link:hover,a{transition:color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.navbar--dark,:root{--ifm-navbar-link-hover-color:var(--ifm-color-primary)}.menu,.navbar-sidebar{overflow-x:hidden}:root,html[data-theme=dark]{--ifm-color-emphasis-500:var(--ifm-color-gray-500)}.animate__headShake,.animate__heartBeat,.animate__pulse{animation-timing-function:ease-in-out}.toggleButton_gllP,html{-webkit-tap-highlight-color:transparent}*,.DocSearch-Container,.DocSearch-Container *,.furion-log-item,.furion-who-custom,.furion-who-des,.modal_wSGk{box-sizing:border-box}:root{--ifm-color-scheme:light;--ifm-dark-value:10%;--ifm-darker-value:15%;--ifm-darkest-value:30%;--ifm-light-value:15%;--ifm-lighter-value:30%;--ifm-lightest-value:50%;--ifm-contrast-background-value:90%;--ifm-contrast-foreground-value:70%;--ifm-contrast-background-dark-value:70%;--ifm-contrast-foreground-dark-value:90%;--ifm-color-primary:#3578e5;--ifm-color-secondary:#ebedf0;--ifm-color-success:#00a400;--ifm-color-info:#54c7ec;--ifm-color-warning:#ffba00;--ifm-color-danger:#fa383e;--ifm-color-primary-dark:#306cce;--ifm-color-primary-darker:#2d66c3;--ifm-color-primary-darkest:#2554a0;--ifm-color-primary-light:#538ce9;--ifm-color-primary-lighter:#72a1ed;--ifm-color-primary-lightest:#9abcf2;--ifm-color-primary-contrast-background:#ebf2fc;--ifm-color-primary-contrast-foreground:#102445;--ifm-color-secondary-dark:#d4d5d8;--ifm-color-secondary-darker:#c8c9cc;--ifm-color-secondary-darkest:#a4a6a8;--ifm-color-secondary-light:#eef0f2;--ifm-color-secondary-lighter:#f1f2f5;--ifm-color-secondary-lightest:#f5f6f8;--ifm-color-secondary-contrast-background:#fdfdfe;--ifm-color-secondary-contrast-foreground:#474748;--ifm-color-success-dark:#009400;--ifm-color-success-darker:#008b00;--ifm-color-success-darkest:#007300;--ifm-color-success-light:#26b226;--ifm-color-success-lighter:#4dbf4d;--ifm-color-success-lightest:#80d280;--ifm-color-success-contrast-background:#e6f6e6;--ifm-color-success-contrast-foreground:#003100;--ifm-color-info-dark:#4cb3d4;--ifm-color-info-darker:#47a9c9;--ifm-color-info-darkest:#3b8ba5;--ifm-color-info-light:#6ecfef;--ifm-color-info-lighter:#87d8f2;--ifm-color-info-lightest:#aae3f6;--ifm-color-info-contrast-background:#eef9fd;--ifm-color-info-contrast-foreground:#193c47;--ifm-color-warning-dark:#e6a700;--ifm-color-warning-darker:#d99e00;--ifm-color-warning-darkest:#b38200;--ifm-color-warning-light:#ffc426;--ifm-color-warning-lighter:#ffcf4d;--ifm-color-warning-lightest:#ffdd80;--ifm-color-warning-contrast-background:#fff8e6;--ifm-color-warning-contrast-foreground:#4d3800;--ifm-color-danger-dark:#e13238;--ifm-color-danger-darker:#d53035;--ifm-color-danger-darkest:#af272b;--ifm-color-danger-light:#fb565b;--ifm-color-danger-lighter:#fb7478;--ifm-color-danger-lightest:#fd9c9f;--ifm-color-danger-contrast-background:#ffebec;--ifm-color-danger-contrast-foreground:#4b1113;--ifm-color-white:#fff;--ifm-color-black:#000;--ifm-color-gray-0:var(--ifm-color-white);--ifm-color-gray-100:#f5f6f7;--ifm-color-gray-200:#ebedf0;--ifm-color-gray-300:#dadde1;--ifm-color-gray-400:#ccd0d5;--ifm-color-gray-500:#bec3c9;--ifm-color-gray-600:#8d949e;--ifm-color-gray-700:#606770;--ifm-color-gray-800:#444950;--ifm-color-gray-900:#1c1e21;--ifm-color-gray-1000:var(--ifm-color-black);--ifm-color-emphasis-0:var(--ifm-color-gray-0);--ifm-color-emphasis-100:var(--ifm-color-gray-100);--ifm-color-emphasis-200:var(--ifm-color-gray-200);--ifm-color-emphasis-300:var(--ifm-color-gray-300);--ifm-color-emphasis-400:var(--ifm-color-gray-400);--ifm-color-emphasis-600:var(--ifm-color-gray-600);--ifm-color-emphasis-700:var(--ifm-color-gray-700);--ifm-color-emphasis-800:var(--ifm-color-gray-800);--ifm-color-emphasis-900:var(--ifm-color-gray-900);--ifm-color-emphasis-1000:var(--ifm-color-gray-1000);--ifm-color-content:var(--ifm-color-emphasis-900);--ifm-color-content-inverse:var(--ifm-color-emphasis-0);--ifm-color-content-secondary:#525860;--ifm-background-color:transparent;--ifm-background-surface-color:var(--ifm-color-content-inverse);--ifm-global-border-width:1px;--ifm-global-radius:0.4rem;--ifm-hover-overlay:rgba(0,0,0,.05);--ifm-font-color-base:var(--ifm-color-content);--ifm-font-color-base-inverse:var(--ifm-color-content-inverse);--ifm-font-color-secondary:var(--ifm-color-content-secondary);--ifm-font-family-base:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--ifm-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--ifm-font-size-base:100%;--ifm-font-weight-light:300;--ifm-font-weight-normal:400;--ifm-font-weight-semibold:500;--ifm-font-weight-bold:700;--ifm-font-weight-base:var(--ifm-font-weight-normal);--ifm-line-height-base:1.65;--ifm-global-spacing:1rem;--ifm-spacing-vertical:var(--ifm-global-spacing);--ifm-spacing-horizontal:var(--ifm-global-spacing);--ifm-transition-fast:200ms;--ifm-transition-slow:400ms;--ifm-transition-timing-default:cubic-bezier(0.08,0.52,0.52,1);--ifm-global-shadow-lw:0 1px 2px 0 rgba(0,0,0,.1);--ifm-global-shadow-md:0 5px 40px rgba(0,0,0,.2);--ifm-global-shadow-tl:0 12px 28px 0 rgba(0,0,0,.2),0 2px 4px 0 rgba(0,0,0,.1);--ifm-z-index-dropdown:100;--ifm-z-index-fixed:200;--ifm-z-index-overlay:400;--ifm-container-width:1140px;--ifm-container-width-xl:1320px;--ifm-code-background:#f6f7f8;--ifm-code-border-radius:var(--ifm-global-radius);--ifm-code-font-size:90%;--ifm-code-padding-horizontal:0.1rem;--ifm-code-padding-vertical:0.1rem;--ifm-pre-background:var(--ifm-code-background);--ifm-pre-border-radius:var(--ifm-code-border-radius);--ifm-pre-color:inherit;--ifm-pre-line-height:1.45;--ifm-pre-padding:1rem;--ifm-heading-color:inherit;--ifm-heading-margin-top:0;--ifm-heading-margin-bottom:var(--ifm-spacing-vertical);--ifm-heading-font-family:var(--ifm-font-family-base);--ifm-heading-font-weight:var(--ifm-font-weight-bold);--ifm-heading-line-height:1.25;--ifm-h1-font-size:2rem;--ifm-h2-font-size:1.5rem;--ifm-h3-font-size:1.25rem;--ifm-h4-font-size:1rem;--ifm-h5-font-size:0.875rem;--ifm-h6-font-size:0.85rem;--ifm-image-alignment-padding:1.25rem;--ifm-leading-desktop:1.25;--ifm-leading:calc(var(--ifm-leading-desktop)*1rem);--ifm-list-left-padding:2rem;--ifm-list-margin:1rem;--ifm-list-item-margin:0.25rem;--ifm-list-paragraph-margin:1rem;--ifm-table-cell-padding:0.75rem;--ifm-table-background:transparent;--ifm-table-stripe-background:rgba(0,0,0,.03);--ifm-table-border-width:1px;--ifm-table-border-color:var(--ifm-color-emphasis-300);--ifm-table-head-background:inherit;--ifm-table-head-color:inherit;--ifm-table-head-font-weight:var(--ifm-font-weight-bold);--ifm-table-cell-color:inherit;--ifm-link-color:var(--ifm-color-primary);--ifm-link-decoration:none;--ifm-link-hover-color:var(--ifm-link-color);--ifm-link-hover-decoration:underline;--ifm-paragraph-margin-bottom:var(--ifm-leading);--ifm-blockquote-font-size:var(--ifm-font-size-base);--ifm-blockquote-border-left-width:2px;--ifm-blockquote-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-blockquote-padding-vertical:0;--ifm-blockquote-shadow:none;--ifm-blockquote-color:var(--ifm-color-emphasis-800);--ifm-blockquote-border-color:var(--ifm-color-emphasis-300);--ifm-hr-background-color:var(--ifm-color-emphasis-500);--ifm-hr-height:1px;--ifm-hr-margin-vertical:1.5rem;--ifm-scrollbar-size:7px;--ifm-scrollbar-track-background-color:#f1f1f1;--ifm-scrollbar-thumb-background-color:silver;--ifm-scrollbar-thumb-hover-background-color:#a7a7a7;--ifm-alert-background-color:inherit;--ifm-alert-border-color:inherit;--ifm-alert-border-radius:var(--ifm-global-radius);--ifm-alert-border-width:0px;--ifm-alert-border-left-width:5px;--ifm-alert-color:var(--ifm-font-color-base);--ifm-alert-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-alert-padding-vertical:var(--ifm-spacing-vertical);--ifm-alert-shadow:var(--ifm-global-shadow-lw);--ifm-avatar-intro-margin:1rem;--ifm-avatar-intro-alignment:inherit;--ifm-avatar-photo-size:3rem;--ifm-badge-background-color:inherit;--ifm-badge-border-color:inherit;--ifm-badge-border-radius:var(--ifm-global-radius);--ifm-badge-border-width:var(--ifm-global-border-width);--ifm-badge-color:var(--ifm-color-white);--ifm-badge-padding-horizontal:calc(var(--ifm-spacing-horizontal)*0.5);--ifm-badge-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-breadcrumb-border-radius:1.5rem;--ifm-breadcrumb-spacing:0.5rem;--ifm-breadcrumb-color-active:var(--ifm-color-primary);--ifm-breadcrumb-item-background-active:var(--ifm-hover-overlay);--ifm-breadcrumb-padding-horizontal:0.8rem;--ifm-breadcrumb-padding-vertical:0.4rem;--ifm-breadcrumb-size-multiplier:1;--ifm-breadcrumb-separator:url('data:image/svg+xml;utf8,');--ifm-breadcrumb-separator-filter:none;--ifm-breadcrumb-separator-size:0.5rem;--ifm-breadcrumb-separator-size-multiplier:1.25;--ifm-button-background-color:inherit;--ifm-button-border-color:var(--ifm-button-background-color);--ifm-button-border-width:var(--ifm-global-border-width);--ifm-button-font-weight:var(--ifm-font-weight-bold);--ifm-button-padding-horizontal:1.5rem;--ifm-button-padding-vertical:0.375rem;--ifm-button-size-multiplier:1;--ifm-button-transition-duration:var(--ifm-transition-fast);--ifm-button-border-radius:calc(var(--ifm-global-radius)*var(--ifm-button-size-multiplier));--ifm-button-group-spacing:2px;--ifm-card-background-color:var(--ifm-background-surface-color);--ifm-card-border-radius:calc(var(--ifm-global-radius)*2);--ifm-card-horizontal-spacing:var(--ifm-global-spacing);--ifm-card-vertical-spacing:var(--ifm-global-spacing);--ifm-toc-border-color:var(--ifm-color-emphasis-300);--ifm-toc-link-color:var(--ifm-color-content-secondary);--ifm-toc-padding-vertical:0.5rem;--ifm-toc-padding-horizontal:0.5rem;--ifm-dropdown-background-color:var(--ifm-background-surface-color);--ifm-dropdown-font-weight:var(--ifm-font-weight-semibold);--ifm-dropdown-link-color:var(--ifm-font-color-base);--ifm-dropdown-hover-background-color:var(--ifm-hover-overlay);--ifm-footer-background-color:var(--ifm-color-emphasis-100);--ifm-footer-color:inherit;--ifm-footer-link-color:var(--ifm-color-emphasis-700);--ifm-footer-link-hover-color:var(--ifm-color-primary);--ifm-footer-link-horizontal-spacing:0.5rem;--ifm-footer-padding-horizontal:calc(var(--ifm-spacing-horizontal)*2);--ifm-footer-padding-vertical:calc(var(--ifm-spacing-vertical)*2);--ifm-footer-title-color:inherit;--ifm-footer-logo-max-width:min(30rem,90vw);--ifm-hero-background-color:var(--ifm-background-surface-color);--ifm-hero-text-color:var(--ifm-color-emphasis-800);--ifm-menu-color:var(--ifm-color-emphasis-700);--ifm-menu-color-active:var(--ifm-color-primary);--ifm-menu-color-background-active:var(--ifm-hover-overlay);--ifm-menu-color-background-hover:var(--ifm-hover-overlay);--ifm-menu-link-padding-horizontal:0.75rem;--ifm-menu-link-padding-vertical:0.375rem;--ifm-menu-link-sublist-icon:url('data:image/svg+xml;utf8,');--ifm-menu-link-sublist-icon-filter:none;--ifm-navbar-background-color:var(--ifm-background-surface-color);--ifm-navbar-height:3.75rem;--ifm-navbar-item-padding-horizontal:0.75rem;--ifm-navbar-item-padding-vertical:0.25rem;--ifm-navbar-link-color:var(--ifm-font-color-base);--ifm-navbar-link-active-color:var(--ifm-link-color);--ifm-navbar-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-navbar-padding-vertical:calc(var(--ifm-spacing-vertical)*0.5);--ifm-navbar-shadow:var(--ifm-global-shadow-lw);--ifm-navbar-search-input-background-color:var(--ifm-color-emphasis-200);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-800);--ifm-navbar-search-input-placeholder-color:var(--ifm-color-emphasis-500);--ifm-navbar-search-input-icon:url('data:image/svg+xml;utf8,');--ifm-navbar-sidebar-width:83vw;--ifm-pagination-border-radius:var(--ifm-global-radius);--ifm-pagination-color-active:var(--ifm-color-primary);--ifm-pagination-font-size:1rem;--ifm-pagination-item-active-background:var(--ifm-hover-overlay);--ifm-pagination-page-spacing:0.2em;--ifm-pagination-padding-horizontal:calc(var(--ifm-spacing-horizontal)*1);--ifm-pagination-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-pagination-nav-border-radius:var(--ifm-global-radius);--ifm-pagination-nav-color-hover:var(--ifm-color-primary);--ifm-pills-color-active:var(--ifm-color-primary);--ifm-pills-color-background-active:var(--ifm-hover-overlay);--ifm-pills-spacing:0.125rem;--ifm-tabs-color:var(--ifm-font-color-secondary);--ifm-tabs-color-active:var(--ifm-color-primary);--ifm-tabs-color-active-border:var(--ifm-tabs-color-active);--ifm-tabs-padding-horizontal:1rem;--ifm-tabs-padding-vertical:1rem;--docusaurus-progress-bar-color:var(--ifm-color-primary);--ifm-color-primary:#25c2a0;--ifm-color-primary-dark:#21af90;--ifm-color-primary-darker:#1fa588;--ifm-color-primary-darkest:#1a8870;--ifm-color-primary-light:#46cbae;--ifm-color-primary-lighter:#66d4bd;--ifm-color-primary-lightest:#92e0d0;--ifm-code-font-size:95%;--animate-duration:1s;--animate-delay:1s;--animate-repeat:1;--docusaurus-announcement-bar-height:auto;--docusaurus-collapse-button-bg:transparent;--docusaurus-collapse-button-bg-hover:rgba(0,0,0,.1);--doc-sidebar-width:300px;--doc-sidebar-hidden-width:30px;--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12);--docsearch-primary-color:var(--ifm-color-primary);--docsearch-text-color:var(--ifm-font-color-base);--docusaurus-tag-list-border:var(--ifm-color-emphasis-300)}.badge--danger,.badge--info,.badge--primary,.badge--secondary,.badge--success,.badge--warning{--ifm-badge-border-color:var(--ifm-badge-background-color)}.button--link,.button--outline{--ifm-button-background-color:transparent}html{-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--ifm-background-color);color:var(--ifm-font-color-base);color-scheme:var(--ifm-color-scheme);font:var(--ifm-font-size-base)/var(--ifm-line-height-base) var(--ifm-font-family-base)}iframe{border:0;color-scheme:auto}.container{margin:0 auto;max-width:var(--ifm-container-width)}.container--fluid{max-width:inherit}.row{display:flex;flex-wrap:wrap;margin:0 calc(var(--ifm-spacing-horizontal)*-1)}.margin-bottom--none,.margin-vert--none,.markdown>:last-child,.system-window pre{margin-bottom:0!important}.margin-top--none,.margin-vert--none,.tabItem_LNqP{margin-top:0!important}.row--no-gutters{margin-left:0;margin-right:0}.margin-horiz--none,.margin-right--none{margin-right:0!important}.row--no-gutters>.col{padding-left:0;padding-right:0}.row--align-top{align-items:flex-start}.row--align-bottom{align-items:flex-end}.menuExternalLink_NmtK,.row--align-center{align-items:center}.row--align-stretch{align-items:stretch}.row--align-baseline{align-items:baseline}.col{--ifm-col-width:100%;flex:1 0;margin-left:0;max-width:var(--ifm-col-width)}.padding-bottom--none,.padding-vert--none{padding-bottom:0!important}.padding-top--none,.padding-vert--none{padding-top:0!important}.padding-horiz--none,.padding-left--none{padding-left:0!important}.padding-horiz--none,.padding-right--none{padding-right:0!important}.col[class*=col--]{flex:0 0 var(--ifm-col-width)}.col--1{--ifm-col-width:8.33333%}.col--offset-1{margin-left:8.33333%}.col--2{--ifm-col-width:16.66667%}.col--offset-2{margin-left:16.66667%}.col--3{--ifm-col-width:25%}.col--offset-3{margin-left:25%}.col--4{--ifm-col-width:33.33333%}.col--offset-4{margin-left:33.33333%}.col--5{--ifm-col-width:41.66667%}.col--offset-5{margin-left:41.66667%}.col--6{--ifm-col-width:50%}.col--offset-6{margin-left:50%}.col--7{--ifm-col-width:58.33333%}.col--offset-7{margin-left:58.33333%}.col--8{--ifm-col-width:66.66667%}.col--offset-8{margin-left:66.66667%}.col--9{--ifm-col-width:75%}.col--offset-9{margin-left:75%}.col--10{--ifm-col-width:83.33333%}.col--offset-10{margin-left:83.33333%}.col--11{--ifm-col-width:91.66667%}.col--offset-11{margin-left:91.66667%}.col--12{--ifm-col-width:100%}.col--offset-12{margin-left:100%}.margin-horiz--none,.margin-left--none{margin-left:0!important}.margin--none{margin:0!important}.markdown>h2,.markdown>h3,.markdown>h4,.markdown>h5,.markdown>h6{margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading))}.margin-bottom--xs,.margin-vert--xs{margin-bottom:.25rem!important}.margin-top--xs,.margin-vert--xs{margin-top:.25rem!important}.margin-horiz--xs,.margin-left--xs{margin-left:.25rem!important}.margin-horiz--xs,.margin-right--xs{margin-right:.25rem!important}.margin--xs{margin:.25rem!important}.margin-bottom--sm,.margin-vert--sm{margin-bottom:.5rem!important}.margin-top--sm,.margin-vert--sm{margin-top:.5rem!important}.margin-horiz--sm,.margin-left--sm{margin-left:.5rem!important}.margin-horiz--sm,.margin-right--sm{margin-right:.5rem!important}.margin--sm{margin:.5rem!important}.margin-bottom--md,.margin-vert--md{margin-bottom:1rem!important}.margin-top--md,.margin-vert--md{margin-top:1rem!important}.margin-horiz--md,.margin-left--md{margin-left:1rem!important}.margin-horiz--md,.margin-right--md{margin-right:1rem!important}.margin--md{margin:1rem!important}.margin-bottom--lg,.margin-vert--lg{margin-bottom:2rem!important}.margin-top--lg,.margin-vert--lg{margin-top:2rem!important}.margin-horiz--lg,.margin-left--lg{margin-left:2rem!important}.margin-horiz--lg,.margin-right--lg{margin-right:2rem!important}.margin--lg{margin:2rem!important}.margin-bottom--xl,.margin-vert--xl{margin-bottom:5rem!important}.margin-top--xl,.margin-vert--xl{margin-top:5rem!important}.margin-horiz--xl,.margin-left--xl{margin-left:5rem!important}.margin-horiz--xl,.margin-right--xl{margin-right:5rem!important}.margin--xl{margin:5rem!important}.padding--none{padding:0!important}.padding-bottom--xs,.padding-vert--xs{padding-bottom:.25rem!important}.padding-top--xs,.padding-vert--xs{padding-top:.25rem!important}.padding-horiz--xs,.padding-left--xs{padding-left:.25rem!important}.padding-horiz--xs,.padding-right--xs{padding-right:.25rem!important}.padding--xs{padding:.25rem!important}.padding-bottom--sm,.padding-vert--sm{padding-bottom:.5rem!important}.padding-top--sm,.padding-vert--sm{padding-top:.5rem!important}.padding-horiz--sm,.padding-left--sm{padding-left:.5rem!important}.padding-horiz--sm,.padding-right--sm{padding-right:.5rem!important}.padding--sm{padding:.5rem!important}.padding-bottom--md,.padding-vert--md{padding-bottom:1rem!important}.padding-top--md,.padding-vert--md{padding-top:1rem!important}.padding-horiz--md,.padding-left--md{padding-left:1rem!important}.padding-horiz--md,.padding-right--md{padding-right:1rem!important}.padding--md{padding:1rem!important}.padding-bottom--lg,.padding-vert--lg{padding-bottom:2rem!important}.padding-top--lg,.padding-vert--lg{padding-top:2rem!important}.padding-horiz--lg,.padding-left--lg{padding-left:2rem!important}.padding-horiz--lg,.padding-right--lg{padding-right:2rem!important}.padding--lg{padding:2rem!important}.padding-bottom--xl,.padding-vert--xl{padding-bottom:5rem!important}.padding-top--xl,.padding-vert--xl{padding-top:5rem!important}.padding-horiz--xl,.padding-left--xl{padding-left:5rem!important}.padding-horiz--xl,.padding-right--xl{padding-right:5rem!important}.padding--xl{padding:5rem!important}code{background-color:var(--ifm-code-background);border:.1rem solid rgba(0,0,0,.1);border-radius:var(--ifm-code-border-radius);font-family:var(--ifm-font-family-monospace);font-size:var(--ifm-code-font-size);padding:var(--ifm-code-padding-vertical) var(--ifm-code-padding-horizontal)}a code{color:inherit}pre{background-color:var(--ifm-pre-background);border-radius:var(--ifm-pre-border-radius);color:var(--ifm-pre-color);font:var(--ifm-code-font-size)/var(--ifm-pre-line-height) var(--ifm-font-family-monospace);padding:var(--ifm-pre-padding)}pre code{background-color:transparent;border:none;font-size:100%;line-height:inherit;padding:0}kbd{background-color:var(--ifm-color-emphasis-0);border:1px solid var(--ifm-color-emphasis-400);border-radius:.2rem;box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-400);color:var(--ifm-color-emphasis-800);font:80% var(--ifm-font-family-monospace);padding:.15rem .3rem}h1,h2,h3,h4,h5,h6{color:var(--ifm-heading-color);font-family:var(--ifm-heading-font-family);font-weight:var(--ifm-heading-font-weight);line-height:var(--ifm-heading-line-height);margin:var(--ifm-heading-margin-top) 0 var(--ifm-heading-margin-bottom) 0}h1{font-size:var(--ifm-h1-font-size)}h2{font-size:var(--ifm-h2-font-size)}h3{font-size:var(--ifm-h3-font-size)}h4{font-size:var(--ifm-h4-font-size)}h5{font-size:var(--ifm-h5-font-size)}h6{font-size:var(--ifm-h6-font-size)}img{max-width:100%}img[align=right]{padding-left:var(--image-alignment-padding)}img[align=left]{padding-right:var(--image-alignment-padding)}.markdown{--ifm-h1-vertical-rhythm-top:3;--ifm-h2-vertical-rhythm-top:2;--ifm-h3-vertical-rhythm-top:1.5;--ifm-heading-vertical-rhythm-top:1.25;--ifm-h1-vertical-rhythm-bottom:1.25;--ifm-heading-vertical-rhythm-bottom:1}.markdown:after,.markdown:before{content:"";display:table}.markdown:after{clear:both}.markdown h1:first-child{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-h1-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown>h2{--ifm-h2-font-size:2rem;margin-top:calc(var(--ifm-h2-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h3{--ifm-h3-font-size:1.5rem;margin-top:calc(var(--ifm-h3-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h4,.markdown>h5,.markdown>h6{margin-top:calc(var(--ifm-heading-vertical-rhythm-top)*var(--ifm-leading))}.markdown>p,.markdown>pre,.markdown>ul,.tabList__CuJ{margin-bottom:var(--ifm-leading)}.markdown li>p{margin-top:var(--ifm-list-paragraph-margin)}.markdown li+li{margin-top:var(--ifm-list-item-margin)}ol,ul{margin:0 0 var(--ifm-list-margin);padding-left:var(--ifm-list-left-padding)}ol ol,ul ol{list-style-type:lower-roman}ol ol ol,ol ul ol,ul ol ol,ul ul ol{list-style-type:lower-alpha}table{border-collapse:collapse;display:block;margin-bottom:var(--ifm-spacing-vertical)}table thead tr{border-bottom:2px solid var(--ifm-table-border-color)}table thead,table tr:nth-child(2n){background-color:var(--ifm-table-stripe-background)}table tr{background-color:var(--ifm-table-background);border-top:var(--ifm-table-border-width) solid var(--ifm-table-border-color)}table td,table th{border:var(--ifm-table-border-width) solid var(--ifm-table-border-color);padding:var(--ifm-table-cell-padding)}table th{background-color:var(--ifm-table-head-background);color:var(--ifm-table-head-color);font-weight:var(--ifm-table-head-font-weight)}table td{color:var(--ifm-table-cell-color)}strong{font-weight:var(--ifm-font-weight-bold)}a{color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}a:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button:hover,.text--no-decoration,.text--no-decoration:hover,a:not([href]){text-decoration:none}p{margin:0 0 var(--ifm-paragraph-margin-bottom)}blockquote{border-left:var(--ifm-blockquote-border-left-width) solid var(--ifm-blockquote-border-color);box-shadow:var(--ifm-blockquote-shadow);color:var(--ifm-blockquote-color);font-size:var(--ifm-blockquote-font-size);padding:var(--ifm-blockquote-padding-vertical) var(--ifm-blockquote-padding-horizontal)}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}hr{background-color:var(--ifm-hr-background-color);border:0;height:var(--ifm-hr-height);margin:var(--ifm-hr-margin-vertical) 0}.shadow--lw{box-shadow:var(--ifm-global-shadow-lw)!important}.shadow--md{box-shadow:var(--ifm-global-shadow-md)!important}.shadow--tl{box-shadow:var(--ifm-global-shadow-tl)!important}.text--primary,.wordWrapButtonEnabled_EoeP .wordWrapButtonIcon_Bwma{color:var(--ifm-color-primary)}.text--secondary{color:var(--ifm-color-secondary)}.text--success{color:var(--ifm-color-success)}.text--info{color:var(--ifm-color-info)}.text--warning{color:var(--ifm-color-warning)}.text--danger{color:var(--ifm-color-danger)}.text--center{text-align:center}.text--left{text-align:left}.text--justify{text-align:justify}.text--right{text-align:right}.text--capitalize{text-transform:capitalize}.text--lowercase{text-transform:lowercase}.admonitionHeading_tbUL,.alert__heading,.text--uppercase{text-transform:uppercase}.text--light{font-weight:var(--ifm-font-weight-light)}.text--normal{font-weight:var(--ifm-font-weight-normal)}.text--semibold{font-weight:var(--ifm-font-weight-semibold)}.text--bold{font-weight:var(--ifm-font-weight-bold)}.text--italic{font-style:italic}.text--truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text--break{word-wrap:break-word!important;word-break:break-word!important}.clean-btn{background:none;border:none;color:inherit;cursor:pointer;font-family:inherit;padding:0}.alert,.alert .close{color:var(--ifm-alert-foreground-color)}.clean-list{list-style:none;padding-left:0}.alert--primary{--ifm-alert-background-color:var(--ifm-color-primary-contrast-background);--ifm-alert-background-color-highlight:rgba(53,120,229,.15);--ifm-alert-foreground-color:var(--ifm-color-primary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-primary-dark)}.alert--secondary{--ifm-alert-background-color:var(--ifm-color-secondary-contrast-background);--ifm-alert-background-color-highlight:rgba(235,237,240,.15);--ifm-alert-foreground-color:var(--ifm-color-secondary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-secondary-dark)}.alert--success{--ifm-alert-background-color:var(--ifm-color-success-contrast-background);--ifm-alert-background-color-highlight:rgba(0,164,0,.15);--ifm-alert-foreground-color:var(--ifm-color-success-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-success-dark)}.alert--info{--ifm-alert-background-color:var(--ifm-color-info-contrast-background);--ifm-alert-background-color-highlight:rgba(84,199,236,.15);--ifm-alert-foreground-color:var(--ifm-color-info-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-info-dark)}.alert--warning{--ifm-alert-background-color:var(--ifm-color-warning-contrast-background);--ifm-alert-background-color-highlight:rgba(255,186,0,.15);--ifm-alert-foreground-color:var(--ifm-color-warning-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-warning-dark)}.alert--danger{--ifm-alert-background-color:var(--ifm-color-danger-contrast-background);--ifm-alert-background-color-highlight:rgba(250,56,62,.15);--ifm-alert-foreground-color:var(--ifm-color-danger-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-danger-dark)}.alert{--ifm-code-background:var(--ifm-alert-background-color-highlight);--ifm-link-color:var(--ifm-alert-foreground-color);--ifm-link-hover-color:var(--ifm-alert-foreground-color);--ifm-link-decoration:underline;--ifm-tabs-color:var(--ifm-alert-foreground-color);--ifm-tabs-color-active:var(--ifm-alert-foreground-color);--ifm-tabs-color-active-border:var(--ifm-alert-border-color);background-color:var(--ifm-alert-background-color);border:var(--ifm-alert-border-width) solid var(--ifm-alert-border-color);border-left-width:var(--ifm-alert-border-left-width);border-radius:var(--ifm-alert-border-radius);box-shadow:var(--ifm-alert-shadow);padding:var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal)}.alert__heading{align-items:center;display:flex;font:700 var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.5rem}.alert__icon{display:inline-flex;margin-right:.4em}.alert__icon svg{fill:var(--ifm-alert-foreground-color);stroke:var(--ifm-alert-foreground-color);stroke-width:0}.alert .close{margin:calc(var(--ifm-alert-padding-vertical)*-1) calc(var(--ifm-alert-padding-horizontal)*-1) 0 0;opacity:.75}.alert .close:focus,.alert .close:hover{opacity:1}.alert a{-webkit-text-decoration-color:var(--ifm-alert-border-color);text-decoration-color:var(--ifm-alert-border-color)}.alert a:hover{text-decoration-thickness:2px}.avatar{column-gap:var(--ifm-avatar-intro-margin);display:flex}.avatar__photo{border-radius:50%;display:block;height:var(--ifm-avatar-photo-size);overflow:hidden;width:var(--ifm-avatar-photo-size)}.card--full-height,.navbar__logo img,body,html{height:100%}.avatar__photo--sm{--ifm-avatar-photo-size:2rem}.avatar__photo--lg{--ifm-avatar-photo-size:4rem}.avatar__photo--xl{--ifm-avatar-photo-size:6rem}.avatar__intro{display:flex;flex:1 1;flex-direction:column;justify-content:center;text-align:var(--ifm-avatar-intro-alignment)}.badge,.breadcrumbs__item,.breadcrumbs__link,.button,.dropdown>.navbar__link:after{display:inline-block}.avatar__name{font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base)}.avatar__subtitle{margin-top:.25rem}.avatar--vertical{--ifm-avatar-intro-alignment:center;--ifm-avatar-intro-margin:0.5rem;align-items:center;flex-direction:column}.badge{background-color:var(--ifm-badge-background-color);border:var(--ifm-badge-border-width) solid var(--ifm-badge-border-color);border-radius:var(--ifm-badge-border-radius);color:var(--ifm-badge-color);font-size:75%;font-weight:var(--ifm-font-weight-bold);line-height:1;padding:var(--ifm-badge-padding-vertical) var(--ifm-badge-padding-horizontal)}.badge--primary{--ifm-badge-background-color:var(--ifm-color-primary)}.badge--secondary{--ifm-badge-background-color:var(--ifm-color-secondary);color:var(--ifm-color-black)}.breadcrumbs__link,.button.button--secondary.button--outline:not(.button--active):not(:hover){color:var(--ifm-font-color-base)}.badge--success{--ifm-badge-background-color:var(--ifm-color-success)}.badge--info{--ifm-badge-background-color:var(--ifm-color-info)}.badge--warning{--ifm-badge-background-color:var(--ifm-color-warning)}.badge--danger{--ifm-badge-background-color:var(--ifm-color-danger)}.breadcrumbs{margin-bottom:0;padding-left:0}.breadcrumbs__item:not(:last-child):after{background:var(--ifm-breadcrumb-separator) center;content:" ";display:inline-block;filter:var(--ifm-breadcrumb-separator-filter);height:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));margin:0 var(--ifm-breadcrumb-spacing);opacity:.5;width:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier))}.breadcrumbs__item--active .breadcrumbs__link{background:var(--ifm-breadcrumb-item-background-active);color:var(--ifm-breadcrumb-color-active)}.breadcrumbs__link{border-radius:var(--ifm-breadcrumb-border-radius);font-size:calc(1rem*var(--ifm-breadcrumb-size-multiplier));padding:calc(var(--ifm-breadcrumb-padding-vertical)*var(--ifm-breadcrumb-size-multiplier)) calc(var(--ifm-breadcrumb-padding-horizontal)*var(--ifm-breadcrumb-size-multiplier));transition-duration:var(--ifm-transition-fast);transition-property:background,color}.breadcrumbs__link:link:hover,.breadcrumbs__link:visited:hover,area.breadcrumbs__link[href]:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs__link:-webkit-any-link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs__link:any-link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs--sm{--ifm-breadcrumb-size-multiplier:0.8}.breadcrumbs--lg{--ifm-breadcrumb-size-multiplier:1.2}.button{background-color:var(--ifm-button-background-color);border:var(--ifm-button-border-width) solid var(--ifm-button-border-color);border-radius:var(--ifm-button-border-radius);cursor:pointer;font-size:calc(.875rem*var(--ifm-button-size-multiplier));font-weight:var(--ifm-button-font-weight);line-height:1.5;padding:calc(var(--ifm-button-padding-vertical)*var(--ifm-button-size-multiplier)) calc(var(--ifm-button-padding-horizontal)*var(--ifm-button-size-multiplier));text-align:center;transition-duration:var(--ifm-button-transition-duration);transition-property:color,background,border-color;-webkit-user-select:none;-ms-user-select:none;user-select:none;white-space:nowrap}.DocSearch-Button,.playground_CMhS{-webkit-user-select:none;-ms-user-select:none}.button,.button:hover{color:var(--ifm-button-color)}.button--outline{--ifm-button-color:var(--ifm-button-border-color)}.button--outline:hover{--ifm-button-background-color:var(--ifm-button-border-color)}.button--link{--ifm-button-border-color:transparent;color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}.button--link.button--active,.button--link:active,.button--link:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button.disabled,.button:disabled,.button[disabled]{opacity:.65;pointer-events:none}.button--sm{--ifm-button-size-multiplier:0.8}.button--lg{--ifm-button-size-multiplier:1.35}.button--block,.furion-contributor-item img{display:block;width:100%}.button.button--secondary{color:var(--ifm-color-gray-900)}:where(.button--primary){--ifm-button-background-color:var(--ifm-color-primary);--ifm-button-border-color:var(--ifm-color-primary)}:where(.button--primary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-primary-dark);--ifm-button-border-color:var(--ifm-color-primary-dark)}.button--primary.button--active,.button--primary:active{--ifm-button-background-color:var(--ifm-color-primary-darker);--ifm-button-border-color:var(--ifm-color-primary-darker)}:where(.button--secondary){--ifm-button-background-color:var(--ifm-color-secondary);--ifm-button-border-color:var(--ifm-color-secondary)}:where(.button--secondary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-secondary-dark);--ifm-button-border-color:var(--ifm-color-secondary-dark)}.button--secondary.button--active,.button--secondary:active{--ifm-button-background-color:var(--ifm-color-secondary-darker);--ifm-button-border-color:var(--ifm-color-secondary-darker)}:where(.button--success){--ifm-button-background-color:var(--ifm-color-success);--ifm-button-border-color:var(--ifm-color-success)}:where(.button--success):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-success-dark);--ifm-button-border-color:var(--ifm-color-success-dark)}.button--success.button--active,.button--success:active{--ifm-button-background-color:var(--ifm-color-success-darker);--ifm-button-border-color:var(--ifm-color-success-darker)}:where(.button--info){--ifm-button-background-color:var(--ifm-color-info);--ifm-button-border-color:var(--ifm-color-info)}:where(.button--info):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-info-dark);--ifm-button-border-color:var(--ifm-color-info-dark)}.button--info.button--active,.button--info:active{--ifm-button-background-color:var(--ifm-color-info-darker);--ifm-button-border-color:var(--ifm-color-info-darker)}:where(.button--warning){--ifm-button-background-color:var(--ifm-color-warning);--ifm-button-border-color:var(--ifm-color-warning)}:where(.button--warning):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-warning-dark);--ifm-button-border-color:var(--ifm-color-warning-dark)}.button--warning.button--active,.button--warning:active{--ifm-button-background-color:var(--ifm-color-warning-darker);--ifm-button-border-color:var(--ifm-color-warning-darker)}:where(.button--danger){--ifm-button-background-color:var(--ifm-color-danger);--ifm-button-border-color:var(--ifm-color-danger)}:where(.button--danger):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-danger-dark);--ifm-button-border-color:var(--ifm-color-danger-dark)}.button--danger.button--active,.button--danger:active{--ifm-button-background-color:var(--ifm-color-danger-darker);--ifm-button-border-color:var(--ifm-color-danger-darker)}.button-group{display:inline-flex;gap:var(--ifm-button-group-spacing)}.button-group>.button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.button-group>.button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.button-group--block{display:flex;justify-content:stretch}.button-group--block>.button{flex-grow:1}.card{background-color:var(--ifm-card-background-color);border-radius:var(--ifm-card-border-radius);box-shadow:var(--ifm-global-shadow-lw);display:flex;flex-direction:column;overflow:hidden}.card__image{padding-top:var(--ifm-card-vertical-spacing)}.card__image:first-child{padding-top:0}.card__body,.card__footer,.card__header{padding:var(--ifm-card-vertical-spacing) var(--ifm-card-horizontal-spacing)}.card__body:not(:last-child),.card__footer:not(:last-child),.card__header:not(:last-child){padding-bottom:0}.card__body>:last-child,.card__footer>:last-child,.card__header>:last-child{margin-bottom:0}.card__footer{margin-top:auto}.table-of-contents{font-size:.8rem;margin-bottom:0;padding:var(--ifm-toc-padding-vertical) 0}.table-of-contents,.table-of-contents ul{list-style:none;padding-left:var(--ifm-toc-padding-horizontal)}.table-of-contents li{margin:var(--ifm-toc-padding-vertical) var(--ifm-toc-padding-horizontal)}.table-of-contents__left-border{border-left:1px solid var(--ifm-toc-border-color)}.table-of-contents__link{color:var(--ifm-toc-link-color);display:block}.table-of-contents__link--active,.table-of-contents__link--active code,.table-of-contents__link:hover,.table-of-contents__link:hover code{color:var(--ifm-color-primary);text-decoration:none}.close{color:var(--ifm-color-black);float:right;font-size:1.5rem;font-weight:var(--ifm-font-weight-bold);line-height:1;opacity:.5;padding:1rem;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.close:hover{opacity:.7}.close:focus,.theme-code-block-highlighted-line .codeLineNumber_Tfdd:before{opacity:.8}.dropdown{display:inline-flex;font-weight:var(--ifm-dropdown-font-weight);position:relative;vertical-align:top}.dropdown--hoverable:hover .dropdown__menu,.dropdown--show .dropdown__menu{opacity:1;pointer-events:all;transform:translateY(-1px);visibility:visible}#nprogress,.dropdown__menu,.navbar__item.dropdown .navbar__link:not([href]){pointer-events:none}.dropdown--right .dropdown__menu{left:inherit;right:0}.dropdown--nocaret .navbar__link:after{content:none!important}.dropdown__menu{background-color:var(--ifm-dropdown-background-color);border-radius:var(--ifm-global-radius);box-shadow:var(--ifm-global-shadow-md);left:0;list-style:none;max-height:80vh;min-width:10rem;opacity:0;overflow-y:auto;padding:.5rem;position:absolute;top:calc(100% - var(--ifm-navbar-item-padding-vertical) + .3rem);transform:translateY(-.625rem);transition-duration:var(--ifm-transition-fast);transition-property:opacity,transform,visibility;transition-timing-function:var(--ifm-transition-timing-default);visibility:hidden;z-index:var(--ifm-z-index-dropdown)}.menu__caret,.menu__link,.menu__list-item-collapsible{border-radius:.25rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.dropdown__link{border-radius:.25rem;color:var(--ifm-dropdown-link-color);display:block;font-size:.875rem;margin-top:.2rem;padding:.25rem .5rem;white-space:nowrap}.dropdown__link--active,.dropdown__link:hover{background-color:var(--ifm-dropdown-hover-background-color);color:var(--ifm-dropdown-link-color);text-decoration:none}.dropdown__link--active,.dropdown__link--active:hover{--ifm-dropdown-link-color:var(--ifm-link-color)}.dropdown>.navbar__link:after{border-color:currentcolor transparent;border-style:solid;border-width:.4em .4em 0;content:"";margin-left:.3em;position:relative;top:2px;transform:translateY(-50%)}.footer{background-color:var(--ifm-footer-background-color);color:var(--ifm-footer-color);padding:var(--ifm-footer-padding-vertical) var(--ifm-footer-padding-horizontal)}.footer--dark{--ifm-footer-background-color:#303846;--ifm-footer-color:var(--ifm-footer-link-color);--ifm-footer-link-color:var(--ifm-color-secondary);--ifm-footer-title-color:var(--ifm-color-white)}.footer__links{margin-bottom:1rem}.footer__link-item{color:var(--ifm-footer-link-color);line-height:2}.footer__link-item:hover{color:var(--ifm-footer-link-hover-color)}.footer__link-separator{margin:0 var(--ifm-footer-link-horizontal-spacing)}.footer__logo{margin-top:1rem;max-width:var(--ifm-footer-logo-max-width)}.footer__title{color:var(--ifm-footer-title-color);font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base);margin-bottom:var(--ifm-heading-margin-bottom)}.menu,.navbar__link{font-weight:var(--ifm-font-weight-semibold)}.docItemContainer_Djhp article>:first-child,.docItemContainer_Djhp header+*,.footer__item{margin-top:0}.admonitionContent_S0QG>:last-child,.collapsibleContent_i85q>:last-child,.footer__items,.tabItem_Ymn6>:last-child{margin-bottom:0}.codeBlockStandalone_MEMb,[type=checkbox]{padding:0}.hero{align-items:center;background-color:var(--ifm-hero-background-color);color:var(--ifm-hero-text-color);display:flex;padding:4rem 2rem}.hero--primary{--ifm-hero-background-color:var(--ifm-color-primary);--ifm-hero-text-color:var(--ifm-font-color-base-inverse)}.hero--dark{--ifm-hero-background-color:#303846;--ifm-hero-text-color:var(--ifm-color-white)}.hero__title,.title_f1Hy{font-size:3rem}.hero__subtitle{font-size:1.5rem}.menu__list{list-style:none;margin:0;padding-left:0}.menu__caret,.menu__link{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu__list .menu__list{flex:0 0 100%;margin-top:.25rem;padding-left:var(--ifm-menu-link-padding-horizontal)}.menu__list-item:not(:first-child){margin-top:.25rem}.menu__list-item--collapsed .menu__list{height:0;overflow:hidden}.details_lb9f[data-collapsed=false].isBrowser_bmU9>summary:before,.details_lb9f[open]:not(.isBrowser_bmU9)>summary:before,.menu__list-item--collapsed .menu__caret:before,.menu__list-item--collapsed .menu__link--sublist:after{transform:rotate(90deg)}.menu__list-item-collapsible{display:flex;flex-wrap:wrap;position:relative}.menu__caret:hover,.menu__link:hover,.menu__list-item-collapsible--active,.menu__list-item-collapsible:hover{background:var(--ifm-menu-color-background-hover)}.menu__list-item-collapsible .menu__link--active,.menu__list-item-collapsible .menu__link:hover{background:none!important}.menu__caret,.menu__link{align-items:center;display:flex}.menu__link{color:var(--ifm-menu-color);flex:1;line-height:1.25}.menu__link:hover{color:var(--ifm-menu-color);text-decoration:none}.menu__caret:before,.menu__link--sublist-caret:after{content:"";height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast) linear;width:1.25rem;filter:var(--ifm-menu-link-sublist-icon-filter)}.menu__link--sublist-caret:after{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem;margin-left:auto;min-width:1.25rem}.menu__link--active,.menu__link--active:hover{color:var(--ifm-menu-color-active)}.navbar__brand,.navbar__link{color:var(--ifm-navbar-link-color)}.menu__link--active:not(.menu__link--sublist){background-color:var(--ifm-menu-color-background-active)}.menu__caret:before{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem}.navbar--dark,html[data-theme=dark]{--ifm-menu-link-sublist-icon-filter:invert(100%) sepia(94%) saturate(17%) hue-rotate(223deg) brightness(104%) contrast(98%)}.navbar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.docsWrapper_BCFX,.navbar,.navbar>.container,.navbar>.container-fluid{display:flex}.navbar--fixed-top{position:-webkit-sticky;position:sticky;top:0;z-index:var(--ifm-z-index-fixed)}.navbar-sidebar,.navbar-sidebar__backdrop{bottom:0;left:0;opacity:0;position:fixed;top:0;transition-timing-function:ease-in-out;visibility:hidden}.navbar__inner{display:flex;flex-wrap:wrap;justify-content:space-between;width:100%}.navbar__brand{align-items:center;display:flex;margin-right:1rem;min-width:0}.navbar__brand:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar__title{flex:1 1 auto}.navbar__toggle{display:none;margin-right:.5rem}.navbar__logo{flex:0 0 auto;height:2rem;margin-right:.5rem}.navbar__items{align-items:center;display:flex;flex:1;min-width:0}.navbar__items--center{flex:0 0 auto}.navbar__items--center .navbar__brand{margin:0}.furion-banner-item,.navbar__items--center+.navbar__items--right{flex:1}.navbar__items--right{flex:0 0 auto;justify-content:flex-end}.navbar__items--right>:last-child{padding-right:0}.navbar__item{display:inline-block;padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.navbar__link--active,.navbar__link:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar--dark,.navbar--primary{--ifm-menu-color:var(--ifm-color-gray-300);--ifm-navbar-link-color:var(--ifm-color-gray-100);--ifm-navbar-search-input-background-color:hsla(0,0%,100%,.1);--ifm-navbar-search-input-placeholder-color:hsla(0,0%,100%,.5);color:var(--ifm-color-white)}.navbar--dark{--ifm-navbar-background-color:#242526;--ifm-menu-color-background-active:hsla(0,0%,100%,.05);--ifm-navbar-search-input-color:var(--ifm-color-white)}.navbar--primary{--ifm-navbar-background-color:var(--ifm-color-primary);--ifm-navbar-link-hover-color:var(--ifm-color-white);--ifm-menu-color-active:var(--ifm-color-white);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-500)}.navbar__search-input{-webkit-appearance:none;appearance:none;background:var(--ifm-navbar-search-input-background-color) var(--ifm-navbar-search-input-icon) no-repeat .75rem center/1rem 1rem;border:none;border-radius:2rem;color:var(--ifm-navbar-search-input-color);cursor:text;display:inline-block;font-size:.9rem;height:2rem;padding:0 .5rem 0 2.25rem;width:12.5rem}.navbar__search-input:-ms-input-placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar__search-input::placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar-sidebar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-global-shadow-md);transform:translate3d(-100%,0,0);transition-duration:.25s;transition-property:opacity,visibility,transform;width:var(--ifm-navbar-sidebar-width)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar__items{transform:translateZ(0)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar--show .navbar-sidebar__backdrop{opacity:1;visibility:visible}.navbar-sidebar__backdrop{background-color:rgba(0,0,0,.6);right:0;transition-duration:.1s;transition-property:opacity,visibility}.navbar-sidebar__brand{align-items:center;box-shadow:var(--ifm-navbar-shadow);display:flex;flex:1;height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar-sidebar__items{display:flex;height:calc(100% - var(--ifm-navbar-height));transition:transform var(--ifm-transition-fast) ease-in-out}.navbar-sidebar__items--show-secondary{transform:translate3d(calc((var(--ifm-navbar-sidebar-width))*-1),0,0)}.navbar-sidebar__item{flex-shrink:0;padding:.5rem;width:calc(var(--ifm-navbar-sidebar-width))}.navbar-sidebar__back{background:var(--ifm-menu-color-background-active);font-size:15px;font-weight:var(--ifm-button-font-weight);margin:0 0 .2rem -.5rem;padding:.6rem 1.5rem;position:relative;text-align:left;top:-.5rem;width:calc(100% + 1rem)}#nprogress .bar,.modal_wSGk{left:0;top:0;position:fixed}.navbar-sidebar__close{display:flex;margin-left:auto}.pagination{column-gap:var(--ifm-pagination-page-spacing);display:flex;font-size:var(--ifm-pagination-font-size);padding-left:0}.pagination--sm{--ifm-pagination-font-size:0.8rem;--ifm-pagination-padding-horizontal:0.8rem;--ifm-pagination-padding-vertical:0.2rem}.pagination--lg{--ifm-pagination-font-size:1.2rem;--ifm-pagination-padding-horizontal:1.2rem;--ifm-pagination-padding-vertical:0.3rem}.pagination__item{display:inline-flex}.pagination__item>span{padding:var(--ifm-pagination-padding-vertical)}.pagination__item--active .pagination__link{color:var(--ifm-pagination-color-active)}.pagination__item--active .pagination__link,.pagination__item:not(.pagination__item--active):hover .pagination__link{background:var(--ifm-pagination-item-active-background)}.pagination__item--disabled,.pagination__item[disabled]{opacity:.25;pointer-events:none}.pagination__link{border-radius:var(--ifm-pagination-border-radius);color:var(--ifm-font-color-base);display:inline-block;padding:var(--ifm-pagination-padding-vertical) var(--ifm-pagination-padding-horizontal);transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination__link:hover,.sidebarItemLink_mo7H:hover{text-decoration:none}.pagination-nav{grid-gap:var(--ifm-spacing-horizontal);display:grid;gap:var(--ifm-spacing-horizontal);grid-template-columns:repeat(2,1fr)}.pagination-nav__link{border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-pagination-nav-border-radius);display:block;height:100%;line-height:var(--ifm-heading-line-height);padding:var(--ifm-global-spacing);transition:border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination-nav__link:hover{border-color:var(--ifm-pagination-nav-color-hover);text-decoration:none}.pagination-nav__link--next{grid-column:2/3;text-align:right}.pagination-nav__label{font-size:var(--ifm-h4-font-size);font-weight:var(--ifm-heading-font-weight);word-break:break-word}.pagination-nav__link--prev .pagination-nav__label:before{content:"« "}.pagination-nav__link--next .pagination-nav__label:after{content:" »"}.pagination-nav__sublabel{color:var(--ifm-color-content-secondary);font-size:var(--ifm-h5-font-size);font-weight:var(--ifm-font-weight-semibold);margin-bottom:.25rem}.pills__item,.sidebarItemTitle_pO2u,.tabs{font-weight:var(--ifm-font-weight-bold)}.pills{display:flex;gap:var(--ifm-pills-spacing);padding-left:0}.pills__item{border-radius:.5rem;cursor:pointer;display:inline-block;padding:.25rem 1rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs,:not(.containsTaskList_mC6p>li)>.containsTaskList_mC6p{padding-left:0}.pills__item--active{color:var(--ifm-pills-color-active)}.pills__item--active,.pills__item:not(.pills__item--active):hover{background:var(--ifm-pills-color-background-active)}.pills--block{justify-content:stretch}.pills--block .pills__item{flex-grow:1;text-align:center}.tabs{color:var(--ifm-tabs-color);display:flex;margin-bottom:0;overflow-x:auto}.tabs__item{border-bottom:3px solid transparent;border-radius:var(--ifm-global-radius);cursor:pointer;display:inline-flex;padding:var(--ifm-tabs-padding-vertical) var(--ifm-tabs-padding-horizontal);transition:background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs__item--active{border-bottom-color:var(--ifm-tabs-color-active-border);border-bottom-left-radius:0;border-bottom-right-radius:0;color:var(--ifm-tabs-color-active)}.tabs__item:hover{background-color:var(--ifm-hover-overlay)}.tabs--block{justify-content:stretch}.tabs--block .tabs__item{flex-grow:1;justify-content:center}html[data-theme=dark]{--ifm-color-scheme:dark;--ifm-color-emphasis-0:var(--ifm-color-gray-1000);--ifm-color-emphasis-100:var(--ifm-color-gray-900);--ifm-color-emphasis-200:var(--ifm-color-gray-800);--ifm-color-emphasis-300:var(--ifm-color-gray-700);--ifm-color-emphasis-400:var(--ifm-color-gray-600);--ifm-color-emphasis-600:var(--ifm-color-gray-400);--ifm-color-emphasis-700:var(--ifm-color-gray-300);--ifm-color-emphasis-800:var(--ifm-color-gray-200);--ifm-color-emphasis-900:var(--ifm-color-gray-100);--ifm-color-emphasis-1000:var(--ifm-color-gray-0);--ifm-background-color:#1b1b1d;--ifm-background-surface-color:#242526;--ifm-hover-overlay:hsla(0,0%,100%,.05);--ifm-color-content:#e3e3e3;--ifm-color-content-secondary:#fff;--ifm-breadcrumb-separator-filter:invert(64%) sepia(11%) saturate(0%) hue-rotate(149deg) brightness(99%) contrast(95%);--ifm-code-background:hsla(0,0%,100%,.1);--ifm-scrollbar-track-background-color:#444;--ifm-scrollbar-thumb-background-color:#686868;--ifm-scrollbar-thumb-hover-background-color:#7a7a7a;--ifm-table-stripe-background:hsla(0,0%,100%,.07);--ifm-toc-border-color:var(--ifm-color-emphasis-200);--ifm-color-primary-contrast-background:#102445;--ifm-color-primary-contrast-foreground:#ebf2fc;--ifm-color-secondary-contrast-background:#474748;--ifm-color-secondary-contrast-foreground:#fdfdfe;--ifm-color-success-contrast-background:#003100;--ifm-color-success-contrast-foreground:#e6f6e6;--ifm-color-info-contrast-background:#193c47;--ifm-color-info-contrast-foreground:#eef9fd;--ifm-color-warning-contrast-background:#4d3800;--ifm-color-warning-contrast-foreground:#fff8e6;--ifm-color-danger-contrast-background:#4b1113;--ifm-color-danger-contrast-foreground:#ffebec;--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,.3);--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}#nprogress .bar{background:var(--docusaurus-progress-bar-color);height:2px;width:100%;z-index:1031}#nprogress .peg{box-shadow:0 0 10px var(--docusaurus-progress-bar-color),0 0 5px var(--docusaurus-progress-bar-color);height:100%;opacity:1;position:absolute;right:0;transform:rotate(3deg) translateY(-4px);width:100px}.docusaurus-highlight-code-line{background-color:#484d5b;display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.animate__animated{animation-duration:1s;animation-duration:var(--animate-duration);animation-fill-mode:both}.animate__animated.animate__infinite{animation-iteration-count:infinite}.animate__animated.animate__repeat-1{animation-iteration-count:1;animation-iteration-count:var(--animate-repeat)}.animate__animated.animate__repeat-2{animation-iteration-count:2;animation-iteration-count:calc(var(--animate-repeat)*2)}.animate__animated.animate__repeat-3{animation-iteration-count:3;animation-iteration-count:calc(var(--animate-repeat)*3)}.animate__animated.animate__delay-1s{animation-delay:1s;animation-delay:var(--animate-delay)}.animate__animated.animate__delay-2s{animation-delay:2s;animation-delay:calc(var(--animate-delay)*2)}.animate__animated.animate__delay-3s{animation-delay:3s;animation-delay:calc(var(--animate-delay)*3)}.animate__animated.animate__delay-4s{animation-delay:4s;animation-delay:calc(var(--animate-delay)*4)}.animate__animated.animate__delay-5s{animation-delay:5s;animation-delay:calc(var(--animate-delay)*5)}.animate__animated.animate__faster{animation-duration:.5s;animation-duration:calc(var(--animate-duration)/2)}.animate__animated.animate__fast{animation-duration:.8s;animation-duration:calc(var(--animate-duration)*.8)}.animate__animated.animate__slow{animation-duration:2s;animation-duration:calc(var(--animate-duration)*2)}.animate__animated.animate__slower{animation-duration:3s;animation-duration:calc(var(--animate-duration)*3)}@keyframes a{0%,20%,53%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1);transform:translateZ(0)}40%,43%{animation-timing-function:cubic-bezier(.755,.05,.855,.06);transform:translate3d(0,-30px,0) scaleY(1.1)}70%{animation-timing-function:cubic-bezier(.755,.05,.855,.06);transform:translate3d(0,-15px,0) scaleY(1.05)}80%{transform:translateZ(0) scaleY(.95);transition-timing-function:cubic-bezier(.215,.61,.355,1)}90%{transform:translate3d(0,-4px,0) scaleY(1.02)}}.animate__bounce{animation-name:a;transform-origin:center bottom}@keyframes b{0%,50%,to{opacity:1}25%,75%{opacity:0}}.animate__flash{animation-name:b}@keyframes c{0%,to{transform:scaleX(1)}50%{transform:scale3d(1.05,1.05,1.05)}}.animate__pulse{animation-name:c}@keyframes d{0%,to{transform:scaleX(1)}30%{transform:scale3d(1.25,.75,1)}40%{transform:scale3d(.75,1.25,1)}50%{transform:scale3d(1.15,.85,1)}65%{transform:scale3d(.95,1.05,1)}75%{transform:scale3d(1.05,.95,1)}}.animate__rubberBand{animation-name:d}@keyframes e{0%,to{transform:translateZ(0)}10%,30%,50%,70%,90%{transform:translate3d(-10px,0,0)}20%,40%,60%,80%{transform:translate3d(10px,0,0)}}.animate__shakeX{animation-name:e}@keyframes f{0%,to{transform:translateZ(0)}10%,30%,50%,70%,90%{transform:translate3d(0,-10px,0)}20%,40%,60%,80%{transform:translate3d(0,10px,0)}}.animate__shakeY{animation-name:f}@keyframes g{0%,50%{transform:translateX(0)}6.5%{transform:translateX(-6px) rotateY(-9deg)}18.5%{transform:translateX(5px) rotateY(7deg)}31.5%{transform:translateX(-3px) rotateY(-5deg)}43.5%{transform:translateX(2px) rotateY(3deg)}}.animate__headShake{animation-name:g}@keyframes h{20%{transform:rotate(15deg)}40%{transform:rotate(-10deg)}60%{transform:rotate(5deg)}80%{transform:rotate(-5deg)}to{transform:rotate(0)}}.animate__swing{animation-name:h;transform-origin:top center}@keyframes i{0%,to{transform:scaleX(1)}10%,20%{transform:scale3d(.9,.9,.9) rotate(-3deg)}30%,50%,70%,90%{transform:scale3d(1.1,1.1,1.1) rotate(3deg)}40%,60%,80%{transform:scale3d(1.1,1.1,1.1) rotate(-3deg)}}.animate__tada{animation-name:i}@keyframes j{0%,to{transform:translateZ(0)}15%{transform:translate3d(-25%,0,0) rotate(-5deg)}30%{transform:translate3d(20%,0,0) rotate(3deg)}45%{transform:translate3d(-15%,0,0) rotate(-3deg)}60%{transform:translate3d(10%,0,0) rotate(2deg)}75%{transform:translate3d(-5%,0,0) rotate(-1deg)}}.animate__wobble{animation-name:j}@keyframes k{0%,11.1%,to{transform:translateZ(0)}22.2%{transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{transform:skewX(6.25deg) skewY(6.25deg)}44.4%{transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{transform:skewX(-.78125deg) skewY(-.78125deg)}77.7%{transform:skewX(.390625deg) skewY(.390625deg)}88.8%{transform:skewX(-.1953125deg) skewY(-.1953125deg)}}.animate__jello{animation-name:k;transform-origin:center}@keyframes l{0%,28%,70%{transform:scale(1)}14%,42%{transform:scale(1.3)}}.animate__heartBeat{animation-duration:1.3s;animation-duration:calc(var(--animate-duration)*1.3);animation-name:l}@keyframes m{0%{opacity:.7;transform:translateY(-1200px) scale(.7)}80%{opacity:.7;transform:translateY(0) scale(.7)}to{opacity:1;transform:scale(1)}}.animate__backInDown{animation-name:m}@keyframes n{0%{opacity:.7;transform:translateX(-2000px) scale(.7)}80%{opacity:.7;transform:translateX(0) scale(.7)}to{opacity:1;transform:scale(1)}}.animate__backInLeft{animation-name:n}@keyframes o{0%{opacity:.7;transform:translateX(2000px) scale(.7)}80%{opacity:.7;transform:translateX(0) scale(.7)}to{opacity:1;transform:scale(1)}}.animate__backInRight{animation-name:o}@keyframes p{0%{opacity:.7;transform:translateY(1200px) scale(.7)}80%{opacity:.7;transform:translateY(0) scale(.7)}to{opacity:1;transform:scale(1)}}.animate__backInUp{animation-name:p}@keyframes q{0%{opacity:1;transform:scale(1)}20%{opacity:.7;transform:translateY(0) scale(.7)}to{opacity:.7;transform:translateY(700px) scale(.7)}}.animate__backOutDown{animation-name:q}@keyframes r{0%{opacity:1;transform:scale(1)}20%{opacity:.7;transform:translateX(0) scale(.7)}to{opacity:.7;transform:translateX(-2000px) scale(.7)}}.animate__backOutLeft{animation-name:r}@keyframes s{0%{opacity:1;transform:scale(1)}20%{opacity:.7;transform:translateX(0) scale(.7)}to{opacity:.7;transform:translateX(2000px) scale(.7)}}.animate__backOutRight{animation-name:s}@keyframes t{0%{opacity:1;transform:scale(1)}20%{opacity:.7;transform:translateY(0) scale(.7)}to{opacity:.7;transform:translateY(-700px) scale(.7)}}.animate__backOutUp{animation-name:t}@keyframes u{0%,20%,40%,60%,80%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:scale3d(.3,.3,.3)}20%{transform:scale3d(1.1,1.1,1.1)}40%{transform:scale3d(.9,.9,.9)}60%{opacity:1;transform:scale3d(1.03,1.03,1.03)}80%{transform:scale3d(.97,.97,.97)}to{opacity:1;transform:scaleX(1)}}.animate__bounceIn{animation-duration:.75s;animation-duration:calc(var(--animate-duration)*.75);animation-name:u}@keyframes v{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,-3000px,0) scaleY(3)}60%{opacity:1;transform:translate3d(0,25px,0) scaleY(.9)}75%{transform:translate3d(0,-10px,0) scaleY(.95)}90%{transform:translate3d(0,5px,0) scaleY(.985)}to{transform:translateZ(0)}}.animate__bounceInDown{animation-name:v}@keyframes w{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(-3000px,0,0) scaleX(3)}60%{opacity:1;transform:translate3d(25px,0,0) scaleX(1)}75%{transform:translate3d(-10px,0,0) scaleX(.98)}90%{transform:translate3d(5px,0,0) scaleX(.995)}to{transform:translateZ(0)}}.animate__bounceInLeft{animation-name:w}@keyframes x{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(3000px,0,0) scaleX(3)}60%{opacity:1;transform:translate3d(-25px,0,0) scaleX(1)}75%{transform:translate3d(10px,0,0) scaleX(.98)}90%{transform:translate3d(-5px,0,0) scaleX(.995)}to{transform:translateZ(0)}}.animate__bounceInRight{animation-name:x}@keyframes y{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,3000px,0) scaleY(5)}60%{opacity:1;transform:translate3d(0,-20px,0) scaleY(.9)}75%{transform:translate3d(0,10px,0) scaleY(.95)}90%{transform:translate3d(0,-5px,0) scaleY(.985)}to{transform:translateZ(0)}}.animate__bounceInUp{animation-name:y}@keyframes z{20%{transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;transform:scale3d(1.1,1.1,1.1)}to{opacity:0;transform:scale3d(.3,.3,.3)}}.animate__bounceOut{animation-duration:.75s;animation-duration:calc(var(--animate-duration)*.75);animation-name:z}@keyframes A{20%{transform:translate3d(0,10px,0) scaleY(.985)}40%,45%{opacity:1;transform:translate3d(0,-20px,0) scaleY(.9)}to{opacity:0;transform:translate3d(0,2000px,0) scaleY(3)}}.animate__bounceOutDown{animation-name:A}@keyframes B{20%{opacity:1;transform:translate3d(20px,0,0) scaleX(.9)}to{opacity:0;transform:translate3d(-2000px,0,0) scaleX(2)}}.animate__bounceOutLeft{animation-name:B}@keyframes C{20%{opacity:1;transform:translate3d(-20px,0,0) scaleX(.9)}to{opacity:0;transform:translate3d(2000px,0,0) scaleX(2)}}.animate__bounceOutRight{animation-name:C}@keyframes D{20%{transform:translate3d(0,-10px,0) scaleY(.985)}40%,45%{opacity:1;transform:translate3d(0,20px,0) scaleY(.9)}to{opacity:0;transform:translate3d(0,-2000px,0) scaleY(3)}}.animate__bounceOutUp{animation-name:D}.animate__fadeIn{animation-name:Ra}@keyframes E{0%{opacity:0;transform:translate3d(0,-100%,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInDown{animation-name:E}@keyframes F{0%{opacity:0;transform:translate3d(0,-2000px,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInDownBig{animation-name:F}@keyframes G{0%{opacity:0;transform:translate3d(-100%,0,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInLeft{animation-name:G}@keyframes H{0%{opacity:0;transform:translate3d(-2000px,0,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInLeftBig{animation-name:H}@keyframes I{0%{opacity:0;transform:translate3d(100%,0,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInRight{animation-name:I}@keyframes J{0%{opacity:0;transform:translate3d(2000px,0,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInRightBig{animation-name:J}@keyframes K{0%{opacity:0;transform:translate3d(0,100%,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInUp{animation-name:K}@keyframes L{0%{opacity:0;transform:translate3d(0,2000px,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInUpBig{animation-name:L}@keyframes M{0%{opacity:0;transform:translate3d(-100%,-100%,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInTopLeft{animation-name:M}@keyframes N{0%{opacity:0;transform:translate3d(100%,-100%,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInTopRight{animation-name:N}@keyframes O{0%{opacity:0;transform:translate3d(-100%,100%,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInBottomLeft{animation-name:O}@keyframes P{0%{opacity:0;transform:translate3d(100%,100%,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInBottomRight{animation-name:P}@keyframes Q{0%{opacity:1}to{opacity:0}}.animate__fadeOut{animation-name:Q}@keyframes R{0%{opacity:1}to{opacity:0;transform:translate3d(0,100%,0)}}.animate__fadeOutDown{animation-name:R}@keyframes S{0%{opacity:1}to{opacity:0;transform:translate3d(0,2000px,0)}}.animate__fadeOutDownBig{animation-name:S}@keyframes T{0%{opacity:1}to{opacity:0;transform:translate3d(-100%,0,0)}}.animate__fadeOutLeft{animation-name:T}@keyframes U{0%{opacity:1}to{opacity:0;transform:translate3d(-2000px,0,0)}}.animate__fadeOutLeftBig{animation-name:U}@keyframes V{0%{opacity:1}to{opacity:0;transform:translate3d(100%,0,0)}}.animate__fadeOutRight{animation-name:V}@keyframes W{0%{opacity:1}to{opacity:0;transform:translate3d(2000px,0,0)}}.animate__fadeOutRightBig{animation-name:W}@keyframes X{0%{opacity:1}to{opacity:0;transform:translate3d(0,-100%,0)}}.animate__fadeOutUp{animation-name:X}@keyframes Y{0%{opacity:1}to{opacity:0;transform:translate3d(0,-2000px,0)}}.animate__fadeOutUpBig{animation-name:Y}@keyframes Z{0%{opacity:1;transform:translateZ(0)}to{opacity:0;transform:translate3d(-100%,-100%,0)}}.animate__fadeOutTopLeft{animation-name:Z}@keyframes aa{0%{opacity:1;transform:translateZ(0)}to{opacity:0;transform:translate3d(100%,-100%,0)}}.animate__fadeOutTopRight{animation-name:aa}@keyframes ba{0%{opacity:1;transform:translateZ(0)}to{opacity:0;transform:translate3d(100%,100%,0)}}.animate__fadeOutBottomRight{animation-name:ba}@keyframes ca{0%{opacity:1;transform:translateZ(0)}to{opacity:0;transform:translate3d(-100%,100%,0)}}.animate__fadeOutBottomLeft{animation-name:ca}@keyframes da{0%{animation-timing-function:ease-out;transform:perspective(400px) scaleX(1) translateZ(0) rotateY(-1turn)}40%{animation-timing-function:ease-out;transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-190deg)}50%{animation-timing-function:ease-in;transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-170deg)}80%{animation-timing-function:ease-in;transform:perspective(400px) scale3d(.95,.95,.95) translateZ(0) rotateY(0)}to{animation-timing-function:ease-in;transform:perspective(400px) scaleX(1) translateZ(0) rotateY(0)}}.animate__animated.animate__flip{animation-name:da;-webkit-backface-visibility:visible;backface-visibility:visible}@keyframes ea{0%{animation-timing-function:ease-in;opacity:0;transform:perspective(400px) rotateX(90deg)}40%{animation-timing-function:ease-in;transform:perspective(400px) rotateX(-20deg)}60%{opacity:1;transform:perspective(400px) rotateX(10deg)}80%{transform:perspective(400px) rotateX(-5deg)}to{transform:perspective(400px)}}.animate__flipInX{animation-name:ea;-webkit-backface-visibility:visible!important;backface-visibility:visible!important}.animate__flipInY,.animate__flipOutX{-webkit-backface-visibility:visible!important}@keyframes fa{0%{animation-timing-function:ease-in;opacity:0;transform:perspective(400px) rotateY(90deg)}40%{animation-timing-function:ease-in;transform:perspective(400px) rotateY(-20deg)}60%{opacity:1;transform:perspective(400px) rotateY(10deg)}80%{transform:perspective(400px) rotateY(-5deg)}to{transform:perspective(400px)}}.animate__flipInY{animation-name:fa;backface-visibility:visible!important}@keyframes ga{0%{transform:perspective(400px)}30%{opacity:1;transform:perspective(400px) rotateX(-20deg)}to{opacity:0;transform:perspective(400px) rotateX(90deg)}}.animate__flipOutX{animation-duration:.75s;animation-duration:calc(var(--animate-duration)*.75);animation-name:ga;backface-visibility:visible!important}@keyframes ha{0%{transform:perspective(400px)}30%{opacity:1;transform:perspective(400px) rotateY(-15deg)}to{opacity:0;transform:perspective(400px) rotateY(90deg)}}.animate__flipOutY{animation-duration:.75s;animation-duration:calc(var(--animate-duration)*.75);animation-name:ha;-webkit-backface-visibility:visible!important;backface-visibility:visible!important}@keyframes ia{0%{opacity:0;transform:translate3d(100%,0,0) skewX(-30deg)}60%{opacity:1;transform:skewX(20deg)}80%{transform:skewX(-5deg)}to{transform:translateZ(0)}}.animate__lightSpeedInRight{animation-name:ia;animation-timing-function:ease-out}@keyframes ja{0%{opacity:0;transform:translate3d(-100%,0,0) skewX(30deg)}60%{opacity:1;transform:skewX(-20deg)}80%{transform:skewX(5deg)}to{transform:translateZ(0)}}.animate__lightSpeedInLeft{animation-name:ja;animation-timing-function:ease-out}@keyframes ka{0%{opacity:1}to{opacity:0;transform:translate3d(100%,0,0) skewX(30deg)}}.animate__lightSpeedOutRight{animation-name:ka;animation-timing-function:ease-in}@keyframes la{0%{opacity:1}to{opacity:0;transform:translate3d(-100%,0,0) skewX(-30deg)}}.animate__lightSpeedOutLeft{animation-name:la;animation-timing-function:ease-in}@keyframes ma{0%{opacity:0;transform:rotate(-200deg)}to{opacity:1;transform:translateZ(0)}}.animate__rotateIn{animation-name:ma;transform-origin:center}@keyframes na{0%{opacity:0;transform:rotate(-45deg)}to{opacity:1;transform:translateZ(0)}}.animate__rotateInDownLeft{animation-name:na;transform-origin:left bottom}.animate__rotateInDownRight{animation-name:oa;transform-origin:right bottom}@keyframes oa{0%{opacity:0;transform:rotate(45deg)}to{opacity:1;transform:translateZ(0)}}.animate__rotateInUpLeft{animation-name:oa;transform-origin:left bottom}@keyframes pa{0%{opacity:0;transform:rotate(-90deg)}to{opacity:1;transform:translateZ(0)}}.animate__rotateInUpRight{animation-name:pa;transform-origin:right bottom}@keyframes qa{0%{opacity:1}to{opacity:0;transform:rotate(200deg)}}.animate__rotateOut{animation-name:qa;transform-origin:center}@keyframes ra{0%{opacity:1}to{opacity:0;transform:rotate(45deg)}}.animate__rotateOutDownLeft{animation-name:ra;transform-origin:left bottom}.animate__rotateOutDownRight{animation-name:sa;transform-origin:right bottom}@keyframes sa{0%{opacity:1}to{opacity:0;transform:rotate(-45deg)}}.animate__rotateOutUpLeft{animation-name:sa;transform-origin:left bottom}@keyframes ta{0%{opacity:1}to{opacity:0;transform:rotate(90deg)}}.animate__rotateOutUpRight{animation-name:ta;transform-origin:right bottom}@keyframes ua{0%{animation-timing-function:ease-in-out}20%,60%{animation-timing-function:ease-in-out;transform:rotate(80deg)}40%,80%{animation-timing-function:ease-in-out;opacity:1;transform:rotate(60deg)}to{opacity:0;transform:translate3d(0,700px,0)}}.animate__hinge{animation-duration:2s;animation-duration:calc(var(--animate-duration)*2);animation-name:ua;transform-origin:top left}@keyframes va{0%{opacity:0;transform:scale(.1) rotate(30deg);transform-origin:center bottom}50%{transform:rotate(-10deg)}70%{transform:rotate(3deg)}to{opacity:1;transform:scale(1)}}.animate__jackInTheBox{animation-name:va}@keyframes wa{0%{opacity:0;transform:translate3d(-100%,0,0) rotate(-120deg)}to{opacity:1;transform:translateZ(0)}}.animate__rollIn{animation-name:wa}@keyframes xa{0%{opacity:1}to{opacity:0;transform:translate3d(100%,0,0) rotate(120deg)}}.animate__rollOut{animation-name:xa}@keyframes ya{0%{opacity:0;transform:scale3d(.3,.3,.3)}50%{opacity:1}}.animate__zoomIn{animation-name:ya}@keyframes za{0%{animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0)}60%{animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,60px,0)}}.animate__zoomInDown{animation-name:za}@keyframes Aa{0%{animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0)}60%{animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(10px,0,0)}}.animate__zoomInLeft{animation-name:Aa}@keyframes Ba{0%{animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(1000px,0,0)}60%{animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(-10px,0,0)}}.animate__zoomInRight{animation-name:Ba}@keyframes Ca{0%{animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,1000px,0)}60%{animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,-60px,0)}}.animate__zoomInUp{animation-name:Ca}@keyframes Da{0%{opacity:1}50%{opacity:0;transform:scale3d(.3,.3,.3)}to{opacity:0}}.animate__zoomOut{animation-name:Da}@keyframes Ea{40%{animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,-60px,0)}to{animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,2000px,0)}}.animate__zoomOutDown{animation-name:Ea;transform-origin:center bottom}@keyframes Fa{40%{opacity:1;transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}to{opacity:0;transform:scale(.1) translate3d(-2000px,0,0)}}.animate__zoomOutLeft{animation-name:Fa;transform-origin:left center}@keyframes Ga{40%{opacity:1;transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}to{opacity:0;transform:scale(.1) translate3d(2000px,0,0)}}.animate__zoomOutRight{animation-name:Ga;transform-origin:right center}@keyframes Ha{40%{animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,60px,0)}to{animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0)}}.animate__zoomOutUp{animation-name:Ha;transform-origin:center bottom}@keyframes Ia{0%{transform:translate3d(0,-100%,0);visibility:visible}to{transform:translateZ(0)}}.animate__slideInDown{animation-name:Ia}@keyframes Ja{0%{transform:translate3d(-100%,0,0);visibility:visible}to{transform:translateZ(0)}}.animate__slideInLeft{animation-name:Ja}@keyframes Ka{0%{transform:translate3d(100%,0,0);visibility:visible}to{transform:translateZ(0)}}.animate__slideInRight{animation-name:Ka}@keyframes La{0%{transform:translate3d(0,100%,0);visibility:visible}to{transform:translateZ(0)}}.animate__slideInUp{animation-name:La}@keyframes Ma{0%{transform:translateZ(0)}to{transform:translate3d(0,100%,0);visibility:hidden}}.animate__slideOutDown{animation-name:Ma}@keyframes Na{0%{transform:translateZ(0)}to{transform:translate3d(-100%,0,0);visibility:hidden}}.animate__slideOutLeft{animation-name:Na}@keyframes Oa{0%{transform:translateZ(0)}to{transform:translate3d(100%,0,0);visibility:hidden}}.animate__slideOutRight{animation-name:Oa}@keyframes Pa{0%{transform:translateZ(0)}to{transform:translate3d(0,-100%,0);visibility:hidden}}.animate__slideOutUp{animation-name:Pa}.button_plxA{background:#8759ff;border-radius:5px;bottom:10px;color:#fff;cursor:pointer;padding:0 10px;position:fixed;right:10px;z-index:1000000}.modal_wSGk{background-color:rgba(0,0,0,.8);display:flex;height:100vh;justify-content:center;overflow:hidden;width:100vw;z-index:99999}.playground_CMhS{border-radius:8px;height:80vh;margin-top:50px;user-select:none;width:80vw}body:not(.navigation-with-keyboard) :not(input):focus{outline:0}#docusaurus-base-url-issue-banner-container,.collapseSidebarButton_PEFL,.docSidebarContainer_b6E3,.sidebarLogo_F_0z,.themedImage_ToTc,[data-theme=dark] .lightToggleIcon_pyhR,[data-theme=light] .darkToggleIcon_wfgR,html[data-announcement-bar-initially-dismissed=true] .announcementBar_mb4j{display:none}.skipToContent_fXgn{background-color:var(--ifm-background-surface-color);color:var(--ifm-color-emphasis-900);left:100%;padding:calc(var(--ifm-global-spacing)/2) var(--ifm-global-spacing);position:fixed;top:1rem;z-index:calc(var(--ifm-z-index-fixed) + 1)}.skipToContent_fXgn:focus{box-shadow:var(--ifm-global-shadow-md);left:1rem}.announcementBar_mb4j{align-items:center;background-color:var(--ifm-color-white);border-bottom:1px solid var(--ifm-color-emphasis-100);color:var(--ifm-color-black);display:flex;height:var(--docusaurus-announcement-bar-height)}.announcementBarPlaceholder_vyr4{flex:0 0 10px}.announcementBarClose_gvF7{align-self:stretch;flex:0 0 30px;line-height:0;padding:0}.announcementBarContent_xLdY{flex:1 1 auto;font-size:85%;padding:5px 0;text-align:center}.announcementBarContent_xLdY a{color:inherit;text-decoration:underline}.toggle_vylO{height:2rem;width:2rem}.toggleButton_gllP{align-items:center;border-radius:50%;display:flex;height:100%;justify-content:center;transition:background var(--ifm-transition-fast);width:100%}.toggleButton_gllP:hover{background:var(--ifm-color-emphasis-200)}.toggleButtonDisabled_aARS{cursor:not-allowed}[data-theme=dark] .themedImage--dark_i4oU,[data-theme=light] .themedImage--light_HNdA{display:initial}.iconExternalLink_nPIU{margin-left:.3rem}.iconLanguage_nlXk{margin-right:5px;vertical-align:text-bottom}.navbarHideable_m1mJ{transition:transform var(--ifm-transition-fast) ease}.navbarHidden_jGov{transform:translate3d(0,calc(-100% - 2px),0)}.footerLogoLink_DDai{opacity:.5;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.footerLogoLink_DDai:hover,.hash-link:focus,:hover>.hash-link{opacity:1}.mainWrapper_z2l0{flex:1 0 auto}.docusaurus-mt-lg{margin-top:3rem}#__docusaurus{display:flex;flex-direction:column;min-height:100%}.sidebar_re4s{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem);overflow-y:auto;position:-webkit-sticky;position:sticky;top:calc(var(--ifm-navbar-height) + 2rem)}.sidebarItemTitle_pO2u{font-size:var(--ifm-h3-font-size)}.container_mt6G,.sidebarItemList_Yudw{font-size:.9rem}.sidebarItem__DBe{margin-top:.7rem}.sidebarItemLink_mo7H{color:var(--ifm-font-color-base);display:block}.sidebarItemLinkActive_I1ZP{color:var(--ifm-color-primary)!important}.searchQueryInput_u2C7,.searchVersionInput_m0Ui{background:var(--docsearch-searchbox-focus-background);border:2px solid var(--ifm-toc-border-color);border-radius:var(--ifm-global-radius);color:var(--docsearch-text-color);font:var(--ifm-font-size-base) var(--ifm-font-family-base);margin-bottom:.5rem;padding:.8rem;transition:border var(--ifm-transition-fast) ease;width:100%}.searchQueryInput_u2C7:focus,.searchVersionInput_m0Ui:focus{border-color:var(--docsearch-primary-color);outline:0}.searchQueryInput_u2C7:-ms-input-placeholder{color:var(--docsearch-muted-color)}.searchQueryInput_u2C7::placeholder{color:var(--docsearch-muted-color)}.searchResultsColumn_JPFH{font-size:.9rem;font-weight:700}.algoliaLogo_rT1R{max-width:150px}.algoliaLogoPathFill_WdUC{fill:var(--ifm-font-color-base)}.searchResultItem_Tv2o{border-bottom:1px solid var(--ifm-toc-border-color);padding:1rem 0}.searchResultItemHeading_KbCB{font-weight:400;margin-bottom:0}.searchResultItemPath_lhe1{--ifm-breadcrumb-separator-size-multiplier:1;color:var(--ifm-color-content-secondary);font-size:.8rem}.searchResultItemSummary_AEaO{font-style:italic;margin:.5rem 0 0}.loadingSpinner_XVxU{animation:1s linear infinite Qa;border:.4em solid #eee;border-radius:50%;border-top:.4em solid var(--ifm-color-primary);height:3rem;margin:0 auto;width:3rem}@keyframes Qa{to{transform:rotate(1turn)}}.loader_vvXV{margin-top:2rem}.search-result-match{background:rgba(255,215,142,.25);color:var(--docsearch-hit-color);padding:.09em 0}.backToTopButton_sjWU{background-color:var(--ifm-color-emphasis-200);border-radius:50%;bottom:1.3rem;box-shadow:var(--ifm-global-shadow-lw);height:3rem;opacity:0;position:fixed;right:1.3rem;transform:scale(0);transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default);visibility:hidden;width:3rem;z-index:calc(var(--ifm-z-index-fixed) - 1)}.backToTopButton_sjWU:after{background-color:var(--ifm-color-emphasis-1000);content:" ";display:inline-block;height:100%;-webkit-mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;width:100%}.backToTopButtonShow_xfvO{opacity:1;transform:scale(1);visibility:visible}[data-theme=dark]:root{--docusaurus-collapse-button-bg:hsla(0,0%,100%,.05);--docusaurus-collapse-button-bg-hover:hsla(0,0%,100%,.1)}.docMainContainer_gTbr,.docPage__5DB{display:flex;width:100%}.authorCol_Hf19{flex-grow:1!important;max-width:inherit!important}.imageOnlyAuthorRow_pa_O{display:flex;flex-flow:row wrap}.DocSearch-Button,.DocSearch-Button-Container{align-items:center;display:flex}.imageOnlyAuthorCol_G86a{margin-left:.3rem;margin-right:.3rem}.DocSearch-Button{background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;font-weight:500;height:36px;justify-content:space-between;padding:0 8px;user-select:none}.DocSearch-Footer,.DocSearch-Help{-webkit-user-select:none;-ms-user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:0}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Hit-Tree,.DocSearch-Hit-action,.DocSearch-Hit-icon,.DocSearch-Reset{stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Input,.DocSearch-Link{-webkit-appearance:none;font:inherit}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border:0;border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 2px;position:relative;top:-1px;width:20px}.DocSearch--active{overflow:hidden!important}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{appearance:none;background:0 0;border:0;color:var(--docsearch-text-color);flex:1;font-size:1.2em;height:100%;outline:0;padding:0 0 0 8px;width:80%}.DocSearch-Hit-action-button,.DocSearch-Reset{-webkit-appearance:none;border:0;cursor:pointer}.DocSearch-Input:-ms-input-placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Cancel,.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator,.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset{animation:.1s ease-in forwards Ra;appearance:none;background:none;border-radius:50%;color:var(--docsearch-icon-color);padding:2px;right:0}.DocSearch-Help,.DocSearch-HitsFooter,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Reset:focus{outline:0}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:0 0}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help{font-size:.9em;margin:0;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}.DocSearch-Hit--deleting{opacity:0;transition:.25s linear}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:.25s linear .25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:-webkit-sticky;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{appearance:none;background:none;border-radius:50%;color:inherit;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon,.tocCollapsibleContent_vkbj a{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:background-color .1s ease-in}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{-webkit-appearance:none;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:0;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;user-select:none;width:100%;z-index:300}.DocSearch-Commands li,.DocSearch-Commands-Key{align-items:center;display:flex}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{background:var(--docsearch-key-gradient);border:0;border-radius:2px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;width:20px}.buttonGroup__atx button,.codeBlockContainer_Ckt0{background:var(--prism-background-color);color:var(--prism-color)}@keyframes Ra{0%{opacity:0}to{opacity:1}}.DocSearch-Button{margin:0;transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.DocSearch-Container{z-index:calc(var(--ifm-z-index-fixed) + 1)}.codeBlockContainer_Ckt0{border-radius:var(--ifm-code-border-radius);box-shadow:var(--ifm-global-shadow-lw);margin-bottom:var(--ifm-leading)}.codeBlockContent_biex{border-radius:inherit;direction:ltr;position:relative}.codeBlockTitle_Ktv7{border-bottom:1px solid var(--ifm-color-emphasis-300);border-top-left-radius:inherit;border-top-right-radius:inherit;font-size:var(--ifm-code-font-size);font-weight:500;padding:.75rem var(--ifm-pre-padding)}.codeBlock_bY9V{--ifm-pre-background:var(--prism-background-color);margin:0;padding:0}.codeBlockTitle_Ktv7+.codeBlockContent_biex .codeBlock_bY9V{border-top-left-radius:0;border-top-right-radius:0}.codeBlockLines_e6Vv{float:left;font:inherit;min-width:100%;padding:var(--ifm-pre-padding)}.codeBlockLinesWithNumbering_o6Pm{display:table;padding:var(--ifm-pre-padding) 0}.buttonGroup__atx{column-gap:.2rem;display:flex;position:absolute;right:calc(var(--ifm-pre-padding)/2);top:calc(var(--ifm-pre-padding)/2)}.buttonGroup__atx button{align-items:center;border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-global-radius);display:flex;line-height:0;opacity:0;padding:.4rem;transition:opacity .2s ease-in-out}.buttonGroup__atx button:focus-visible,.buttonGroup__atx button:hover{opacity:1!important}.theme-code-block:hover .buttonGroup__atx button{opacity:.4}.iconEdit_Z9Sw{margin-right:.3em;vertical-align:sub}:where(:root){--docusaurus-highlighted-code-line-bg:#484d5b}:where([data-theme=dark]){--docusaurus-highlighted-code-line-bg:#646464}.theme-code-block-highlighted-line{background-color:var(--docusaurus-highlighted-code-line-bg);display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.codeLine_lJS_{counter-increment:a;display:table-row}.codeLineNumber_Tfdd{background:var(--ifm-pre-background);display:table-cell;left:0;padding:0 var(--ifm-pre-padding);position:-webkit-sticky;position:sticky;text-align:right;width:1%}.codeLineNumber_Tfdd:before{content:counter(a);opacity:.4}.codeLineContent_feaV{padding-right:var(--ifm-pre-padding)}.tag_zVej{border:1px solid var(--docusaurus-tag-list-border);transition:border var(--ifm-transition-fast)}.tag_zVej:hover{--docusaurus-tag-list-border:var(--ifm-link-color);text-decoration:none}.tagRegular_sFm0{border-radius:.5rem;font-size:90%;padding:.3rem .5rem}.tagWithCount_h2kH{align-items:center;border-left:0;display:flex;padding:0 .5rem 0 1rem;position:relative}.tagWithCount_h2kH:after,.tagWithCount_h2kH:before{border:1px solid var(--docusaurus-tag-list-border);content:"";position:absolute;top:50%;transition:inherit}.tagWithCount_h2kH:before{border-bottom:0;border-right:0;height:1.18rem;right:100%;transform:translate(50%,-50%) rotate(-45deg);width:1.18rem}.tagWithCount_h2kH:after{border-radius:50%;height:.5rem;left:0;transform:translateY(-50%);width:.5rem}.tagWithCount_h2kH span{background:var(--ifm-color-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-color-black);font-size:.7rem;line-height:1.2;margin-left:.3rem;padding:.1rem .4rem}.tag_Nnez{display:inline-block;margin:.5rem .5rem 0 1rem}.theme-code-block:hover .copyButtonCopied_obH4{opacity:1!important}.copyButtonIcons_eSgA{height:1.125rem;position:relative;width:1.125rem}.copyButtonIcon_y97N,.copyButtonSuccessIcon_LjdS{fill:currentColor;height:inherit;left:0;opacity:inherit;position:absolute;top:0;transition:.15s;width:inherit}.copyButtonSuccessIcon_LjdS{color:#00d600;left:50%;opacity:0;top:50%;transform:translate(-50%,-50%) scale(.33)}.copyButtonCopied_obH4 .copyButtonIcon_y97N{opacity:0;transform:scale(.33)}.copyButtonCopied_obH4 .copyButtonSuccessIcon_LjdS{opacity:1;transform:translate(-50%,-50%) scale(1);transition-delay:75ms}.tags_jXut{display:inline}.tag_QGVx{display:inline-block;margin:0 .4rem .5rem 0}.lastUpdated_vwxv{font-size:smaller;font-style:italic;margin-top:.2rem}.tocCollapsibleButton_TO0P{align-items:center;display:flex;font-size:inherit;justify-content:space-between;padding:.4rem .8rem;width:100%}.tocCollapsibleButton_TO0P:after{background:var(--ifm-menu-link-sublist-icon) 50% 50%/2rem 2rem no-repeat;content:"";filter:var(--ifm-menu-link-sublist-icon-filter);height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast);width:1.25rem}.tocCollapsibleButtonExpanded_MG3E:after,.tocCollapsibleExpanded_sAul{transform:none}.tocCollapsible_ETCw{background-color:var(--ifm-menu-color-background-active);border-radius:var(--ifm-global-radius);margin:1rem 0}.tocCollapsibleContent_vkbj>ul{border-left:none;border-top:1px solid var(--ifm-color-emphasis-300);font-size:15px;padding:.2rem 0}.tocCollapsibleContent_vkbj ul li{margin:.4rem .8rem}.wordWrapButtonIcon_Bwma{height:1.2rem;width:1.2rem}.details_lb9f{--docusaurus-details-summary-arrow-size:0.38rem;--docusaurus-details-transition:transform 200ms ease;--docusaurus-details-decoration-color:grey}.details_lb9f>summary{cursor:pointer;list-style:none;padding-left:1rem;position:relative}.details_lb9f>summary::-webkit-details-marker{display:none}.details_lb9f>summary:before{border-color:transparent transparent transparent var(--docusaurus-details-decoration-color);border-style:solid;border-width:var(--docusaurus-details-summary-arrow-size);content:"";left:0;position:absolute;top:.45rem;transform:rotate(0);transform-origin:calc(var(--docusaurus-details-summary-arrow-size)/2) 50%;transition:var(--docusaurus-details-transition)}.collapsibleContent_i85q{border-top:1px solid var(--docusaurus-details-decoration-color);margin-top:1rem;padding-top:1rem}.details_b_Ee{--docusaurus-details-decoration-color:var(--ifm-alert-border-color);--docusaurus-details-transition:transform var(--ifm-transition-fast) ease;border:1px solid var(--ifm-alert-border-color);margin:0 0 var(--ifm-spacing-vertical)}.anchorWithStickyNavbar_LWe7{scroll-margin-top:calc(var(--ifm-navbar-height) + .5rem)}.anchorWithHideOnScrollNavbar_WYt5{scroll-margin-top:.5rem}.hash-link{opacity:0;padding-left:.5rem;transition:opacity var(--ifm-transition-fast);-webkit-user-select:none;-ms-user-select:none;user-select:none}.hash-link:before{content:"#"}.containsTaskList_mC6p{list-style:none}.img_ev3q{height:auto}.admonition_LlT9{margin-bottom:1em}.admonitionHeading_tbUL{font:var(--ifm-heading-font-weight) var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.3rem}.admonitionHeading_tbUL code{text-transform:none}.admonitionIcon_kALy{display:inline-block;margin-right:.4em;vertical-align:middle}.admonitionIcon_kALy svg{fill:var(--ifm-alert-foreground-color);display:inline-block;height:1.6em;width:1.6em}.blogPostFooterDetailsFull_mRVl{flex-direction:column}.tableOfContents_jeP5{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem);overflow-y:auto;position:-webkit-sticky;position:sticky;top:calc(var(--ifm-navbar-height) + 1rem)}.breadcrumbsContainer_Z_bl{--ifm-breadcrumb-size-multiplier:0.8;margin-bottom:.8rem}.breadcrumbHomeIcon_OVgt{height:1.1rem;position:relative;top:1px;vertical-align:top;width:1.1rem}.furion-banner{align-items:center;background-color:#211b50;color:#fff;padding:4rem 2rem}.furion-banner-container{display:flex;justify-content:space-between;margin:0 auto;max-width:1140px}.furion-banner-project{font-size:1.5em;font-weight:700}.furion-banner-description{-webkit-text-fill-color:transparent;-webkit-background-clip:text;background-clip:text;background-image:linear-gradient(81deg,#8759ff,#3fc4fe,#42ffac);font-size:2.5em;font-weight:700;line-height:1.25;margin:24px 0}.furion-banner-spec{font-family:Muli;font-size:1em;font-weight:500;line-height:1.33;opacity:.7;padding:0}.furion-banner-spec li{list-style:none;margin-bottom:1em;padding-left:1em;position:relative}.furion-banner-spec li:before{background-color:#8759ff;content:"";height:4px;left:0;position:absolute;top:.5em;width:4px}.furion-support-platform{color:#fff;font-family:Muli;font-size:.85em;font-weight:500;line-height:2;margin-top:3em;opacity:.6}.furion-support-icons{display:flex;margin-top:12px}.furion-support-icons span{margin-right:20px}.furion-get-start,.furion-try-demo{background:#8759ff;border-radius:2em;color:#fff;display:inline-block;line-height:1.5;margin-top:4em;min-width:145px;padding:8px 32px;position:relative;text-align:center;text-decoration:none;white-space:nowrap}.furion-try-demo{background-color:#21b091;margin-left:20px}.furion-get-start:hover{background:rgba(135,89,255,.9)}.furion-try-demo:hover{opacity:.9}.furion-banner-item .system-window{width:34rem}.furion-get-start:hover,.furion-try-demo:hover{color:#fff;text-decoration:none}.system-top-bar{background-image:linear-gradient(90deg,rgba(136,89,255,.2),rgba(63,196,254,.2) 90%,rgba(66,255,172,.2));padding:.25em 1em}.system-top-bar-circle{border-radius:50%;display:inline-block;filter:brightness(100%);height:.5em;margin-left:.3em;width:.5em}.system-window{--ifm-leading:0;background:#211b50;border-radius:1em;overflow:hidden;padding:0;width:95%}.system-window iframe{border-radius:unset}.blue-accent{--uni-border-color:#3fbbfe;--uni-box-shadow-color:rgba(63,187,254,.1);--ifm-menu-color-active:#3fbbfe}.preview-border{border:1px solid #3fbbfe;box-shadow:0 6px 58px 0 rgba(63,187,254,.1)}.furion-content{margin-bottom:4em;margin-top:4em;text-align:center}.furion-small-title{color:#412a94;font-family:Muli;font-size:1em;font-weight:600;letter-spacing:1px;opacity:.6}.furion-big-title.dark,.furion-contributor-item.dark a,.furion-log-number span.dark,.furion-remark-p p.dark,.furion-small-title.dark{color:#f5f6f7}.furion-big-title{color:#412a94;font-family:Poppins;font-size:2em;font-weight:700;line-height:1.31;margin-bottom:2em}.furion-gitee-log{display:flex;flex-wrap:nowrap;justify-content:center}.furion-log-item{height:173px;margin-right:65px;position:relative;width:260px}.furion-log-jiao{background:#fff;border-right:1px dashed #a795e8;border-top:1px dashed #a795e8;height:100px;position:absolute;right:-6px;top:-6px;width:100px}.furion-log-jiao.dark{background:#18191a}.furion-log-item:last-child{margin-right:0}.furion-log-number{align-items:center;display:flex;flex-direction:column;height:100%;justify-content:center;position:relative;width:100%;z-index:2}.furion-log-number div{font-size:3em;font-weight:700}.furion-log-number span{color:#1c1e21;font-family:Poppins,sans-serif;font-stretch:normal;font-style:normal;letter-spacing:normal;line-height:normal}.furion-remark{display:flex;justify-content:center}.furion-remark-item{border-image-slice:1;border-image-source:linear-gradient(var(--uni-border-gradient-degrees),#8759ff,#3fc4fe 51%,#42ffac);border-style:solid;border-width:6px;height:100%;margin:2em;max-width:320px;padding:4em 2em}.furion-remark-item:first-child{--uni-border-gradient-degrees:41deg;border-right:0;border-top:0}.furion-remark-item:nth-child(2){--uni-border-gradient-degrees:100deg;border:0}.furion-remark-item:last-child{--uni-border-gradient-degrees:221deg;border-bottom:0;border-left:0}.furion-remark-p{height:150px}.furion-remark-p h1{font-size:24px}.furion-remark-p p,.furion-who-des p{font-family:Muli;font-size:1em;line-height:1.75;opacity:.8}.furion-remark-p p{color:#474747;text-align:center}.furion-whouse{align-items:center;background-color:#412a94!important;color:#fff;display:flex;padding:5rem 0}.furion-who-custom{align-items:center;background-color:#fff;color:#723cff;display:flex;flex-wrap:wrap;justify-content:flex-end;min-height:500px;padding:6rem;text-align:right;width:60%}.furion-custom-img{color:transparent;margin-left:3em;text-decoration:none}.furion-who-des{padding:0 5rem}.furion-who-des p{color:#fff;margin-bottom:.8em}.footer{background-color:#211b50!important}.furion-links{margin:4em;text-align:center}.furion-links-content a{display:inline-block;font-size:20px;font-weight:600;margin:0 1em}.furion-contributors,.furion-proccesson{margin:4em 0;text-align:center}#dotnet-china{height:100px}.furion-contributor-item{background-color:#f3f3f3;border-radius:4px;box-shadow:4px 3px 16px -3px #0009;box-sizing:border-box;color:#333;display:inline-block;height:170px;margin:10px 5px;overflow:hidden;padding:10px;position:relative;text-align:center;width:130px}.furion-contributor-extra{background-color:#412a94;border-radius:4px;color:#fff;font-size:12px;padding:2px 5px;position:absolute;right:0;text-align:left;top:-9px}.furion-contributor-item a{color:#333;display:block;font-size:10pt;font-weight:700;text-decoration:none}.furion-contributor-item div{margin-top:10px}.furion-contributor-item.dark{background:#333}.furion-get-start-btn{display:flex;position:relative}.furion-version{color:#ff0;font-size:16px;position:absolute;right:0;top:-10px;z-index:10}.navbar{background-color:#211b50}.navbar__brand,.navbar__items,.navbar__link{color:#fff}.navbar__link--active,.navbar__link:hover{color:#ff0}.menu__list-item .navbar__link--active,.menu__list-item .navbar__link:hover{color:#743dff}@media (min-width:997px){.collapseSidebarButton_PEFL,.expandButton_m80_{background-color:var(--docusaurus-collapse-button-bg)}:root{--docusaurus-announcement-bar-height:30px}.announcementBarClose_gvF7,.announcementBarPlaceholder_vyr4{flex-basis:50px}.searchBox_ZlJk{padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.collapseSidebarButton_PEFL{border:1px solid var(--ifm-toc-border-color);border-radius:0;bottom:0;display:block!important;height:40px;position:-webkit-sticky;position:sticky}.collapseSidebarButtonIcon_kv0_{margin-top:4px;transform:rotate(180deg)}.expandButtonIcon_BlDH,[dir=rtl] .collapseSidebarButtonIcon_kv0_{transform:rotate(0)}.collapseSidebarButton_PEFL:focus,.collapseSidebarButton_PEFL:hover,.expandButton_m80_:focus,.expandButton_m80_:hover{background-color:var(--docusaurus-collapse-button-bg-hover)}.menuHtmlItem_M9Kj{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu_SIkG{flex-grow:1;padding:.5rem}@supports (scrollbar-gutter:stable){.menu_SIkG{padding:.5rem 0 .5rem .5rem;scrollbar-gutter:stable}}.menuWithAnnouncementBar_GW3s{margin-bottom:var(--docusaurus-announcement-bar-height)}.sidebar_mhZE{display:flex;flex-direction:column;height:100%;max-height:100vh;padding-top:var(--ifm-navbar-height);position:-webkit-sticky;position:sticky;top:0;transition:opacity 50ms;width:var(--doc-sidebar-width)}.sidebarWithHideableNavbar__6UL{padding-top:0}.sidebarHidden__LRd{height:0;opacity:0;overflow:hidden;visibility:hidden}.sidebarLogo_F_0z{align-items:center;color:inherit!important;display:flex!important;margin:0 var(--ifm-navbar-padding-horizontal);max-height:var(--ifm-navbar-height);min-height:var(--ifm-navbar-height);text-decoration:none!important}.sidebarLogo_F_0z img{height:2rem;margin-right:.5rem}.expandButton_m80_{align-items:center;display:flex;height:100%;justify-content:center;max-height:100vh;position:-webkit-sticky;position:sticky;top:0;transition:background-color var(--ifm-transition-fast) ease}[dir=rtl] .expandButtonIcon_BlDH{transform:rotate(180deg)}.docSidebarContainer_b6E3{border-right:1px solid var(--ifm-toc-border-color);-webkit-clip-path:inset(0);clip-path:inset(0);display:block;margin-top:calc(var(--ifm-navbar-height)*-1);transition:width var(--ifm-transition-fast) ease;width:var(--doc-sidebar-width);will-change:width}.docSidebarContainerHidden_b3ry{cursor:pointer;width:var(--doc-sidebar-hidden-width)}.docMainContainer_gTbr{flex-grow:1;max-width:calc(100% - var(--doc-sidebar-width))}.docMainContainerEnhanced_Uz_u{max-width:calc(100% - var(--doc-sidebar-hidden-width))}.docItemWrapperEnhanced_czyv{max-width:calc(var(--ifm-container-width) + var(--doc-sidebar-width))!important}.lastUpdated_vwxv{text-align:right}.tocMobile_ITEo{display:none}.docItemCol_VOVn{max-width:75%!important}}@media (min-width:1440px){.container{max-width:var(--ifm-container-width-xl)}}@media screen and (max-width:1024px){.furion-banner-container{flex-direction:column;justify-content:unset}.furion-get-start-btn{text-align:center}#dotnet-china{height:45px}.furion-banner-item .system-window{margin-top:3rem;width:100%}.furion-gitee-log{align-items:center;flex-direction:column;flex-wrap:unset;justify-content:center;padding:20px}.furion-log-item{height:173px;margin-right:0;margin-top:25px;width:100%}.furion-big-title{margin-bottom:1em}.furion-remark,.furion-whouse{flex-direction:column}.furion-whouse{padding-bottom:1em}.furion-who-des{padding-bottom:2em;padding-top:1em}.furion-remark-item{border:none;margin:0;max-width:unset;padding-bottom:0;width:100%}.furion-custom-img{margin-bottom:2em;margin-left:0}.furion-custom-img img{max-width:unset}.furion-who-custom{align-items:center;justify-content:center;text-align:center;width:100%}.furion-contributors{margin:4em 0}}@media (max-width:996px){.col{--ifm-col-width:100%;flex-basis:var(--ifm-col-width);margin-left:0}.footer{--ifm-footer-padding-horizontal:0}.colorModeToggle_DEke,.footer__link-separator,.navbar__item,.sidebar_re4s,.tableOfContents_jeP5{display:none}.footer__col{margin-bottom:calc(var(--ifm-spacing-vertical)*3)}.footer__link-item{display:block}.hero{padding-left:0;padding-right:0}.navbar>.container,.navbar>.container-fluid{padding:0}.navbar__toggle{display:inherit}.navbar__search-input{width:9rem}.pills--block,.tabs--block{flex-direction:column}.searchBox_ZlJk{position:absolute;right:var(--ifm-navbar-padding-horizontal)}.docItemContainer_hgFs{padding:0 .3rem}}@media only screen and (max-width:996px){.searchQueryColumn_RTkw,.searchResultsColumn_JPFH{max-width:60%!important}.searchLogoColumn_rJIA,.searchVersionColumn_ypXd{max-width:40%!important}.searchLogoColumn_rJIA{padding-left:0!important}}@media (max-width:750px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder,.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%;max-height:calc(var(--docsearch-vh,1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh,1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh,1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Cancel{-webkit-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:0;overflow:hidden;padding:0;-webkit-user-select:none;-ms-user-select:none;user-select:none;white-space:nowrap}}@media (max-width:576px){.markdown h1:first-child{--ifm-h1-font-size:2rem}.markdown>h2{--ifm-h2-font-size:1.5rem}.markdown>h3{--ifm-h3-font-size:1.25rem}.title_f1Hy{font-size:2rem}}@media screen and (max-width:576px){.searchQueryColumn_RTkw{max-width:100%!important}.searchVersionColumn_ypXd{max-width:100%!important;padding-left:var(--ifm-spacing-horizontal)!important}}@media (hover:hover){.backToTopButton_sjWU:hover{background-color:var(--ifm-color-emphasis-300)}}@media (pointer:fine){.thin-scrollbar{scrollbar-width:thin}.thin-scrollbar::-webkit-scrollbar{height:var(--ifm-scrollbar-size);width:var(--ifm-scrollbar-size)}.thin-scrollbar::-webkit-scrollbar-track{background:var(--ifm-scrollbar-track-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb{background:var(--ifm-scrollbar-thumb-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--ifm-scrollbar-thumb-hover-background-color)}}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{stroke-width:var(--docsearch-icon-stroke-width);animation:none;-webkit-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0}.DocSearch-Hit--deleting,.DocSearch-Hit--favoriting{transition:none}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:none}}@media print{.announcementBar_mb4j,.footer,.menu,.navbar,.pagination-nav,.table-of-contents,.tocMobile_ITEo{display:none}.tabs{page-break-inside:avoid}.codeBlockLines_e6Vv{white-space:pre-wrap}}@media (prefers-reduced-motion:reduce),print{.animate__animated{animation-duration:1ms!important;animation-iteration-count:1!important;transition-duration:1ms!important}.animate__animated[class*=Out]{opacity:0}} \ No newline at end of file +@charset "UTF-8";.col,.container{padding:0 var(--ifm-spacing-horizontal);width:100%}.markdown li,body{word-wrap:break-word}body,ol ol,ol ul,ul ol,ul ul{margin:0}pre,table{overflow:auto}blockquote,pre{margin:0 0 var(--ifm-spacing-vertical)}.breadcrumbs__link,.button{transition-timing-function:var(--ifm-transition-timing-default)}.button,code{vertical-align:middle}.button--outline.button--active,.button--outline:active,.button--outline:hover,:root{--ifm-button-color:var(--ifm-font-color-base-inverse)}.menu__link:hover,a{transition:color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.navbar--dark,:root{--ifm-navbar-link-hover-color:var(--ifm-color-primary)}.menu,.navbar-sidebar{overflow-x:hidden}:root,html[data-theme=dark]{--ifm-color-emphasis-500:var(--ifm-color-gray-500)}.animate__headShake,.animate__heartBeat,.animate__pulse{animation-timing-function:ease-in-out}.toggleButton_gllP,html{-webkit-tap-highlight-color:transparent}*,.DocSearch-Container,.DocSearch-Container *,.furion-log-item,.furion-who-custom,.furion-who-des,.modal_wSGk{box-sizing:border-box}:root{--ifm-color-scheme:light;--ifm-dark-value:10%;--ifm-darker-value:15%;--ifm-darkest-value:30%;--ifm-light-value:15%;--ifm-lighter-value:30%;--ifm-lightest-value:50%;--ifm-contrast-background-value:90%;--ifm-contrast-foreground-value:70%;--ifm-contrast-background-dark-value:70%;--ifm-contrast-foreground-dark-value:90%;--ifm-color-primary:#3578e5;--ifm-color-secondary:#ebedf0;--ifm-color-success:#00a400;--ifm-color-info:#54c7ec;--ifm-color-warning:#ffba00;--ifm-color-danger:#fa383e;--ifm-color-primary-dark:#306cce;--ifm-color-primary-darker:#2d66c3;--ifm-color-primary-darkest:#2554a0;--ifm-color-primary-light:#538ce9;--ifm-color-primary-lighter:#72a1ed;--ifm-color-primary-lightest:#9abcf2;--ifm-color-primary-contrast-background:#ebf2fc;--ifm-color-primary-contrast-foreground:#102445;--ifm-color-secondary-dark:#d4d5d8;--ifm-color-secondary-darker:#c8c9cc;--ifm-color-secondary-darkest:#a4a6a8;--ifm-color-secondary-light:#eef0f2;--ifm-color-secondary-lighter:#f1f2f5;--ifm-color-secondary-lightest:#f5f6f8;--ifm-color-secondary-contrast-background:#fdfdfe;--ifm-color-secondary-contrast-foreground:#474748;--ifm-color-success-dark:#009400;--ifm-color-success-darker:#008b00;--ifm-color-success-darkest:#007300;--ifm-color-success-light:#26b226;--ifm-color-success-lighter:#4dbf4d;--ifm-color-success-lightest:#80d280;--ifm-color-success-contrast-background:#e6f6e6;--ifm-color-success-contrast-foreground:#003100;--ifm-color-info-dark:#4cb3d4;--ifm-color-info-darker:#47a9c9;--ifm-color-info-darkest:#3b8ba5;--ifm-color-info-light:#6ecfef;--ifm-color-info-lighter:#87d8f2;--ifm-color-info-lightest:#aae3f6;--ifm-color-info-contrast-background:#eef9fd;--ifm-color-info-contrast-foreground:#193c47;--ifm-color-warning-dark:#e6a700;--ifm-color-warning-darker:#d99e00;--ifm-color-warning-darkest:#b38200;--ifm-color-warning-light:#ffc426;--ifm-color-warning-lighter:#ffcf4d;--ifm-color-warning-lightest:#ffdd80;--ifm-color-warning-contrast-background:#fff8e6;--ifm-color-warning-contrast-foreground:#4d3800;--ifm-color-danger-dark:#e13238;--ifm-color-danger-darker:#d53035;--ifm-color-danger-darkest:#af272b;--ifm-color-danger-light:#fb565b;--ifm-color-danger-lighter:#fb7478;--ifm-color-danger-lightest:#fd9c9f;--ifm-color-danger-contrast-background:#ffebec;--ifm-color-danger-contrast-foreground:#4b1113;--ifm-color-white:#fff;--ifm-color-black:#000;--ifm-color-gray-0:var(--ifm-color-white);--ifm-color-gray-100:#f5f6f7;--ifm-color-gray-200:#ebedf0;--ifm-color-gray-300:#dadde1;--ifm-color-gray-400:#ccd0d5;--ifm-color-gray-500:#bec3c9;--ifm-color-gray-600:#8d949e;--ifm-color-gray-700:#606770;--ifm-color-gray-800:#444950;--ifm-color-gray-900:#1c1e21;--ifm-color-gray-1000:var(--ifm-color-black);--ifm-color-emphasis-0:var(--ifm-color-gray-0);--ifm-color-emphasis-100:var(--ifm-color-gray-100);--ifm-color-emphasis-200:var(--ifm-color-gray-200);--ifm-color-emphasis-300:var(--ifm-color-gray-300);--ifm-color-emphasis-400:var(--ifm-color-gray-400);--ifm-color-emphasis-600:var(--ifm-color-gray-600);--ifm-color-emphasis-700:var(--ifm-color-gray-700);--ifm-color-emphasis-800:var(--ifm-color-gray-800);--ifm-color-emphasis-900:var(--ifm-color-gray-900);--ifm-color-emphasis-1000:var(--ifm-color-gray-1000);--ifm-color-content:var(--ifm-color-emphasis-900);--ifm-color-content-inverse:var(--ifm-color-emphasis-0);--ifm-color-content-secondary:#525860;--ifm-background-color:transparent;--ifm-background-surface-color:var(--ifm-color-content-inverse);--ifm-global-border-width:1px;--ifm-global-radius:0.4rem;--ifm-hover-overlay:rgba(0,0,0,.05);--ifm-font-color-base:var(--ifm-color-content);--ifm-font-color-base-inverse:var(--ifm-color-content-inverse);--ifm-font-color-secondary:var(--ifm-color-content-secondary);--ifm-font-family-base:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--ifm-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--ifm-font-size-base:100%;--ifm-font-weight-light:300;--ifm-font-weight-normal:400;--ifm-font-weight-semibold:500;--ifm-font-weight-bold:700;--ifm-font-weight-base:var(--ifm-font-weight-normal);--ifm-line-height-base:1.65;--ifm-global-spacing:1rem;--ifm-spacing-vertical:var(--ifm-global-spacing);--ifm-spacing-horizontal:var(--ifm-global-spacing);--ifm-transition-fast:200ms;--ifm-transition-slow:400ms;--ifm-transition-timing-default:cubic-bezier(0.08,0.52,0.52,1);--ifm-global-shadow-lw:0 1px 2px 0 rgba(0,0,0,.1);--ifm-global-shadow-md:0 5px 40px rgba(0,0,0,.2);--ifm-global-shadow-tl:0 12px 28px 0 rgba(0,0,0,.2),0 2px 4px 0 rgba(0,0,0,.1);--ifm-z-index-dropdown:100;--ifm-z-index-fixed:200;--ifm-z-index-overlay:400;--ifm-container-width:1140px;--ifm-container-width-xl:1320px;--ifm-code-background:#f6f7f8;--ifm-code-border-radius:var(--ifm-global-radius);--ifm-code-font-size:90%;--ifm-code-padding-horizontal:0.1rem;--ifm-code-padding-vertical:0.1rem;--ifm-pre-background:var(--ifm-code-background);--ifm-pre-border-radius:var(--ifm-code-border-radius);--ifm-pre-color:inherit;--ifm-pre-line-height:1.45;--ifm-pre-padding:1rem;--ifm-heading-color:inherit;--ifm-heading-margin-top:0;--ifm-heading-margin-bottom:var(--ifm-spacing-vertical);--ifm-heading-font-family:var(--ifm-font-family-base);--ifm-heading-font-weight:var(--ifm-font-weight-bold);--ifm-heading-line-height:1.25;--ifm-h1-font-size:2rem;--ifm-h2-font-size:1.5rem;--ifm-h3-font-size:1.25rem;--ifm-h4-font-size:1rem;--ifm-h5-font-size:0.875rem;--ifm-h6-font-size:0.85rem;--ifm-image-alignment-padding:1.25rem;--ifm-leading-desktop:1.25;--ifm-leading:calc(var(--ifm-leading-desktop)*1rem);--ifm-list-left-padding:2rem;--ifm-list-margin:1rem;--ifm-list-item-margin:0.25rem;--ifm-list-paragraph-margin:1rem;--ifm-table-cell-padding:0.75rem;--ifm-table-background:transparent;--ifm-table-stripe-background:rgba(0,0,0,.03);--ifm-table-border-width:1px;--ifm-table-border-color:var(--ifm-color-emphasis-300);--ifm-table-head-background:inherit;--ifm-table-head-color:inherit;--ifm-table-head-font-weight:var(--ifm-font-weight-bold);--ifm-table-cell-color:inherit;--ifm-link-color:var(--ifm-color-primary);--ifm-link-decoration:none;--ifm-link-hover-color:var(--ifm-link-color);--ifm-link-hover-decoration:underline;--ifm-paragraph-margin-bottom:var(--ifm-leading);--ifm-blockquote-font-size:var(--ifm-font-size-base);--ifm-blockquote-border-left-width:2px;--ifm-blockquote-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-blockquote-padding-vertical:0;--ifm-blockquote-shadow:none;--ifm-blockquote-color:var(--ifm-color-emphasis-800);--ifm-blockquote-border-color:var(--ifm-color-emphasis-300);--ifm-hr-background-color:var(--ifm-color-emphasis-500);--ifm-hr-height:1px;--ifm-hr-margin-vertical:1.5rem;--ifm-scrollbar-size:7px;--ifm-scrollbar-track-background-color:#f1f1f1;--ifm-scrollbar-thumb-background-color:silver;--ifm-scrollbar-thumb-hover-background-color:#a7a7a7;--ifm-alert-background-color:inherit;--ifm-alert-border-color:inherit;--ifm-alert-border-radius:var(--ifm-global-radius);--ifm-alert-border-width:0px;--ifm-alert-border-left-width:5px;--ifm-alert-color:var(--ifm-font-color-base);--ifm-alert-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-alert-padding-vertical:var(--ifm-spacing-vertical);--ifm-alert-shadow:var(--ifm-global-shadow-lw);--ifm-avatar-intro-margin:1rem;--ifm-avatar-intro-alignment:inherit;--ifm-avatar-photo-size:3rem;--ifm-badge-background-color:inherit;--ifm-badge-border-color:inherit;--ifm-badge-border-radius:var(--ifm-global-radius);--ifm-badge-border-width:var(--ifm-global-border-width);--ifm-badge-color:var(--ifm-color-white);--ifm-badge-padding-horizontal:calc(var(--ifm-spacing-horizontal)*0.5);--ifm-badge-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-breadcrumb-border-radius:1.5rem;--ifm-breadcrumb-spacing:0.5rem;--ifm-breadcrumb-color-active:var(--ifm-color-primary);--ifm-breadcrumb-item-background-active:var(--ifm-hover-overlay);--ifm-breadcrumb-padding-horizontal:0.8rem;--ifm-breadcrumb-padding-vertical:0.4rem;--ifm-breadcrumb-size-multiplier:1;--ifm-breadcrumb-separator:url('data:image/svg+xml;utf8,');--ifm-breadcrumb-separator-filter:none;--ifm-breadcrumb-separator-size:0.5rem;--ifm-breadcrumb-separator-size-multiplier:1.25;--ifm-button-background-color:inherit;--ifm-button-border-color:var(--ifm-button-background-color);--ifm-button-border-width:var(--ifm-global-border-width);--ifm-button-font-weight:var(--ifm-font-weight-bold);--ifm-button-padding-horizontal:1.5rem;--ifm-button-padding-vertical:0.375rem;--ifm-button-size-multiplier:1;--ifm-button-transition-duration:var(--ifm-transition-fast);--ifm-button-border-radius:calc(var(--ifm-global-radius)*var(--ifm-button-size-multiplier));--ifm-button-group-spacing:2px;--ifm-card-background-color:var(--ifm-background-surface-color);--ifm-card-border-radius:calc(var(--ifm-global-radius)*2);--ifm-card-horizontal-spacing:var(--ifm-global-spacing);--ifm-card-vertical-spacing:var(--ifm-global-spacing);--ifm-toc-border-color:var(--ifm-color-emphasis-300);--ifm-toc-link-color:var(--ifm-color-content-secondary);--ifm-toc-padding-vertical:0.5rem;--ifm-toc-padding-horizontal:0.5rem;--ifm-dropdown-background-color:var(--ifm-background-surface-color);--ifm-dropdown-font-weight:var(--ifm-font-weight-semibold);--ifm-dropdown-link-color:var(--ifm-font-color-base);--ifm-dropdown-hover-background-color:var(--ifm-hover-overlay);--ifm-footer-background-color:var(--ifm-color-emphasis-100);--ifm-footer-color:inherit;--ifm-footer-link-color:var(--ifm-color-emphasis-700);--ifm-footer-link-hover-color:var(--ifm-color-primary);--ifm-footer-link-horizontal-spacing:0.5rem;--ifm-footer-padding-horizontal:calc(var(--ifm-spacing-horizontal)*2);--ifm-footer-padding-vertical:calc(var(--ifm-spacing-vertical)*2);--ifm-footer-title-color:inherit;--ifm-footer-logo-max-width:min(30rem,90vw);--ifm-hero-background-color:var(--ifm-background-surface-color);--ifm-hero-text-color:var(--ifm-color-emphasis-800);--ifm-menu-color:var(--ifm-color-emphasis-700);--ifm-menu-color-active:var(--ifm-color-primary);--ifm-menu-color-background-active:var(--ifm-hover-overlay);--ifm-menu-color-background-hover:var(--ifm-hover-overlay);--ifm-menu-link-padding-horizontal:0.75rem;--ifm-menu-link-padding-vertical:0.375rem;--ifm-menu-link-sublist-icon:url('data:image/svg+xml;utf8,');--ifm-menu-link-sublist-icon-filter:none;--ifm-navbar-background-color:var(--ifm-background-surface-color);--ifm-navbar-height:3.75rem;--ifm-navbar-item-padding-horizontal:0.75rem;--ifm-navbar-item-padding-vertical:0.25rem;--ifm-navbar-link-color:var(--ifm-font-color-base);--ifm-navbar-link-active-color:var(--ifm-link-color);--ifm-navbar-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-navbar-padding-vertical:calc(var(--ifm-spacing-vertical)*0.5);--ifm-navbar-shadow:var(--ifm-global-shadow-lw);--ifm-navbar-search-input-background-color:var(--ifm-color-emphasis-200);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-800);--ifm-navbar-search-input-placeholder-color:var(--ifm-color-emphasis-500);--ifm-navbar-search-input-icon:url('data:image/svg+xml;utf8,');--ifm-navbar-sidebar-width:83vw;--ifm-pagination-border-radius:var(--ifm-global-radius);--ifm-pagination-color-active:var(--ifm-color-primary);--ifm-pagination-font-size:1rem;--ifm-pagination-item-active-background:var(--ifm-hover-overlay);--ifm-pagination-page-spacing:0.2em;--ifm-pagination-padding-horizontal:calc(var(--ifm-spacing-horizontal)*1);--ifm-pagination-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-pagination-nav-border-radius:var(--ifm-global-radius);--ifm-pagination-nav-color-hover:var(--ifm-color-primary);--ifm-pills-color-active:var(--ifm-color-primary);--ifm-pills-color-background-active:var(--ifm-hover-overlay);--ifm-pills-spacing:0.125rem;--ifm-tabs-color:var(--ifm-font-color-secondary);--ifm-tabs-color-active:var(--ifm-color-primary);--ifm-tabs-color-active-border:var(--ifm-tabs-color-active);--ifm-tabs-padding-horizontal:1rem;--ifm-tabs-padding-vertical:1rem;--docusaurus-progress-bar-color:var(--ifm-color-primary);--ifm-color-primary:#25c2a0;--ifm-color-primary-dark:#21af90;--ifm-color-primary-darker:#1fa588;--ifm-color-primary-darkest:#1a8870;--ifm-color-primary-light:#46cbae;--ifm-color-primary-lighter:#66d4bd;--ifm-color-primary-lightest:#92e0d0;--ifm-code-font-size:95%;--animate-duration:1s;--animate-delay:1s;--animate-repeat:1;--docusaurus-announcement-bar-height:auto;--docusaurus-collapse-button-bg:transparent;--docusaurus-collapse-button-bg-hover:rgba(0,0,0,.1);--doc-sidebar-width:300px;--doc-sidebar-hidden-width:30px;--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12);--docsearch-primary-color:var(--ifm-color-primary);--docsearch-text-color:var(--ifm-font-color-base);--docusaurus-tag-list-border:var(--ifm-color-emphasis-300)}.badge--danger,.badge--info,.badge--primary,.badge--secondary,.badge--success,.badge--warning{--ifm-badge-border-color:var(--ifm-badge-background-color)}.button--link,.button--outline{--ifm-button-background-color:transparent}html{-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--ifm-background-color);color:var(--ifm-font-color-base);color-scheme:var(--ifm-color-scheme);font:var(--ifm-font-size-base)/var(--ifm-line-height-base) var(--ifm-font-family-base)}iframe{border:0;color-scheme:auto}.container{margin:0 auto;max-width:var(--ifm-container-width)}.container--fluid{max-width:inherit}.row{display:flex;flex-wrap:wrap;margin:0 calc(var(--ifm-spacing-horizontal)*-1)}.margin-bottom--none,.margin-vert--none,.markdown>:last-child,.system-window pre{margin-bottom:0!important}.margin-top--none,.margin-vert--none,.tabItem_LNqP{margin-top:0!important}.row--no-gutters{margin-left:0;margin-right:0}.margin-horiz--none,.margin-right--none{margin-right:0!important}.row--no-gutters>.col{padding-left:0;padding-right:0}.row--align-top{align-items:flex-start}.row--align-bottom{align-items:flex-end}.menuExternalLink_NmtK,.row--align-center{align-items:center}.row--align-stretch{align-items:stretch}.row--align-baseline{align-items:baseline}.col{--ifm-col-width:100%;flex:1 0;margin-left:0;max-width:var(--ifm-col-width)}.padding-bottom--none,.padding-vert--none{padding-bottom:0!important}.padding-top--none,.padding-vert--none{padding-top:0!important}.padding-horiz--none,.padding-left--none{padding-left:0!important}.padding-horiz--none,.padding-right--none{padding-right:0!important}.col[class*=col--]{flex:0 0 var(--ifm-col-width)}.col--1{--ifm-col-width:8.33333%}.col--offset-1{margin-left:8.33333%}.col--2{--ifm-col-width:16.66667%}.col--offset-2{margin-left:16.66667%}.col--3{--ifm-col-width:25%}.col--offset-3{margin-left:25%}.col--4{--ifm-col-width:33.33333%}.col--offset-4{margin-left:33.33333%}.col--5{--ifm-col-width:41.66667%}.col--offset-5{margin-left:41.66667%}.col--6{--ifm-col-width:50%}.col--offset-6{margin-left:50%}.col--7{--ifm-col-width:58.33333%}.col--offset-7{margin-left:58.33333%}.col--8{--ifm-col-width:66.66667%}.col--offset-8{margin-left:66.66667%}.col--9{--ifm-col-width:75%}.col--offset-9{margin-left:75%}.col--10{--ifm-col-width:83.33333%}.col--offset-10{margin-left:83.33333%}.col--11{--ifm-col-width:91.66667%}.col--offset-11{margin-left:91.66667%}.col--12{--ifm-col-width:100%}.col--offset-12{margin-left:100%}.margin-horiz--none,.margin-left--none{margin-left:0!important}.margin--none{margin:0!important}.markdown>h2,.markdown>h3,.markdown>h4,.markdown>h5,.markdown>h6{margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading))}.margin-bottom--xs,.margin-vert--xs{margin-bottom:.25rem!important}.margin-top--xs,.margin-vert--xs{margin-top:.25rem!important}.margin-horiz--xs,.margin-left--xs{margin-left:.25rem!important}.margin-horiz--xs,.margin-right--xs{margin-right:.25rem!important}.margin--xs{margin:.25rem!important}.margin-bottom--sm,.margin-vert--sm{margin-bottom:.5rem!important}.margin-top--sm,.margin-vert--sm{margin-top:.5rem!important}.margin-horiz--sm,.margin-left--sm{margin-left:.5rem!important}.margin-horiz--sm,.margin-right--sm{margin-right:.5rem!important}.margin--sm{margin:.5rem!important}.margin-bottom--md,.margin-vert--md{margin-bottom:1rem!important}.margin-top--md,.margin-vert--md{margin-top:1rem!important}.margin-horiz--md,.margin-left--md{margin-left:1rem!important}.margin-horiz--md,.margin-right--md{margin-right:1rem!important}.margin--md{margin:1rem!important}.margin-bottom--lg,.margin-vert--lg{margin-bottom:2rem!important}.margin-top--lg,.margin-vert--lg{margin-top:2rem!important}.margin-horiz--lg,.margin-left--lg{margin-left:2rem!important}.margin-horiz--lg,.margin-right--lg{margin-right:2rem!important}.margin--lg{margin:2rem!important}.margin-bottom--xl,.margin-vert--xl{margin-bottom:5rem!important}.margin-top--xl,.margin-vert--xl{margin-top:5rem!important}.margin-horiz--xl,.margin-left--xl{margin-left:5rem!important}.margin-horiz--xl,.margin-right--xl{margin-right:5rem!important}.margin--xl{margin:5rem!important}.padding--none{padding:0!important}.padding-bottom--xs,.padding-vert--xs{padding-bottom:.25rem!important}.padding-top--xs,.padding-vert--xs{padding-top:.25rem!important}.padding-horiz--xs,.padding-left--xs{padding-left:.25rem!important}.padding-horiz--xs,.padding-right--xs{padding-right:.25rem!important}.padding--xs{padding:.25rem!important}.padding-bottom--sm,.padding-vert--sm{padding-bottom:.5rem!important}.padding-top--sm,.padding-vert--sm{padding-top:.5rem!important}.padding-horiz--sm,.padding-left--sm{padding-left:.5rem!important}.padding-horiz--sm,.padding-right--sm{padding-right:.5rem!important}.padding--sm{padding:.5rem!important}.padding-bottom--md,.padding-vert--md{padding-bottom:1rem!important}.padding-top--md,.padding-vert--md{padding-top:1rem!important}.padding-horiz--md,.padding-left--md{padding-left:1rem!important}.padding-horiz--md,.padding-right--md{padding-right:1rem!important}.padding--md{padding:1rem!important}.padding-bottom--lg,.padding-vert--lg{padding-bottom:2rem!important}.padding-top--lg,.padding-vert--lg{padding-top:2rem!important}.padding-horiz--lg,.padding-left--lg{padding-left:2rem!important}.padding-horiz--lg,.padding-right--lg{padding-right:2rem!important}.padding--lg{padding:2rem!important}.padding-bottom--xl,.padding-vert--xl{padding-bottom:5rem!important}.padding-top--xl,.padding-vert--xl{padding-top:5rem!important}.padding-horiz--xl,.padding-left--xl{padding-left:5rem!important}.padding-horiz--xl,.padding-right--xl{padding-right:5rem!important}.padding--xl{padding:5rem!important}code{background-color:var(--ifm-code-background);border:.1rem solid rgba(0,0,0,.1);border-radius:var(--ifm-code-border-radius);font-family:var(--ifm-font-family-monospace);font-size:var(--ifm-code-font-size);padding:var(--ifm-code-padding-vertical) var(--ifm-code-padding-horizontal)}a code{color:inherit}pre{background-color:var(--ifm-pre-background);border-radius:var(--ifm-pre-border-radius);color:var(--ifm-pre-color);font:var(--ifm-code-font-size)/var(--ifm-pre-line-height) var(--ifm-font-family-monospace);padding:var(--ifm-pre-padding)}pre code{background-color:transparent;border:none;font-size:100%;line-height:inherit;padding:0}kbd{background-color:var(--ifm-color-emphasis-0);border:1px solid var(--ifm-color-emphasis-400);border-radius:.2rem;box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-400);color:var(--ifm-color-emphasis-800);font:80% var(--ifm-font-family-monospace);padding:.15rem .3rem}h1,h2,h3,h4,h5,h6{color:var(--ifm-heading-color);font-family:var(--ifm-heading-font-family);font-weight:var(--ifm-heading-font-weight);line-height:var(--ifm-heading-line-height);margin:var(--ifm-heading-margin-top) 0 var(--ifm-heading-margin-bottom) 0}h1{font-size:var(--ifm-h1-font-size)}h2{font-size:var(--ifm-h2-font-size)}h3{font-size:var(--ifm-h3-font-size)}h4{font-size:var(--ifm-h4-font-size)}h5{font-size:var(--ifm-h5-font-size)}h6{font-size:var(--ifm-h6-font-size)}img{max-width:100%}img[align=right]{padding-left:var(--image-alignment-padding)}img[align=left]{padding-right:var(--image-alignment-padding)}.markdown{--ifm-h1-vertical-rhythm-top:3;--ifm-h2-vertical-rhythm-top:2;--ifm-h3-vertical-rhythm-top:1.5;--ifm-heading-vertical-rhythm-top:1.25;--ifm-h1-vertical-rhythm-bottom:1.25;--ifm-heading-vertical-rhythm-bottom:1}.markdown:after,.markdown:before{content:"";display:table}.markdown:after{clear:both}.markdown h1:first-child{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-h1-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown>h2{--ifm-h2-font-size:2rem;margin-top:calc(var(--ifm-h2-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h3{--ifm-h3-font-size:1.5rem;margin-top:calc(var(--ifm-h3-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h4,.markdown>h5,.markdown>h6{margin-top:calc(var(--ifm-heading-vertical-rhythm-top)*var(--ifm-leading))}.markdown>p,.markdown>pre,.markdown>ul,.tabList__CuJ{margin-bottom:var(--ifm-leading)}.markdown li>p{margin-top:var(--ifm-list-paragraph-margin)}.markdown li+li{margin-top:var(--ifm-list-item-margin)}ol,ul{margin:0 0 var(--ifm-list-margin);padding-left:var(--ifm-list-left-padding)}ol ol,ul ol{list-style-type:lower-roman}ol ol ol,ol ul ol,ul ol ol,ul ul ol{list-style-type:lower-alpha}table{border-collapse:collapse;display:block;margin-bottom:var(--ifm-spacing-vertical)}table thead tr{border-bottom:2px solid var(--ifm-table-border-color)}table thead,table tr:nth-child(2n){background-color:var(--ifm-table-stripe-background)}table tr{background-color:var(--ifm-table-background);border-top:var(--ifm-table-border-width) solid var(--ifm-table-border-color)}table td,table th{border:var(--ifm-table-border-width) solid var(--ifm-table-border-color);padding:var(--ifm-table-cell-padding)}table th{background-color:var(--ifm-table-head-background);color:var(--ifm-table-head-color);font-weight:var(--ifm-table-head-font-weight)}table td{color:var(--ifm-table-cell-color)}strong{font-weight:var(--ifm-font-weight-bold)}a{color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}a:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button:hover,.text--no-decoration,.text--no-decoration:hover,a:not([href]){text-decoration:none}p{margin:0 0 var(--ifm-paragraph-margin-bottom)}blockquote{border-left:var(--ifm-blockquote-border-left-width) solid var(--ifm-blockquote-border-color);box-shadow:var(--ifm-blockquote-shadow);color:var(--ifm-blockquote-color);font-size:var(--ifm-blockquote-font-size);padding:var(--ifm-blockquote-padding-vertical) var(--ifm-blockquote-padding-horizontal)}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}hr{background-color:var(--ifm-hr-background-color);border:0;height:var(--ifm-hr-height);margin:var(--ifm-hr-margin-vertical) 0}.shadow--lw{box-shadow:var(--ifm-global-shadow-lw)!important}.shadow--md{box-shadow:var(--ifm-global-shadow-md)!important}.shadow--tl{box-shadow:var(--ifm-global-shadow-tl)!important}.text--primary,.wordWrapButtonEnabled_EoeP .wordWrapButtonIcon_Bwma{color:var(--ifm-color-primary)}.text--secondary{color:var(--ifm-color-secondary)}.text--success{color:var(--ifm-color-success)}.text--info{color:var(--ifm-color-info)}.text--warning{color:var(--ifm-color-warning)}.text--danger{color:var(--ifm-color-danger)}.text--center{text-align:center}.text--left{text-align:left}.text--justify{text-align:justify}.text--right{text-align:right}.text--capitalize{text-transform:capitalize}.text--lowercase{text-transform:lowercase}.admonitionHeading_tbUL,.alert__heading,.text--uppercase{text-transform:uppercase}.text--light{font-weight:var(--ifm-font-weight-light)}.text--normal{font-weight:var(--ifm-font-weight-normal)}.text--semibold{font-weight:var(--ifm-font-weight-semibold)}.text--bold{font-weight:var(--ifm-font-weight-bold)}.text--italic{font-style:italic}.text--truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text--break{word-wrap:break-word!important;word-break:break-word!important}.clean-btn{background:none;border:none;color:inherit;cursor:pointer;font-family:inherit;padding:0}.alert,.alert .close{color:var(--ifm-alert-foreground-color)}.clean-list{list-style:none;padding-left:0}.alert--primary{--ifm-alert-background-color:var(--ifm-color-primary-contrast-background);--ifm-alert-background-color-highlight:rgba(53,120,229,.15);--ifm-alert-foreground-color:var(--ifm-color-primary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-primary-dark)}.alert--secondary{--ifm-alert-background-color:var(--ifm-color-secondary-contrast-background);--ifm-alert-background-color-highlight:rgba(235,237,240,.15);--ifm-alert-foreground-color:var(--ifm-color-secondary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-secondary-dark)}.alert--success{--ifm-alert-background-color:var(--ifm-color-success-contrast-background);--ifm-alert-background-color-highlight:rgba(0,164,0,.15);--ifm-alert-foreground-color:var(--ifm-color-success-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-success-dark)}.alert--info{--ifm-alert-background-color:var(--ifm-color-info-contrast-background);--ifm-alert-background-color-highlight:rgba(84,199,236,.15);--ifm-alert-foreground-color:var(--ifm-color-info-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-info-dark)}.alert--warning{--ifm-alert-background-color:var(--ifm-color-warning-contrast-background);--ifm-alert-background-color-highlight:rgba(255,186,0,.15);--ifm-alert-foreground-color:var(--ifm-color-warning-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-warning-dark)}.alert--danger{--ifm-alert-background-color:var(--ifm-color-danger-contrast-background);--ifm-alert-background-color-highlight:rgba(250,56,62,.15);--ifm-alert-foreground-color:var(--ifm-color-danger-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-danger-dark)}.alert{--ifm-code-background:var(--ifm-alert-background-color-highlight);--ifm-link-color:var(--ifm-alert-foreground-color);--ifm-link-hover-color:var(--ifm-alert-foreground-color);--ifm-link-decoration:underline;--ifm-tabs-color:var(--ifm-alert-foreground-color);--ifm-tabs-color-active:var(--ifm-alert-foreground-color);--ifm-tabs-color-active-border:var(--ifm-alert-border-color);background-color:var(--ifm-alert-background-color);border:var(--ifm-alert-border-width) solid var(--ifm-alert-border-color);border-left-width:var(--ifm-alert-border-left-width);border-radius:var(--ifm-alert-border-radius);box-shadow:var(--ifm-alert-shadow);padding:var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal)}.alert__heading{align-items:center;display:flex;font:700 var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.5rem}.alert__icon{display:inline-flex;margin-right:.4em}.alert__icon svg{fill:var(--ifm-alert-foreground-color);stroke:var(--ifm-alert-foreground-color);stroke-width:0}.alert .close{margin:calc(var(--ifm-alert-padding-vertical)*-1) calc(var(--ifm-alert-padding-horizontal)*-1) 0 0;opacity:.75}.alert .close:focus,.alert .close:hover{opacity:1}.alert a{-webkit-text-decoration-color:var(--ifm-alert-border-color);text-decoration-color:var(--ifm-alert-border-color)}.alert a:hover{text-decoration-thickness:2px}.avatar{column-gap:var(--ifm-avatar-intro-margin);display:flex}.avatar__photo{border-radius:50%;display:block;height:var(--ifm-avatar-photo-size);overflow:hidden;width:var(--ifm-avatar-photo-size)}.card--full-height,.navbar__logo img,body,html{height:100%}.avatar__photo--sm{--ifm-avatar-photo-size:2rem}.avatar__photo--lg{--ifm-avatar-photo-size:4rem}.avatar__photo--xl{--ifm-avatar-photo-size:6rem}.avatar__intro{display:flex;flex:1 1;flex-direction:column;justify-content:center;text-align:var(--ifm-avatar-intro-alignment)}.badge,.breadcrumbs__item,.breadcrumbs__link,.button,.dropdown>.navbar__link:after{display:inline-block}.avatar__name{font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base)}.avatar__subtitle{margin-top:.25rem}.avatar--vertical{--ifm-avatar-intro-alignment:center;--ifm-avatar-intro-margin:0.5rem;align-items:center;flex-direction:column}.badge{background-color:var(--ifm-badge-background-color);border:var(--ifm-badge-border-width) solid var(--ifm-badge-border-color);border-radius:var(--ifm-badge-border-radius);color:var(--ifm-badge-color);font-size:75%;font-weight:var(--ifm-font-weight-bold);line-height:1;padding:var(--ifm-badge-padding-vertical) var(--ifm-badge-padding-horizontal)}.badge--primary{--ifm-badge-background-color:var(--ifm-color-primary)}.badge--secondary{--ifm-badge-background-color:var(--ifm-color-secondary);color:var(--ifm-color-black)}.breadcrumbs__link,.button.button--secondary.button--outline:not(.button--active):not(:hover){color:var(--ifm-font-color-base)}.badge--success{--ifm-badge-background-color:var(--ifm-color-success)}.badge--info{--ifm-badge-background-color:var(--ifm-color-info)}.badge--warning{--ifm-badge-background-color:var(--ifm-color-warning)}.badge--danger{--ifm-badge-background-color:var(--ifm-color-danger)}.breadcrumbs{margin-bottom:0;padding-left:0}.breadcrumbs__item:not(:last-child):after{background:var(--ifm-breadcrumb-separator) center;content:" ";display:inline-block;filter:var(--ifm-breadcrumb-separator-filter);height:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));margin:0 var(--ifm-breadcrumb-spacing);opacity:.5;width:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier))}.breadcrumbs__item--active .breadcrumbs__link{background:var(--ifm-breadcrumb-item-background-active);color:var(--ifm-breadcrumb-color-active)}.breadcrumbs__link{border-radius:var(--ifm-breadcrumb-border-radius);font-size:calc(1rem*var(--ifm-breadcrumb-size-multiplier));padding:calc(var(--ifm-breadcrumb-padding-vertical)*var(--ifm-breadcrumb-size-multiplier)) calc(var(--ifm-breadcrumb-padding-horizontal)*var(--ifm-breadcrumb-size-multiplier));transition-duration:var(--ifm-transition-fast);transition-property:background,color}.breadcrumbs__link:link:hover,.breadcrumbs__link:visited:hover,area.breadcrumbs__link[href]:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs__link:-webkit-any-link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs__link:any-link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs--sm{--ifm-breadcrumb-size-multiplier:0.8}.breadcrumbs--lg{--ifm-breadcrumb-size-multiplier:1.2}.button{background-color:var(--ifm-button-background-color);border:var(--ifm-button-border-width) solid var(--ifm-button-border-color);border-radius:var(--ifm-button-border-radius);cursor:pointer;font-size:calc(.875rem*var(--ifm-button-size-multiplier));font-weight:var(--ifm-button-font-weight);line-height:1.5;padding:calc(var(--ifm-button-padding-vertical)*var(--ifm-button-size-multiplier)) calc(var(--ifm-button-padding-horizontal)*var(--ifm-button-size-multiplier));text-align:center;transition-duration:var(--ifm-button-transition-duration);transition-property:color,background,border-color;-webkit-user-select:none;-ms-user-select:none;user-select:none;white-space:nowrap}.DocSearch-Button,.playground_CMhS{-webkit-user-select:none;-ms-user-select:none}.button,.button:hover{color:var(--ifm-button-color)}.button--outline{--ifm-button-color:var(--ifm-button-border-color)}.button--outline:hover{--ifm-button-background-color:var(--ifm-button-border-color)}.button--link{--ifm-button-border-color:transparent;color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}.button--link.button--active,.button--link:active,.button--link:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button.disabled,.button:disabled,.button[disabled]{opacity:.65;pointer-events:none}.button--sm{--ifm-button-size-multiplier:0.8}.button--lg{--ifm-button-size-multiplier:1.35}.button--block,.furion-contributor-item img{display:block;width:100%}.button.button--secondary{color:var(--ifm-color-gray-900)}:where(.button--primary){--ifm-button-background-color:var(--ifm-color-primary);--ifm-button-border-color:var(--ifm-color-primary)}:where(.button--primary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-primary-dark);--ifm-button-border-color:var(--ifm-color-primary-dark)}.button--primary.button--active,.button--primary:active{--ifm-button-background-color:var(--ifm-color-primary-darker);--ifm-button-border-color:var(--ifm-color-primary-darker)}:where(.button--secondary){--ifm-button-background-color:var(--ifm-color-secondary);--ifm-button-border-color:var(--ifm-color-secondary)}:where(.button--secondary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-secondary-dark);--ifm-button-border-color:var(--ifm-color-secondary-dark)}.button--secondary.button--active,.button--secondary:active{--ifm-button-background-color:var(--ifm-color-secondary-darker);--ifm-button-border-color:var(--ifm-color-secondary-darker)}:where(.button--success){--ifm-button-background-color:var(--ifm-color-success);--ifm-button-border-color:var(--ifm-color-success)}:where(.button--success):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-success-dark);--ifm-button-border-color:var(--ifm-color-success-dark)}.button--success.button--active,.button--success:active{--ifm-button-background-color:var(--ifm-color-success-darker);--ifm-button-border-color:var(--ifm-color-success-darker)}:where(.button--info){--ifm-button-background-color:var(--ifm-color-info);--ifm-button-border-color:var(--ifm-color-info)}:where(.button--info):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-info-dark);--ifm-button-border-color:var(--ifm-color-info-dark)}.button--info.button--active,.button--info:active{--ifm-button-background-color:var(--ifm-color-info-darker);--ifm-button-border-color:var(--ifm-color-info-darker)}:where(.button--warning){--ifm-button-background-color:var(--ifm-color-warning);--ifm-button-border-color:var(--ifm-color-warning)}:where(.button--warning):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-warning-dark);--ifm-button-border-color:var(--ifm-color-warning-dark)}.button--warning.button--active,.button--warning:active{--ifm-button-background-color:var(--ifm-color-warning-darker);--ifm-button-border-color:var(--ifm-color-warning-darker)}:where(.button--danger){--ifm-button-background-color:var(--ifm-color-danger);--ifm-button-border-color:var(--ifm-color-danger)}:where(.button--danger):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-danger-dark);--ifm-button-border-color:var(--ifm-color-danger-dark)}.button--danger.button--active,.button--danger:active{--ifm-button-background-color:var(--ifm-color-danger-darker);--ifm-button-border-color:var(--ifm-color-danger-darker)}.button-group{display:inline-flex;gap:var(--ifm-button-group-spacing)}.button-group>.button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.button-group>.button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.button-group--block{display:flex;justify-content:stretch}.button-group--block>.button{flex-grow:1}.card{background-color:var(--ifm-card-background-color);border-radius:var(--ifm-card-border-radius);box-shadow:var(--ifm-global-shadow-lw);display:flex;flex-direction:column;overflow:hidden}.card__image{padding-top:var(--ifm-card-vertical-spacing)}.card__image:first-child{padding-top:0}.card__body,.card__footer,.card__header{padding:var(--ifm-card-vertical-spacing) var(--ifm-card-horizontal-spacing)}.card__body:not(:last-child),.card__footer:not(:last-child),.card__header:not(:last-child){padding-bottom:0}.card__body>:last-child,.card__footer>:last-child,.card__header>:last-child{margin-bottom:0}.card__footer{margin-top:auto}.table-of-contents{font-size:.8rem;margin-bottom:0;padding:var(--ifm-toc-padding-vertical) 0}.table-of-contents,.table-of-contents ul{list-style:none;padding-left:var(--ifm-toc-padding-horizontal)}.table-of-contents li{margin:var(--ifm-toc-padding-vertical) var(--ifm-toc-padding-horizontal)}.table-of-contents__left-border{border-left:1px solid var(--ifm-toc-border-color)}.table-of-contents__link{color:var(--ifm-toc-link-color);display:block}.table-of-contents__link--active,.table-of-contents__link--active code,.table-of-contents__link:hover,.table-of-contents__link:hover code{color:var(--ifm-color-primary);text-decoration:none}.close{color:var(--ifm-color-black);float:right;font-size:1.5rem;font-weight:var(--ifm-font-weight-bold);line-height:1;opacity:.5;padding:1rem;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.close:hover{opacity:.7}.close:focus,.theme-code-block-highlighted-line .codeLineNumber_Tfdd:before{opacity:.8}.dropdown{display:inline-flex;font-weight:var(--ifm-dropdown-font-weight);position:relative;vertical-align:top}.dropdown--hoverable:hover .dropdown__menu,.dropdown--show .dropdown__menu{opacity:1;pointer-events:all;transform:translateY(-1px);visibility:visible}#nprogress,.dropdown__menu,.navbar__item.dropdown .navbar__link:not([href]){pointer-events:none}.dropdown--right .dropdown__menu{left:inherit;right:0}.dropdown--nocaret .navbar__link:after{content:none!important}.dropdown__menu{background-color:var(--ifm-dropdown-background-color);border-radius:var(--ifm-global-radius);box-shadow:var(--ifm-global-shadow-md);left:0;list-style:none;max-height:80vh;min-width:10rem;opacity:0;overflow-y:auto;padding:.5rem;position:absolute;top:calc(100% - var(--ifm-navbar-item-padding-vertical) + .3rem);transform:translateY(-.625rem);transition-duration:var(--ifm-transition-fast);transition-property:opacity,transform,visibility;transition-timing-function:var(--ifm-transition-timing-default);visibility:hidden;z-index:var(--ifm-z-index-dropdown)}.menu__caret,.menu__link,.menu__list-item-collapsible{border-radius:.25rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.dropdown__link{border-radius:.25rem;color:var(--ifm-dropdown-link-color);display:block;font-size:.875rem;margin-top:.2rem;padding:.25rem .5rem;white-space:nowrap}.dropdown__link--active,.dropdown__link:hover{background-color:var(--ifm-dropdown-hover-background-color);color:var(--ifm-dropdown-link-color);text-decoration:none}.dropdown__link--active,.dropdown__link--active:hover{--ifm-dropdown-link-color:var(--ifm-link-color)}.dropdown>.navbar__link:after{border-color:currentcolor transparent;border-style:solid;border-width:.4em .4em 0;content:"";margin-left:.3em;position:relative;top:2px;transform:translateY(-50%)}.footer{background-color:var(--ifm-footer-background-color);color:var(--ifm-footer-color);padding:var(--ifm-footer-padding-vertical) var(--ifm-footer-padding-horizontal)}.footer--dark{--ifm-footer-background-color:#303846;--ifm-footer-color:var(--ifm-footer-link-color);--ifm-footer-link-color:var(--ifm-color-secondary);--ifm-footer-title-color:var(--ifm-color-white)}.footer__links{margin-bottom:1rem}.footer__link-item{color:var(--ifm-footer-link-color);line-height:2}.footer__link-item:hover{color:var(--ifm-footer-link-hover-color)}.footer__link-separator{margin:0 var(--ifm-footer-link-horizontal-spacing)}.footer__logo{margin-top:1rem;max-width:var(--ifm-footer-logo-max-width)}.footer__title{color:var(--ifm-footer-title-color);font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base);margin-bottom:var(--ifm-heading-margin-bottom)}.menu,.navbar__link{font-weight:var(--ifm-font-weight-semibold)}.docItemContainer_Djhp article>:first-child,.docItemContainer_Djhp header+*,.footer__item{margin-top:0}.admonitionContent_S0QG>:last-child,.collapsibleContent_i85q>:last-child,.footer__items,.tabItem_Ymn6>:last-child{margin-bottom:0}.codeBlockStandalone_MEMb,[type=checkbox]{padding:0}.hero{align-items:center;background-color:var(--ifm-hero-background-color);color:var(--ifm-hero-text-color);display:flex;padding:4rem 2rem}.hero--primary{--ifm-hero-background-color:var(--ifm-color-primary);--ifm-hero-text-color:var(--ifm-font-color-base-inverse)}.hero--dark{--ifm-hero-background-color:#303846;--ifm-hero-text-color:var(--ifm-color-white)}.hero__title,.title_f1Hy{font-size:3rem}.hero__subtitle{font-size:1.5rem}.menu__list{list-style:none;margin:0;padding-left:0}.menu__caret,.menu__link{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu__list .menu__list{flex:0 0 100%;margin-top:.25rem;padding-left:var(--ifm-menu-link-padding-horizontal)}.menu__list-item:not(:first-child){margin-top:.25rem}.menu__list-item--collapsed .menu__list{height:0;overflow:hidden}.details_lb9f[data-collapsed=false].isBrowser_bmU9>summary:before,.details_lb9f[open]:not(.isBrowser_bmU9)>summary:before,.menu__list-item--collapsed .menu__caret:before,.menu__list-item--collapsed .menu__link--sublist:after{transform:rotate(90deg)}.menu__list-item-collapsible{display:flex;flex-wrap:wrap;position:relative}.menu__caret:hover,.menu__link:hover,.menu__list-item-collapsible--active,.menu__list-item-collapsible:hover{background:var(--ifm-menu-color-background-hover)}.menu__list-item-collapsible .menu__link--active,.menu__list-item-collapsible .menu__link:hover{background:none!important}.menu__caret,.menu__link{align-items:center;display:flex}.menu__link{color:var(--ifm-menu-color);flex:1;line-height:1.25}.menu__link:hover{color:var(--ifm-menu-color);text-decoration:none}.menu__caret:before,.menu__link--sublist-caret:after{content:"";height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast) linear;width:1.25rem;filter:var(--ifm-menu-link-sublist-icon-filter)}.menu__link--sublist-caret:after{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem;margin-left:auto;min-width:1.25rem}.menu__link--active,.menu__link--active:hover{color:var(--ifm-menu-color-active)}.navbar__brand,.navbar__link{color:var(--ifm-navbar-link-color)}.menu__link--active:not(.menu__link--sublist){background-color:var(--ifm-menu-color-background-active)}.menu__caret:before{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem}.navbar--dark,html[data-theme=dark]{--ifm-menu-link-sublist-icon-filter:invert(100%) sepia(94%) saturate(17%) hue-rotate(223deg) brightness(104%) contrast(98%)}.navbar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.docsWrapper_BCFX,.navbar,.navbar>.container,.navbar>.container-fluid{display:flex}.navbar--fixed-top{position:-webkit-sticky;position:sticky;top:0;z-index:var(--ifm-z-index-fixed)}.navbar-sidebar,.navbar-sidebar__backdrop{bottom:0;left:0;opacity:0;position:fixed;top:0;transition-timing-function:ease-in-out;visibility:hidden}.navbar__inner{display:flex;flex-wrap:wrap;justify-content:space-between;width:100%}.navbar__brand{align-items:center;display:flex;margin-right:1rem;min-width:0}.navbar__brand:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.announcementBarContent_xLdY,.navbar__title{flex:1 1 auto}.navbar__toggle{display:none;margin-right:.5rem}.navbar__logo{flex:0 0 auto;height:2rem;margin-right:.5rem}.navbar__items{align-items:center;display:flex;flex:1;min-width:0}.navbar__items--center{flex:0 0 auto}.navbar__items--center .navbar__brand{margin:0}.furion-banner-item,.navbar__items--center+.navbar__items--right{flex:1}.navbar__items--right{flex:0 0 auto;justify-content:flex-end}.navbar__items--right>:last-child{padding-right:0}.navbar__item{display:inline-block;padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.navbar__link--active,.navbar__link:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar--dark,.navbar--primary{--ifm-menu-color:var(--ifm-color-gray-300);--ifm-navbar-link-color:var(--ifm-color-gray-100);--ifm-navbar-search-input-background-color:hsla(0,0%,100%,.1);--ifm-navbar-search-input-placeholder-color:hsla(0,0%,100%,.5);color:var(--ifm-color-white)}.navbar--dark{--ifm-navbar-background-color:#242526;--ifm-menu-color-background-active:hsla(0,0%,100%,.05);--ifm-navbar-search-input-color:var(--ifm-color-white)}.navbar--primary{--ifm-navbar-background-color:var(--ifm-color-primary);--ifm-navbar-link-hover-color:var(--ifm-color-white);--ifm-menu-color-active:var(--ifm-color-white);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-500)}.navbar__search-input{-webkit-appearance:none;appearance:none;background:var(--ifm-navbar-search-input-background-color) var(--ifm-navbar-search-input-icon) no-repeat .75rem center/1rem 1rem;border:none;border-radius:2rem;color:var(--ifm-navbar-search-input-color);cursor:text;display:inline-block;font-size:.9rem;height:2rem;padding:0 .5rem 0 2.25rem;width:12.5rem}.navbar__search-input:-ms-input-placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar__search-input::placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar-sidebar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-global-shadow-md);transform:translate3d(-100%,0,0);transition-duration:.25s;transition-property:opacity,visibility,transform;width:var(--ifm-navbar-sidebar-width)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar__items{transform:translateZ(0)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar--show .navbar-sidebar__backdrop{opacity:1;visibility:visible}.navbar-sidebar__backdrop{background-color:rgba(0,0,0,.6);right:0;transition-duration:.1s;transition-property:opacity,visibility}.navbar-sidebar__brand{align-items:center;box-shadow:var(--ifm-navbar-shadow);display:flex;flex:1;height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar-sidebar__items{display:flex;height:calc(100% - var(--ifm-navbar-height));transition:transform var(--ifm-transition-fast) ease-in-out}.navbar-sidebar__items--show-secondary{transform:translate3d(calc((var(--ifm-navbar-sidebar-width))*-1),0,0)}.navbar-sidebar__item{flex-shrink:0;padding:.5rem;width:calc(var(--ifm-navbar-sidebar-width))}.navbar-sidebar__back{background:var(--ifm-menu-color-background-active);font-size:15px;font-weight:var(--ifm-button-font-weight);margin:0 0 .2rem -.5rem;padding:.6rem 1.5rem;position:relative;text-align:left;top:-.5rem;width:calc(100% + 1rem)}#nprogress .bar,.modal_wSGk{left:0;top:0;position:fixed}.navbar-sidebar__close{display:flex;margin-left:auto}.pagination{column-gap:var(--ifm-pagination-page-spacing);display:flex;font-size:var(--ifm-pagination-font-size);padding-left:0}.pagination--sm{--ifm-pagination-font-size:0.8rem;--ifm-pagination-padding-horizontal:0.8rem;--ifm-pagination-padding-vertical:0.2rem}.pagination--lg{--ifm-pagination-font-size:1.2rem;--ifm-pagination-padding-horizontal:1.2rem;--ifm-pagination-padding-vertical:0.3rem}.pagination__item{display:inline-flex}.pagination__item>span{padding:var(--ifm-pagination-padding-vertical)}.pagination__item--active .pagination__link{color:var(--ifm-pagination-color-active)}.pagination__item--active .pagination__link,.pagination__item:not(.pagination__item--active):hover .pagination__link{background:var(--ifm-pagination-item-active-background)}.pagination__item--disabled,.pagination__item[disabled]{opacity:.25;pointer-events:none}.pagination__link{border-radius:var(--ifm-pagination-border-radius);color:var(--ifm-font-color-base);display:inline-block;padding:var(--ifm-pagination-padding-vertical) var(--ifm-pagination-padding-horizontal);transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination__link:hover,.sidebarItemLink_mo7H:hover{text-decoration:none}.pagination-nav{grid-gap:var(--ifm-spacing-horizontal);display:grid;gap:var(--ifm-spacing-horizontal);grid-template-columns:repeat(2,1fr)}.pagination-nav__link{border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-pagination-nav-border-radius);display:block;height:100%;line-height:var(--ifm-heading-line-height);padding:var(--ifm-global-spacing);transition:border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination-nav__link:hover{border-color:var(--ifm-pagination-nav-color-hover);text-decoration:none}.DocSearch-Hit[aria-selected=true] mark,.content_knG7 a{text-decoration:underline}.pagination-nav__link--next{grid-column:2/3;text-align:right}.pagination-nav__label{font-size:var(--ifm-h4-font-size);font-weight:var(--ifm-heading-font-weight);word-break:break-word}.pagination-nav__link--prev .pagination-nav__label:before{content:"« "}.pagination-nav__link--next .pagination-nav__label:after{content:" »"}.pagination-nav__sublabel{color:var(--ifm-color-content-secondary);font-size:var(--ifm-h5-font-size);font-weight:var(--ifm-font-weight-semibold);margin-bottom:.25rem}.pills__item,.sidebarItemTitle_pO2u,.tabs{font-weight:var(--ifm-font-weight-bold)}.pills{display:flex;gap:var(--ifm-pills-spacing);padding-left:0}.pills__item{border-radius:.5rem;cursor:pointer;display:inline-block;padding:.25rem 1rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs,:not(.containsTaskList_mC6p>li)>.containsTaskList_mC6p{padding-left:0}.pills__item--active{color:var(--ifm-pills-color-active)}.pills__item--active,.pills__item:not(.pills__item--active):hover{background:var(--ifm-pills-color-background-active)}.pills--block{justify-content:stretch}.pills--block .pills__item{flex-grow:1;text-align:center}.tabs{color:var(--ifm-tabs-color);display:flex;margin-bottom:0;overflow-x:auto}.tabs__item{border-bottom:3px solid transparent;border-radius:var(--ifm-global-radius);cursor:pointer;display:inline-flex;padding:var(--ifm-tabs-padding-vertical) var(--ifm-tabs-padding-horizontal);transition:background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs__item--active{border-bottom-color:var(--ifm-tabs-color-active-border);border-bottom-left-radius:0;border-bottom-right-radius:0;color:var(--ifm-tabs-color-active)}.tabs__item:hover{background-color:var(--ifm-hover-overlay)}.tabs--block{justify-content:stretch}.tabs--block .tabs__item{flex-grow:1;justify-content:center}html[data-theme=dark]{--ifm-color-scheme:dark;--ifm-color-emphasis-0:var(--ifm-color-gray-1000);--ifm-color-emphasis-100:var(--ifm-color-gray-900);--ifm-color-emphasis-200:var(--ifm-color-gray-800);--ifm-color-emphasis-300:var(--ifm-color-gray-700);--ifm-color-emphasis-400:var(--ifm-color-gray-600);--ifm-color-emphasis-600:var(--ifm-color-gray-400);--ifm-color-emphasis-700:var(--ifm-color-gray-300);--ifm-color-emphasis-800:var(--ifm-color-gray-200);--ifm-color-emphasis-900:var(--ifm-color-gray-100);--ifm-color-emphasis-1000:var(--ifm-color-gray-0);--ifm-background-color:#1b1b1d;--ifm-background-surface-color:#242526;--ifm-hover-overlay:hsla(0,0%,100%,.05);--ifm-color-content:#e3e3e3;--ifm-color-content-secondary:#fff;--ifm-breadcrumb-separator-filter:invert(64%) sepia(11%) saturate(0%) hue-rotate(149deg) brightness(99%) contrast(95%);--ifm-code-background:hsla(0,0%,100%,.1);--ifm-scrollbar-track-background-color:#444;--ifm-scrollbar-thumb-background-color:#686868;--ifm-scrollbar-thumb-hover-background-color:#7a7a7a;--ifm-table-stripe-background:hsla(0,0%,100%,.07);--ifm-toc-border-color:var(--ifm-color-emphasis-200);--ifm-color-primary-contrast-background:#102445;--ifm-color-primary-contrast-foreground:#ebf2fc;--ifm-color-secondary-contrast-background:#474748;--ifm-color-secondary-contrast-foreground:#fdfdfe;--ifm-color-success-contrast-background:#003100;--ifm-color-success-contrast-foreground:#e6f6e6;--ifm-color-info-contrast-background:#193c47;--ifm-color-info-contrast-foreground:#eef9fd;--ifm-color-warning-contrast-background:#4d3800;--ifm-color-warning-contrast-foreground:#fff8e6;--ifm-color-danger-contrast-background:#4b1113;--ifm-color-danger-contrast-foreground:#ffebec;--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,.3);--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}#nprogress .bar{background:var(--docusaurus-progress-bar-color);height:2px;width:100%;z-index:1031}#nprogress .peg{box-shadow:0 0 10px var(--docusaurus-progress-bar-color),0 0 5px var(--docusaurus-progress-bar-color);height:100%;opacity:1;position:absolute;right:0;transform:rotate(3deg) translateY(-4px);width:100px}.docusaurus-highlight-code-line{background-color:#484d5b;display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.animate__animated{animation-duration:1s;animation-duration:var(--animate-duration);animation-fill-mode:both}.animate__animated.animate__infinite{animation-iteration-count:infinite}.animate__animated.animate__repeat-1{animation-iteration-count:1;animation-iteration-count:var(--animate-repeat)}.animate__animated.animate__repeat-2{animation-iteration-count:2;animation-iteration-count:calc(var(--animate-repeat)*2)}.animate__animated.animate__repeat-3{animation-iteration-count:3;animation-iteration-count:calc(var(--animate-repeat)*3)}.animate__animated.animate__delay-1s{animation-delay:1s;animation-delay:var(--animate-delay)}.animate__animated.animate__delay-2s{animation-delay:2s;animation-delay:calc(var(--animate-delay)*2)}.animate__animated.animate__delay-3s{animation-delay:3s;animation-delay:calc(var(--animate-delay)*3)}.animate__animated.animate__delay-4s{animation-delay:4s;animation-delay:calc(var(--animate-delay)*4)}.animate__animated.animate__delay-5s{animation-delay:5s;animation-delay:calc(var(--animate-delay)*5)}.animate__animated.animate__faster{animation-duration:.5s;animation-duration:calc(var(--animate-duration)/2)}.animate__animated.animate__fast{animation-duration:.8s;animation-duration:calc(var(--animate-duration)*.8)}.animate__animated.animate__slow{animation-duration:2s;animation-duration:calc(var(--animate-duration)*2)}.animate__animated.animate__slower{animation-duration:3s;animation-duration:calc(var(--animate-duration)*3)}@keyframes a{0%,20%,53%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1);transform:translateZ(0)}40%,43%{animation-timing-function:cubic-bezier(.755,.05,.855,.06);transform:translate3d(0,-30px,0) scaleY(1.1)}70%{animation-timing-function:cubic-bezier(.755,.05,.855,.06);transform:translate3d(0,-15px,0) scaleY(1.05)}80%{transform:translateZ(0) scaleY(.95);transition-timing-function:cubic-bezier(.215,.61,.355,1)}90%{transform:translate3d(0,-4px,0) scaleY(1.02)}}.animate__bounce{animation-name:a;transform-origin:center bottom}@keyframes b{0%,50%,to{opacity:1}25%,75%{opacity:0}}.animate__flash{animation-name:b}@keyframes c{0%,to{transform:scaleX(1)}50%{transform:scale3d(1.05,1.05,1.05)}}.animate__pulse{animation-name:c}@keyframes d{0%,to{transform:scaleX(1)}30%{transform:scale3d(1.25,.75,1)}40%{transform:scale3d(.75,1.25,1)}50%{transform:scale3d(1.15,.85,1)}65%{transform:scale3d(.95,1.05,1)}75%{transform:scale3d(1.05,.95,1)}}.animate__rubberBand{animation-name:d}@keyframes e{0%,to{transform:translateZ(0)}10%,30%,50%,70%,90%{transform:translate3d(-10px,0,0)}20%,40%,60%,80%{transform:translate3d(10px,0,0)}}.animate__shakeX{animation-name:e}@keyframes f{0%,to{transform:translateZ(0)}10%,30%,50%,70%,90%{transform:translate3d(0,-10px,0)}20%,40%,60%,80%{transform:translate3d(0,10px,0)}}.animate__shakeY{animation-name:f}@keyframes g{0%,50%{transform:translateX(0)}6.5%{transform:translateX(-6px) rotateY(-9deg)}18.5%{transform:translateX(5px) rotateY(7deg)}31.5%{transform:translateX(-3px) rotateY(-5deg)}43.5%{transform:translateX(2px) rotateY(3deg)}}.animate__headShake{animation-name:g}@keyframes h{20%{transform:rotate(15deg)}40%{transform:rotate(-10deg)}60%{transform:rotate(5deg)}80%{transform:rotate(-5deg)}to{transform:rotate(0)}}.animate__swing{animation-name:h;transform-origin:top center}@keyframes i{0%,to{transform:scaleX(1)}10%,20%{transform:scale3d(.9,.9,.9) rotate(-3deg)}30%,50%,70%,90%{transform:scale3d(1.1,1.1,1.1) rotate(3deg)}40%,60%,80%{transform:scale3d(1.1,1.1,1.1) rotate(-3deg)}}.animate__tada{animation-name:i}@keyframes j{0%,to{transform:translateZ(0)}15%{transform:translate3d(-25%,0,0) rotate(-5deg)}30%{transform:translate3d(20%,0,0) rotate(3deg)}45%{transform:translate3d(-15%,0,0) rotate(-3deg)}60%{transform:translate3d(10%,0,0) rotate(2deg)}75%{transform:translate3d(-5%,0,0) rotate(-1deg)}}.animate__wobble{animation-name:j}@keyframes k{0%,11.1%,to{transform:translateZ(0)}22.2%{transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{transform:skewX(6.25deg) skewY(6.25deg)}44.4%{transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{transform:skewX(-.78125deg) skewY(-.78125deg)}77.7%{transform:skewX(.390625deg) skewY(.390625deg)}88.8%{transform:skewX(-.1953125deg) skewY(-.1953125deg)}}.animate__jello{animation-name:k;transform-origin:center}@keyframes l{0%,28%,70%{transform:scale(1)}14%,42%{transform:scale(1.3)}}.animate__heartBeat{animation-duration:1.3s;animation-duration:calc(var(--animate-duration)*1.3);animation-name:l}@keyframes m{0%{opacity:.7;transform:translateY(-1200px) scale(.7)}80%{opacity:.7;transform:translateY(0) scale(.7)}to{opacity:1;transform:scale(1)}}.animate__backInDown{animation-name:m}@keyframes n{0%{opacity:.7;transform:translateX(-2000px) scale(.7)}80%{opacity:.7;transform:translateX(0) scale(.7)}to{opacity:1;transform:scale(1)}}.animate__backInLeft{animation-name:n}@keyframes o{0%{opacity:.7;transform:translateX(2000px) scale(.7)}80%{opacity:.7;transform:translateX(0) scale(.7)}to{opacity:1;transform:scale(1)}}.animate__backInRight{animation-name:o}@keyframes p{0%{opacity:.7;transform:translateY(1200px) scale(.7)}80%{opacity:.7;transform:translateY(0) scale(.7)}to{opacity:1;transform:scale(1)}}.animate__backInUp{animation-name:p}@keyframes q{0%{opacity:1;transform:scale(1)}20%{opacity:.7;transform:translateY(0) scale(.7)}to{opacity:.7;transform:translateY(700px) scale(.7)}}.animate__backOutDown{animation-name:q}@keyframes r{0%{opacity:1;transform:scale(1)}20%{opacity:.7;transform:translateX(0) scale(.7)}to{opacity:.7;transform:translateX(-2000px) scale(.7)}}.animate__backOutLeft{animation-name:r}@keyframes s{0%{opacity:1;transform:scale(1)}20%{opacity:.7;transform:translateX(0) scale(.7)}to{opacity:.7;transform:translateX(2000px) scale(.7)}}.animate__backOutRight{animation-name:s}@keyframes t{0%{opacity:1;transform:scale(1)}20%{opacity:.7;transform:translateY(0) scale(.7)}to{opacity:.7;transform:translateY(-700px) scale(.7)}}.animate__backOutUp{animation-name:t}@keyframes u{0%,20%,40%,60%,80%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:scale3d(.3,.3,.3)}20%{transform:scale3d(1.1,1.1,1.1)}40%{transform:scale3d(.9,.9,.9)}60%{opacity:1;transform:scale3d(1.03,1.03,1.03)}80%{transform:scale3d(.97,.97,.97)}to{opacity:1;transform:scaleX(1)}}.animate__bounceIn{animation-duration:.75s;animation-duration:calc(var(--animate-duration)*.75);animation-name:u}@keyframes v{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,-3000px,0) scaleY(3)}60%{opacity:1;transform:translate3d(0,25px,0) scaleY(.9)}75%{transform:translate3d(0,-10px,0) scaleY(.95)}90%{transform:translate3d(0,5px,0) scaleY(.985)}to{transform:translateZ(0)}}.animate__bounceInDown{animation-name:v}@keyframes w{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(-3000px,0,0) scaleX(3)}60%{opacity:1;transform:translate3d(25px,0,0) scaleX(1)}75%{transform:translate3d(-10px,0,0) scaleX(.98)}90%{transform:translate3d(5px,0,0) scaleX(.995)}to{transform:translateZ(0)}}.animate__bounceInLeft{animation-name:w}@keyframes x{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(3000px,0,0) scaleX(3)}60%{opacity:1;transform:translate3d(-25px,0,0) scaleX(1)}75%{transform:translate3d(10px,0,0) scaleX(.98)}90%{transform:translate3d(-5px,0,0) scaleX(.995)}to{transform:translateZ(0)}}.animate__bounceInRight{animation-name:x}@keyframes y{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,3000px,0) scaleY(5)}60%{opacity:1;transform:translate3d(0,-20px,0) scaleY(.9)}75%{transform:translate3d(0,10px,0) scaleY(.95)}90%{transform:translate3d(0,-5px,0) scaleY(.985)}to{transform:translateZ(0)}}.animate__bounceInUp{animation-name:y}@keyframes z{20%{transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;transform:scale3d(1.1,1.1,1.1)}to{opacity:0;transform:scale3d(.3,.3,.3)}}.animate__bounceOut{animation-duration:.75s;animation-duration:calc(var(--animate-duration)*.75);animation-name:z}@keyframes A{20%{transform:translate3d(0,10px,0) scaleY(.985)}40%,45%{opacity:1;transform:translate3d(0,-20px,0) scaleY(.9)}to{opacity:0;transform:translate3d(0,2000px,0) scaleY(3)}}.animate__bounceOutDown{animation-name:A}@keyframes B{20%{opacity:1;transform:translate3d(20px,0,0) scaleX(.9)}to{opacity:0;transform:translate3d(-2000px,0,0) scaleX(2)}}.animate__bounceOutLeft{animation-name:B}@keyframes C{20%{opacity:1;transform:translate3d(-20px,0,0) scaleX(.9)}to{opacity:0;transform:translate3d(2000px,0,0) scaleX(2)}}.animate__bounceOutRight{animation-name:C}@keyframes D{20%{transform:translate3d(0,-10px,0) scaleY(.985)}40%,45%{opacity:1;transform:translate3d(0,20px,0) scaleY(.9)}to{opacity:0;transform:translate3d(0,-2000px,0) scaleY(3)}}.animate__bounceOutUp{animation-name:D}.animate__fadeIn{animation-name:Ra}@keyframes E{0%{opacity:0;transform:translate3d(0,-100%,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInDown{animation-name:E}@keyframes F{0%{opacity:0;transform:translate3d(0,-2000px,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInDownBig{animation-name:F}@keyframes G{0%{opacity:0;transform:translate3d(-100%,0,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInLeft{animation-name:G}@keyframes H{0%{opacity:0;transform:translate3d(-2000px,0,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInLeftBig{animation-name:H}@keyframes I{0%{opacity:0;transform:translate3d(100%,0,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInRight{animation-name:I}@keyframes J{0%{opacity:0;transform:translate3d(2000px,0,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInRightBig{animation-name:J}@keyframes K{0%{opacity:0;transform:translate3d(0,100%,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInUp{animation-name:K}@keyframes L{0%{opacity:0;transform:translate3d(0,2000px,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInUpBig{animation-name:L}@keyframes M{0%{opacity:0;transform:translate3d(-100%,-100%,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInTopLeft{animation-name:M}@keyframes N{0%{opacity:0;transform:translate3d(100%,-100%,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInTopRight{animation-name:N}@keyframes O{0%{opacity:0;transform:translate3d(-100%,100%,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInBottomLeft{animation-name:O}@keyframes P{0%{opacity:0;transform:translate3d(100%,100%,0)}to{opacity:1;transform:translateZ(0)}}.animate__fadeInBottomRight{animation-name:P}@keyframes Q{0%{opacity:1}to{opacity:0}}.animate__fadeOut{animation-name:Q}@keyframes R{0%{opacity:1}to{opacity:0;transform:translate3d(0,100%,0)}}.animate__fadeOutDown{animation-name:R}@keyframes S{0%{opacity:1}to{opacity:0;transform:translate3d(0,2000px,0)}}.animate__fadeOutDownBig{animation-name:S}@keyframes T{0%{opacity:1}to{opacity:0;transform:translate3d(-100%,0,0)}}.animate__fadeOutLeft{animation-name:T}@keyframes U{0%{opacity:1}to{opacity:0;transform:translate3d(-2000px,0,0)}}.animate__fadeOutLeftBig{animation-name:U}@keyframes V{0%{opacity:1}to{opacity:0;transform:translate3d(100%,0,0)}}.animate__fadeOutRight{animation-name:V}@keyframes W{0%{opacity:1}to{opacity:0;transform:translate3d(2000px,0,0)}}.animate__fadeOutRightBig{animation-name:W}@keyframes X{0%{opacity:1}to{opacity:0;transform:translate3d(0,-100%,0)}}.animate__fadeOutUp{animation-name:X}@keyframes Y{0%{opacity:1}to{opacity:0;transform:translate3d(0,-2000px,0)}}.animate__fadeOutUpBig{animation-name:Y}@keyframes Z{0%{opacity:1;transform:translateZ(0)}to{opacity:0;transform:translate3d(-100%,-100%,0)}}.animate__fadeOutTopLeft{animation-name:Z}@keyframes aa{0%{opacity:1;transform:translateZ(0)}to{opacity:0;transform:translate3d(100%,-100%,0)}}.animate__fadeOutTopRight{animation-name:aa}@keyframes ba{0%{opacity:1;transform:translateZ(0)}to{opacity:0;transform:translate3d(100%,100%,0)}}.animate__fadeOutBottomRight{animation-name:ba}@keyframes ca{0%{opacity:1;transform:translateZ(0)}to{opacity:0;transform:translate3d(-100%,100%,0)}}.animate__fadeOutBottomLeft{animation-name:ca}@keyframes da{0%{animation-timing-function:ease-out;transform:perspective(400px) scaleX(1) translateZ(0) rotateY(-1turn)}40%{animation-timing-function:ease-out;transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-190deg)}50%{animation-timing-function:ease-in;transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-170deg)}80%{animation-timing-function:ease-in;transform:perspective(400px) scale3d(.95,.95,.95) translateZ(0) rotateY(0)}to{animation-timing-function:ease-in;transform:perspective(400px) scaleX(1) translateZ(0) rotateY(0)}}.animate__animated.animate__flip{animation-name:da;-webkit-backface-visibility:visible;backface-visibility:visible}@keyframes ea{0%{animation-timing-function:ease-in;opacity:0;transform:perspective(400px) rotateX(90deg)}40%{animation-timing-function:ease-in;transform:perspective(400px) rotateX(-20deg)}60%{opacity:1;transform:perspective(400px) rotateX(10deg)}80%{transform:perspective(400px) rotateX(-5deg)}to{transform:perspective(400px)}}.animate__flipInX{animation-name:ea;-webkit-backface-visibility:visible!important;backface-visibility:visible!important}.animate__flipInY,.animate__flipOutX{-webkit-backface-visibility:visible!important}@keyframes fa{0%{animation-timing-function:ease-in;opacity:0;transform:perspective(400px) rotateY(90deg)}40%{animation-timing-function:ease-in;transform:perspective(400px) rotateY(-20deg)}60%{opacity:1;transform:perspective(400px) rotateY(10deg)}80%{transform:perspective(400px) rotateY(-5deg)}to{transform:perspective(400px)}}.animate__flipInY{animation-name:fa;backface-visibility:visible!important}@keyframes ga{0%{transform:perspective(400px)}30%{opacity:1;transform:perspective(400px) rotateX(-20deg)}to{opacity:0;transform:perspective(400px) rotateX(90deg)}}.animate__flipOutX{animation-duration:.75s;animation-duration:calc(var(--animate-duration)*.75);animation-name:ga;backface-visibility:visible!important}@keyframes ha{0%{transform:perspective(400px)}30%{opacity:1;transform:perspective(400px) rotateY(-15deg)}to{opacity:0;transform:perspective(400px) rotateY(90deg)}}.animate__flipOutY{animation-duration:.75s;animation-duration:calc(var(--animate-duration)*.75);animation-name:ha;-webkit-backface-visibility:visible!important;backface-visibility:visible!important}@keyframes ia{0%{opacity:0;transform:translate3d(100%,0,0) skewX(-30deg)}60%{opacity:1;transform:skewX(20deg)}80%{transform:skewX(-5deg)}to{transform:translateZ(0)}}.animate__lightSpeedInRight{animation-name:ia;animation-timing-function:ease-out}@keyframes ja{0%{opacity:0;transform:translate3d(-100%,0,0) skewX(30deg)}60%{opacity:1;transform:skewX(-20deg)}80%{transform:skewX(5deg)}to{transform:translateZ(0)}}.animate__lightSpeedInLeft{animation-name:ja;animation-timing-function:ease-out}@keyframes ka{0%{opacity:1}to{opacity:0;transform:translate3d(100%,0,0) skewX(30deg)}}.animate__lightSpeedOutRight{animation-name:ka;animation-timing-function:ease-in}@keyframes la{0%{opacity:1}to{opacity:0;transform:translate3d(-100%,0,0) skewX(-30deg)}}.animate__lightSpeedOutLeft{animation-name:la;animation-timing-function:ease-in}@keyframes ma{0%{opacity:0;transform:rotate(-200deg)}to{opacity:1;transform:translateZ(0)}}.animate__rotateIn{animation-name:ma;transform-origin:center}@keyframes na{0%{opacity:0;transform:rotate(-45deg)}to{opacity:1;transform:translateZ(0)}}.animate__rotateInDownLeft{animation-name:na;transform-origin:left bottom}.animate__rotateInDownRight{animation-name:oa;transform-origin:right bottom}@keyframes oa{0%{opacity:0;transform:rotate(45deg)}to{opacity:1;transform:translateZ(0)}}.animate__rotateInUpLeft{animation-name:oa;transform-origin:left bottom}@keyframes pa{0%{opacity:0;transform:rotate(-90deg)}to{opacity:1;transform:translateZ(0)}}.animate__rotateInUpRight{animation-name:pa;transform-origin:right bottom}@keyframes qa{0%{opacity:1}to{opacity:0;transform:rotate(200deg)}}.animate__rotateOut{animation-name:qa;transform-origin:center}@keyframes ra{0%{opacity:1}to{opacity:0;transform:rotate(45deg)}}.animate__rotateOutDownLeft{animation-name:ra;transform-origin:left bottom}.animate__rotateOutDownRight{animation-name:sa;transform-origin:right bottom}@keyframes sa{0%{opacity:1}to{opacity:0;transform:rotate(-45deg)}}.animate__rotateOutUpLeft{animation-name:sa;transform-origin:left bottom}@keyframes ta{0%{opacity:1}to{opacity:0;transform:rotate(90deg)}}.animate__rotateOutUpRight{animation-name:ta;transform-origin:right bottom}@keyframes ua{0%{animation-timing-function:ease-in-out}20%,60%{animation-timing-function:ease-in-out;transform:rotate(80deg)}40%,80%{animation-timing-function:ease-in-out;opacity:1;transform:rotate(60deg)}to{opacity:0;transform:translate3d(0,700px,0)}}.animate__hinge{animation-duration:2s;animation-duration:calc(var(--animate-duration)*2);animation-name:ua;transform-origin:top left}@keyframes va{0%{opacity:0;transform:scale(.1) rotate(30deg);transform-origin:center bottom}50%{transform:rotate(-10deg)}70%{transform:rotate(3deg)}to{opacity:1;transform:scale(1)}}.animate__jackInTheBox{animation-name:va}@keyframes wa{0%{opacity:0;transform:translate3d(-100%,0,0) rotate(-120deg)}to{opacity:1;transform:translateZ(0)}}.animate__rollIn{animation-name:wa}@keyframes xa{0%{opacity:1}to{opacity:0;transform:translate3d(100%,0,0) rotate(120deg)}}.animate__rollOut{animation-name:xa}@keyframes ya{0%{opacity:0;transform:scale3d(.3,.3,.3)}50%{opacity:1}}.animate__zoomIn{animation-name:ya}@keyframes za{0%{animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0)}60%{animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,60px,0)}}.animate__zoomInDown{animation-name:za}@keyframes Aa{0%{animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0)}60%{animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(10px,0,0)}}.animate__zoomInLeft{animation-name:Aa}@keyframes Ba{0%{animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(1000px,0,0)}60%{animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(-10px,0,0)}}.animate__zoomInRight{animation-name:Ba}@keyframes Ca{0%{animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,1000px,0)}60%{animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,-60px,0)}}.animate__zoomInUp{animation-name:Ca}@keyframes Da{0%{opacity:1}50%{opacity:0;transform:scale3d(.3,.3,.3)}to{opacity:0}}.animate__zoomOut{animation-name:Da}@keyframes Ea{40%{animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,-60px,0)}to{animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,2000px,0)}}.animate__zoomOutDown{animation-name:Ea;transform-origin:center bottom}@keyframes Fa{40%{opacity:1;transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}to{opacity:0;transform:scale(.1) translate3d(-2000px,0,0)}}.animate__zoomOutLeft{animation-name:Fa;transform-origin:left center}@keyframes Ga{40%{opacity:1;transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}to{opacity:0;transform:scale(.1) translate3d(2000px,0,0)}}.animate__zoomOutRight{animation-name:Ga;transform-origin:right center}@keyframes Ha{40%{animation-timing-function:cubic-bezier(.55,.055,.675,.19);opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,60px,0)}to{animation-timing-function:cubic-bezier(.175,.885,.32,1);opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0)}}.animate__zoomOutUp{animation-name:Ha;transform-origin:center bottom}@keyframes Ia{0%{transform:translate3d(0,-100%,0);visibility:visible}to{transform:translateZ(0)}}.animate__slideInDown{animation-name:Ia}@keyframes Ja{0%{transform:translate3d(-100%,0,0);visibility:visible}to{transform:translateZ(0)}}.animate__slideInLeft{animation-name:Ja}@keyframes Ka{0%{transform:translate3d(100%,0,0);visibility:visible}to{transform:translateZ(0)}}.animate__slideInRight{animation-name:Ka}@keyframes La{0%{transform:translate3d(0,100%,0);visibility:visible}to{transform:translateZ(0)}}.animate__slideInUp{animation-name:La}@keyframes Ma{0%{transform:translateZ(0)}to{transform:translate3d(0,100%,0);visibility:hidden}}.animate__slideOutDown{animation-name:Ma}@keyframes Na{0%{transform:translateZ(0)}to{transform:translate3d(-100%,0,0);visibility:hidden}}.animate__slideOutLeft{animation-name:Na}@keyframes Oa{0%{transform:translateZ(0)}to{transform:translate3d(100%,0,0);visibility:hidden}}.animate__slideOutRight{animation-name:Oa}@keyframes Pa{0%{transform:translateZ(0)}to{transform:translate3d(0,-100%,0);visibility:hidden}}.animate__slideOutUp{animation-name:Pa}.button_plxA{background:#8759ff;border-radius:5px;bottom:10px;color:#fff;cursor:pointer;padding:0 10px;position:fixed;right:10px;z-index:1000000}.modal_wSGk{background-color:rgba(0,0,0,.8);display:flex;height:100vh;justify-content:center;overflow:hidden;width:100vw;z-index:99999}.announcementBar_mb4j,.skipToContent_fXgn{z-index:calc(var(--ifm-z-index-fixed) + 1)}.playground_CMhS{border-radius:8px;height:80vh;margin-top:50px;user-select:none;width:80vw}body:not(.navigation-with-keyboard) :not(input):focus{outline:0}#docusaurus-base-url-issue-banner-container,.collapseSidebarButton_PEFL,.docSidebarContainer_b6E3,.sidebarLogo_F_0z,.themedImage_ToTc,[data-theme=dark] .lightToggleIcon_pyhR,[data-theme=light] .darkToggleIcon_wfgR,html[data-announcement-bar-initially-dismissed=true] .announcementBar_mb4j{display:none}.skipToContent_fXgn{background-color:var(--ifm-background-surface-color);color:var(--ifm-color-emphasis-900);left:100%;padding:calc(var(--ifm-global-spacing)/2) var(--ifm-global-spacing);position:fixed;top:1rem}.skipToContent_fXgn:focus{box-shadow:var(--ifm-global-shadow-md);left:1rem}.closeButton_CVFx{line-height:0;padding:0}.content_knG7{font-size:85%;padding:5px 0;text-align:center}.content_knG7 a{color:inherit}.announcementBar_mb4j{align-items:center;background-color:var(--ifm-color-white);box-shadow:var(--ifm-global-shadow-lw);color:var(--ifm-color-black);display:flex;height:var(--docusaurus-announcement-bar-height)}.announcementBarPlaceholder_vyr4{flex:0 0 10px}.announcementBarClose_gvF7{align-self:stretch;flex:0 0 30px}.toggle_vylO{height:2rem;width:2rem}.toggleButton_gllP{align-items:center;border-radius:50%;display:flex;height:100%;justify-content:center;transition:background var(--ifm-transition-fast);width:100%}.toggleButton_gllP:hover{background:var(--ifm-color-emphasis-200)}.toggleButtonDisabled_aARS{cursor:not-allowed}[data-theme=dark] .themedImage--dark_i4oU,[data-theme=light] .themedImage--light_HNdA{display:initial}.iconExternalLink_nPIU{margin-left:.3rem}.iconLanguage_nlXk{margin-right:5px;vertical-align:text-bottom}.navbarHideable_m1mJ{transition:transform var(--ifm-transition-fast) ease}.navbarHidden_jGov{transform:translate3d(0,calc(-100% - 2px),0)}.footerLogoLink_DDai{opacity:.5;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.footerLogoLink_DDai:hover,.hash-link:focus,:hover>.hash-link{opacity:1}.mainWrapper_z2l0{flex:1 0 auto}.docusaurus-mt-lg{margin-top:3rem}#__docusaurus{display:flex;flex-direction:column;min-height:100%}.sidebar_re4s{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem);overflow-y:auto;position:-webkit-sticky;position:sticky;top:calc(var(--ifm-navbar-height) + 2rem)}.sidebarItemTitle_pO2u{font-size:var(--ifm-h3-font-size)}.container_mt6G,.sidebarItemList_Yudw{font-size:.9rem}.sidebarItem__DBe{margin-top:.7rem}.sidebarItemLink_mo7H{color:var(--ifm-font-color-base);display:block}.sidebarItemLinkActive_I1ZP{color:var(--ifm-color-primary)!important}.searchQueryInput_u2C7,.searchVersionInput_m0Ui{background:var(--docsearch-searchbox-focus-background);border:2px solid var(--ifm-toc-border-color);border-radius:var(--ifm-global-radius);color:var(--docsearch-text-color);font:var(--ifm-font-size-base) var(--ifm-font-family-base);margin-bottom:.5rem;padding:.8rem;transition:border var(--ifm-transition-fast) ease;width:100%}.searchQueryInput_u2C7:focus,.searchVersionInput_m0Ui:focus{border-color:var(--docsearch-primary-color);outline:0}.searchQueryInput_u2C7:-ms-input-placeholder{color:var(--docsearch-muted-color)}.searchQueryInput_u2C7::placeholder{color:var(--docsearch-muted-color)}.searchResultsColumn_JPFH{font-size:.9rem;font-weight:700}.algoliaLogo_rT1R{max-width:150px}.algoliaLogoPathFill_WdUC{fill:var(--ifm-font-color-base)}.searchResultItem_Tv2o{border-bottom:1px solid var(--ifm-toc-border-color);padding:1rem 0}.searchResultItemHeading_KbCB{font-weight:400;margin-bottom:0}.searchResultItemPath_lhe1{--ifm-breadcrumb-separator-size-multiplier:1;color:var(--ifm-color-content-secondary);font-size:.8rem}.searchResultItemSummary_AEaO{font-style:italic;margin:.5rem 0 0}.loadingSpinner_XVxU{animation:1s linear infinite Qa;border:.4em solid #eee;border-radius:50%;border-top:.4em solid var(--ifm-color-primary);height:3rem;margin:0 auto;width:3rem}@keyframes Qa{to{transform:rotate(1turn)}}.loader_vvXV{margin-top:2rem}.search-result-match{background:rgba(255,215,142,.25);color:var(--docsearch-hit-color);padding:.09em 0}.backToTopButton_sjWU{background-color:var(--ifm-color-emphasis-200);border-radius:50%;bottom:1.3rem;box-shadow:var(--ifm-global-shadow-lw);height:3rem;opacity:0;position:fixed;right:1.3rem;transform:scale(0);transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default);visibility:hidden;width:3rem;z-index:calc(var(--ifm-z-index-fixed) - 1)}.backToTopButton_sjWU:after{background-color:var(--ifm-color-emphasis-1000);content:" ";display:inline-block;height:100%;-webkit-mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;width:100%}.backToTopButtonShow_xfvO{opacity:1;transform:scale(1);visibility:visible}[data-theme=dark]:root{--docusaurus-collapse-button-bg:hsla(0,0%,100%,.05);--docusaurus-collapse-button-bg-hover:hsla(0,0%,100%,.1)}.docMainContainer_gTbr,.docPage__5DB{display:flex;width:100%}.authorCol_Hf19{flex-grow:1!important;max-width:inherit!important}.imageOnlyAuthorRow_pa_O{display:flex;flex-flow:row wrap}.DocSearch-Button,.DocSearch-Button-Container{align-items:center;display:flex}.imageOnlyAuthorCol_G86a{margin-left:.3rem;margin-right:.3rem}.DocSearch-Button{background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;font-weight:500;height:36px;justify-content:space-between;padding:0 8px;user-select:none}.DocSearch-Footer,.DocSearch-Help{-webkit-user-select:none;-ms-user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:0}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Hit-Tree,.DocSearch-Hit-action,.DocSearch-Hit-icon,.DocSearch-Reset{stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Input,.DocSearch-Link{-webkit-appearance:none;font:inherit}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border:0;border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 2px;position:relative;top:-1px;width:20px}.DocSearch--active{overflow:hidden!important}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{appearance:none;background:0 0;border:0;color:var(--docsearch-text-color);flex:1;font-size:1.2em;height:100%;outline:0;padding:0 0 0 8px;width:80%}.DocSearch-Hit-action-button,.DocSearch-Reset{-webkit-appearance:none;border:0;cursor:pointer}.DocSearch-Input:-ms-input-placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Cancel,.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator,.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset{animation:.1s ease-in forwards Ra;appearance:none;background:none;border-radius:50%;color:var(--docsearch-icon-color);padding:2px;right:0}.DocSearch-Help,.DocSearch-HitsFooter,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Reset:focus{outline:0}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:0 0}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help{font-size:.9em;margin:0;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}.DocSearch-Hit--deleting{opacity:0;transition:.25s linear}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:.25s linear .25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:-webkit-sticky;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{appearance:none;background:none;border-radius:50%;color:inherit;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon,.tocCollapsibleContent_vkbj a{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:background-color .1s ease-in}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{-webkit-appearance:none;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:0;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;user-select:none;width:100%;z-index:300}.DocSearch-Commands li,.DocSearch-Commands-Key{align-items:center;display:flex}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{background:var(--docsearch-key-gradient);border:0;border-radius:2px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;width:20px}.buttonGroup__atx button,.codeBlockContainer_Ckt0{background:var(--prism-background-color);color:var(--prism-color)}@keyframes Ra{0%{opacity:0}to{opacity:1}}.DocSearch-Button{margin:0;transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.DocSearch-Container{z-index:calc(var(--ifm-z-index-fixed) + 1)}.codeBlockContainer_Ckt0{border-radius:var(--ifm-code-border-radius);box-shadow:var(--ifm-global-shadow-lw);margin-bottom:var(--ifm-leading)}.codeBlockContent_biex{border-radius:inherit;direction:ltr;position:relative}.codeBlockTitle_Ktv7{border-bottom:1px solid var(--ifm-color-emphasis-300);border-top-left-radius:inherit;border-top-right-radius:inherit;font-size:var(--ifm-code-font-size);font-weight:500;padding:.75rem var(--ifm-pre-padding)}.codeBlock_bY9V{--ifm-pre-background:var(--prism-background-color);margin:0;padding:0}.codeBlockTitle_Ktv7+.codeBlockContent_biex .codeBlock_bY9V{border-top-left-radius:0;border-top-right-radius:0}.codeBlockLines_e6Vv{float:left;font:inherit;min-width:100%;padding:var(--ifm-pre-padding)}.codeBlockLinesWithNumbering_o6Pm{display:table;padding:var(--ifm-pre-padding) 0}.buttonGroup__atx{column-gap:.2rem;display:flex;position:absolute;right:calc(var(--ifm-pre-padding)/2);top:calc(var(--ifm-pre-padding)/2)}.buttonGroup__atx button{align-items:center;border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-global-radius);display:flex;line-height:0;opacity:0;padding:.4rem;transition:opacity .2s ease-in-out}.buttonGroup__atx button:focus-visible,.buttonGroup__atx button:hover{opacity:1!important}.theme-code-block:hover .buttonGroup__atx button{opacity:.4}.iconEdit_Z9Sw{margin-right:.3em;vertical-align:sub}:where(:root){--docusaurus-highlighted-code-line-bg:#484d5b}:where([data-theme=dark]){--docusaurus-highlighted-code-line-bg:#646464}.theme-code-block-highlighted-line{background-color:var(--docusaurus-highlighted-code-line-bg);display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.codeLine_lJS_{counter-increment:a;display:table-row}.codeLineNumber_Tfdd{background:var(--ifm-pre-background);display:table-cell;left:0;overflow-wrap:normal;padding:0 var(--ifm-pre-padding);position:-webkit-sticky;position:sticky;text-align:right;width:1%}.codeLineNumber_Tfdd:before{content:counter(a);opacity:.4}.codeLineContent_feaV{padding-right:var(--ifm-pre-padding)}.tag_zVej{border:1px solid var(--docusaurus-tag-list-border);transition:border var(--ifm-transition-fast)}.tag_zVej:hover{--docusaurus-tag-list-border:var(--ifm-link-color);text-decoration:none}.tagRegular_sFm0{border-radius:.5rem;font-size:90%;padding:.2rem .5rem .3rem}.tagWithCount_h2kH{align-items:center;border-left:0;display:flex;padding:0 .5rem 0 1rem;position:relative}.tagWithCount_h2kH:after,.tagWithCount_h2kH:before{border:1px solid var(--docusaurus-tag-list-border);content:"";position:absolute;top:50%;transition:inherit}.tagWithCount_h2kH:before{border-bottom:0;border-right:0;height:1.18rem;right:100%;transform:translate(50%,-50%) rotate(-45deg);width:1.18rem}.tagWithCount_h2kH:after{border-radius:50%;height:.5rem;left:0;transform:translateY(-50%);width:.5rem}.tagWithCount_h2kH span{background:var(--ifm-color-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-color-black);font-size:.7rem;line-height:1.2;margin-left:.3rem;padding:.1rem .4rem}.tag_Nnez{display:inline-block;margin:.5rem .5rem 0 1rem}.theme-code-block:hover .copyButtonCopied_obH4{opacity:1!important}.copyButtonIcons_eSgA{height:1.125rem;position:relative;width:1.125rem}.copyButtonIcon_y97N,.copyButtonSuccessIcon_LjdS{fill:currentColor;height:inherit;left:0;opacity:inherit;position:absolute;top:0;transition:.15s;width:inherit}.copyButtonSuccessIcon_LjdS{color:#00d600;left:50%;opacity:0;top:50%;transform:translate(-50%,-50%) scale(.33)}.copyButtonCopied_obH4 .copyButtonIcon_y97N{opacity:0;transform:scale(.33)}.copyButtonCopied_obH4 .copyButtonSuccessIcon_LjdS{opacity:1;transform:translate(-50%,-50%) scale(1);transition-delay:75ms}.tags_jXut{display:inline}.tag_QGVx{display:inline-block;margin:0 .4rem .5rem 0}.lastUpdated_vwxv{font-size:smaller;font-style:italic;margin-top:.2rem}.tocCollapsibleButton_TO0P{align-items:center;display:flex;font-size:inherit;justify-content:space-between;padding:.4rem .8rem;width:100%}.tocCollapsibleButton_TO0P:after{background:var(--ifm-menu-link-sublist-icon) 50% 50%/2rem 2rem no-repeat;content:"";filter:var(--ifm-menu-link-sublist-icon-filter);height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast);width:1.25rem}.tocCollapsibleButtonExpanded_MG3E:after,.tocCollapsibleExpanded_sAul{transform:none}.tocCollapsible_ETCw{background-color:var(--ifm-menu-color-background-active);border-radius:var(--ifm-global-radius);margin:1rem 0}.tocCollapsibleContent_vkbj>ul{border-left:none;border-top:1px solid var(--ifm-color-emphasis-300);font-size:15px;padding:.2rem 0}.tocCollapsibleContent_vkbj ul li{margin:.4rem .8rem}.wordWrapButtonIcon_Bwma{height:1.2rem;width:1.2rem}.details_lb9f{--docusaurus-details-summary-arrow-size:0.38rem;--docusaurus-details-transition:transform 200ms ease;--docusaurus-details-decoration-color:grey}.details_lb9f>summary{cursor:pointer;list-style:none;padding-left:1rem;position:relative}.details_lb9f>summary::-webkit-details-marker{display:none}.details_lb9f>summary:before{border-color:transparent transparent transparent var(--docusaurus-details-decoration-color);border-style:solid;border-width:var(--docusaurus-details-summary-arrow-size);content:"";left:0;position:absolute;top:.45rem;transform:rotate(0);transform-origin:calc(var(--docusaurus-details-summary-arrow-size)/2) 50%;transition:var(--docusaurus-details-transition)}.collapsibleContent_i85q{border-top:1px solid var(--docusaurus-details-decoration-color);margin-top:1rem;padding-top:1rem}.details_b_Ee{--docusaurus-details-decoration-color:var(--ifm-alert-border-color);--docusaurus-details-transition:transform var(--ifm-transition-fast) ease;border:1px solid var(--ifm-alert-border-color);margin:0 0 var(--ifm-spacing-vertical)}.anchorWithStickyNavbar_LWe7{scroll-margin-top:calc(var(--ifm-navbar-height) + .5rem)}.anchorWithHideOnScrollNavbar_WYt5{scroll-margin-top:.5rem}.hash-link{opacity:0;padding-left:.5rem;transition:opacity var(--ifm-transition-fast);-webkit-user-select:none;-ms-user-select:none;user-select:none}.hash-link:before{content:"#"}.containsTaskList_mC6p{list-style:none}.img_ev3q{height:auto}.admonition_LlT9{margin-bottom:1em}.admonitionHeading_tbUL{font:var(--ifm-heading-font-weight) var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.3rem}.admonitionHeading_tbUL code{text-transform:none}.admonitionIcon_kALy{display:inline-block;margin-right:.4em;vertical-align:middle}.admonitionIcon_kALy svg{fill:var(--ifm-alert-foreground-color);display:inline-block;height:1.6em;width:1.6em}.blogPostFooterDetailsFull_mRVl{flex-direction:column}.tableOfContents_jeP5{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem);overflow-y:auto;position:-webkit-sticky;position:sticky;top:calc(var(--ifm-navbar-height) + 1rem)}.breadcrumbsContainer_Z_bl{--ifm-breadcrumb-size-multiplier:0.8;margin-bottom:.8rem}.breadcrumbHomeIcon_OVgt{height:1.1rem;position:relative;top:1px;vertical-align:top;width:1.1rem}.furion-banner{align-items:center;background-color:#211b50;color:#fff;padding:4rem 2rem}.furion-banner-container{display:flex;justify-content:space-between;margin:0 auto;max-width:1140px}.furion-banner-project{font-size:1.5em;font-weight:700}.furion-banner-description{-webkit-text-fill-color:transparent;-webkit-background-clip:text;background-clip:text;background-image:linear-gradient(81deg,#8759ff,#3fc4fe,#42ffac);font-size:2.5em;font-weight:700;line-height:1.25;margin:24px 0}.furion-banner-spec{font-family:Muli;font-size:1em;font-weight:500;line-height:1.33;opacity:.7;padding:0}.furion-banner-spec li{list-style:none;margin-bottom:1em;padding-left:1em;position:relative}.furion-banner-spec li:before{background-color:#8759ff;content:"";height:4px;left:0;position:absolute;top:.5em;width:4px}.furion-support-platform{color:#fff;font-family:Muli;font-size:.85em;font-weight:500;line-height:2;margin-top:3em;opacity:.6}.furion-support-icons{display:flex;margin-top:12px}.furion-support-icons span{margin-right:20px}.furion-get-start,.furion-try-demo{background:#8759ff;border-radius:2em;color:#fff;display:inline-block;line-height:1.5;margin-top:4em;min-width:145px;padding:8px 32px;position:relative;text-align:center;text-decoration:none;white-space:nowrap}.furion-try-demo{background-color:#21b091;margin-left:20px}.furion-get-start:hover{background:rgba(135,89,255,.9)}.furion-try-demo:hover{opacity:.9}.furion-banner-item .system-window{width:34rem}.furion-get-start:hover,.furion-try-demo:hover{color:#fff;text-decoration:none}.system-top-bar{background-image:linear-gradient(90deg,rgba(136,89,255,.2),rgba(63,196,254,.2) 90%,rgba(66,255,172,.2));padding:.25em 1em}.system-top-bar-circle{border-radius:50%;display:inline-block;filter:brightness(100%);height:.5em;margin-left:.3em;width:.5em}.system-window{--ifm-leading:0;background:#211b50;border-radius:1em;overflow:hidden;padding:0;width:95%}.system-window iframe{border-radius:unset}.blue-accent{--uni-border-color:#3fbbfe;--uni-box-shadow-color:rgba(63,187,254,.1);--ifm-menu-color-active:#3fbbfe}.preview-border{border:1px solid #3fbbfe;box-shadow:0 6px 58px 0 rgba(63,187,254,.1)}.furion-content{margin-bottom:4em;margin-top:4em;text-align:center}.furion-small-title{color:#412a94;font-family:Muli;font-size:1em;font-weight:600;letter-spacing:1px;opacity:.6}.furion-big-title.dark,.furion-contributor-item.dark a,.furion-log-number span.dark,.furion-remark-p p.dark,.furion-small-title.dark{color:#f5f6f7}.furion-big-title{color:#412a94;font-family:Poppins;font-size:2em;font-weight:700;line-height:1.31;margin-bottom:2em}.furion-gitee-log{display:flex;flex-wrap:nowrap;justify-content:center}.furion-log-item{height:173px;margin-right:65px;position:relative;width:260px}.furion-log-jiao{background:#fff;border-right:1px dashed #a795e8;border-top:1px dashed #a795e8;height:100px;position:absolute;right:-6px;top:-6px;width:100px}.furion-log-jiao.dark{background:#18191a}.furion-log-item:last-child{margin-right:0}.furion-log-number{align-items:center;display:flex;flex-direction:column;height:100%;justify-content:center;position:relative;width:100%;z-index:2}.furion-log-number div{font-size:3em;font-weight:700}.furion-log-number span{color:#1c1e21;font-family:Poppins,sans-serif;font-stretch:normal;font-style:normal;letter-spacing:normal;line-height:normal}.furion-remark{display:flex;justify-content:center}.furion-remark-item{border-image-slice:1;border-image-source:linear-gradient(var(--uni-border-gradient-degrees),#8759ff,#3fc4fe 51%,#42ffac);border-style:solid;border-width:6px;height:100%;margin:2em;max-width:320px;padding:4em 2em}.furion-remark-item:first-child{--uni-border-gradient-degrees:41deg;border-right:0;border-top:0}.furion-remark-item:nth-child(2){--uni-border-gradient-degrees:100deg;border:0}.furion-remark-item:last-child{--uni-border-gradient-degrees:221deg;border-bottom:0;border-left:0}.furion-remark-p{height:150px}.furion-remark-p h1{font-size:24px}.furion-remark-p p,.furion-who-des p{font-family:Muli;font-size:1em;line-height:1.75;opacity:.8}.furion-remark-p p{color:#474747;text-align:center}.furion-whouse{align-items:center;background-color:#412a94!important;color:#fff;display:flex;padding:5rem 0}.furion-who-custom{align-items:center;background-color:#fff;color:#723cff;display:flex;flex-wrap:wrap;justify-content:flex-end;min-height:500px;padding:6rem;text-align:right;width:60%}.furion-custom-img{color:transparent;margin-left:3em;text-decoration:none}.furion-who-des{padding:0 5rem}.furion-who-des p{color:#fff;margin-bottom:.8em}.footer{background-color:#211b50!important}.furion-links{margin:4em;text-align:center}.furion-links-content a{display:inline-block;font-size:20px;font-weight:600;margin:0 1em}.furion-contributors,.furion-proccesson{margin:4em 0;text-align:center}#dotnet-china{height:100px}.furion-contributor-item{background-color:#f3f3f3;border-radius:4px;box-shadow:4px 3px 16px -3px #0009;box-sizing:border-box;color:#333;display:inline-block;height:170px;margin:10px 5px;overflow:hidden;padding:10px;position:relative;text-align:center;width:130px}.furion-contributor-extra{background-color:#412a94;border-radius:4px;color:#fff;font-size:12px;padding:2px 5px;position:absolute;right:0;text-align:left;top:-9px}.furion-contributor-item a{color:#333;display:block;font-size:10pt;font-weight:700;text-decoration:none}.furion-contributor-item div{margin-top:10px}.furion-contributor-item.dark{background:#333}.furion-get-start-btn{display:flex;position:relative}.furion-version{color:#ff0;font-size:16px;position:absolute;right:0;top:-10px;z-index:10}.navbar{background-color:#211b50}.navbar__brand,.navbar__items,.navbar__link{color:#fff}.navbar__link--active,.navbar__link:hover{color:#ff0}.menu__list-item .navbar__link--active,.menu__list-item .navbar__link:hover{color:#743dff}@media (min-width:997px){.collapseSidebarButton_PEFL,.expandButton_m80_{background-color:var(--docusaurus-collapse-button-bg)}:root{--docusaurus-announcement-bar-height:30px}.announcementBarClose_gvF7,.announcementBarPlaceholder_vyr4{flex-basis:50px}.searchBox_ZlJk{padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.collapseSidebarButton_PEFL{border:1px solid var(--ifm-toc-border-color);border-radius:0;bottom:0;display:block!important;height:40px;position:-webkit-sticky;position:sticky}.collapseSidebarButtonIcon_kv0_{margin-top:4px;transform:rotate(180deg)}.expandButtonIcon_BlDH,[dir=rtl] .collapseSidebarButtonIcon_kv0_{transform:rotate(0)}.collapseSidebarButton_PEFL:focus,.collapseSidebarButton_PEFL:hover,.expandButton_m80_:focus,.expandButton_m80_:hover{background-color:var(--docusaurus-collapse-button-bg-hover)}.menuHtmlItem_M9Kj{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu_SIkG{flex-grow:1;padding:.5rem}@supports (scrollbar-gutter:stable){.menu_SIkG{padding:.5rem 0 .5rem .5rem;scrollbar-gutter:stable}}.menuWithAnnouncementBar_GW3s{margin-bottom:var(--docusaurus-announcement-bar-height)}.sidebar_mhZE{display:flex;flex-direction:column;height:100%;max-height:100vh;padding-top:var(--ifm-navbar-height);position:-webkit-sticky;position:sticky;top:0;transition:opacity 50ms;width:var(--doc-sidebar-width)}.sidebarWithHideableNavbar__6UL{padding-top:0}.sidebarHidden__LRd{height:0;opacity:0;overflow:hidden;visibility:hidden}.sidebarLogo_F_0z{align-items:center;color:inherit!important;display:flex!important;margin:0 var(--ifm-navbar-padding-horizontal);max-height:var(--ifm-navbar-height);min-height:var(--ifm-navbar-height);text-decoration:none!important}.sidebarLogo_F_0z img{height:2rem;margin-right:.5rem}.expandButton_m80_{align-items:center;display:flex;height:100%;justify-content:center;max-height:100vh;position:-webkit-sticky;position:sticky;top:0;transition:background-color var(--ifm-transition-fast) ease}[dir=rtl] .expandButtonIcon_BlDH{transform:rotate(180deg)}.docSidebarContainer_b6E3{border-right:1px solid var(--ifm-toc-border-color);-webkit-clip-path:inset(0);clip-path:inset(0);display:block;margin-top:calc(var(--ifm-navbar-height)*-1);transition:width var(--ifm-transition-fast) ease;width:var(--doc-sidebar-width);will-change:width}.docSidebarContainerHidden_b3ry{cursor:pointer;width:var(--doc-sidebar-hidden-width)}.docMainContainer_gTbr{flex-grow:1;max-width:calc(100% - var(--doc-sidebar-width))}.docMainContainerEnhanced_Uz_u{max-width:calc(100% - var(--doc-sidebar-hidden-width))}.docItemWrapperEnhanced_czyv{max-width:calc(var(--ifm-container-width) + var(--doc-sidebar-width))!important}.lastUpdated_vwxv{text-align:right}.tocMobile_ITEo{display:none}.docItemCol_VOVn{max-width:75%!important}}@media (min-width:1440px){.container{max-width:var(--ifm-container-width-xl)}}@media screen and (max-width:1024px){.furion-banner-container{flex-direction:column;justify-content:unset}.furion-get-start-btn{text-align:center}#dotnet-china{height:45px}.furion-banner-item .system-window{margin-top:3rem;width:100%}.furion-gitee-log{align-items:center;flex-direction:column;flex-wrap:unset;justify-content:center;padding:20px}.furion-log-item{height:173px;margin-right:0;margin-top:25px;width:100%}.furion-big-title{margin-bottom:1em}.furion-remark,.furion-whouse{flex-direction:column}.furion-whouse{padding-bottom:1em}.furion-who-des{padding-bottom:2em;padding-top:1em}.furion-remark-item{border:none;margin:0;max-width:unset;padding-bottom:0;width:100%}.furion-custom-img{margin-bottom:2em;margin-left:0}.furion-custom-img img{max-width:unset}.furion-who-custom{align-items:center;justify-content:center;text-align:center;width:100%}.furion-contributors{margin:4em 0}}@media (max-width:996px){.col{--ifm-col-width:100%;flex-basis:var(--ifm-col-width);margin-left:0}.footer{--ifm-footer-padding-horizontal:0}.colorModeToggle_DEke,.footer__link-separator,.navbar__item,.sidebar_re4s,.tableOfContents_jeP5{display:none}.footer__col{margin-bottom:calc(var(--ifm-spacing-vertical)*3)}.footer__link-item{display:block}.hero{padding-left:0;padding-right:0}.navbar>.container,.navbar>.container-fluid{padding:0}.navbar__toggle{display:inherit}.navbar__search-input{width:9rem}.pills--block,.tabs--block{flex-direction:column}.searchBox_ZlJk{position:absolute;right:var(--ifm-navbar-padding-horizontal)}.docItemContainer_hgFs{padding:0 .3rem}}@media only screen and (max-width:996px){.searchQueryColumn_RTkw,.searchResultsColumn_JPFH{max-width:60%!important}.searchLogoColumn_rJIA,.searchVersionColumn_ypXd{max-width:40%!important}.searchLogoColumn_rJIA{padding-left:0!important}}@media (max-width:750px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder,.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%;max-height:calc(var(--docsearch-vh,1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh,1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh,1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Cancel{-webkit-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:0;overflow:hidden;padding:0;-webkit-user-select:none;-ms-user-select:none;user-select:none;white-space:nowrap}}@media (max-width:576px){.markdown h1:first-child{--ifm-h1-font-size:2rem}.markdown>h2{--ifm-h2-font-size:1.5rem}.markdown>h3{--ifm-h3-font-size:1.25rem}.title_f1Hy{font-size:2rem}}@media screen and (max-width:576px){.searchQueryColumn_RTkw{max-width:100%!important}.searchVersionColumn_ypXd{max-width:100%!important;padding-left:var(--ifm-spacing-horizontal)!important}}@media (hover:hover){.backToTopButton_sjWU:hover{background-color:var(--ifm-color-emphasis-300)}}@media (pointer:fine){.thin-scrollbar{scrollbar-width:thin}.thin-scrollbar::-webkit-scrollbar{height:var(--ifm-scrollbar-size);width:var(--ifm-scrollbar-size)}.thin-scrollbar::-webkit-scrollbar-track{background:var(--ifm-scrollbar-track-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb{background:var(--ifm-scrollbar-thumb-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--ifm-scrollbar-thumb-hover-background-color)}}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{stroke-width:var(--docsearch-icon-stroke-width);animation:none;-webkit-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0}.DocSearch-Hit--deleting,.DocSearch-Hit--favoriting{transition:none}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:none}}@media print{.announcementBar_mb4j,.footer,.menu,.navbar,.pagination-nav,.table-of-contents,.tocMobile_ITEo{display:none}.tabs{page-break-inside:avoid}.codeBlockLines_e6Vv{white-space:pre-wrap}}@media (prefers-reduced-motion:reduce),print{.animate__animated{animation-duration:1ms!important;animation-iteration-count:1!important;transition-duration:1ms!important}.animate__animated[class*=Out]{opacity:0}} \ No newline at end of file diff --git a/handbook/build/assets/js/000e798f.49cd0fb3.js b/handbook/build/assets/js/000e798f.49cd0fb3.js deleted file mode 100644 index 98687cf90a..0000000000 --- a/handbook/build/assets/js/000e798f.49cd0fb3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4847],{4240:function(e,t,n){n.r(t),n.d(t,{assets:function(){return s},contentTitle:function(){return u},default:function(){return m},frontMatter:function(){return l},metadata:function(){return p},toc:function(){return c}});var r=n(3117),o=n(102),i=(n(7294),n(3905)),a=(n(1402),["components"]),l={slug:"net6-preview5",title:"3. .NET 6 Preview 5 \u5c1d\u9c9c",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5",".net6"]},u=void 0,p={permalink:"/furion/blog/net6-preview5",editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/blog/2021-06-18-net6-preview5.mdx",source:"@site/blog/2021-06-18-net6-preview5.mdx",title:"3. .NET 6 Preview 5 \u5c1d\u9c9c",description:"",date:"2021-06-18T00:00:00.000Z",formattedDate:"June 18, 2021",tags:[{label:"furion",permalink:"/furion/blog/tags/furion"},{label:"furos",permalink:"/furion/blog/tags/furos"},{label:".net",permalink:"/furion/blog/tags/net"},{label:".netcore",permalink:"/furion/blog/tags/netcore"},{label:".net5",permalink:"/furion/blog/tags/net-5"},{label:".net6",permalink:"/furion/blog/tags/net-6"}],readingTime:1.29,hasTruncateMarker:!1,authors:[{name:"dotNET China",title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",url:"https://www.chinadot.net",imageURL:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png"}],frontMatter:{slug:"net6-preview5",title:"3. .NET 6 Preview 5 \u5c1d\u9c9c",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5",".net6"]},prevItem:{title:"4. .NET 6 Preview 6 \u5c1d\u9c9c",permalink:"/furion/blog/net6-preview6"},nextItem:{title:"2. \u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d",permalink:"/furion/blog/fileupload-download"}},s={authorsImageUrls:[void 0]},c=[{value:"\u7b49\u4e0d\u53ca\u5c1d\u9c9c\u4e86",id:"\u7b49\u4e0d\u53ca\u5c1d\u9c9c\u4e86",level:2},{value:"\u5b89\u88c5 .NET 6 Preview 5 SDK",id:"\u5b89\u88c5-net-6-preview-5-sdk",level:3},{value:"\u5347\u7ea7 Visual Studio 2019",id:"\u5347\u7ea7-visual-studio-2019",level:3},{value:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:3},{value:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",level:3}],d={toc:c};function m(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"2021 \u5e74 06 \u6708 18 \u65e5\uff0c\u5fae\u8f6f\u53d1\u5e03\u4e86 ",(0,i.kt)("inlineCode",{parentName:"strong"},".NET 6 Preview 5")," \u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5728\u5f53\u5929\u7b2c\u4e00\u65f6\u95f4\u9002\u914d\u4e86\u8be5\u7248\u672c\uff0c\u5e76\u53d1\u5e03 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v3.0.0-preview.5.21301.9")," \u7248\u672c\u3002")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/tree/net6.0-preview5/"},"Furion .NET 6 Preview 5 \u6e90\u7801\u5730\u5740")),(0,i.kt)("h2",{id:"\u7b49\u4e0d\u53ca\u5c1d\u9c9c\u4e86"},"\u7b49\u4e0d\u53ca\u5c1d\u9c9c\u4e86"),(0,i.kt)("h3",{id:"\u5b89\u88c5-net-6-preview-5-sdk"},"\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h3"},".NET 6 Preview 5 SDK")),(0,i.kt)("p",null,"\u5c1d\u9c9c\u4e4b\u524d\uff0c\u9996\u5148\u5148\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 5 SDK"),"\uff0c\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/download/dotnet/6.0"},"https://dotnet.microsoft.com/download/dotnet/6.0")),(0,i.kt)("p",null,"\u4e0b\u8f7d\u5bf9\u5e94\u7cfb\u7edf\u548c\u5904\u7406\u5668\u7248\u672c\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"\u5347\u7ea7-visual-studio-2019"},"\u5347\u7ea7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Visual Studio 2019")),(0,i.kt)("p",null,"\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 5")," \u652f\u6301\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview 16.11.0 Preview 2.0")," \u7248\u672c\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u662f ",(0,i.kt)("inlineCode",{parentName:"strong"},"Preview")," \u6700\u65b0\u7248\u672c"),"\u3002\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16"},"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16")),(0,i.kt)("p",null,"\u5df2\u7ecf\u5b89\u88c5\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview")," \u7248\u672c\u7684\u670b\u53cb\u76f4\u63a5\u5347\u7ea7\u5230\u6700\u65b0\u7248\u5373\u53ef\u3002"),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio Code")," \u5f00\u53d1\uff0c\u53ef\u5ffd\u7565\u6b64\u9009\u9879\u3002")),(0,i.kt)("h3",{id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion v3.0.0-preview.5.21301.9")," \u76ee\u524d\u63d0\u4f9b\u4e86\u6240\u6709\u7c7b\u578b\u7684\u811a\u624b\u67b6\uff0c\u7248\u672c\u53f7\u7edf\u4e00 ",(0,i.kt)("inlineCode",{parentName:"p"},"3.0.0-preview.5.21301.9"),"\u3002"),(0,i.kt)("p",null,"\u5b89\u88c5\u811a\u624b\u67b6\uff0c\u6253\u5f00 ",(0,i.kt)("inlineCode",{parentName:"p"},"CMD/Powershell")," \u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9\n")),(0,i.kt)("p",null,"\u521b\u5efa\u9879\u76ee"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new furionapi -n FurionNET6\n")),(0,i.kt)("h3",{id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"},"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"),(0,i.kt)("p",null,"\u6253\u5f00\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u5373\u53ef\u3002"))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return m}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},s=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=o,f=d["".concat(u,".").concat(m)]||d[m]||c[m]||i;return n?r.createElement(f,a(a({ref:t},s),{},{components:n})):r.createElement(f,a({ref:t},s))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var p=2;p=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},s=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=o,f=d["".concat(u,".").concat(m)]||d[m]||c[m]||i;return n?r.createElement(f,a(a({ref:t},s),{},{components:n})):r.createElement(f,a({ref:t},s))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var p=2;p.NET 6 Preview 5 SDK",id:"\u5b89\u88c5-net-6-preview-5-sdk",level:3},{value:"\u5347\u7ea7 Visual Studio 2019",id:"\u5347\u7ea7-visual-studio-2019",level:3},{value:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:3},{value:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",level:3}],d={toc:c};function m(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"2021 \u5e74 06 \u6708 18 \u65e5\uff0c\u5fae\u8f6f\u53d1\u5e03\u4e86 ",(0,i.kt)("inlineCode",{parentName:"strong"},".NET 6 Preview 5")," \u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5728\u5f53\u5929\u7b2c\u4e00\u65f6\u95f4\u9002\u914d\u4e86\u8be5\u7248\u672c\uff0c\u5e76\u53d1\u5e03 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v3.0.0-preview.5.21301.9")," \u7248\u672c\u3002")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/tree/net6.0-preview5/"},"Furion .NET 6 Preview 5 \u6e90\u7801\u5730\u5740")),(0,i.kt)("h2",{id:"\u7b49\u4e0d\u53ca\u5c1d\u9c9c\u4e86"},"\u7b49\u4e0d\u53ca\u5c1d\u9c9c\u4e86"),(0,i.kt)("h3",{id:"\u5b89\u88c5-net-6-preview-5-sdk"},"\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h3"},".NET 6 Preview 5 SDK")),(0,i.kt)("p",null,"\u5c1d\u9c9c\u4e4b\u524d\uff0c\u9996\u5148\u5148\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 5 SDK"),"\uff0c\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/download/dotnet/6.0"},"https://dotnet.microsoft.com/download/dotnet/6.0")),(0,i.kt)("p",null,"\u4e0b\u8f7d\u5bf9\u5e94\u7cfb\u7edf\u548c\u5904\u7406\u5668\u7248\u672c\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"\u5347\u7ea7-visual-studio-2019"},"\u5347\u7ea7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Visual Studio 2019")),(0,i.kt)("p",null,"\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 5")," \u652f\u6301\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview 16.11.0 Preview 2.0")," \u7248\u672c\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u662f ",(0,i.kt)("inlineCode",{parentName:"strong"},"Preview")," \u6700\u65b0\u7248\u672c"),"\u3002\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16"},"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16")),(0,i.kt)("p",null,"\u5df2\u7ecf\u5b89\u88c5\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview")," \u7248\u672c\u7684\u670b\u53cb\u76f4\u63a5\u5347\u7ea7\u5230\u6700\u65b0\u7248\u5373\u53ef\u3002"),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio Code")," \u5f00\u53d1\uff0c\u53ef\u5ffd\u7565\u6b64\u9009\u9879\u3002")),(0,i.kt)("h3",{id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion v3.0.0-preview.5.21301.9")," \u76ee\u524d\u63d0\u4f9b\u4e86\u6240\u6709\u7c7b\u578b\u7684\u811a\u624b\u67b6\uff0c\u7248\u672c\u53f7\u7edf\u4e00 ",(0,i.kt)("inlineCode",{parentName:"p"},"3.0.0-preview.5.21301.9"),"\u3002"),(0,i.kt)("p",null,"\u5b89\u88c5\u811a\u624b\u67b6\uff0c\u6253\u5f00 ",(0,i.kt)("inlineCode",{parentName:"p"},"CMD/Powershell")," \u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9\n")),(0,i.kt)("p",null,"\u521b\u5efa\u9879\u76ee"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new furionapi -n FurionNET6\n")),(0,i.kt)("h3",{id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"},"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"),(0,i.kt)("p",null,"\u6253\u5f00\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u5373\u53ef\u3002"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/00cf5050.0557c5ee.js b/handbook/build/assets/js/00cf5050.0557c5ee.js new file mode 100644 index 0000000000..d6996fa8ee --- /dev/null +++ b/handbook/build/assets/js/00cf5050.0557c5ee.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[8133],{3905:function(e,t,n){n.d(t,{Zo:function(){return u},kt:function(){return m}});var a=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var p=a.createContext({}),s=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},u=function(e){var t=s(e.components);return a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},c=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,r=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),c=s(n),m=i,k=c["".concat(p,".").concat(m)]||c[m]||d[m]||r;return n?a.createElement(k,l(l({ref:t},u),{},{components:n})):a.createElement(k,l({ref:t},u))}));function m(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=n.length,l=new Array(r);l[0]=c;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:i,l[1]=o;for(var s=2;sCORS \u670d\u52a1",id:"1641-\u6dfb\u52a0-cors-\u670d\u52a1",level:3},{value:"16.4.2 \u914d\u7f6e\u5141\u8bb8\u8de8\u57df\u57df\u540d",id:"1642-\u914d\u7f6e\u5141\u8bb8\u8de8\u57df\u57df\u540d",level:3},{value:"16.5 CorsAccessorSettings \u914d\u7f6e",id:"165-corsaccessorsettings-\u914d\u7f6e",level:2},{value:"16.6 \u524d\u7aef\u4e0d\u80fd\u8bfb\u53d6\u54cd\u5e94\u5934\u6ce8\u610f\u4e8b\u9879",id:"166-\u524d\u7aef\u4e0d\u80fd\u8bfb\u53d6\u54cd\u5e94\u5934\u6ce8\u610f\u4e8b\u9879",level:2},{value:"16.7 \u4f7f\u7528 $.ajax \u524d\u7aef\u6ce8\u610f\u4e8b\u9879",id:"167-\u4f7f\u7528-ajax-\u524d\u7aef\u6ce8\u610f\u4e8b\u9879",level:2},{value:"16.8 \u7981\u7528\u8de8\u57df",id:"168-\u7981\u7528\u8de8\u57df",level:2},{value:"16.9 SignalR \u8de8\u57df\u95ee\u9898",id:"169-signalr-\u8de8\u57df\u95ee\u9898",level:2},{value:"16.10 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"1610-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:d};function m(e){var t=e.components,n=(0,i.Z)(e,l);return(0,r.kt)("wrapper",(0,a.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"161-\u4ec0\u4e48\u662f\u8de8\u57df"},"16.1 \u4ec0\u4e48\u662f\u8de8\u57df"),(0,r.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u5f53\u4e00\u4e2a\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"p"},"url")," \u7684\u534f\u8bae\u3001\u57df\u540d\u3001\u7aef\u53e3\u4e09\u8005\u4e4b\u95f4\u4efb\u610f\u4e00\u4e2a\u4e0e\u5f53\u524d\u9875\u9762 ",(0,r.kt)("inlineCode",{parentName:"p"},"url")," \u4e0d\u540c\u5373\u4e3a\u8de8\u57df\u3002\u90a3\u4e3a\u4ec0\u4e48\u4f1a\u51fa\u73b0\u8de8\u57df\u95ee\u9898\u5462\uff1f"),(0,r.kt)("p",null,"\u51fa\u4e8e\u6d4f\u89c8\u5668\u7684\u540c\u6e90\u7b56\u7565\u9650\u5236\u3002\u540c\u6e90\u7b56\u7565\uff08Sameoriginpolicy\uff09\u662f\u4e00\u79cd\u7ea6\u5b9a\uff0c\u5b83\u662f\u6d4f\u89c8\u5668\u6700\u6838\u5fc3\u4e5f\u6700\u57fa\u672c\u7684\u5b89\u5168\u529f\u80fd\uff0c\u5982\u679c\u7f3a\u5c11\u4e86\u540c\u6e90\u7b56\u7565\uff0c\u5219\u6d4f\u89c8\u5668\u7684\u6b63\u5e38\u529f\u80fd\u53ef\u80fd\u90fd\u4f1a\u53d7\u5230\u5f71\u54cd\u3002\u53ef\u4ee5\u8bf4 ",(0,r.kt)("inlineCode",{parentName:"p"},"Web")," \u662f\u6784\u5efa\u5728\u540c\u6e90\u7b56\u7565\u57fa\u7840\u4e4b\u4e0a\u7684\uff0c\u6d4f\u89c8\u5668\u53ea\u662f\u9488\u5bf9\u540c\u6e90\u7b56\u7565\u7684\u4e00\u79cd\u5b9e\u73b0\u3002\u540c\u6e90\u7b56\u7565\u4f1a\u963b\u6b62\u4e00\u4e2a\u57df\u7684 javascript \u811a\u672c\u548c\u53e6\u5916\u4e00\u4e2a\u57df\u7684\u5185\u5bb9\u8fdb\u884c\u4ea4\u4e92\u3002\u6240\u8c13\u540c\u6e90\uff08\u5373\u6307\u5728\u540c\u4e00\u4e2a\u57df\uff09\u5c31\u662f\u4e24\u4e2a\u9875\u9762\u5177\u6709\u76f8\u540c\u7684\u534f\u8bae\uff08protocol\uff09\uff0c\u4e3b\u673a\uff08host\uff09\u548c\u7aef\u53e3\u53f7\uff08port\uff09"),(0,r.kt)("h2",{id:"162-\u6709\u8de8\u57df\u884c\u4e3a\u793a\u4f8b"},"16.2 \u6709\u8de8\u57df\u884c\u4e3a\u793a\u4f8b"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u5f53\u524d\u9875\u9762 url"),(0,r.kt)("th",{parentName:"tr",align:null},"\u88ab\u8bf7\u6c42\u9875\u9762 url"),(0,r.kt)("th",{parentName:"tr",align:null},"\u662f\u5426\u8de8\u57df"),(0,r.kt)("th",{parentName:"tr",align:null},"\u539f\u56e0"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.furion.icu/"},"http://www.furion.icu/")),(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.furion.icu/index.html"},"http://www.furion.icu/index.html")),(0,r.kt)("td",{parentName:"tr",align:null},"\u5426"),(0,r.kt)("td",{parentName:"tr",align:null},"\u540c\u6e90\uff08\u534f\u8bae\u3001\u57df\u540d\u3001\u7aef\u53e3\u53f7\u76f8\u540c\uff09")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.furion.icu/"},"http://www.furion.icu/")),(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"https://www.furion.icu/index.html"},"https://www.furion.icu/index.html")),(0,r.kt)("td",{parentName:"tr",align:null},"\u8de8\u57df"),(0,r.kt)("td",{parentName:"tr",align:null},"\u534f\u8bae\u4e0d\u540c\uff08http/https\uff09")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.furion.icu/"},"http://www.furion.icu/")),(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.baidu.com/"},"http://www.baidu.com/")),(0,r.kt)("td",{parentName:"tr",align:null},"\u8de8\u57df"),(0,r.kt)("td",{parentName:"tr",align:null},"\u4e3b\u57df\u540d\u4e0d\u540c\uff08chinadot/baidu\uff09")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.furion.icu/"},"http://www.furion.icu/")),(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://blog.furion.icu/"},"http://blog.furion.icu/")),(0,r.kt)("td",{parentName:"tr",align:null},"\u8de8\u57df"),(0,r.kt)("td",{parentName:"tr",align:null},"\u5b50\u57df\u540d\u4e0d\u540c\uff08www/blog\uff09")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.furion.icu:8080/"},"http://www.furion.icu:8080/")),(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.furion.icu:7001/"},"http://www.furion.icu:7001/")),(0,r.kt)("td",{parentName:"tr",align:null},"\u8de8\u57df"),(0,r.kt)("td",{parentName:"tr",align:null},"\u7aef\u53e3\u53f7\u4e0d\u540c\uff088080/7001\uff09")))),(0,r.kt)("h2",{id:"163-\u4ec0\u4e48\u662f-cors"},"16.3 \u4ec0\u4e48\u662f CORS"),(0,r.kt)("p",null,"\u8de8\u6e90\u8d44\u6e90\u5171\u4eab (",(0,r.kt)("inlineCode",{parentName:"p"},"CORS"),") \uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u662f\u4e00\u79cd ",(0,r.kt)("inlineCode",{parentName:"li"},"W3C")," \u6807\u51c6\uff0c\u53ef\u8ba9\u670d\u52a1\u5668\u653e\u5bbd\u76f8\u540c\u7684\u6e90\u7b56\u7565\u3002"),(0,r.kt)("li",{parentName:"ul"},"\u4e0d\u662f\u4e00\u9879\u5b89\u5168\u529f\u80fd\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"CORS")," \u653e\u5bbd ",(0,r.kt)("inlineCode",{parentName:"li"},"security"),"\u3002 ",(0,r.kt)("inlineCode",{parentName:"li"},"API")," \u4e0d\u80fd\u901a\u8fc7\u5141\u8bb8 ",(0,r.kt)("inlineCode",{parentName:"li"},"CORS")," \u6765\u66f4\u5b89\u5168\u3002 \u6709\u5173\u8be6\u7ec6\u4fe1\u606f\uff0c\u8bf7\u53c2\u9605 ",(0,r.kt)("a",{parentName:"li",href:"https://docs.microsoft.com/zh-cn/aspnet/core/security/cors?view=aspnetcore-5.0#how-cors"},"CORS \u5de5\u4f5c\u539f\u7406"),"\u3002"),(0,r.kt)("li",{parentName:"ul"},"\u5141\u8bb8\u670d\u52a1\u5668\u660e\u786e\u5141\u8bb8\u4e00\u4e9b\u8de8\u6e90\u8bf7\u6c42\uff0c\u540c\u65f6\u62d2\u7edd\u5176\u4ed6\u8bf7\u6c42\u3002"),(0,r.kt)("li",{parentName:"ul"},"\u6bd4\u65e9\u671f\u7684\u6280\u672f\uff08\u5982 JSONP\uff09\u66f4\u5b89\u5168\u4e14\u66f4\u7075\u6d3b\u3002")),(0,r.kt)("h2",{id:"164-\u5982\u4f55\u4f7f\u7528"},"16.4 \u5982\u4f55\u4f7f\u7528"),(0,r.kt)("h3",{id:"1641-\u6dfb\u52a0-cors-\u670d\u52a1"},"16.4.1 \u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"h3"},"CORS")," \u670d\u52a1"),(0,r.kt)("p",null,"\u542f\u7528\u8de8\u57df ",(0,r.kt)("inlineCode",{parentName:"p"},"Cors")," \u652f\u6301\u9996\u5148\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"CorsAccessor")," \u670d\u52a1\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,22}",showLineNumbers:!0,"":!0,"{13,22}":!0},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Furion.Web.Core\n{\n [AppStartup(700)]\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddCorsAccessor();\n\n // ...\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n //...\n\n app.UseCorsAccessor();\n\n // ...\n }\n }\n}\n")),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"services.AddCorsAccessor();")," \u9700\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"services.AddControllers()")," \u4e4b\u524d\u6ce8\u518c\u3002"),(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"app.UseCorsAccessor();")," \u9700\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"app.UseRouting();")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"app.UseAuthentication();")," \u4e4b\u95f4\u6ce8\u518c\u3002")),(0,r.kt)("h3",{id:"1642-\u914d\u7f6e\u5141\u8bb8\u8de8\u57df\u57df\u540d"},"16.4.2 \u914d\u7f6e\u5141\u8bb8\u8de8\u57df\u57df\u540d"),(0,r.kt)("admonition",{title:"\u5c0f\u63d0\u9192",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u5141\u8bb8\u6240\u6709\u57df\u540d\u6765\u6e90\u8bbf\u95ee\uff0c\u4e5f\u5c31\u662f\u65e0\u9700\u914d\u7f6e\u4efb\u4f55\u6765\u6e90\u57df\u540d\uff0c\u53e6\u5916\u524d\u7aef\u4e5f\u9700\u8981\u8bbe\u7f6e\u8bf7\u6c42\u53c2\u6570\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"withCredentials:false"))),(0,r.kt)("p",null,"\u5982\u679c\u9700\u8981\u6307\u5b9a\u7279\u5b9a\u57df\u540d\uff0c\u5219\u6dfb\u52a0\u4ee5\u4e0b\u914d\u7f6e\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},'{\n "CorsAccessorSettings": {\n "PolicyName": "\u81ea\u5b9a\u4e49\u8de8\u57df\u7b56\u7565\u540d",\n "WithOrigins": ["http://localhost:4200", "https://furion.icu"]\n }\n}\n')),(0,r.kt)("h2",{id:"165-corsaccessorsettings-\u914d\u7f6e"},"16.5 ",(0,r.kt)("inlineCode",{parentName:"h2"},"CorsAccessorSettings")," \u914d\u7f6e"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"CorsAccessorSettings"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"PolicyName"),"\uff1a\u8de8\u57df\u7b56\u7565\u540d\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u5fc5\u586b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"App.Cors.Policy")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"WithOrigins"),"\uff1a\u5141\u8bb8\u8de8\u57df\u7684\u57df\u540d\u5217\u8868\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string[]")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"*")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"WithHeaders"),"\uff1a\u8bf7\u6c42\u8868\u5934\uff0c\u6ca1\u6709\u914d\u7f6e\u5219\u5141\u8bb8\u6240\u6709\u8868\u5934\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string[]")," \u7c7b\u578b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"WithExposedHeaders"),"\uff1a\u8bbe\u7f6e\u5ba2\u6237\u7aef\u53ef\u83b7\u53d6\u7684\u54cd\u5e94\u6807\u5934\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string[]")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},'["access-token", "x-access-token"]')),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"WithMethods"),"\uff1a\u8bbe\u7f6e\u8de8\u57df\u5141\u8bb8\u8bf7\u6c42\u8c13\u8bcd\uff0c\u6ca1\u6709\u914d\u7f6e\u5219\u5141\u8bb8\u6240\u6709\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string[]")," \u7c7b\u578b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AllowCredentials"),"\uff1a\u662f\u5426\u5141\u8bb8\u8de8\u57df\u8bf7\u6c42\u4e2d\u7684\u51ed\u636e\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4\u503c ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SetPreflightMaxAge"),"\uff1a\u8bbe\u7f6e\u9884\u68c0\u8fc7\u671f\u65f6\u95f4\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"int")," \u7c7b\u578b\uff0c\u9ed8\u8ba4\u503c ",(0,r.kt)("inlineCode",{parentName:"li"},"24\u5c0f\u65f6")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"FixedClientToken"),"\uff1a\u662f\u5426\u9ed8\u8ba4\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"WithExposedHeaders"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SignalRSupport"),"\uff1a\u662f\u5426\u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"SignalR")," \u8de8\u57df\u652f\u6301\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false"))))),(0,r.kt)("h2",{id:"166-\u524d\u7aef\u4e0d\u80fd\u8bfb\u53d6\u54cd\u5e94\u5934\u6ce8\u610f\u4e8b\u9879"},"16.6 \u524d\u7aef\u4e0d\u80fd\u8bfb\u53d6\u54cd\u5e94\u5934\u6ce8\u610f\u4e8b\u9879"),(0,r.kt)("p",null,"\u6709\u65f6\u5019\uff0c\u6211\u4eec\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"ajax")," \u6216\u8005 ",(0,r.kt)("inlineCode",{parentName:"p"},"axios")," \u7b2c\u4e09\u65b9\u5e93\u65e0\u6cd5\u8bfb\u53d6\u54cd\u5e94\u5934\u81ea\u5b9a\u4e49\u4fe1\u606f\uff0c\u8fd9\u65f6\u9700\u8981\u54cd\u5e94\u62a5\u6587\u4e2d\u516c\u5f00\u7279\u5b9a ",(0,r.kt)("inlineCode",{parentName:"p"},"Header")," \u624d\u80fd\u653e\u884c\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"Access-Control-Expose-Headers: xxxxx"),"\uff0c\u6240\u4ee5\uff0c\u9700\u8981\u6dfb\u52a0\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="appsettings.json"',showLineNumbers:!0,title:'"appsettings.json"'},'{\n "CorsAccessorSettings": {\n "WithExposedHeaders": ["access-token","x-access-token"]\n }\n}\n')),(0,r.kt)("p",null,"\u9700\u8981\u83b7\u53d6\u54ea\u4e2a\u5934\uff0c\u5c31\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"WithExposedHeaders")," \u6570\u7ec4\u4e2d\u914d\u7f6e\u5373\u53ef\u3002\u5982\u679c\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"ajax")," \u53ef\u4ee5\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"xhr.getResponseHeader(key)")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"xhr.getAllResponseHeaders()")," \u83b7\u53d6\u914d\u7f6e\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"key"),"\u3002"),(0,r.kt)("p",null,"\u7279\u522b\u60c5\u51b5\u4e0b\u4e0d\u80fd\u8bf7\u6c42\uff0c\u53ef\u4ee5\u8003\u8651\u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"withCredentials: false")," \u3002"),(0,r.kt)("h2",{id:"167-\u4f7f\u7528-ajax-\u524d\u7aef\u6ce8\u610f\u4e8b\u9879"},"16.7 \u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"h2"},"$.ajax")," \u524d\u7aef\u6ce8\u610f\u4e8b\u9879"),(0,r.kt)("p",null,"\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"Jquery")," \u524d\u7aef\u8bf7\u6c42\u53ef\u4ee5\u53c2\u8003\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4-7}",showLineNumbers:!0,"":!0,"{4-7}":!0},'$.ajax({\n \xa0 \xa0 \xa0 \xa0url: "https://localhost:5001/api/system/getdata",\n \xa0 \xa0 \xa0 \xa0type: "GET",\n \xa0 \xa0 \xa0 \xa0xhrFields: {\n \xa0 \xa0 \xa0 \xa0\xa0 \xa0 withCredentials: false // \u5982\u679c\u662fhttps\u8bf7\u6c42\uff0c\u53ef\u4ee5\u8bd5\u8bd5 true\n \xa0 \xa0 \xa0 \xa0},\n \xa0 \xa0 \xa0 \xa0crossDomain: true,\n \xa0 \xa0 \xa0 \xa0success: function (res) {\n \xa0 \xa0 \xa0 \xa0\xa0 \xa0 render(res);\n \xa0 \xa0 \xa0 \xa0}\n});\n')),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u5728\u672c\u5730\u5f00\u53d1\u9636\u6bb5\uff0c\u8bf7\u6c42\u5982\u679c\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"p"}," Access to XMLHttpRequest...has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header...")," \u9519\u8bef\uff0c\u8bf7\u786e\u4fdd ",(0,r.kt)("inlineCode",{parentName:"p"},"ajax")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"url")," \u53c2\u6570\u662f\u6b63\u786e\u7684\uff0c\u901a\u5e38",(0,r.kt)("strong",{parentName:"p"},"\u9519\u8bef\u7684\u505a\u6cd5"),"\u662f\uff1a"),(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},"\u4f7f\u7528\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"127.0.0.1")," \u800c\u4e0d\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"localhost")," \u4e3b\u673a\u5730\u5740"),(0,r.kt)("li",{parentName:"ul"},"\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"http")," \u800c\u4e0d\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"https")," \u4e3b\u673a\u534f\u8bae"),(0,r.kt)("li",{parentName:"ul"},"\u4f7f\u7528\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"5000")," \u800c\u4e0d\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"5001")," \u4e3b\u673a\u7aef\u53e3"))),(0,r.kt)("h2",{id:"168-\u7981\u7528\u8de8\u57df"},"16.8 \u7981\u7528\u8de8\u57df"),(0,r.kt)("p",null,"\u6709\u65f6\u5019\uff0c\u6211\u4eec\u5e0c\u671b\u67d0\u4e2a\u65b9\u6cd5\u4e0d\u68c0\u67e5\u8de8\u57df\u8bf7\u6c42\uff0c\u53ef\u4ee5\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Action")," \u4e2d\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[DisableCors]")," \u7279\u6027\u5373\u53ef\u3002"),(0,r.kt)("h2",{id:"169-signalr-\u8de8\u57df\u95ee\u9898"},"16.9 ",(0,r.kt)("inlineCode",{parentName:"h2"},"SignalR")," \u8de8\u57df\u95ee\u9898"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"SignalR")," \u5b9e\u73b0\u8de8\u57df\u9700\u8981\u6ee1\u8db3\u4e0b\u9762\u51e0\u4e2a\u6761\u4ef6\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u5141\u8bb8\u7279\u5b9a\u7684\u9884\u671f\u6765\u6e90\uff0c\u5141\u8bb8\u4efb\u4f55\u6765\u6e90\u662f\u53ef\u884c\u7684\uff0c\u4f46\u4e0d\u5b89\u5168\u6216\u4e0d\u63a8\u8350\u4f7f\u7528"),(0,r.kt)("li",{parentName:"ul"},"\u5fc5\u987b\u5141\u8bb8\u4f7f\u7528 HTTP \u65b9\u6cd5 ",(0,r.kt)("inlineCode",{parentName:"li"},"GET")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"POST")),(0,r.kt)("li",{parentName:"ul"},"\u4e3a\u4e86\u4f7f\u57fa\u4e8e ",(0,r.kt)("inlineCode",{parentName:"li"},"cookie")," \u7684\u7c98\u6ede\u4f1a\u8bdd\u6b63\u5e38\u5de5\u4f5c\uff0c\u5fc5\u987b\u5141\u8bb8\u4f7f\u7528\u51ed\u636e\uff0c\u5373\u4f7f\u672a\u4f7f\u7528\u8eab\u4efd\u9a8c\u8bc1\uff0c\u4e5f\u5fc5\u987b\u542f\u7528\u5b83\u4eec\u3002")),(0,r.kt)("p",null,"\u5b98\u65b9\u6587\u6863\u8bf4\u660e ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/signalr/security?view=aspnetcore-6.0"},"https://docs.microsoft.com/zh-cn/aspnet/core/signalr/security?view=aspnetcore-6.0")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion 4.1.4+")," \u7248\u672c\u5df2\u4fee\u6b63 ",(0,r.kt)("inlineCode",{parentName:"strong"},"SignalR")," \u8de8\u57df\u95ee\u9898\uff0c\u53ea\u9700\u8981\u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"strong"},"SignalRSupport")," \u914d\u7f6e\u5373\u53ef"),"\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2,3}",showLineNumbers:!0,"{2,3}":!0},'{\n "CorsAccessorSettings": {\n "SignalRSupport": true\n }\n}\n')),(0,r.kt)("h2",{id:"1610-\u53cd\u9988\u4e0e\u5efa\u8bae"},"16.10 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,r.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,r.kt)("hr",null),(0,r.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"p"},"\u8de8\u57df\u8bf7\u6c42")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/security/cors?view=aspnetcore-5.0"},"ASP.NET Core - \u542f\u7528\u8de8\u57df\u8bf7\u6c42")," \u7ae0\u8282\u3002")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/00cf5050.edbd97d1.js b/handbook/build/assets/js/00cf5050.edbd97d1.js deleted file mode 100644 index 50940dcbc6..0000000000 --- a/handbook/build/assets/js/00cf5050.edbd97d1.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[8133],{9625:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return p},default:function(){return m},frontMatter:function(){return o},metadata:function(){return s},toc:function(){return d}});var a=n(3117),i=n(102),r=(n(7294),n(3905)),l=["components"],o={id:"cors",title:"16. CORS \u8de8\u57df",sidebar_label:"16. CORS \u8de8\u57df"},p=void 0,s={unversionedId:"cors",id:"cors",title:"16. CORS \u8de8\u57df",description:"16.1 \u4ec0\u4e48\u662f\u8de8\u57df",source:"@site/docs/cors.mdx",sourceDirName:".",slug:"/cors",permalink:"/furion/docs/cors",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/cors.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1659267650,formattedLastUpdatedAt:"Jul 31, 2022",frontMatter:{id:"cors",title:"16. CORS \u8de8\u57df",sidebar_label:"16. CORS \u8de8\u57df"},sidebar:"docs",previous:{title:"15. \u5b89\u5168\u9274\u6743",permalink:"/furion/docs/auth-control"},next:{title:"17. \u89c6\u56fe\u5f15\u64ce",permalink:"/furion/docs/view-engine"}},u={},d=[{value:"16.1 \u4ec0\u4e48\u662f\u8de8\u57df",id:"161-\u4ec0\u4e48\u662f\u8de8\u57df",level:2},{value:"16.2 \u6709\u8de8\u57df\u884c\u4e3a\u793a\u4f8b",id:"162-\u6709\u8de8\u57df\u884c\u4e3a\u793a\u4f8b",level:2},{value:"16.3 \u4ec0\u4e48\u662f CORS",id:"163-\u4ec0\u4e48\u662f-cors",level:2},{value:"16.4 \u5982\u4f55\u4f7f\u7528",id:"164-\u5982\u4f55\u4f7f\u7528",level:2},{value:"16.4.1 \u6dfb\u52a0 CORS \u670d\u52a1",id:"1641-\u6dfb\u52a0-cors-\u670d\u52a1",level:3},{value:"16.4.2 \u914d\u7f6e\u5141\u8bb8\u8de8\u57df\u57df\u540d",id:"1642-\u914d\u7f6e\u5141\u8bb8\u8de8\u57df\u57df\u540d",level:3},{value:"16.5 CorsAccessorSettings \u914d\u7f6e",id:"165-corsaccessorsettings-\u914d\u7f6e",level:2},{value:"16.6 \u524d\u7aef\u4e0d\u80fd\u8bfb\u53d6\u54cd\u5e94\u5934\u6ce8\u610f\u4e8b\u9879",id:"166-\u524d\u7aef\u4e0d\u80fd\u8bfb\u53d6\u54cd\u5e94\u5934\u6ce8\u610f\u4e8b\u9879",level:2},{value:"16.7 \u4f7f\u7528 $.ajax \u524d\u7aef\u6ce8\u610f\u4e8b\u9879",id:"167-\u4f7f\u7528-ajax-\u524d\u7aef\u6ce8\u610f\u4e8b\u9879",level:2},{value:"16.8 \u7981\u7528\u8de8\u57df",id:"168-\u7981\u7528\u8de8\u57df",level:2},{value:"16.9 SignalR \u8de8\u57df\u95ee\u9898",id:"169-signalr-\u8de8\u57df\u95ee\u9898",level:2},{value:"16.10 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"1610-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:d};function m(e){var t=e.components,n=(0,i.Z)(e,l);return(0,r.kt)("wrapper",(0,a.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"161-\u4ec0\u4e48\u662f\u8de8\u57df"},"16.1 \u4ec0\u4e48\u662f\u8de8\u57df"),(0,r.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u5f53\u4e00\u4e2a\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"p"},"url")," \u7684\u534f\u8bae\u3001\u57df\u540d\u3001\u7aef\u53e3\u4e09\u8005\u4e4b\u95f4\u4efb\u610f\u4e00\u4e2a\u4e0e\u5f53\u524d\u9875\u9762 ",(0,r.kt)("inlineCode",{parentName:"p"},"url")," \u4e0d\u540c\u5373\u4e3a\u8de8\u57df\u3002\u90a3\u4e3a\u4ec0\u4e48\u4f1a\u51fa\u73b0\u8de8\u57df\u95ee\u9898\u5462\uff1f"),(0,r.kt)("p",null,"\u51fa\u4e8e\u6d4f\u89c8\u5668\u7684\u540c\u6e90\u7b56\u7565\u9650\u5236\u3002\u540c\u6e90\u7b56\u7565\uff08Sameoriginpolicy\uff09\u662f\u4e00\u79cd\u7ea6\u5b9a\uff0c\u5b83\u662f\u6d4f\u89c8\u5668\u6700\u6838\u5fc3\u4e5f\u6700\u57fa\u672c\u7684\u5b89\u5168\u529f\u80fd\uff0c\u5982\u679c\u7f3a\u5c11\u4e86\u540c\u6e90\u7b56\u7565\uff0c\u5219\u6d4f\u89c8\u5668\u7684\u6b63\u5e38\u529f\u80fd\u53ef\u80fd\u90fd\u4f1a\u53d7\u5230\u5f71\u54cd\u3002\u53ef\u4ee5\u8bf4 ",(0,r.kt)("inlineCode",{parentName:"p"},"Web")," \u662f\u6784\u5efa\u5728\u540c\u6e90\u7b56\u7565\u57fa\u7840\u4e4b\u4e0a\u7684\uff0c\u6d4f\u89c8\u5668\u53ea\u662f\u9488\u5bf9\u540c\u6e90\u7b56\u7565\u7684\u4e00\u79cd\u5b9e\u73b0\u3002\u540c\u6e90\u7b56\u7565\u4f1a\u963b\u6b62\u4e00\u4e2a\u57df\u7684 javascript \u811a\u672c\u548c\u53e6\u5916\u4e00\u4e2a\u57df\u7684\u5185\u5bb9\u8fdb\u884c\u4ea4\u4e92\u3002\u6240\u8c13\u540c\u6e90\uff08\u5373\u6307\u5728\u540c\u4e00\u4e2a\u57df\uff09\u5c31\u662f\u4e24\u4e2a\u9875\u9762\u5177\u6709\u76f8\u540c\u7684\u534f\u8bae\uff08protocol\uff09\uff0c\u4e3b\u673a\uff08host\uff09\u548c\u7aef\u53e3\u53f7\uff08port\uff09"),(0,r.kt)("h2",{id:"162-\u6709\u8de8\u57df\u884c\u4e3a\u793a\u4f8b"},"16.2 \u6709\u8de8\u57df\u884c\u4e3a\u793a\u4f8b"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u5f53\u524d\u9875\u9762 url"),(0,r.kt)("th",{parentName:"tr",align:null},"\u88ab\u8bf7\u6c42\u9875\u9762 url"),(0,r.kt)("th",{parentName:"tr",align:null},"\u662f\u5426\u8de8\u57df"),(0,r.kt)("th",{parentName:"tr",align:null},"\u539f\u56e0"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.furion.icu/"},"http://www.furion.icu/")),(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.furion.icu/index.html"},"http://www.furion.icu/index.html")),(0,r.kt)("td",{parentName:"tr",align:null},"\u5426"),(0,r.kt)("td",{parentName:"tr",align:null},"\u540c\u6e90\uff08\u534f\u8bae\u3001\u57df\u540d\u3001\u7aef\u53e3\u53f7\u76f8\u540c\uff09")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.furion.icu/"},"http://www.furion.icu/")),(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"https://www.furion.icu/index.html"},"https://www.furion.icu/index.html")),(0,r.kt)("td",{parentName:"tr",align:null},"\u8de8\u57df"),(0,r.kt)("td",{parentName:"tr",align:null},"\u534f\u8bae\u4e0d\u540c\uff08http/https\uff09")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.furion.icu/"},"http://www.furion.icu/")),(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.baidu.com/"},"http://www.baidu.com/")),(0,r.kt)("td",{parentName:"tr",align:null},"\u8de8\u57df"),(0,r.kt)("td",{parentName:"tr",align:null},"\u4e3b\u57df\u540d\u4e0d\u540c\uff08chinadot/baidu\uff09")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.furion.icu/"},"http://www.furion.icu/")),(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://blog.furion.icu/"},"http://blog.furion.icu/")),(0,r.kt)("td",{parentName:"tr",align:null},"\u8de8\u57df"),(0,r.kt)("td",{parentName:"tr",align:null},"\u5b50\u57df\u540d\u4e0d\u540c\uff08www/blog\uff09")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.furion.icu:8080/"},"http://www.furion.icu:8080/")),(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("a",{parentName:"td",href:"http://www.furion.icu:7001/"},"http://www.furion.icu:7001/")),(0,r.kt)("td",{parentName:"tr",align:null},"\u8de8\u57df"),(0,r.kt)("td",{parentName:"tr",align:null},"\u7aef\u53e3\u53f7\u4e0d\u540c\uff088080/7001\uff09")))),(0,r.kt)("h2",{id:"163-\u4ec0\u4e48\u662f-cors"},"16.3 \u4ec0\u4e48\u662f CORS"),(0,r.kt)("p",null,"\u8de8\u6e90\u8d44\u6e90\u5171\u4eab (",(0,r.kt)("inlineCode",{parentName:"p"},"CORS"),") \uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u662f\u4e00\u79cd ",(0,r.kt)("inlineCode",{parentName:"li"},"W3C")," \u6807\u51c6\uff0c\u53ef\u8ba9\u670d\u52a1\u5668\u653e\u5bbd\u76f8\u540c\u7684\u6e90\u7b56\u7565\u3002"),(0,r.kt)("li",{parentName:"ul"},"\u4e0d\u662f\u4e00\u9879\u5b89\u5168\u529f\u80fd\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"CORS")," \u653e\u5bbd ",(0,r.kt)("inlineCode",{parentName:"li"},"security"),"\u3002 ",(0,r.kt)("inlineCode",{parentName:"li"},"API")," \u4e0d\u80fd\u901a\u8fc7\u5141\u8bb8 ",(0,r.kt)("inlineCode",{parentName:"li"},"CORS")," \u6765\u66f4\u5b89\u5168\u3002 \u6709\u5173\u8be6\u7ec6\u4fe1\u606f\uff0c\u8bf7\u53c2\u9605 ",(0,r.kt)("a",{parentName:"li",href:"https://docs.microsoft.com/zh-cn/aspnet/core/security/cors?view=aspnetcore-5.0#how-cors"},"CORS \u5de5\u4f5c\u539f\u7406"),"\u3002"),(0,r.kt)("li",{parentName:"ul"},"\u5141\u8bb8\u670d\u52a1\u5668\u660e\u786e\u5141\u8bb8\u4e00\u4e9b\u8de8\u6e90\u8bf7\u6c42\uff0c\u540c\u65f6\u62d2\u7edd\u5176\u4ed6\u8bf7\u6c42\u3002"),(0,r.kt)("li",{parentName:"ul"},"\u6bd4\u65e9\u671f\u7684\u6280\u672f\uff08\u5982 JSONP\uff09\u66f4\u5b89\u5168\u4e14\u66f4\u7075\u6d3b\u3002")),(0,r.kt)("h2",{id:"164-\u5982\u4f55\u4f7f\u7528"},"16.4 \u5982\u4f55\u4f7f\u7528"),(0,r.kt)("h3",{id:"1641-\u6dfb\u52a0-cors-\u670d\u52a1"},"16.4.1 \u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"h3"},"CORS")," \u670d\u52a1"),(0,r.kt)("p",null,"\u542f\u7528\u8de8\u57df ",(0,r.kt)("inlineCode",{parentName:"p"},"Cors")," \u652f\u6301\u9996\u5148\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"CorsAccessor")," \u670d\u52a1\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,22}",showLineNumbers:!0,"":!0,"{13,22}":!0},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Furion.Web.Core\n{\n [AppStartup(700)]\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddCorsAccessor();\n\n // ...\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n //...\n\n app.UseCorsAccessor();\n\n // ...\n }\n }\n}\n")),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"services.AddCorsAccessor();")," \u9700\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"services.AddControllers()")," \u4e4b\u524d\u6ce8\u518c\u3002"),(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"app.UseCorsAccessor();")," \u9700\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"app.UseRouting();")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"app.UseAuthentication();")," \u4e4b\u95f4\u6ce8\u518c\u3002")),(0,r.kt)("h3",{id:"1642-\u914d\u7f6e\u5141\u8bb8\u8de8\u57df\u57df\u540d"},"16.4.2 \u914d\u7f6e\u5141\u8bb8\u8de8\u57df\u57df\u540d"),(0,r.kt)("admonition",{title:"\u5c0f\u63d0\u9192",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u5141\u8bb8\u6240\u6709\u57df\u540d\u6765\u6e90\u8bbf\u95ee\uff0c\u4e5f\u5c31\u662f\u65e0\u9700\u914d\u7f6e\u4efb\u4f55\u6765\u6e90\u57df\u540d\uff0c\u53e6\u5916\u524d\u7aef\u4e5f\u9700\u8981\u8bbe\u7f6e\u8bf7\u6c42\u53c2\u6570\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"withCredentials:false"))),(0,r.kt)("p",null,"\u5982\u679c\u9700\u8981\u6307\u5b9a\u7279\u5b9a\u57df\u540d\uff0c\u5219\u6dfb\u52a0\u4ee5\u4e0b\u914d\u7f6e\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},'{\n "CorsAccessorSettings": {\n "PolicyName": "\u81ea\u5b9a\u4e49\u8de8\u57df\u7b56\u7565\u540d",\n "WithOrigins": ["http://localhost:4200", "https://furion.icu"]\n }\n}\n')),(0,r.kt)("h2",{id:"165-corsaccessorsettings-\u914d\u7f6e"},"16.5 ",(0,r.kt)("inlineCode",{parentName:"h2"},"CorsAccessorSettings")," \u914d\u7f6e"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"CorsAccessorSettings"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"PolicyName"),"\uff1a\u8de8\u57df\u7b56\u7565\u540d\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u5fc5\u586b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"App.Cors.Policy")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"WithOrigins"),"\uff1a\u5141\u8bb8\u8de8\u57df\u7684\u57df\u540d\u5217\u8868\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string[]")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"*")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"WithHeaders"),"\uff1a\u8bf7\u6c42\u8868\u5934\uff0c\u6ca1\u6709\u914d\u7f6e\u5219\u5141\u8bb8\u6240\u6709\u8868\u5934\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string[]")," \u7c7b\u578b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"WithExposedHeaders"),"\uff1a\u8bbe\u7f6e\u5ba2\u6237\u7aef\u53ef\u83b7\u53d6\u7684\u54cd\u5e94\u6807\u5934\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string[]")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},'["access-token", "x-access-token"]')),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"WithMethods"),"\uff1a\u8bbe\u7f6e\u8de8\u57df\u5141\u8bb8\u8bf7\u6c42\u8c13\u8bcd\uff0c\u6ca1\u6709\u914d\u7f6e\u5219\u5141\u8bb8\u6240\u6709\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string[]")," \u7c7b\u578b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AllowCredentials"),"\uff1a\u662f\u5426\u5141\u8bb8\u8de8\u57df\u8bf7\u6c42\u4e2d\u7684\u51ed\u636e\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4\u503c ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SetPreflightMaxAge"),"\uff1a\u8bbe\u7f6e\u9884\u68c0\u8fc7\u671f\u65f6\u95f4\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"int")," \u7c7b\u578b\uff0c\u9ed8\u8ba4\u503c ",(0,r.kt)("inlineCode",{parentName:"li"},"24\u5c0f\u65f6")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"FixedClientToken"),"\uff1a\u662f\u5426\u9ed8\u8ba4\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"WithExposedHeaders"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SignalRSupport"),"\uff1a\u662f\u5426\u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"SignalR")," \u8de8\u57df\u652f\u6301\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false"))))),(0,r.kt)("h2",{id:"166-\u524d\u7aef\u4e0d\u80fd\u8bfb\u53d6\u54cd\u5e94\u5934\u6ce8\u610f\u4e8b\u9879"},"16.6 \u524d\u7aef\u4e0d\u80fd\u8bfb\u53d6\u54cd\u5e94\u5934\u6ce8\u610f\u4e8b\u9879"),(0,r.kt)("p",null,"\u6709\u65f6\u5019\uff0c\u6211\u4eec\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"ajax")," \u6216\u8005 ",(0,r.kt)("inlineCode",{parentName:"p"},"axios")," \u7b2c\u4e09\u65b9\u5e93\u65e0\u6cd5\u8bfb\u53d6\u54cd\u5e94\u5934\u81ea\u5b9a\u4e49\u4fe1\u606f\uff0c\u8fd9\u65f6\u9700\u8981\u54cd\u5e94\u62a5\u6587\u4e2d\u516c\u5f00\u7279\u5b9a ",(0,r.kt)("inlineCode",{parentName:"p"},"Header")," \u624d\u80fd\u653e\u884c\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"Access-Control-Expose-Headers: xxxxx"),"\uff0c\u6240\u4ee5\uff0c\u9700\u8981\u6dfb\u52a0\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="appsettings.json"',showLineNumbers:!0,title:'"appsettings.json"'},'{\n "CorsAccessorSettings": {\n "WithExposedHeaders": ["access-token","x-access-token"]\n }\n}\n')),(0,r.kt)("p",null,"\u9700\u8981\u83b7\u53d6\u54ea\u4e2a\u5934\uff0c\u5c31\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"WithExposedHeaders")," \u6570\u7ec4\u4e2d\u914d\u7f6e\u5373\u53ef\u3002\u5982\u679c\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"ajax")," \u53ef\u4ee5\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"xhr.getResponseHeader(key)")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"xhr.getAllResponseHeaders()")," \u83b7\u53d6\u914d\u7f6e\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"key"),"\u3002"),(0,r.kt)("p",null,"\u7279\u522b\u60c5\u51b5\u4e0b\u4e0d\u80fd\u8bf7\u6c42\uff0c\u53ef\u4ee5\u8003\u8651\u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"withCredentials: false")," \u3002"),(0,r.kt)("h2",{id:"167-\u4f7f\u7528-ajax-\u524d\u7aef\u6ce8\u610f\u4e8b\u9879"},"16.7 \u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"h2"},"$.ajax")," \u524d\u7aef\u6ce8\u610f\u4e8b\u9879"),(0,r.kt)("p",null,"\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"Jquery")," \u524d\u7aef\u8bf7\u6c42\u53ef\u4ee5\u53c2\u8003\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4-7}",showLineNumbers:!0,"":!0,"{4-7}":!0},'$.ajax({\n \xa0 \xa0 \xa0 \xa0url: "https://localhost:5001/api/system/getdata",\n \xa0 \xa0 \xa0 \xa0type: "GET",\n \xa0 \xa0 \xa0 \xa0xhrFields: {\n \xa0 \xa0 \xa0 \xa0\xa0 \xa0 withCredentials: false // \u5982\u679c\u662fhttps\u8bf7\u6c42\uff0c\u53ef\u4ee5\u8bd5\u8bd5 true\n \xa0 \xa0 \xa0 \xa0},\n \xa0 \xa0 \xa0 \xa0crossDomain: true,\n \xa0 \xa0 \xa0 \xa0success: function (res) {\n \xa0 \xa0 \xa0 \xa0\xa0 \xa0 render(res);\n \xa0 \xa0 \xa0 \xa0}\n});\n')),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u5728\u672c\u5730\u5f00\u53d1\u9636\u6bb5\uff0c\u8bf7\u6c42\u5982\u679c\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"p"}," Access to XMLHttpRequest...has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header...")," \u9519\u8bef\uff0c\u8bf7\u786e\u4fdd ",(0,r.kt)("inlineCode",{parentName:"p"},"ajax")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"url")," \u53c2\u6570\u662f\u6b63\u786e\u7684\uff0c\u901a\u5e38",(0,r.kt)("strong",{parentName:"p"},"\u9519\u8bef\u7684\u505a\u6cd5"),"\u662f\uff1a"),(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},"\u4f7f\u7528\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"127.0.0.1")," \u800c\u4e0d\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"localhost")," \u4e3b\u673a\u5730\u5740"),(0,r.kt)("li",{parentName:"ul"},"\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"http")," \u800c\u4e0d\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"https")," \u4e3b\u673a\u534f\u8bae"),(0,r.kt)("li",{parentName:"ul"},"\u4f7f\u7528\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"5000")," \u800c\u4e0d\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"5001")," \u4e3b\u673a\u7aef\u53e3"))),(0,r.kt)("h2",{id:"168-\u7981\u7528\u8de8\u57df"},"16.8 \u7981\u7528\u8de8\u57df"),(0,r.kt)("p",null,"\u6709\u65f6\u5019\uff0c\u6211\u4eec\u5e0c\u671b\u67d0\u4e2a\u65b9\u6cd5\u4e0d\u68c0\u67e5\u8de8\u57df\u8bf7\u6c42\uff0c\u53ef\u4ee5\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Action")," \u4e2d\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[DisableCors]")," \u7279\u6027\u5373\u53ef\u3002"),(0,r.kt)("h2",{id:"169-signalr-\u8de8\u57df\u95ee\u9898"},"16.9 ",(0,r.kt)("inlineCode",{parentName:"h2"},"SignalR")," \u8de8\u57df\u95ee\u9898"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"SignalR")," \u5b9e\u73b0\u8de8\u57df\u9700\u8981\u6ee1\u8db3\u4e0b\u9762\u51e0\u4e2a\u6761\u4ef6\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u5141\u8bb8\u7279\u5b9a\u7684\u9884\u671f\u6765\u6e90\uff0c\u5141\u8bb8\u4efb\u4f55\u6765\u6e90\u662f\u53ef\u884c\u7684\uff0c\u4f46\u4e0d\u5b89\u5168\u6216\u4e0d\u63a8\u8350\u4f7f\u7528"),(0,r.kt)("li",{parentName:"ul"},"\u5fc5\u987b\u5141\u8bb8\u4f7f\u7528 HTTP \u65b9\u6cd5 ",(0,r.kt)("inlineCode",{parentName:"li"},"GET")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"POST")),(0,r.kt)("li",{parentName:"ul"},"\u4e3a\u4e86\u4f7f\u57fa\u4e8e ",(0,r.kt)("inlineCode",{parentName:"li"},"cookie")," \u7684\u7c98\u6ede\u4f1a\u8bdd\u6b63\u5e38\u5de5\u4f5c\uff0c\u5fc5\u987b\u5141\u8bb8\u4f7f\u7528\u51ed\u636e\uff0c\u5373\u4f7f\u672a\u4f7f\u7528\u8eab\u4efd\u9a8c\u8bc1\uff0c\u4e5f\u5fc5\u987b\u542f\u7528\u5b83\u4eec\u3002")),(0,r.kt)("p",null,"\u5b98\u65b9\u6587\u6863\u8bf4\u660e ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/signalr/security?view=aspnetcore-6.0"},"https://docs.microsoft.com/zh-cn/aspnet/core/signalr/security?view=aspnetcore-6.0")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion 4.1.4+")," \u7248\u672c\u5df2\u4fee\u6b63 ",(0,r.kt)("inlineCode",{parentName:"strong"},"SignalR")," \u8de8\u57df\u95ee\u9898\uff0c\u53ea\u9700\u8981\u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"strong"},"SignalRSupport")," \u914d\u7f6e\u5373\u53ef"),"\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2,3}",showLineNumbers:!0,"{2,3}":!0},'{\n "CorsAccessorSettings": {\n "SignalRSupport": true\n }\n}\n')),(0,r.kt)("h2",{id:"1610-\u53cd\u9988\u4e0e\u5efa\u8bae"},"16.10 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,r.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,r.kt)("hr",null),(0,r.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"p"},"\u8de8\u57df\u8bf7\u6c42")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/security/cors?view=aspnetcore-5.0"},"ASP.NET Core - \u542f\u7528\u8de8\u57df\u8bf7\u6c42")," \u7ae0\u8282\u3002")))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return u},kt:function(){return m}});var a=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var p=a.createContext({}),s=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},u=function(e){var t=s(e.components);return a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},c=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,r=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),c=s(n),m=i,k=c["".concat(p,".").concat(m)]||c[m]||d[m]||r;return n?a.createElement(k,l(l({ref:t},u),{},{components:n})):a.createElement(k,l({ref:t},u))}));function m(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=n.length,l=new Array(r);l[0]=c;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:i,l[1]=o;for(var s=2;s.NET6 SDK",id:"2511-\u5b89\u88c5-net6-sdk",level:3},{value:"2.5.1.2 \u7f16\u8f91 .csproj \u6587\u4ef6",id:"2512-\u7f16\u8f91-csproj-\u6587\u4ef6",level:3},{value:"2.5.1.3 \u5347\u7ea7 Nuget \u5305",id:"2513-\u5347\u7ea7-nuget-\u5305",level:3},{value:"2.5.1.4 \u5220\u9664 Startup.cs \u6587\u4ef6",id:"2514-\u5220\u9664-startupcs-\u6587\u4ef6",level:3},{value:"2.5.1.5 \u7f16\u8f91 Web \u542f\u52a8\u5c42 .csproj",id:"2515-\u7f16\u8f91-web-\u542f\u52a8\u5c42-csproj",level:3},{value:"2.5.1.6 \u66ff\u6362 Program.cs \u5185\u5bb9\u4e3a\uff1a",id:"2516-\u66ff\u6362-programcs-\u5185\u5bb9\u4e3a",level:3},{value:"2.5.1.7 \u91cd\u65b0\u7f16\u8bd1\u6574\u4e2a\u89e3\u51b3\u65b9\u6848",id:"2517-\u91cd\u65b0\u7f16\u8bd1\u6574\u4e2a\u89e3\u51b3\u65b9\u6848",level:3}],m={toc:s};function k(e){var t=e.components,n=(0,o.Z)(e,p);return(0,i.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"251-\u5347\u7ea7\u6ce8\u610f\u4e8b\u9879"},"2.5.1 \u5347\u7ea7\u6ce8\u610f\u4e8b\u9879"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u76ee\u524d\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v2.x")," \u7248\u672c\u7684\u7528\u6237\u5747\u53ef\u4ee5\u5feb\u901f\u65e0\u7f1d\u5347\u7ea7\u81f3 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v4.x")," \u7248\u672c\uff0c\u53ea\u9700\u8981\u505a\u5c11\u91cf\u66f4\u6539\u5373\u53ef\u3002")),(0,i.kt)("h3",{id:"2511-\u5b89\u88c5-net6-sdk"},"2.5.1.1 \u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h3"},".NET6 SDK")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/download/dotnet/6.0"},"https://dotnet.microsoft.com/download/dotnet/6.0")),(0,i.kt)("h3",{id:"2512-\u7f16\u8f91-csproj-\u6587\u4ef6"},"2.5.1.2 \u7f16\u8f91 ",(0,i.kt)("inlineCode",{parentName:"h3"},".csproj")," \u6587\u4ef6"),(0,i.kt)("p",null,"\u7f16\u8f91\u89e3\u51b3\u65b9\u6848\u6240\u6709\u9879\u76ee\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},".csproj")," \u6587\u4ef6\uff0c\u5e76\u66ff\u6362 ",(0,i.kt)("inlineCode",{parentName:"p"},"net5.0")," \u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"net6.0"),"\uff0c\u5982\uff1a"),(0,i.kt)("img",{src:(0,a.Z)("img/sjl1.png")}),(0,i.kt)("p",null,"\u5f53\u7136\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Ctrl + F")," \u5168\u5c40\u66ff\u6362"),(0,i.kt)("img",{src:(0,a.Z)("img/sjl2.png")}),(0,i.kt)("h3",{id:"2513-\u5347\u7ea7-nuget-\u5305"},"2.5.1.3 \u5347\u7ea7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Nuget")," \u5305"),(0,i.kt)("p",null,"\u5c06 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6240\u6709\u5305\u5347\u7ea7\u81f3 ",(0,i.kt)("inlineCode",{parentName:"p"},"v4.3.9")," \u7248\u672c\uff0c\u540c\u65f6 ",(0,i.kt)("inlineCode",{parentName:"p"},"Microsoft")," \u6240\u6709\u5305\u5347\u7ea7\u81f3 ",(0,i.kt)("inlineCode",{parentName:"p"},"v6.0.8")," \u7248\u672c\uff0c\u5982\uff1a"),(0,i.kt)("img",{src:(0,a.Z)("img/sjl3.png")}),(0,i.kt)("h3",{id:"2514-\u5220\u9664-startupcs-\u6587\u4ef6"},"2.5.1.4 \u5220\u9664 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Startup.cs")," \u6587\u4ef6"),(0,i.kt)("p",null,"\u5220\u9664 ",(0,i.kt)("inlineCode",{parentName:"p"},"Web \u542f\u52a8\u5c42")," \u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u6587\u4ef6\uff0c\u5982\uff1a"),(0,i.kt)("img",{src:(0,a.Z)("img/sjl4.png")}),(0,i.kt)("h3",{id:"2515-\u7f16\u8f91-web-\u542f\u52a8\u5c42-csproj"},"2.5.1.5 \u7f16\u8f91 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Web")," \u542f\u52a8\u5c42 ",(0,i.kt)("inlineCode",{parentName:"h3"},".csproj")),(0,i.kt)("p",null,"\u7f16\u8f91 ",(0,i.kt)("inlineCode",{parentName:"p"},"Web")," \u542f\u52a8\u5c42 ",(0,i.kt)("inlineCode",{parentName:"p"},".csproj")," \u6587\u4ef6\uff0c\u5e76\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"p"},"enable"),"\uff0c\u5982\uff1a"),(0,i.kt)("img",{src:(0,a.Z)("img/sjl5.png")}),(0,i.kt)("h3",{id:"2516-\u66ff\u6362-programcs-\u5185\u5bb9\u4e3a"},"2.5.1.6 \u66ff\u6362 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Program.cs")," \u5185\u5bb9\u4e3a\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var builder = WebApplication.CreateBuilder(args).Inject();\nvar app = builder.Build();\napp.Run();\n")),(0,i.kt)("admonition",{title:"v3.6.4+ \u7248\u672c",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 3.6.4+")," \u7248\u672c\uff0c\u53ef\u76f4\u63a5\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Serve.Run(RunOptions.Default);")," \u66ff\u4ee3\u4e0a\u9762\u5373\u53ef\u3002")),(0,i.kt)("admonition",{title:"\u5c0f\u63d0\u9192",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Serilog")," \u65e5\u5fd7\u7ec4\u4ef6\uff0c\u53ef\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"p"},"builder.UseSerilogDefault();")),(0,i.kt)("p",{parentName:"admonition"},"\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Serve.Run(RunOptions.Default.ConfigureBuilder(builder => builder.UseSerilogDefault()));"),"\u3002"),(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"pgsql")," \u6570\u636e\u5e93\uff0c\u4f60\u8fd8\u53ef\u80fd\u9700\u8981\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"p"},'AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);'),"\n=> ",(0,i.kt)("a",{parentName:"p",href:"https://www.npgsql.org/doc/types/datetime.html"},"\u76f8\u5173\u8bf4\u660e\uff1a\u5728 .NET6 \u4e2d Npgsql 6.0 \u5bf9\u65f6\u95f4\u6233\u7684\u6620\u5c04\u65b9\u5f0f\u8fdb\u884c\u4e86\u4e00\u4e9b\u91cd\u8981\u7684\u66f4\u6539\u3002"))),(0,i.kt)("img",{src:(0,a.Z)("img/sjl6.png")}),(0,i.kt)("h3",{id:"2517-\u91cd\u65b0\u7f16\u8bd1\u6574\u4e2a\u89e3\u51b3\u65b9\u6848"},"2.5.1.7 \u91cd\u65b0\u7f16\u8bd1\u6574\u4e2a\u89e3\u51b3\u65b9\u6848"),(0,i.kt)("p",null,"\u5347\u7ea7\u5b8c\u6210\uff01\uff01\uff01"))}k.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return d},kt:function(){return m}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},d=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},s=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,d=p(e,["components","mdxType","originalType","parentName"]),s=c(n),m=o,k=s["".concat(l,".").concat(m)]||s[m]||u[m]||i;return n?r.createElement(k,a(a({ref:t},d),{},{components:n})):r.createElement(k,a({ref:t},d))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=s;var p={};for(var l in t)hasOwnProperty.call(t,l)&&(p[l]=t[l]);p.originalType=e,p.mdxType="string"==typeof e?e:o,a[1]=p;for(var c=2;c=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},d=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},s=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,d=p(e,["components","mdxType","originalType","parentName"]),s=c(n),m=o,k=s["".concat(l,".").concat(m)]||s[m]||u[m]||i;return n?r.createElement(k,a(a({ref:t},d),{},{components:n})):r.createElement(k,a({ref:t},d))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=s;var p={};for(var l in t)hasOwnProperty.call(t,l)&&(p[l]=t[l]);p.originalType=e,p.mdxType="string"==typeof e?e:o,a[1]=p;for(var c=2;c.NET6 SDK",id:"2511-\u5b89\u88c5-net6-sdk",level:3},{value:"2.5.1.2 \u7f16\u8f91 .csproj \u6587\u4ef6",id:"2512-\u7f16\u8f91-csproj-\u6587\u4ef6",level:3},{value:"2.5.1.3 \u5347\u7ea7 Nuget \u5305",id:"2513-\u5347\u7ea7-nuget-\u5305",level:3},{value:"2.5.1.4 \u5220\u9664 Startup.cs \u6587\u4ef6",id:"2514-\u5220\u9664-startupcs-\u6587\u4ef6",level:3},{value:"2.5.1.5 \u7f16\u8f91 Web \u542f\u52a8\u5c42 .csproj",id:"2515-\u7f16\u8f91-web-\u542f\u52a8\u5c42-csproj",level:3},{value:"2.5.1.6 \u66ff\u6362 Program.cs \u5185\u5bb9\u4e3a\uff1a",id:"2516-\u66ff\u6362-programcs-\u5185\u5bb9\u4e3a",level:3},{value:"2.5.1.7 \u91cd\u65b0\u7f16\u8bd1\u6574\u4e2a\u89e3\u51b3\u65b9\u6848",id:"2517-\u91cd\u65b0\u7f16\u8bd1\u6574\u4e2a\u89e3\u51b3\u65b9\u6848",level:3}],m={toc:s};function k(e){var t=e.components,n=(0,o.Z)(e,p);return(0,i.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"251-\u5347\u7ea7\u6ce8\u610f\u4e8b\u9879"},"2.5.1 \u5347\u7ea7\u6ce8\u610f\u4e8b\u9879"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u76ee\u524d\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v2.x")," \u7248\u672c\u7684\u7528\u6237\u5747\u53ef\u4ee5\u5feb\u901f\u65e0\u7f1d\u5347\u7ea7\u81f3 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v4.x")," \u7248\u672c\uff0c\u53ea\u9700\u8981\u505a\u5c11\u91cf\u66f4\u6539\u5373\u53ef\u3002")),(0,i.kt)("h3",{id:"2511-\u5b89\u88c5-net6-sdk"},"2.5.1.1 \u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h3"},".NET6 SDK")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/download/dotnet/6.0"},"https://dotnet.microsoft.com/download/dotnet/6.0")),(0,i.kt)("h3",{id:"2512-\u7f16\u8f91-csproj-\u6587\u4ef6"},"2.5.1.2 \u7f16\u8f91 ",(0,i.kt)("inlineCode",{parentName:"h3"},".csproj")," \u6587\u4ef6"),(0,i.kt)("p",null,"\u7f16\u8f91\u89e3\u51b3\u65b9\u6848\u6240\u6709\u9879\u76ee\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},".csproj")," \u6587\u4ef6\uff0c\u5e76\u66ff\u6362 ",(0,i.kt)("inlineCode",{parentName:"p"},"net5.0")," \u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"net6.0"),"\uff0c\u5982\uff1a"),(0,i.kt)("img",{src:(0,a.Z)("img/sjl1.png")}),(0,i.kt)("p",null,"\u5f53\u7136\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Ctrl + F")," \u5168\u5c40\u66ff\u6362"),(0,i.kt)("img",{src:(0,a.Z)("img/sjl2.png")}),(0,i.kt)("h3",{id:"2513-\u5347\u7ea7-nuget-\u5305"},"2.5.1.3 \u5347\u7ea7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Nuget")," \u5305"),(0,i.kt)("p",null,"\u5c06 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6240\u6709\u5305\u5347\u7ea7\u81f3 ",(0,i.kt)("inlineCode",{parentName:"p"},"v4.4.0")," \u7248\u672c\uff0c\u540c\u65f6 ",(0,i.kt)("inlineCode",{parentName:"p"},"Microsoft")," \u6240\u6709\u5305\u5347\u7ea7\u81f3 ",(0,i.kt)("inlineCode",{parentName:"p"},"v6.0.8")," \u7248\u672c\uff0c\u5982\uff1a"),(0,i.kt)("img",{src:(0,a.Z)("img/sjl3.png")}),(0,i.kt)("h3",{id:"2514-\u5220\u9664-startupcs-\u6587\u4ef6"},"2.5.1.4 \u5220\u9664 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Startup.cs")," \u6587\u4ef6"),(0,i.kt)("p",null,"\u5220\u9664 ",(0,i.kt)("inlineCode",{parentName:"p"},"Web \u542f\u52a8\u5c42")," \u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u6587\u4ef6\uff0c\u5982\uff1a"),(0,i.kt)("img",{src:(0,a.Z)("img/sjl4.png")}),(0,i.kt)("h3",{id:"2515-\u7f16\u8f91-web-\u542f\u52a8\u5c42-csproj"},"2.5.1.5 \u7f16\u8f91 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Web")," \u542f\u52a8\u5c42 ",(0,i.kt)("inlineCode",{parentName:"h3"},".csproj")),(0,i.kt)("p",null,"\u7f16\u8f91 ",(0,i.kt)("inlineCode",{parentName:"p"},"Web")," \u542f\u52a8\u5c42 ",(0,i.kt)("inlineCode",{parentName:"p"},".csproj")," \u6587\u4ef6\uff0c\u5e76\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"p"},"enable"),"\uff0c\u5982\uff1a"),(0,i.kt)("img",{src:(0,a.Z)("img/sjl5.png")}),(0,i.kt)("h3",{id:"2516-\u66ff\u6362-programcs-\u5185\u5bb9\u4e3a"},"2.5.1.6 \u66ff\u6362 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Program.cs")," \u5185\u5bb9\u4e3a\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var builder = WebApplication.CreateBuilder(args).Inject();\nvar app = builder.Build();\napp.Run();\n")),(0,i.kt)("admonition",{title:"v3.6.4+ \u7248\u672c",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 3.6.4+")," \u7248\u672c\uff0c\u53ef\u76f4\u63a5\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Serve.Run(RunOptions.Default);")," \u66ff\u4ee3\u4e0a\u9762\u5373\u53ef\u3002")),(0,i.kt)("admonition",{title:"\u5c0f\u63d0\u9192",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Serilog")," \u65e5\u5fd7\u7ec4\u4ef6\uff0c\u53ef\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"p"},"builder.UseSerilogDefault();")),(0,i.kt)("p",{parentName:"admonition"},"\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Serve.Run(RunOptions.Default.ConfigureBuilder(builder => builder.UseSerilogDefault()));"),"\u3002"),(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"pgsql")," \u6570\u636e\u5e93\uff0c\u4f60\u8fd8\u53ef\u80fd\u9700\u8981\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"p"},'AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);'),"\n=> ",(0,i.kt)("a",{parentName:"p",href:"https://www.npgsql.org/doc/types/datetime.html"},"\u76f8\u5173\u8bf4\u660e\uff1a\u5728 .NET6 \u4e2d Npgsql 6.0 \u5bf9\u65f6\u95f4\u6233\u7684\u6620\u5c04\u65b9\u5f0f\u8fdb\u884c\u4e86\u4e00\u4e9b\u91cd\u8981\u7684\u66f4\u6539\u3002"))),(0,i.kt)("img",{src:(0,a.Z)("img/sjl6.png")}),(0,i.kt)("h3",{id:"2517-\u91cd\u65b0\u7f16\u8bd1\u6574\u4e2a\u89e3\u51b3\u65b9\u6848"},"2.5.1.7 \u91cd\u65b0\u7f16\u8bd1\u6574\u4e2a\u89e3\u51b3\u65b9\u6848"),(0,i.kt)("p",null,"\u5347\u7ea7\u5b8c\u6210\uff01\uff01\uff01"))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/01a85c17.a0e539b3.js b/handbook/build/assets/js/01a85c17.4b3a9f27.js similarity index 46% rename from handbook/build/assets/js/01a85c17.a0e539b3.js rename to handbook/build/assets/js/01a85c17.4b3a9f27.js index 9db24f7dee..f2c7589df5 100644 --- a/handbook/build/assets/js/01a85c17.a0e539b3.js +++ b/handbook/build/assets/js/01a85c17.4b3a9f27.js @@ -1 +1 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4013],{1485:function(e,t,a){a.d(t,{Z:function(){return _}});var n=a(102),r=a(7294),l=a(4334),i=a(4832),c=a(4980),s=a(8746),m=a(1614),o="sidebar_re4s",u="sidebarItemTitle_pO2u",g="sidebarItemList_Yudw",d="sidebarItem__DBe",b="sidebarItemLink_mo7H",E="sidebarItemLinkActive_I1ZP";function f(e){var t=e.sidebar;return r.createElement("aside",{className:"col col--3"},r.createElement("nav",{className:(0,l.Z)(o,"thin-scrollbar"),"aria-label":(0,m.I)({id:"theme.blog.sidebar.navAriaLabel",message:"Blog recent posts navigation",description:"The ARIA label for recent posts in the blog sidebar"})},r.createElement("div",{className:(0,l.Z)(u,"margin-bottom--md")},t.title),r.createElement("ul",{className:(0,l.Z)(g,"clean-list")},t.items.map((function(e){return r.createElement("li",{key:e.permalink,className:d},r.createElement(s.Z,{isNavLink:!0,to:e.permalink,className:b,activeClassName:E},e.title))})))))}var p=a(2306);function v(e){var t=e.sidebar;return r.createElement("ul",{className:"menu__list"},t.items.map((function(e){return r.createElement("li",{key:e.permalink,className:"menu__list-item"},r.createElement(s.Z,{isNavLink:!0,to:e.permalink,className:"menu__link",activeClassName:"menu__link--active"},e.title))})))}function h(e){return r.createElement(p.Zo,{component:v,props:e})}function k(e){var t=e.sidebar,a=(0,c.i)();return null!=t&&t.items.length?"mobile"===a?r.createElement(h,{sidebar:t}):r.createElement(f,{sidebar:t}):null}var N=["sidebar","toc","children"];function _(e){var t=e.sidebar,a=e.toc,c=e.children,s=(0,n.Z)(e,N),m=t&&t.items.length>0;return r.createElement(i.Z,s,r.createElement("div",{className:"container margin-vert--lg"},r.createElement("div",{className:"row"},r.createElement(k,{sidebar:t}),r.createElement("main",{className:(0,l.Z)("col",{"col--7":m,"col--9 col--offset-1":!m}),itemScope:!0,itemType:"http://schema.org/Blog"},c),a&&r.createElement("div",{className:"col col--2"},a))))}},4057:function(e,t,a){a.r(t),a.d(t,{default:function(){return b}});var n=a(7294),r=a(4334),l=a(1614);var i=a(4873),c=a(8015),s=a(1485),m=a(4588),o="tag_Nnez";function u(e){var t=e.letterEntry;return n.createElement("article",null,n.createElement("h2",null,t.letter),n.createElement("ul",{className:"padding--none"},t.tags.map((function(e){return n.createElement("li",{key:e.permalink,className:o},n.createElement(m.Z,e))}))),n.createElement("hr",null))}function g(e){var t=function(e){var t={};return Object.values(e).forEach((function(e){var a=function(e){return e[0].toUpperCase()}(e.label);null!=t[a]||(t[a]=[]),t[a].push(e)})),Object.entries(t).sort((function(e,t){var a=e[0],n=t[0];return a.localeCompare(n)})).map((function(e){return{letter:e[0],tags:e[1].sort((function(e,t){return e.label.localeCompare(t.label)}))}}))}(e.tags);return n.createElement("section",{className:"margin-vert--lg"},t.map((function(e){return n.createElement(u,{key:e.letter,letterEntry:e})})))}var d=a(6145);function b(e){var t=e.tags,a=e.sidebar,m=(0,l.I)({id:"theme.tags.tagsPageTitle",message:"Tags",description:"The title of the tag list page"});return n.createElement(i.FG,{className:(0,r.Z)(c.k.wrapper.blogPages,c.k.page.blogTagsListPage)},n.createElement(i.d,{title:m}),n.createElement(d.Z,{tag:"blog_tags_list"}),n.createElement(s.Z,{sidebar:a},n.createElement("h1",null,m),n.createElement(g,{tags:t})))}},4588:function(e,t,a){a.d(t,{Z:function(){return m}});var n=a(7294),r=a(4334),l=a(8746),i="tag_zVej",c="tagRegular_sFm0",s="tagWithCount_h2kH";function m(e){var t=e.permalink,a=e.label,m=e.count;return n.createElement(l.Z,{href:t,className:(0,r.Z)(i,m?s:c)},a,m&&n.createElement("span",null,m))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4013],{9058:function(e,t,a){a.d(t,{Z:function(){return _}});var n=a(102),r=a(7294),l=a(4334),i=a(7302),c=a(7524),s=a(9960),m=a(5999),o="sidebar_re4s",u="sidebarItemTitle_pO2u",g="sidebarItemList_Yudw",d="sidebarItem__DBe",b="sidebarItemLink_mo7H",E="sidebarItemLinkActive_I1ZP";function f(e){var t=e.sidebar;return r.createElement("aside",{className:"col col--3"},r.createElement("nav",{className:(0,l.Z)(o,"thin-scrollbar"),"aria-label":(0,m.I)({id:"theme.blog.sidebar.navAriaLabel",message:"Blog recent posts navigation",description:"The ARIA label for recent posts in the blog sidebar"})},r.createElement("div",{className:(0,l.Z)(u,"margin-bottom--md")},t.title),r.createElement("ul",{className:(0,l.Z)(g,"clean-list")},t.items.map((function(e){return r.createElement("li",{key:e.permalink,className:d},r.createElement(s.Z,{isNavLink:!0,to:e.permalink,className:b,activeClassName:E},e.title))})))))}var p=a(3102);function v(e){var t=e.sidebar;return r.createElement("ul",{className:"menu__list"},t.items.map((function(e){return r.createElement("li",{key:e.permalink,className:"menu__list-item"},r.createElement(s.Z,{isNavLink:!0,to:e.permalink,className:"menu__link",activeClassName:"menu__link--active"},e.title))})))}function h(e){return r.createElement(p.Zo,{component:v,props:e})}function k(e){var t=e.sidebar,a=(0,c.i)();return null!=t&&t.items.length?"mobile"===a?r.createElement(h,{sidebar:t}):r.createElement(f,{sidebar:t}):null}var N=["sidebar","toc","children"];function _(e){var t=e.sidebar,a=e.toc,c=e.children,s=(0,n.Z)(e,N),m=t&&t.items.length>0;return r.createElement(i.Z,s,r.createElement("div",{className:"container margin-vert--lg"},r.createElement("div",{className:"row"},r.createElement(k,{sidebar:t}),r.createElement("main",{className:(0,l.Z)("col",{"col--7":m,"col--9 col--offset-1":!m}),itemScope:!0,itemType:"http://schema.org/Blog"},c),a&&r.createElement("div",{className:"col col--2"},a))))}},1223:function(e,t,a){a.r(t),a.d(t,{default:function(){return b}});var n=a(7294),r=a(4334),l=a(5999);var i=a(833),c=a(5281),s=a(9058),m=a(3008),o="tag_Nnez";function u(e){var t=e.letterEntry;return n.createElement("article",null,n.createElement("h2",null,t.letter),n.createElement("ul",{className:"padding--none"},t.tags.map((function(e){return n.createElement("li",{key:e.permalink,className:o},n.createElement(m.Z,e))}))),n.createElement("hr",null))}function g(e){var t=function(e){var t={};return Object.values(e).forEach((function(e){var a=function(e){return e[0].toUpperCase()}(e.label);null!=t[a]||(t[a]=[]),t[a].push(e)})),Object.entries(t).sort((function(e,t){var a=e[0],n=t[0];return a.localeCompare(n)})).map((function(e){return{letter:e[0],tags:e[1].sort((function(e,t){return e.label.localeCompare(t.label)}))}}))}(e.tags);return n.createElement("section",{className:"margin-vert--lg"},t.map((function(e){return n.createElement(u,{key:e.letter,letterEntry:e})})))}var d=a(197);function b(e){var t=e.tags,a=e.sidebar,m=(0,l.I)({id:"theme.tags.tagsPageTitle",message:"Tags",description:"The title of the tag list page"});return n.createElement(i.FG,{className:(0,r.Z)(c.k.wrapper.blogPages,c.k.page.blogTagsListPage)},n.createElement(i.d,{title:m}),n.createElement(d.Z,{tag:"blog_tags_list"}),n.createElement(s.Z,{sidebar:a},n.createElement("h1",null,m),n.createElement(g,{tags:t})))}},3008:function(e,t,a){a.d(t,{Z:function(){return m}});var n=a(7294),r=a(4334),l=a(9960),i="tag_zVej",c="tagRegular_sFm0",s="tagWithCount_h2kH";function m(e){var t=e.permalink,a=e.label,m=e.count;return n.createElement(l.Z,{href:t,className:(0,r.Z)(i,m?s:c)},a,m&&n.createElement("span",null,m))}}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/0249e0f1.8dca2318.js b/handbook/build/assets/js/0249e0f1.8dca2318.js deleted file mode 100644 index 7e096aa334..0000000000 --- a/handbook/build/assets/js/0249e0f1.8dca2318.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[590],{4879:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return u},default:function(){return d},frontMatter:function(){return l},metadata:function(){return p},toc:function(){return s}});var r=n(3117),o=n(102),a=(n(7294),n(3905)),i=(n(1402),["components"]),l={slug:"fileupload-download",title:"2. \u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5","upload","download"]},u=void 0,p={permalink:"/furion/blog/fileupload-download",editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/blog/2021-02-02-fileupload-download.mdx",source:"@site/blog/2021-02-02-fileupload-download.mdx",title:"2. \u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d",description:"",date:"2021-02-02T00:00:00.000Z",formattedDate:"February 2, 2021",tags:[{label:"furion",permalink:"/furion/blog/tags/furion"},{label:"furos",permalink:"/furion/blog/tags/furos"},{label:".net",permalink:"/furion/blog/tags/net"},{label:".netcore",permalink:"/furion/blog/tags/netcore"},{label:".net5",permalink:"/furion/blog/tags/net-5"},{label:"upload",permalink:"/furion/blog/tags/upload"},{label:"download",permalink:"/furion/blog/tags/download"}],readingTime:1.435,hasTruncateMarker:!0,authors:[{name:"dotNET China",title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",url:"https://www.chinadot.net",imageURL:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png"}],frontMatter:{slug:"fileupload-download",title:"2. \u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5","upload","download"]},prevItem:{title:"3. .NET 6 Preview 5 \u5c1d\u9c9c",permalink:"/furion/blog/net6-preview5"},nextItem:{title:"1. HttpContext \u5e94\u7528",permalink:"/furion/blog/httpcontext"}},c={authorsImageUrls:[void 0]},s=[{value:"\u6587\u4ef6\u4e0b\u8f7d",id:"\u6587\u4ef6\u4e0b\u8f7d",level:2}],f={toc:s};function d(e){var t=e.components,n=(0,o.Z)(e,i);return(0,a.kt)("wrapper",(0,r.Z)({},f,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"\u6587\u4ef6\u4e0b\u8f7d"},"\u6587\u4ef6\u4e0b\u8f7d"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[HttpGet, NonUnify]\npublic IActionResult FileDownload(string path, string fileName)\n{\n string filePath = "\u8fd9\u91cc\u83b7\u53d6\u5b8c\u6574\u7684\u6587\u4ef6\u4e0b\u8f7d\u8def\u5f84";\n return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };\n}\n')),(0,a.kt)("admonition",{title:"\u5173\u4e8e\u524d\u7aef\u83b7\u53d6\u6587\u4ef6\u540d",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u524d\u7aef\u83b7\u53d6\u4e0d\u5230\u6587\u4ef6\u5939\uff0c\u53ef\u6dfb\u52a0\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={\u6587\u4ef6\u540d}");\n_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");\n'))))}d.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return c},kt:function(){return d}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},f=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,u=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),f=p(n),d=o,m=f["".concat(u,".").concat(d)]||f[d]||s[d]||a;return n?r.createElement(m,i(i({ref:t},c),{},{components:n})):r.createElement(m,i({ref:t},c))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=f;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var p=2;p=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},f=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,u=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),f=p(n),d=o,m=f["".concat(u,".").concat(d)]||f[d]||s[d]||a;return n?r.createElement(m,i(i({ref:t},c),{},{components:n})):r.createElement(m,i({ref:t},c))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=f;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var p=2;pHttpContext",id:"521-\u5173\u4e8e-httpcontext",level:2},{value:"5.2.2 \u83b7\u53d6 HttpContext",id:"522-\u83b7\u53d6-httpcontext",level:2},{value:"5.2.2.1 \u5728 ControllerBase \u6d3e\u751f\u7c7b\u4e2d",id:"5221-\u5728-controllerbase-\u6d3e\u751f\u7c7b\u4e2d",level:3},{value:"5.2.2.2 \u6ce8\u5165 IHttpContextAccessor",id:"5222-\u6ce8\u5165-ihttpcontextaccessor",level:3},{value:"5.2.2.3 \u901a\u8fc7 App.HttpContext",id:"5223-\u901a\u8fc7-apphttpcontext",level:3},{value:"5.2.3 HttpContext \u62d3\u5c55\u65b9\u6cd5",id:"523-httpcontext-\u62d3\u5c55\u65b9\u6cd5",level:2},{value:"5.2.3.1 \u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027 Attribute",id:"5231-\u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027-attribute",level:3},{value:"5.2.3.2 \u8bbe\u7f6e Swagger \u81ea\u52a8\u6388\u6743",id:"5232-\u8bbe\u7f6e-swagger-\u81ea\u52a8\u6388\u6743",level:3},{value:"5.2.3.3 \u9000\u51fa Swagger \u6388\u6743",id:"5233-\u9000\u51fa-swagger-\u6388\u6743",level:3},{value:"5.2.3.4 \u83b7\u53d6\u672c\u5730 IP \u5730\u5740",id:"5234-\u83b7\u53d6\u672c\u5730-ip-\u5730\u5740",level:3},{value:"5.2.3.5 \u83b7\u53d6\u5ba2\u6237\u7aef IP \u5730\u5740",id:"5235-\u83b7\u53d6\u5ba2\u6237\u7aef-ip-\u5730\u5740",level:3},{value:"5.2.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"524-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:c};function u(e){var t=e.components,n=(0,o.Z)(e,i);return(0,a.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"521-\u5173\u4e8e-httpcontext"},"5.2.1 \u5173\u4e8e ",(0,a.kt)("inlineCode",{parentName:"h2"},"HttpContext")),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET")," \u7684\u65f6\u4ee3\uff0c\u6211\u4eec\u901a\u5e38\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5168\u5c40\u9759\u6001\u7c7b\u83b7\u53d6\u8bf7\u6c42\u4e0a\u4e0b\u6587\uff0c\u4f46\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u4e2d\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u662f\u4e00\u4e2a\u975e\u9759\u6001\u7684\u62bd\u8c61\u7c7b\uff0c\u65e0\u6cd5\u624b\u52a8\u521b\u5efa\uff0c\u4e5f\u65e0\u6cd5\u901a\u8fc7\u9759\u6001\u83b7\u53d6\u3002"),(0,a.kt)("p",null,"\u867d\u7136\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u4e2d\u65e0\u6cd5\u76f4\u63a5\u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5bf9\u8c61\u3002\u4f46\u662f\u5fae\u8f6f\u4e5f\u63d0\u4f9b\u4e86\u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"p"},"IHttpContextAccessor")," \u65b9\u5f0f\u83b7\u53d6\u3002"),(0,a.kt)("h2",{id:"522-\u83b7\u53d6-httpcontext"},"5.2.2 \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"HttpContext")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u591a\u79cd\u8bbf\u95ee ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u7684\u65b9\u5f0f\u3002"),(0,a.kt)("h3",{id:"5221-\u5728-controllerbase-\u6d3e\u751f\u7c7b\u4e2d"},"5.2.2.1 \u5728 ",(0,a.kt)("inlineCode",{parentName:"h3"},"ControllerBase")," \u6d3e\u751f\u7c7b\u4e2d"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ControllerBase")," \u6d3e\u751f\u7c7b\u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u76f4\u63a5\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5c5e\u6027\u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5bf9\u8c61\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5-6}",showLineNumbers:!0,"{5-6}":!0},"public class HomeController : Controller\n{\n public IActionResult Index()\n {\n // \u5728\u8fd9\u91ccHttpContext \u662f Controller/ControllerBase \u5bf9\u8c61\u7684\u5c5e\u6027\n var httpContext = HttpContext;\n\n return View();\n }\n}\n")),(0,a.kt)("h3",{id:"5222-\u6ce8\u5165-ihttpcontextaccessor"},"5.2.2.2 \u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"h3"},"IHttpContextAccessor")),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u5df2\u7ecf\u6ce8\u518c\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"IHttpContextAccessor")," \u670d\u52a1\uff0c\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u6784\u9020\u51fd\u6570\u6ce8\u5165\u8be5\u63a5\u53e3\u83b7\u53d6\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5}",showLineNumbers:!0,"":!0,"{3,5}":!0},"public class AppService\n{\n public AppService(IHttpContextAccessor httpContextAccessor)\n {\n var httpContext = httpContextAccessor.HttpContext;\n }\n}\n")),(0,a.kt)("h3",{id:"5223-\u901a\u8fc7-apphttpcontext"},"5.2.2.3 \u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"h3"},"App.HttpContext")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"App")," \u9759\u6001\u7c7b\u4e5f\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"App.HttpContext")," \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5bf9\u8c61\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var request = App.HttpContext.Request;\n")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u975e ",(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Web")," \u4e2d\u8bbf\u95ee"),(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u5b8c\u6574\u7684\u751f\u547d\u5468\u671f\u5185\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"App.HttpContext")," \u90fd\u662f\u6709\u6548\u7684\uff0c\u4f46\u5728\u975e ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u4e2d\u8fd4\u56de ",(0,a.kt)("inlineCode",{parentName:"p"},"null"),"\uff0c\u907f\u514d\u5728\u591a\u7ebf\u7a0b\uff0c\u4e8b\u4ef6\u603b\u7ebf\uff0c\u5b9a\u65f6\u4efb\u52a1\u7b49\u4e2d\u4f7f\u7528\u3002")),(0,a.kt)("h2",{id:"523-httpcontext-\u62d3\u5c55\u65b9\u6cd5"},"5.2.3 ",(0,a.kt)("inlineCode",{parentName:"h2"},"HttpContext")," \u62d3\u5c55\u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u57fa\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u63d0\u4f9b\u4e86\u4e00\u4e9b\u5e38\u7528\u7684\u62d3\u5c55\u65b9\u6cd5\u3002"),(0,a.kt)("h3",{id:"5231-\u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027-attribute"},"5.2.3.1 \u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Attribute")),(0,a.kt)("p",null,"\u4e0b\u5217\u4ee3\u7801\u901a\u5e38\u7528\u4e8e\u6388\u6743 ",(0,a.kt)("inlineCode",{parentName:"p"},"Handler")," \u4e2d\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var attribute = httpContext.GetMetadata();\n")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Middleware")," \u4e2d\u95f4\u4ef6\u83b7\u53d6\u7279\u6027\u65b9\u5f0f"),(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Middleware")," \u4e2d\u95f4\u4ef6\u4e2d\u83b7\u53d6\u6709\u6240\u533a\u522b\uff0c\u4e3b\u8981\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Features")," \u83b7\u53d6\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var endpointFeature = httpContext.Features.Get();\nvar attribute = endpointFeature?.Endpoint?.Metadata?.GetMetadata();\n"))),(0,a.kt)("h3",{id:"5232-\u8bbe\u7f6e-swagger-\u81ea\u52a8\u6388\u6743"},"5.2.3.2 \u8bbe\u7f6e ",(0,a.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u81ea\u52a8\u6388\u6743"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"Swagger")," \u9ed8\u8ba4\u4e0d\u80fd\u8bb0\u4f4f\u6388\u6743\u4fe1\u606f\uff0c\u4e00\u65e6\u5237\u65b0\u6d4f\u89c8\u5668\u5c31\u81ea\u52a8\u6e05\u7a7a"),"\uff0c\u6240\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u8be5\u62d3\u5c55\uff0c\u5373\u4f7f\u5237\u65b0\u6d4f\u89c8\u5668\u4e5f\u80fd\u4fdd\u6301\u6388\u6743\u72b6\u6001\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4-5}",showLineNumbers:!0,"{4-5}":!0},'// \u68c0\u67e5\u7528\u6237\u767b\u5f55\u548c\u751f\u6210 token \u4ee3\u7801...\n// .....\n\n// \u4e4b\u540e\u8c03\u7528\u8be5\u62d3\u5c55\uff0c\u8fd9\u6837\u5c31\u53ef\u4ee5\u5b9e\u73b0 Swagger \u5237\u65b0\u4e5f\u80fd\u8bb0\u4f4f\u767b\u5f55\u4e86\nhttpContext.SigninToSwagger("\u4f60\u7684token");\n')),(0,a.kt)("h3",{id:"5233-\u9000\u51fa-swagger-\u6388\u6743"},"5.2.3.3 \u9000\u51fa ",(0,a.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u6388\u6743"),(0,a.kt)("p",null,"\u901a\u8fc7\u540e\u7aef\u4ee3\u7801\u5f3a\u5236\u6027\u8ba9 ",(0,a.kt)("inlineCode",{parentName:"p"},"Swagger")," \u6388\u6743\u5b9e\u73b0\uff0c",(0,a.kt)("strong",{parentName:"p"},"\u53ea\u9488\u5bf9\u4e0b\u4e00\u6b21\u8bf7\u6c42\u6709\u6548\uff01")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"httpContext.SignoutToSwagger();\n")),(0,a.kt)("h3",{id:"5234-\u83b7\u53d6\u672c\u5730-ip-\u5730\u5740"},"5.2.3.4 \u83b7\u53d6\u672c\u5730 IP \u5730\u5740"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ipv4\nvar ipv4 = httpContext.GetLocalIpAddressToIPv4();\n\n// ipv6\nvar ipv6 = httpContext.GetLocalIpAddressToIPv6();\n")),(0,a.kt)("h3",{id:"5235-\u83b7\u53d6\u5ba2\u6237\u7aef-ip-\u5730\u5740"},"5.2.3.5 \u83b7\u53d6\u5ba2\u6237\u7aef IP \u5730\u5740"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ipv4\nvar ipv4 = httpContext.GetRemoteIpAddressToIPv4();\n\n// ipv6\nvar ipv6 = httpContext.GetRemoteIpAddressToIPv6();\n")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Nginx")," \u65e0\u6cd5\u83b7\u53d6\u6b63\u786e\u5ba2\u6237\u7aef ",(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"IP")," \u95ee\u9898"),(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u670d\u52a1\u5668\u7aef\u4f7f\u7528\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"nginx")," \u7b49\u53cd\u5411\u4ee3\u7406\u5de5\u5177\uff0c\u53ef\u6dfb\u52a0\u4ee5\u4e0b\u4ee3\u7801\u914d\u7f6e\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="Startup.cs" {1-4,6-7}',showLineNumbers:!0,title:'"Startup.cs"',"{1-4,6-7}":!0},"services.Configure(options =>\n{\n options.ForwardedHeaders = ForwardedHeaders.All;\n});\n\n// \u6ce8\u610f\u5728 Configure \u6700\u524d\u9762\u914d\u7f6e\napp.UseForwardedHeaders();\n"))),(0,a.kt)("h2",{id:"524-\u53cd\u9988\u4e0e\u5efa\u8bae"},"5.2.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}u.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return u}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),d=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},s=function(e){var t=d(e.components);return r.createElement(l.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,s=p(e,["components","mdxType","originalType","parentName"]),m=d(n),u=o,k=m["".concat(l,".").concat(u)]||m[u]||c[u]||a;return n?r.createElement(k,i(i({ref:t},s),{},{components:n})):r.createElement(k,i({ref:t},s))}));function u(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=m;var p={};for(var l in t)hasOwnProperty.call(t,l)&&(p[l]=t[l]);p.originalType=e,p.mdxType="string"==typeof e?e:o,i[1]=p;for(var d=2;d=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),d=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},s=function(e){var t=d(e.components);return r.createElement(l.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,s=p(e,["components","mdxType","originalType","parentName"]),m=d(n),u=o,k=m["".concat(l,".").concat(u)]||m[u]||c[u]||a;return n?r.createElement(k,i(i({ref:t},s),{},{components:n})):r.createElement(k,i({ref:t},s))}));function u(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=m;var p={};for(var l in t)hasOwnProperty.call(t,l)&&(p[l]=t[l]);p.originalType=e,p.mdxType="string"==typeof e?e:o,i[1]=p;for(var d=2;dHttpContext",id:"521-\u5173\u4e8e-httpcontext",level:2},{value:"5.2.2 \u83b7\u53d6 HttpContext",id:"522-\u83b7\u53d6-httpcontext",level:2},{value:"5.2.2.1 \u5728 ControllerBase \u6d3e\u751f\u7c7b\u4e2d",id:"5221-\u5728-controllerbase-\u6d3e\u751f\u7c7b\u4e2d",level:3},{value:"5.2.2.2 \u6ce8\u5165 IHttpContextAccessor",id:"5222-\u6ce8\u5165-ihttpcontextaccessor",level:3},{value:"5.2.2.3 \u901a\u8fc7 App.HttpContext",id:"5223-\u901a\u8fc7-apphttpcontext",level:3},{value:"5.2.3 HttpContext \u62d3\u5c55\u65b9\u6cd5",id:"523-httpcontext-\u62d3\u5c55\u65b9\u6cd5",level:2},{value:"5.2.3.1 \u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027 Attribute",id:"5231-\u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027-attribute",level:3},{value:"5.2.3.2 \u8bbe\u7f6e Swagger \u81ea\u52a8\u6388\u6743",id:"5232-\u8bbe\u7f6e-swagger-\u81ea\u52a8\u6388\u6743",level:3},{value:"5.2.3.3 \u9000\u51fa Swagger \u6388\u6743",id:"5233-\u9000\u51fa-swagger-\u6388\u6743",level:3},{value:"5.2.3.4 \u83b7\u53d6\u672c\u5730 IP \u5730\u5740",id:"5234-\u83b7\u53d6\u672c\u5730-ip-\u5730\u5740",level:3},{value:"5.2.3.5 \u83b7\u53d6\u5ba2\u6237\u7aef IP \u5730\u5740",id:"5235-\u83b7\u53d6\u5ba2\u6237\u7aef-ip-\u5730\u5740",level:3},{value:"5.2.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"524-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:c};function u(e){var t=e.components,n=(0,o.Z)(e,i);return(0,a.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"521-\u5173\u4e8e-httpcontext"},"5.2.1 \u5173\u4e8e ",(0,a.kt)("inlineCode",{parentName:"h2"},"HttpContext")),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET")," \u7684\u65f6\u4ee3\uff0c\u6211\u4eec\u901a\u5e38\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5168\u5c40\u9759\u6001\u7c7b\u83b7\u53d6\u8bf7\u6c42\u4e0a\u4e0b\u6587\uff0c\u4f46\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u4e2d\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u662f\u4e00\u4e2a\u975e\u9759\u6001\u7684\u62bd\u8c61\u7c7b\uff0c\u65e0\u6cd5\u624b\u52a8\u521b\u5efa\uff0c\u4e5f\u65e0\u6cd5\u901a\u8fc7\u9759\u6001\u83b7\u53d6\u3002"),(0,a.kt)("p",null,"\u867d\u7136\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u4e2d\u65e0\u6cd5\u76f4\u63a5\u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5bf9\u8c61\u3002\u4f46\u662f\u5fae\u8f6f\u4e5f\u63d0\u4f9b\u4e86\u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"p"},"IHttpContextAccessor")," \u65b9\u5f0f\u83b7\u53d6\u3002"),(0,a.kt)("h2",{id:"522-\u83b7\u53d6-httpcontext"},"5.2.2 \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"HttpContext")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u591a\u79cd\u8bbf\u95ee ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u7684\u65b9\u5f0f\u3002"),(0,a.kt)("h3",{id:"5221-\u5728-controllerbase-\u6d3e\u751f\u7c7b\u4e2d"},"5.2.2.1 \u5728 ",(0,a.kt)("inlineCode",{parentName:"h3"},"ControllerBase")," \u6d3e\u751f\u7c7b\u4e2d"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ControllerBase")," \u6d3e\u751f\u7c7b\u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u76f4\u63a5\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5c5e\u6027\u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5bf9\u8c61\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5-6}",showLineNumbers:!0,"{5-6}":!0},"public class HomeController : Controller\n{\n public IActionResult Index()\n {\n // \u5728\u8fd9\u91ccHttpContext \u662f Controller/ControllerBase \u5bf9\u8c61\u7684\u5c5e\u6027\n var httpContext = HttpContext;\n\n return View();\n }\n}\n")),(0,a.kt)("h3",{id:"5222-\u6ce8\u5165-ihttpcontextaccessor"},"5.2.2.2 \u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"h3"},"IHttpContextAccessor")),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u5df2\u7ecf\u6ce8\u518c\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"IHttpContextAccessor")," \u670d\u52a1\uff0c\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u6784\u9020\u51fd\u6570\u6ce8\u5165\u8be5\u63a5\u53e3\u83b7\u53d6\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5}",showLineNumbers:!0,"":!0,"{3,5}":!0},"public class AppService\n{\n public AppService(IHttpContextAccessor httpContextAccessor)\n {\n var httpContext = httpContextAccessor.HttpContext;\n }\n}\n")),(0,a.kt)("h3",{id:"5223-\u901a\u8fc7-apphttpcontext"},"5.2.2.3 \u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"h3"},"App.HttpContext")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"App")," \u9759\u6001\u7c7b\u4e5f\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"App.HttpContext")," \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5bf9\u8c61\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var request = App.HttpContext.Request;\n")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u975e ",(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Web")," \u4e2d\u8bbf\u95ee"),(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u5b8c\u6574\u7684\u751f\u547d\u5468\u671f\u5185\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"App.HttpContext")," \u90fd\u662f\u6709\u6548\u7684\uff0c\u4f46\u5728\u975e ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u4e2d\u8fd4\u56de ",(0,a.kt)("inlineCode",{parentName:"p"},"null"),"\uff0c\u907f\u514d\u5728\u591a\u7ebf\u7a0b\uff0c\u4e8b\u4ef6\u603b\u7ebf\uff0c\u5b9a\u65f6\u4efb\u52a1\u7b49\u4e2d\u4f7f\u7528\u3002")),(0,a.kt)("h2",{id:"523-httpcontext-\u62d3\u5c55\u65b9\u6cd5"},"5.2.3 ",(0,a.kt)("inlineCode",{parentName:"h2"},"HttpContext")," \u62d3\u5c55\u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u57fa\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u63d0\u4f9b\u4e86\u4e00\u4e9b\u5e38\u7528\u7684\u62d3\u5c55\u65b9\u6cd5\u3002"),(0,a.kt)("h3",{id:"5231-\u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027-attribute"},"5.2.3.1 \u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Attribute")),(0,a.kt)("p",null,"\u4e0b\u5217\u4ee3\u7801\u901a\u5e38\u7528\u4e8e\u6388\u6743 ",(0,a.kt)("inlineCode",{parentName:"p"},"Handler")," \u4e2d\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var attribute = httpContext.GetMetadata();\n")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Middleware")," \u4e2d\u95f4\u4ef6\u83b7\u53d6\u7279\u6027\u65b9\u5f0f"),(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Middleware")," \u4e2d\u95f4\u4ef6\u4e2d\u83b7\u53d6\u6709\u6240\u533a\u522b\uff0c\u4e3b\u8981\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Features")," \u83b7\u53d6\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var endpointFeature = httpContext.Features.Get();\nvar attribute = endpointFeature?.Endpoint?.Metadata?.GetMetadata();\n"))),(0,a.kt)("h3",{id:"5232-\u8bbe\u7f6e-swagger-\u81ea\u52a8\u6388\u6743"},"5.2.3.2 \u8bbe\u7f6e ",(0,a.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u81ea\u52a8\u6388\u6743"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"Swagger")," \u9ed8\u8ba4\u4e0d\u80fd\u8bb0\u4f4f\u6388\u6743\u4fe1\u606f\uff0c\u4e00\u65e6\u5237\u65b0\u6d4f\u89c8\u5668\u5c31\u81ea\u52a8\u6e05\u7a7a"),"\uff0c\u6240\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u8be5\u62d3\u5c55\uff0c\u5373\u4f7f\u5237\u65b0\u6d4f\u89c8\u5668\u4e5f\u80fd\u4fdd\u6301\u6388\u6743\u72b6\u6001\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4-5}",showLineNumbers:!0,"{4-5}":!0},'// \u68c0\u67e5\u7528\u6237\u767b\u5f55\u548c\u751f\u6210 token \u4ee3\u7801...\n// .....\n\n// \u4e4b\u540e\u8c03\u7528\u8be5\u62d3\u5c55\uff0c\u8fd9\u6837\u5c31\u53ef\u4ee5\u5b9e\u73b0 Swagger \u5237\u65b0\u4e5f\u80fd\u8bb0\u4f4f\u767b\u5f55\u4e86\nhttpContext.SigninToSwagger("\u4f60\u7684token");\n')),(0,a.kt)("h3",{id:"5233-\u9000\u51fa-swagger-\u6388\u6743"},"5.2.3.3 \u9000\u51fa ",(0,a.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u6388\u6743"),(0,a.kt)("p",null,"\u901a\u8fc7\u540e\u7aef\u4ee3\u7801\u5f3a\u5236\u6027\u8ba9 ",(0,a.kt)("inlineCode",{parentName:"p"},"Swagger")," \u6388\u6743\u5b9e\u73b0\uff0c",(0,a.kt)("strong",{parentName:"p"},"\u53ea\u9488\u5bf9\u4e0b\u4e00\u6b21\u8bf7\u6c42\u6709\u6548\uff01")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"httpContext.SignoutToSwagger();\n")),(0,a.kt)("h3",{id:"5234-\u83b7\u53d6\u672c\u5730-ip-\u5730\u5740"},"5.2.3.4 \u83b7\u53d6\u672c\u5730 IP \u5730\u5740"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ipv4\nvar ipv4 = httpContext.GetLocalIpAddressToIPv4();\n\n// ipv6\nvar ipv6 = httpContext.GetLocalIpAddressToIPv6();\n")),(0,a.kt)("h3",{id:"5235-\u83b7\u53d6\u5ba2\u6237\u7aef-ip-\u5730\u5740"},"5.2.3.5 \u83b7\u53d6\u5ba2\u6237\u7aef IP \u5730\u5740"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ipv4\nvar ipv4 = httpContext.GetRemoteIpAddressToIPv4();\n\n// ipv6\nvar ipv6 = httpContext.GetRemoteIpAddressToIPv6();\n")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Nginx")," \u65e0\u6cd5\u83b7\u53d6\u6b63\u786e\u5ba2\u6237\u7aef ",(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"IP")," \u95ee\u9898"),(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u670d\u52a1\u5668\u7aef\u4f7f\u7528\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"nginx")," \u7b49\u53cd\u5411\u4ee3\u7406\u5de5\u5177\uff0c\u53ef\u6dfb\u52a0\u4ee5\u4e0b\u4ee3\u7801\u914d\u7f6e\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="Startup.cs" {1-4,6-7}',showLineNumbers:!0,title:'"Startup.cs"',"{1-4,6-7}":!0},"services.Configure(options =>\n{\n options.ForwardedHeaders = ForwardedHeaders.All;\n});\n\n// \u6ce8\u610f\u5728 Configure \u6700\u524d\u9762\u914d\u7f6e\napp.UseForwardedHeaders();\n"))),(0,a.kt)("h2",{id:"524-\u53cd\u9988\u4e0e\u5efa\u8bae"},"5.2.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/0482bd9e.8e52c7b9.js b/handbook/build/assets/js/0482bd9e.8e52c7b9.js deleted file mode 100644 index 9bb121c521..0000000000 --- a/handbook/build/assets/js/0482bd9e.8e52c7b9.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[3533],{6370:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return p},default:function(){return d},frontMatter:function(){return s},metadata:function(){return m},toc:function(){return u}});var r=n(3117),a=n(102),i=(n(7294),n(3905)),o=["components"],s={id:"dbcontext-entitytrigger",title:"9.25. \u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668",sidebar_label:"9.25. \u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668"},p=void 0,m={unversionedId:"dbcontext-entitytrigger",id:"dbcontext-entitytrigger",title:"9.25. \u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668",description:"9.25.1 \u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668",source:"@site/docs/dbcontext-entitytrigger.mdx",sourceDirName:".",slug:"/dbcontext-entitytrigger",permalink:"/furion/docs/dbcontext-entitytrigger",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-entitytrigger.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"dbcontext-entitytrigger",title:"9.25. \u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668",sidebar_label:"9.25. \u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668"},sidebar:"docs",previous:{title:"9.24 \u6570\u636e\u5e93\u64cd\u4f5c\u62e6\u622a\u5668",permalink:"/furion/docs/dbcontext-Interceptor"},next:{title:"9.26 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143 (UnitOfWork)",permalink:"/furion/docs/tran"}},l={},u=[{value:"9.25.1 \u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668",id:"9251-\u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668",level:2},{value:"9.25.2 \u6709\u4f55\u4f5c\u7528",id:"9252-\u6709\u4f55\u4f5c\u7528",level:2},{value:"9.25.3 \u5982\u4f55\u4f7f\u7528",id:"9253-\u5982\u4f55\u4f7f\u7528",level:2},{value:"9.25.3.1 \u542f\u7528\u6570\u636e\u76d1\u542c",id:"92531-\u542f\u7528\u6570\u636e\u76d1\u542c",level:3},{value:"9.25.3.2 \u76d1\u542c\u7279\u5b9a\u5b9e\u4f53\u6570\u636e",id:"92532-\u76d1\u542c\u7279\u5b9a\u5b9e\u4f53\u6570\u636e",level:3},{value:"9.25.4 IEntityChangedListener \u5b9a\u4e49",id:"9254-ientitychangedlistener-\u5b9a\u4e49",level:2},{value:"9.25.5 [SuppressChangedListener] \u8df3\u8fc7\u76d1\u542c",id:"9255-suppresschangedlistener-\u8df3\u8fc7\u76d1\u542c",level:2},{value:"9.25.6 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9256-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:u};function d(e){var t=e.components,n=(0,a.Z)(e,o);return(0,i.kt)("wrapper",(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"9251-\u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668"},"9.25.1 \u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668"),(0,i.kt)("p",null,"\u5728\u6700\u65b0\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"1.1.6+")," \u7248\u672c\u4e2d\uff0c\u65b0\u589e\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"IEntityChangedListener")," \u5b9e\u4f53\u6570\u636e\u76d1\u542c\u63a5\u53e3\uff0c\u53ef\u4ee5\u76d1\u542c ",(0,i.kt)("inlineCode",{parentName:"p"},"EFCore")," \u4efb\u4f55\u5b9e\u4f53\u8868 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u589e\u5220\u6539")," \u64cd\u4f5c\u3002"),(0,i.kt)("h2",{id:"9252-\u6709\u4f55\u4f5c\u7528"},"9.25.2 \u6709\u4f55\u4f5c\u7528"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u7c7b\u4f3c\u6570\u636e\u5e93 ",(0,i.kt)("inlineCode",{parentName:"li"},"\u89e6\u53d1\u5668")," \u529f\u80fd\uff0c\u53ef\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"li"},"\u589e\u5220\u6539")," \u76d1\u542c"),(0,i.kt)("li",{parentName:"ul"},"\u53ef\u4ee5\u5b9e\u73b0\u7279\u6b8a\u64cd\u4f5c\uff0c\u6bd4\u5982\u5237\u65b0\u7f13\u5b58\uff0c\u8bb0\u5f55\u65e5\u5fd7\u7b49")),(0,i.kt)("h2",{id:"9253-\u5982\u4f55\u4f7f\u7528"},"9.25.3 \u5982\u4f55\u4f7f\u7528"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u4e0d\u542f\u7528\u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668\uff0c\u5982\u60f3\u542f\u7528\uff0c\u53ea\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587")," \u6784\u9020\u51fd\u6570\u4e2d\u542f\u7528\u5373\u53ef\uff1a"),(0,i.kt)("h3",{id:"92531-\u542f\u7528\u6570\u636e\u76d1\u542c"},"9.25.3.1 \u542f\u7528\u6570\u636e\u76d1\u542c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11}",showLineNumbers:!0,"":!0,"{11}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class DefaultDbContext : AppDbContext\n {\n public DefaultDbContext(DbContextOptions options) : base(options)\n {\n EnabledEntityChangedListener = true;\n }\n }\n}\n')),(0,i.kt)("h3",{id:"92532-\u76d1\u542c\u7279\u5b9a\u5b9e\u4f53\u6570\u636e"},"9.25.3.2 \u76d1\u542c\u7279\u5b9a\u5b9e\u4f53\u6570\u636e"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,30-41}",showLineNumbers:!0,"":!0,"{9,30-41}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.Extensions.Caching.Memory;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Furion.Core\n{\n public class Post : Entity, IEntityChangedListener\n {\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n public Post()\n {\n CreatedTime = DateTimeOffset.UtcNow;\n IsDeleted = false;\n }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n\n /// \n /// Person \u96c6\u5408\n /// \n public ICollection Persons { get; set; }\n\n /// \n /// \u5b9e\u4f53\u66f4\u6539\u540e\u89e6\u53d1\n /// \n /// \u65b0\u6570\u636e\n /// \u65e7\u6570\u636e\n /// \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n /// \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\n /// \u5b9e\u4f53\u72b6\u6001\n public void OnChanged(Post entity, Post oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state)\n {\n // \u5237\u65b0\u7f13\u5b58\n App.GetService().Set("Key", "Value");\n }\n }\n}\n')),(0,i.kt)("h2",{id:"9254-ientitychangedlistener-\u5b9a\u4e49"},"9.25.4 ",(0,i.kt)("inlineCode",{parentName:"h2"},"IEntityChangedListener")," \u5b9a\u4e49"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {25}",showLineNumbers:!0,"":!0,"{25}":!0},'/// \n/// \u5b9e\u4f53\u6570\u636e\u6539\u53d8\u76d1\u542c\u4f9d\u8d56\u63a5\u53e3\n/// \n/// \npublic interface IEntityChangedListener\n where TEntity : class, IPrivateEntity, new()\n{\n /// \n /// \u76d1\u542c\u6570\u636e\u6539\u53d8\u4e4b\u524d\uff08\u4ec5\u652f\u6301EFCore\u64cd\u4f5c\uff09\n /// \n /// \n /// \n /// \n /// \n void OnChanging(TEntity entity, DbContext dbContext, Type dbContextLocator, EntityState state) { }\n\n /// \n /// \u76d1\u542c\u6570\u636e\u6539\u53d8\u4e4b\u540e\uff08\u4ec5\u652f\u6301EFCore\u64cd\u4f5c\uff09\n /// \n /// \u65b0\u503c\n /// \u65e7\u503c\n /// \n /// \n /// \n void OnChanged(TEntity newEntity, TEntity oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state);\n\n /// \n /// \u76d1\u542c\u6570\u636e\u6539\u53d8\u5931\u8d25\uff08\u4ec5\u652f\u6301EFCore\u64cd\u4f5c\uff09\n /// \n /// \n /// \n /// \n /// \n void OnChangeFailed(TEntity entity, DbContext dbContext, Type dbContextLocator, EntityState state) { }\n}\n')),(0,i.kt)("h2",{id:"9255-suppresschangedlistener-\u8df3\u8fc7\u76d1\u542c"},"9.25.5 ",(0,i.kt)("inlineCode",{parentName:"h2"},"[SuppressChangedListener]")," \u8df3\u8fc7\u76d1\u542c"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4f1a\u5bf9\u6240\u6709\u65b0\u589e\u3001\u66f4\u65b0\u3001\u7f16\u8f91\u7684\u5b9e\u4f53\u8fdb\u884c\u76d1\u542c\uff0c\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u65e0\u9700\u76d1\u542c\u7279\u5b9a\u5b9e\u4f53\uff0c\u53ea\u9700\u8981\u5728\u5b9e\u4f53\u4e0a\u8d34 ",(0,i.kt)("inlineCode",{parentName:"p"},"[SuppressChangedListener]")," \u7279\u6027\u5373\u53ef\u3002"),(0,i.kt)("h2",{id:"9256-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.25.6 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}d.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return l},kt:function(){return d}});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=r.createContext({}),m=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},l=function(e){var t=m(e.components);return r.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},c=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,p=e.parentName,l=s(e,["components","mdxType","originalType","parentName"]),c=m(n),d=a,y=c["".concat(p,".").concat(d)]||c[d]||u[d]||i;return n?r.createElement(y,o(o({ref:t},l),{},{components:n})):r.createElement(y,o({ref:t},l))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,o=new Array(i);o[0]=c;var s={};for(var p in t)hasOwnProperty.call(t,p)&&(s[p]=t[p]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var m=2;m=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=r.createContext({}),m=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},l=function(e){var t=m(e.components);return r.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},c=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,p=e.parentName,l=s(e,["components","mdxType","originalType","parentName"]),c=m(n),d=a,y=c["".concat(p,".").concat(d)]||c[d]||u[d]||i;return n?r.createElement(y,o(o({ref:t},l),{},{components:n})):r.createElement(y,o({ref:t},l))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,o=new Array(i);o[0]=c;var s={};for(var p in t)hasOwnProperty.call(t,p)&&(s[p]=t[p]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var m=2;mIEntityChangedListener \u5b9a\u4e49",id:"9254-ientitychangedlistener-\u5b9a\u4e49",level:2},{value:"9.25.5 [SuppressChangedListener] \u8df3\u8fc7\u76d1\u542c",id:"9255-suppresschangedlistener-\u8df3\u8fc7\u76d1\u542c",level:2},{value:"9.25.6 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9256-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:u};function d(e){var t=e.components,n=(0,a.Z)(e,o);return(0,i.kt)("wrapper",(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"9251-\u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668"},"9.25.1 \u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668"),(0,i.kt)("p",null,"\u5728\u6700\u65b0\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"1.1.6+")," \u7248\u672c\u4e2d\uff0c\u65b0\u589e\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"IEntityChangedListener")," \u5b9e\u4f53\u6570\u636e\u76d1\u542c\u63a5\u53e3\uff0c\u53ef\u4ee5\u76d1\u542c ",(0,i.kt)("inlineCode",{parentName:"p"},"EFCore")," \u4efb\u4f55\u5b9e\u4f53\u8868 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u589e\u5220\u6539")," \u64cd\u4f5c\u3002"),(0,i.kt)("h2",{id:"9252-\u6709\u4f55\u4f5c\u7528"},"9.25.2 \u6709\u4f55\u4f5c\u7528"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u7c7b\u4f3c\u6570\u636e\u5e93 ",(0,i.kt)("inlineCode",{parentName:"li"},"\u89e6\u53d1\u5668")," \u529f\u80fd\uff0c\u53ef\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"li"},"\u589e\u5220\u6539")," \u76d1\u542c"),(0,i.kt)("li",{parentName:"ul"},"\u53ef\u4ee5\u5b9e\u73b0\u7279\u6b8a\u64cd\u4f5c\uff0c\u6bd4\u5982\u5237\u65b0\u7f13\u5b58\uff0c\u8bb0\u5f55\u65e5\u5fd7\u7b49")),(0,i.kt)("h2",{id:"9253-\u5982\u4f55\u4f7f\u7528"},"9.25.3 \u5982\u4f55\u4f7f\u7528"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u4e0d\u542f\u7528\u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668\uff0c\u5982\u60f3\u542f\u7528\uff0c\u53ea\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587")," \u6784\u9020\u51fd\u6570\u4e2d\u542f\u7528\u5373\u53ef\uff1a"),(0,i.kt)("h3",{id:"92531-\u542f\u7528\u6570\u636e\u76d1\u542c"},"9.25.3.1 \u542f\u7528\u6570\u636e\u76d1\u542c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11}",showLineNumbers:!0,"":!0,"{11}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class DefaultDbContext : AppDbContext\n {\n public DefaultDbContext(DbContextOptions options) : base(options)\n {\n EnabledEntityChangedListener = true;\n }\n }\n}\n')),(0,i.kt)("h3",{id:"92532-\u76d1\u542c\u7279\u5b9a\u5b9e\u4f53\u6570\u636e"},"9.25.3.2 \u76d1\u542c\u7279\u5b9a\u5b9e\u4f53\u6570\u636e"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,30-41}",showLineNumbers:!0,"":!0,"{9,30-41}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.Extensions.Caching.Memory;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Furion.Core\n{\n public class Post : Entity, IEntityChangedListener\n {\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n public Post()\n {\n CreatedTime = DateTimeOffset.UtcNow;\n IsDeleted = false;\n }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n\n /// \n /// Person \u96c6\u5408\n /// \n public ICollection Persons { get; set; }\n\n /// \n /// \u5b9e\u4f53\u66f4\u6539\u540e\u89e6\u53d1\n /// \n /// \u65b0\u6570\u636e\n /// \u65e7\u6570\u636e\n /// \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n /// \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\n /// \u5b9e\u4f53\u72b6\u6001\n public void OnChanged(Post entity, Post oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state)\n {\n // \u5237\u65b0\u7f13\u5b58\n App.GetService().Set("Key", "Value");\n }\n }\n}\n')),(0,i.kt)("h2",{id:"9254-ientitychangedlistener-\u5b9a\u4e49"},"9.25.4 ",(0,i.kt)("inlineCode",{parentName:"h2"},"IEntityChangedListener")," \u5b9a\u4e49"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {25}",showLineNumbers:!0,"":!0,"{25}":!0},'/// \n/// \u5b9e\u4f53\u6570\u636e\u6539\u53d8\u76d1\u542c\u4f9d\u8d56\u63a5\u53e3\n/// \n/// \npublic interface IEntityChangedListener\n where TEntity : class, IPrivateEntity, new()\n{\n /// \n /// \u76d1\u542c\u6570\u636e\u6539\u53d8\u4e4b\u524d\uff08\u4ec5\u652f\u6301EFCore\u64cd\u4f5c\uff09\n /// \n /// \n /// \n /// \n /// \n void OnChanging(TEntity entity, DbContext dbContext, Type dbContextLocator, EntityState state) { }\n\n /// \n /// \u76d1\u542c\u6570\u636e\u6539\u53d8\u4e4b\u540e\uff08\u4ec5\u652f\u6301EFCore\u64cd\u4f5c\uff09\n /// \n /// \u65b0\u503c\n /// \u65e7\u503c\n /// \n /// \n /// \n void OnChanged(TEntity newEntity, TEntity oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state);\n\n /// \n /// \u76d1\u542c\u6570\u636e\u6539\u53d8\u5931\u8d25\uff08\u4ec5\u652f\u6301EFCore\u64cd\u4f5c\uff09\n /// \n /// \n /// \n /// \n /// \n void OnChangeFailed(TEntity entity, DbContext dbContext, Type dbContextLocator, EntityState state) { }\n}\n')),(0,i.kt)("h2",{id:"9255-suppresschangedlistener-\u8df3\u8fc7\u76d1\u542c"},"9.25.5 ",(0,i.kt)("inlineCode",{parentName:"h2"},"[SuppressChangedListener]")," \u8df3\u8fc7\u76d1\u542c"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4f1a\u5bf9\u6240\u6709\u65b0\u589e\u3001\u66f4\u65b0\u3001\u7f16\u8f91\u7684\u5b9e\u4f53\u8fdb\u884c\u76d1\u542c\uff0c\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u65e0\u9700\u76d1\u542c\u7279\u5b9a\u5b9e\u4f53\uff0c\u53ea\u9700\u8981\u5728\u5b9e\u4f53\u4e0a\u8d34 ",(0,i.kt)("inlineCode",{parentName:"p"},"[SuppressChangedListener]")," \u7279\u6027\u5373\u53ef\u3002"),(0,i.kt)("h2",{id:"9256-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.25.6 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/04b9380e.66397e23.js b/handbook/build/assets/js/04b9380e.66397e23.js new file mode 100644 index 0000000000..9d8abf11be --- /dev/null +++ b/handbook/build/assets/js/04b9380e.66397e23.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[3867],{3905:function(e,n,t){t.d(n,{Zo:function(){return c},kt:function(){return d}});var r=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function i(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var s=r.createContext({}),u=function(e){var n=r.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},c=function(e){var n=u(e.components);return r.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},m=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),m=u(t),d=a,v=m["".concat(s,".").concat(d)]||m[d]||p[d]||o;return t?r.createElement(v,i(i({ref:n},c),{},{components:t})):r.createElement(v,i({ref:n},c))}));function d(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var o=t.length,i=new Array(o);i[0]=m;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var u=2;uRabbitMQ \u81ea\u5b9a\u4e49\u6307\u5357",id:"2241-rabbitmq-\u81ea\u5b9a\u4e49\u6307\u5357",level:3},{value:"22.5 \u81ea\u5b9a\u4e49\u4e8b\u4ef6\u53d1\u5e03\u8005",id:"225-\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u53d1\u5e03\u8005",level:2},{value:"22.6 \u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u76d1\u89c6\u5668",id:"226-\u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u76d1\u89c6\u5668",level:2},{value:"22.7 \u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u5668",id:"227-\u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u5668",level:2},{value:"22.8 \u4f7f\u7528\u6709\u4f5c\u7528\u57df\u7684\u670d\u52a1",id:"228-\u4f7f\u7528\u6709\u4f5c\u7528\u57df\u7684\u670d\u52a1",level:2},{value:"22.9 \u8ba2\u9605\u6267\u884c\u4efb\u52a1\u610f\u5916\u5f02\u5e38",id:"229-\u8ba2\u9605\u6267\u884c\u4efb\u52a1\u610f\u5916\u5f02\u5e38",level:2},{value:"22.10 \u4e8b\u4ef6\u603b\u7ebf\u5de5\u5382",id:"2210-\u4e8b\u4ef6\u603b\u7ebf\u5de5\u5382",level:2},{value:"22.11 MessageCenter \u9759\u6001\u7c7b",id:"2211-messagecenter-\u9759\u6001\u7c7b",level:2},{value:"22.12 EventBusOptionsBuilder \u914d\u7f6e",id:"2212-eventbusoptionsbuilder-\u914d\u7f6e",level:2},{value:"22.13 \u5982\u4f55\u5b9e\u73b0\u6570\u636e\u5e93\u4e8b\u52a1\u63a7\u5236",id:"2213-\u5982\u4f55\u5b9e\u73b0\u6570\u636e\u5e93\u4e8b\u52a1\u63a7\u5236",level:2},{value:"22.14 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"2214-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:m};function v(e){var n=e.components,t=(0,a.Z)(e,l);return(0,o.kt)("wrapper",(0,r.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{title:"v2.20 \u4ee5\u4e0b\u7248\u672c\u8bf4\u660e",type:"warning"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("strong",{parentName:"p"},"\u5728 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Furion v2.20+")," \u7248\u672c\u540e\u91c7\u7528 ",(0,o.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Jaina"},"Jaina")," \u4e8b\u4ef6\u603b\u7ebf\u66ff\u6362\u539f\u6709\u7684 ",(0,o.kt)("inlineCode",{parentName:"strong"},"EventBus")),"\uff0c",(0,o.kt)("a",{parentName:"p",href:"./event-bus-old"},"\u67e5\u770b\u65e7\u6587\u6863"))),(0,o.kt)("h2",{id:"221-\u5173\u4e8e\u4e8b\u4ef6\u603b\u7ebf"},"22.1 \u5173\u4e8e\u4e8b\u4ef6\u603b\u7ebf"),(0,o.kt)("p",null,"\u4e8b\u4ef6\u603b\u7ebf\u662f\u5bf9\u53d1\u5e03-\u8ba2\u9605\u6a21\u5f0f\u7684\u4e00\u79cd\u5b9e\u73b0\u3002\u5b83\u662f\u4e00\u79cd\u96c6\u4e2d\u5f0f\u4e8b\u4ef6\u5904\u7406\u673a\u5236\uff0c\u5141\u8bb8\u4e0d\u540c\u7684\u7ec4\u4ef6\u4e4b\u95f4\u8fdb\u884c\u5f7c\u6b64\u901a\u4fe1\u800c\u53c8\u4e0d\u9700\u8981\u76f8\u4e92\u4f9d\u8d56\uff0c\u8fbe\u5230\u4e00\u79cd\u89e3\u8026\u7684\u76ee\u7684\u3002"),(0,o.kt)("img",{src:(0,i.Z)("img/ebs.png")}),(0,o.kt)("h2",{id:"222-\u5feb\u901f\u5165\u95e8"},"22.2 \u5feb\u901f\u5165\u95e8"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"\u5b9a\u4e49\u4e8b\u4ef6\u8ba2\u9605\u8005 ",(0,o.kt)("inlineCode",{parentName:"li"},"ToDoEventSubscriber"),"\uff1a")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,10-11,19-21,28-30,32,36-38,44-48}",showLineNumbers:!0,"":!0,"{2,10-11,19-21,28-30,32,36-38,44-48}":!0},'// \u5b9e\u73b0 IEventSubscriber \u63a5\u53e3\npublic class ToDoEventSubscriber : IEventSubscriber\n{\n private readonly ILogger _logger;\n public ToDoEventSubscriber(ILogger logger)\n {\n _logger = logger;\n }\n\n [EventSubscribe("ToDo:Create")]\n public async Task CreateToDo(EventHandlerExecutingContext context)\n {\n var todo = context.Source;\n _logger.LogInformation("\u521b\u5efa\u4e00\u4e2a ToDo\uff1a{Name}", todo.Payload);\n await Task.CompletedTask;\n }\n\n // \u652f\u6301\u591a\u4e2a\n [EventSubscribe("ToDo:Create")]\n [EventSubscribe("ToDo:Update")]\n public async Task CreateOrUpdateToDo(EventHandlerExecutingContext context)\n {\n var todo = context.Source;\n _logger.LogInformation("\u521b\u5efa\u6216\u66f4\u65b0\u4e00\u4e2a ToDo\uff1a{Name}", todo.Payload);\n await Task.CompletedTask;\n }\n\n // \u652f\u6301\u679a\u4e3e\u7c7b\u578b\uff0cv3.4.3+ \u7248\u672c\u652f\u6301\n [EventSubscribe(YourEnum.Some)]\n public async Task EnumHandler(EventHandlerExecutingContext context)\n {\n var eventEnum = context.Source.EventId.ParseToEnum(); // \u5c06\u4e8b\u4ef6 Id \u8f6c\u6362\u6210\u679a\u4e3e\u5bf9\u8c61\n await Task.CompletedTask;\n }\n\n // \u652f\u6301\u6b63\u5219\u8868\u8fbe\u5f0f\u5339\u914d\uff0c4.2.10+ \u7248\u672c\u652f\u6301\n [EventSubscribe("(^1[3456789][0-9]{9}$)|((^[0-9]{3,4}\\\\-[0-9]{3,8}$)|(^[0-9]{3,8}$)|(^\\\\([0-9]{3,4}\\\\)[0-9]{3,8}$)|(^0{0,1}13[0-9]{9}$))", FuzzyMatch = true)]\n public async Task RegexHandler(EventHandlerExecutingContext context)\n {\n var eventId = context.Source.EventId;\n await Task.CompletedTask;\n }\n\n // \u652f\u6301\u591a\u79cd\u5f02\u5e38\u91cd\u8bd5\u914d\u7f6e\uff0c4.2.10+ \u7248\u672c\u652f\u6301\n [EventSubscribe("test:error", NumRetries = 3)]\n [EventSubscribe("test:error", NumRetries = 3, RetryTimeout = 1000)] // \u91cd\u8bd5\u95f4\u9694\u65f6\u95f4\n [EventSubscribe("test:error", NumRetries = 3, ExceptionTypes = new[] { typeof(ArgumentException) })] // \u7279\u5b9a\u7c7b\u578b\u5f02\u5e38\u624d\u91cd\u8bd5\n public async Task ExceptionHandler(EventHandlerExecutingContext context)\n {\n var eventId = context.Source.EventId;\n await Task.CompletedTask;\n }\n}\n')),(0,o.kt)("ol",{start:2},(0,o.kt)("li",{parentName:"ol"},"\u521b\u5efa\u63a7\u5236\u5668 ",(0,o.kt)("inlineCode",{parentName:"li"},"ToDoController"),"\uff0c\u4f9d\u8d56\u6ce8\u5165 ",(0,o.kt)("inlineCode",{parentName:"li"},"IEventPublisher")," \u670d\u52a1\uff1a")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,13,16-21}",showLineNumbers:!0,"":!0,"{4,13,16-21}":!0},'public class ToDoController : ControllerBase\n{\n // \u4f9d\u8d56\u6ce8\u5165\u4e8b\u4ef6\u53d1\u5e03\u8005 IEventPublisher\n private readonly IEventPublisher _eventPublisher;\n public ToDoController(IEventPublisher eventPublisher)\n {\n _eventPublisher = eventPublisher;\n }\n\n // \u53d1\u5e03 ToDo:Create \u6d88\u606f\n public async Task CreateDoTo(string name)\n {\n await _eventPublisher.PublishAsync(new ChannelEventSource("ToDo:Create", name));\n }\n\n // v3.4.3+ \u7248\u672c\u652f\u6301\u53d1\u9001\u6d88\u606f\u7b80\u5316\n public async Task CreateDoTo(string name)\n {\n await _eventPublisher.PublishAsync("ToDo:Create", name);\n // \u4e5f\u652f\u6301\u679a\u4e3e\n await _eventPublisher.PublishAsync(YourEnum.Some);\n }\n}\n')),(0,o.kt)("ol",{start:3},(0,o.kt)("li",{parentName:"ol"},"\u5728 ",(0,o.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"li"},"EventBus")," \u670d\u52a1\uff1a")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5}",showLineNumbers:!0,"":!0,"{2,5}":!0},"// \u6ce8\u518c EventBus \u670d\u52a1\nservices.AddEventBus(builder =>\n{\n // \u6ce8\u518c ToDo \u4e8b\u4ef6\u8ba2\u9605\u8005\n builder.AddSubscriber();\n\n // \u901a\u8fc7\u7c7b\u578b\u6ce8\u518c\uff0cFurion 4.2.1+ \u7248\u672c\n builder.AddSubscriber(typeof(ToDoEventSubscriber));\n\n // \u6279\u91cf\u6ce8\u518c\u4e8b\u4ef6\u8ba2\u9605\u8005\n builder.AddSubscribers(ass1, ass2, ....);\n});\n")),(0,o.kt)("admonition",{title:"\u61d2\u4eba\u63d0\u9192",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e2d\u53ef\u4ee5\u4e0d\u7528\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"builder.AddSubscriber()")," \u65b9\u5f0f\u4e00\u4e00\u6ce8\u518c\uff0c\u53ea\u9700\u8981\u5b9e\u73b0 ",(0,o.kt)("inlineCode",{parentName:"p"},"ISingleton")," \u63a5\u53e3\u5373\u53ef\uff0c\u5982\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"public class ToDoEventSubscriber : IEventSubscriber, ISingleton\n{\n}\n")),(0,o.kt)("p",{parentName:"admonition"},"\u8fd9\u6837\u5c31\u65e0\u9700\u5199 ",(0,o.kt)("del",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"del"},"builder.AddSubscriber();"))," \u4ee3\u7801\u4e86\uff0c\u53ea\u9700\u4fdd\u7559 ",(0,o.kt)("inlineCode",{parentName:"p"},"services.AddEventBus()")," \u670d\u52a1\u5373\u53ef\u3002")),(0,o.kt)("ol",{start:4},(0,o.kt)("li",{parentName:"ol"},"\u8fd0\u884c\u9879\u76ee\uff1a")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"info: Jaina.Samples.ToDoEventSubscriber[0]\n \u521b\u5efa\u4e00\u4e2a ToDo\uff1aJaina\n")),(0,o.kt)("h2",{id:"223-\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u6e90"},"22.3 \u81ea\u5b9a\u4e49\u4e8b\u4ef6\u6e90"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventSource")," \u4f5c\u4e3a\u6d88\u606f\u8f7d\u4f53\uff0c\u4efb\u4f55\u5b9e\u73b0\u8be5\u63a5\u53e3\u7684\u7c7b\u90fd\u53ef\u4ee5\u5145\u5f53\u6d88\u606f\u8f7d\u4f53\u3002"),(0,o.kt)("p",null,"\u5982\u9700\u81ea\u5b9a\u4e49\uff0c\u53ea\u9700\u5b9e\u73b0 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventSource")," \u63a5\u53e3\u5373\u53ef\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,14,19,24,29,35-37}",showLineNumbers:!0,"":!0,"{1,3,14,19,24,29,35-37}":!0},"public class ToDoEventSource : IEventSource\n{\n public ToDoEventSource()\n {\n }\n\n public ToDoEventSource(string eventId, string todoName)\n {\n EventId = eventId;\n ToDoName = todoName;\n }\n\n // \u81ea\u5b9a\u4e49\u5c5e\u6027\n public string ToDoName { get; set; }\n\n /// \n /// \u4e8b\u4ef6 Id\n /// \n public string EventId { get; set; }\n\n /// \n /// \u4e8b\u4ef6\u627f\u8f7d\uff08\u643a\u5e26\uff09\u6570\u636e\n /// \n public object Payload { get; set; }\n\n /// \n /// \u4e8b\u4ef6\u521b\u5efa\u65f6\u95f4\n /// \n public DateTime CreatedTime { get; set; } = DateTime.UtcNow;\n\n /// \n /// \u53d6\u6d88\u4efb\u52a1 Token\n /// \n /// \u7528\u4e8e\u53d6\u6d88\u672c\u6b21\u6d88\u606f\u5904\u7406\n [Newtonsoft.Json.JsonIgnore]\n [System.Text.Json.Serialization.JsonIgnore]\n public CancellationToken CancellationToken { get; set; }\n}\n")),(0,o.kt)("p",null,"\u4f7f\u7528\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await _eventPublisher.PublishAsync(new ToDoEventSource ("ToDo:Create", "\u6211\u7684 ToDo Name"));\n')),(0,o.kt)("h2",{id:"224-\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u6e90\u5b58\u50a8\u5668"},"22.4 \u81ea\u5b9a\u4e49\u4e8b\u4ef6\u6e90\u5b58\u50a8\u5668"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Fruion")," \u9ed8\u8ba4\u91c7\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"Channel")," \u4f5c\u4e3a\u4e8b\u4ef6\u6e90 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventSource")," \u5b58\u50a8\u5668\uff0c\u5f00\u53d1\u8005\u53ef\u4ee5\u4f7f\u7528\u4efb\u4f55\u6d88\u606f\u961f\u5217\u7ec4\u4ef6\u8fdb\u884c\u66ff\u6362\uff0c\u5982 ",(0,o.kt)("inlineCode",{parentName:"p"},"Kafka\u3001RabbitMQ\u3001ActiveMQ")," \u7b49\uff0c\u4e5f\u53ef\u4ee5\u4f7f\u7528\u90e8\u5206\u6570\u636e\u5e93 ",(0,o.kt)("inlineCode",{parentName:"p"},"Redis\u3001SQL Server\u3001MySql")," \u5b9e\u73b0\u3002"),(0,o.kt)("p",null,"\u5982\u9700\u81ea\u5b9a\u4e49\uff0c\u53ea\u9700\u5b9e\u73b0 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventSourceStorer")," \u63a5\u53e3\u5373\u53ef\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,11,17}",showLineNumbers:!0,"":!0,"{1,11,17}":!0},"public class RedisEventSourceStorer : IEventSourceStorer\n{\n private readonly IRedisClient _redisClient;\n\n public RedisEventSourceStorer(IRedisClient redisClient)\n {\n _redisClient = redisClient;\n }\n\n // \u5f80 Redis \u4e2d\u5199\u5165\u4e00\u6761\n public async ValueTask WriteAsync(IEventSource eventSource, CancellationToken cancellationToken)\n {\n await _redisClient.WriteAsync(...., cancellationToken);\n }\n\n // \u4ece Redis \u4e2d\u8bfb\u53d6\u4e00\u6761\n public async ValueTask ReadAsync(CancellationToken cancellationToken)\n {\n return await _redisClient.ReadAsync(...., cancellationToken);\n }\n}\n")),(0,o.kt)("p",null,"\u6700\u540e\uff0c\u5728\u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"p"},"EventBus")," \u670d\u52a1\u4e2d\u66ff\u6362\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventSourceStorer"),"\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4-8}",showLineNumbers:!0,"":!0,"{4-8}":!0},"services.AddEventBus(builder =>\n{\n // \u66ff\u6362\u4e8b\u4ef6\u6e90\u5b58\u50a8\u5668\n builder.ReplaceStorer(serviceProvider =>\n {\n var redisClient = serviceProvider.GetService();\n return new RedisEventSourceStorer(redisClient);\n });\n});\n")),(0,o.kt)("h3",{id:"2241-rabbitmq-\u81ea\u5b9a\u4e49\u6307\u5357"},"22.4.1 ",(0,o.kt)("inlineCode",{parentName:"h3"},"RabbitMQ")," \u81ea\u5b9a\u4e49\u6307\u5357"),(0,o.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 4.3.4 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,o.kt)("p",null,"\u7531\u4e8e\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"RabbitMQ")," \u4f5c\u4e3a\u4e8b\u4ef6\u603b\u7ebf\u5b58\u50a8\u5668\u7684\u6bd4\u8f83\u591a\uff0c\u6240\u4ee5\u8fd9\u91cc\u63d0\u4f9b\u4e86\u5b8c\u6574\u7684\u4f7f\u7528\u4f8b\u5b50\u3002"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"1. \u5b89\u88c5 ",(0,o.kt)("inlineCode",{parentName:"strong"},"RabbitMQ.Client")," \u62d3\u5c55\u5305")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"Install-Package RabbitMQ.Client -Version 6.4.0\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"2. \u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"strong"},"RabbitMQEventSourceStorer")," \u81ea\u5b9a\u4e49\u5b58\u50a8\u5668")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,41,60,66-78,99-103,116-117,125-126}",showLineNumbers:!0,"{13,41,60,66-78,99-103,116-117,125-126}":!0},'using Furion.EventBus;\nusing RabbitMQ.Client;\nusing RabbitMQ.Client.Events;\nusing System;\nusing System.Text;\nusing System.Text.Json;\nusing System.Threading;\nusing System.Threading.Channels;\nusing System.Threading.Tasks;\n\nnamespace Furion.Core;\n\npublic sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable\n{\n /// \n /// \u5185\u5b58\u901a\u9053\u4e8b\u4ef6\u6e90\u5b58\u50a8\u5668\n /// \n private readonly Channel _channel;\n\n /// \n /// \u901a\u9053\u5bf9\u8c61\n /// \n private readonly IModel _model;\n\n /// \n /// \u8fde\u63a5\u5bf9\u8c61\n /// \n private readonly IConnection _connection;\n\n /// \n /// \u8def\u7531\u952e\n /// \n private readonly string _routeKey;\n\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n /// \u8fde\u63a5\u5de5\u5382\n /// \u8def\u7531\u952e\n /// \u5b58\u50a8\u5668\u6700\u591a\u80fd\u591f\u5904\u7406\u591a\u5c11\u6d88\u606f\uff0c\u8d85\u8fc7\u8be5\u5bb9\u91cf\u8fdb\u5165\u7b49\u5f85\u5199\u5165\n public RabbitMQEventSourceStorer(ConnectionFactory factory, string routeKey, int capacity)\n {\n // \u914d\u7f6e\u901a\u9053\uff0c\u8bbe\u7f6e\u8d85\u51fa\u9ed8\u8ba4\u5bb9\u91cf\u540e\u8fdb\u5165\u7b49\u5f85\n var boundedChannelOptions = new BoundedChannelOptions(capacity)\n {\n FullMode = BoundedChannelFullMode.Wait\n };\n\n // \u521b\u5efa\u6709\u9650\u5bb9\u91cf\u901a\u9053\n _channel = Channel.CreateBounded(boundedChannelOptions);\n\n // \u521b\u5efa\u8fde\u63a5\n _connection = factory.CreateConnection();\n _routeKey = routeKey;\n\n // \u521b\u5efa\u901a\u9053\n _model = _connection.CreateModel();\n\n // \u58f0\u660e\u8def\u7531\u961f\u5217\n _model.QueueDeclare(routeKey, false, false, false, null);\n\n // \u521b\u5efa\u6d88\u606f\u8ba2\u9605\u8005\n var consumer = new EventingBasicConsumer(_model);\n\n // \u8ba2\u9605\u6d88\u606f\u5e76\u5199\u5165\u5185\u5b58 Channel\n consumer.Received += (ch, ea) =>\n {\n // \u8bfb\u53d6\u539f\u59cb\u6d88\u606f\n var stringEventSource = Encoding.UTF8.GetString(ea.Body.ToArray());\n\n // \u8f6c\u6362\u4e3a IEventSource\uff0c\u8fd9\u91cc\u53ef\u4ee5\u9009\u62e9\u81ea\u5df1\u559c\u6b22\u7684\u5e8f\u5217\u5316\u5de5\u5177\uff0c\u5982\u679c\u81ea\u5b9a\u4e49\u4e86 EventSource\uff0c\u6ce8\u610f\u5c5e\u6027\u662f\u53ef\u8bfb\u53ef\u5199\n var eventSource = JsonSerializer.Deserialize(stringEventSource);\n\n // \u5199\u5165\u5185\u5b58\u7ba1\u9053\u5b58\u50a8\u5668\n _channel.Writer.TryWrite(eventSource);\n\n // \u786e\u8ba4\u8be5\u6d88\u606f\u5df2\u88ab\u6d88\u8d39\n _model.BasicAck(ea.DeliveryTag, false);\n };\n\n // \u542f\u52a8\u6d88\u8d39\u8005 \u8bbe\u7f6e\u4e3a\u624b\u52a8\u5e94\u7b54\u6d88\u606f\n _model.BasicConsume(routeKey, false, consumer);\n }\n\n /// \n /// \u5c06\u4e8b\u4ef6\u6e90\u5199\u5165\u5b58\u50a8\u5668\n /// \n /// \u4e8b\u4ef6\u6e90\u5bf9\u8c61\n /// \u53d6\u6d88\u4efb\u52a1 Token\n /// \n public ValueTask WriteAsync(IEventSource eventSource, CancellationToken cancellationToken)\n {\n // \u7a7a\u68c0\u67e5\n if (eventSource == default)\n {\n throw new ArgumentNullException(nameof(eventSource));\n }\n\n // \u5e8f\u5217\u5316\uff0c\u8fd9\u91cc\u53ef\u4ee5\u9009\u62e9\u81ea\u5df1\u559c\u6b22\u7684\u5e8f\u5217\u5316\u5de5\u5177\n var data = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(eventSource));\n\n // \u53d1\u5e03\n _model.BasicPublish("", _routeKey, null, data);\n\n return ValueTask.CompletedTask;\n }\n\n /// \n /// \u4ece\u5b58\u50a8\u5668\u4e2d\u8bfb\u53d6\u4e00\u6761\u4e8b\u4ef6\u6e90\n /// \n /// \u53d6\u6d88\u4efb\u52a1 Token\n /// \u4e8b\u4ef6\u6e90\u5bf9\u8c61\n public async ValueTask ReadAsync(CancellationToken cancellationToken)\n {\n // \u8bfb\u53d6\u4e00\u6761\u4e8b\u4ef6\u6e90\n var eventSource = await _channel.Reader.ReadAsync(cancellationToken);\n return eventSource;\n }\n\n /// \n /// \u91ca\u653e\u975e\u6258\u7ba1\u8d44\u6e90\n /// \n public void Dispose()\n {\n _model.Dispose();\n _connection.Dispose();\n }\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"3. \u66ff\u6362\u9ed8\u8ba4\u4e8b\u4ef6\u5b58\u50a8\u5668")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4-8,11,14-16}",showLineNumbers:!0,"{1,4-8,11,14-16}":!0},'services.AddEventBus(options =>\n{\n // \u521b\u5efa\u8fde\u63a5\u5de5\u5382\n var factory = new ConnectionFactory\n {\n UserName = "admin",\n Password = "q1w2e3",\n };\n\n // \u521b\u5efa\u9ed8\u8ba4\u5185\u5b58\u901a\u9053\u4e8b\u4ef6\u6e90\u5bf9\u8c61\uff0c\u53ef\u81ea\u5b9a\u4e49\u961f\u5217\u8def\u7531key\uff0c\u6bd4\u5982\u8fd9\u91cc\u662f eventbus\n var rbmqEventSourceStorer = new RabbitMQEventSourceStorer(factory, "eventbus", 3000);\n\n // \u66ff\u6362\u9ed8\u8ba4\u4e8b\u4ef6\u603b\u7ebf\u5b58\u50a8\u5668\n options.ReplaceStorer(serviceProvider =>\n {\n return rbmqEventSourceStorer;\n });\n});\n')),(0,o.kt)("img",{src:(0,i.Z)("img/evs1.png")}),(0,o.kt)("h2",{id:"225-\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u53d1\u5e03\u8005"},"22.5 \u81ea\u5b9a\u4e49\u4e8b\u4ef6\u53d1\u5e03\u8005"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u9ed8\u8ba4\u5185\u7f6e\u57fa\u4e8e ",(0,o.kt)("inlineCode",{parentName:"p"},"Channel")," \u7684\u4e8b\u4ef6\u53d1\u5e03\u8005 ",(0,o.kt)("inlineCode",{parentName:"p"},"ChannelEventPublisher"),"\u3002"),(0,o.kt)("p",null,"\u5982\u9700\u81ea\u5b9a\u4e49\uff0c\u53ea\u9700\u5b9e\u73b0 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventPublisher")," \u63a5\u53e3\u5373\u53ef\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,10}",showLineNumbers:!0,"":!0,"{1,10}":!0},"public class ToDoEventPublisher : IEventPublisher\n{\n private readonly IEventSourceStorer _eventSourceStorer;\n\n public ChannelEventPublisher(IEventSourceStorer eventSourceStorer)\n {\n _eventSourceStorer = eventSourceStorer;\n }\n\n public async Task PublishAsync(IEventSource eventSource)\n {\n await _eventSourceStorer.WriteAsync(eventSource, eventSource.CancellationToken);\n }\n}\n")),(0,o.kt)("p",null,"\u6700\u540e\uff0c\u5728\u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"p"},"EventBus")," \u670d\u52a1\u4e2d\u66ff\u6362\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventPublisher"),"\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"services.AddEventBus(builder =>\n{\n // \u66ff\u6362\u4e8b\u4ef6\u6e90\u5b58\u50a8\u5668\n builder.ReplacePublisher();\n});\n")),(0,o.kt)("h2",{id:"226-\u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u76d1\u89c6\u5668"},"22.6 \u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u76d1\u89c6\u5668"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventHandlerMonitor")," \u76d1\u89c6\u5668\u63a5\u53e3\uff0c\u5b9e\u73b0\u8be5\u63a5\u53e3\u53ef\u4ee5\u76d1\u89c6\u6240\u6709\u8ba2\u9605\u4e8b\u4ef6\uff0c\u5305\u62ec ",(0,o.kt)("inlineCode",{parentName:"p"},"\u6267\u884c\u4e4b\u524d\u3001\u6267\u884c\u4e4b\u540e\uff0c\u6267\u884c\u5f02\u5e38\uff0c\u5171\u4eab\u4e0a\u4e0b\u6587\u6570\u636e"),"\u3002"),(0,o.kt)("p",null,"\u5982\u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"p"},"ToDoEventHandlerMonitor"),"\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,9,15}",showLineNumbers:!0,"":!0,"{1,9,15}":!0},'public class ToDoEventHandlerMonitor : IEventHandlerMonitor\n{\n private readonly ILogger _logger;\n public ToDoEventHandlerMonitor(ILogger logger)\n {\n _logger = logger;\n }\n\n public Task OnExecutingAsync(EventHandlerExecutingContext context)\n {\n _logger.LogInformation("\u6267\u884c\u4e4b\u524d\uff1a{EventId}", context.Source.EventId);\n return Task.CompletedTask;\n }\n\n public Task OnExecutedAsync(EventHandlerExecutedContext context)\n {\n _logger.LogInformation("\u6267\u884c\u4e4b\u540e\uff1a{EventId}", context.Source.EventId);\n\n if (context.Exception != null)\n {\n _logger.LogError(context.Exception, "\u6267\u884c\u51fa\u9519\u5566\uff1a{EventId}", context.Source.EventId);\n }\n\n return Task.CompletedTask;\n }\n}\n')),(0,o.kt)("p",null,"\u6700\u540e\uff0c\u5728\u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"p"},"EventBus")," \u670d\u52a1\u4e2d\u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"p"},"ToDoEventHandlerMonitor"),"\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"services.AddEventBus(builder =>\n{\n // \u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u76d1\u89c6\u5668\n builder.AddMonitor();\n});\n")),(0,o.kt)("h2",{id:"227-\u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u5668"},"22.7 \u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u5668"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventHandlerExecutor")," \u6267\u884c\u5668\u63a5\u53e3\uff0c\u53ef\u4ee5\u8ba9\u5f00\u53d1\u8005\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u5904\u7406\u51fd\u6570\u6267\u884c\u7b56\u7565\uff0c\u5982 ",(0,o.kt)("inlineCode",{parentName:"p"},"\u8d85\u65f6\u63a7\u5236\uff0c\u5931\u8d25\u91cd\u8bd5\u3001\u7194\u65ad\u7b49\u7b49"),"\u3002"),(0,o.kt)("p",null,"\u5982\u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"p"},"RetryEventHandlerExecutor"),"\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3}",showLineNumbers:!0,"":!0,"{1,3}":!0},"public class RetryEventHandlerExecutor : IEventHandlerExecutor\n{\n public async Task ExecuteAsync(EventHandlerExecutingContext context, Func handler)\n {\n // \u5982\u679c\u6267\u884c\u5931\u8d25\uff0c\u6bcf\u9694 1s \u91cd\u8bd5\uff0c\u6700\u591a\u4e09\u6b21\n await Retry.InvokeAsync(async () => {\n await handler(context);\n }, 3, 1000);\n }\n}\n")),(0,o.kt)("p",null,"\u6700\u540e\uff0c\u5728\u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"p"},"EventBus")," \u670d\u52a1\u4e2d\u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"p"},"RetryEventHandlerExecutor"),"\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"services.AddEventBus(builder =>\n{\n // \u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u5668\n builder.AddExecutor();\n});\n")),(0,o.kt)("h2",{id:"228-\u4f7f\u7528\u6709\u4f5c\u7528\u57df\u7684\u670d\u52a1"},"22.8 \u4f7f\u7528\u6709\u4f5c\u7528\u57df\u7684\u670d\u52a1"),(0,o.kt)("p",null,"\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e2d\uff0c ",(0,o.kt)("inlineCode",{parentName:"p"},"Event Bus")," \u6240\u6709\u670d\u52a1\u5747\u6ce8\u518c\u4e3a\u5355\u4f8b\uff0c\u5982\u9700\u4f7f\u7528\u4f5c\u7528\u57df\u670d\u52a1\uff08\u5355\u4f8b\u670d\u52a1\u53ef\u76f4\u63a5\u6ce8\u5165\uff09\uff0c\u53ef\u901a\u8fc7\u4f9d\u8d56\u6ce8\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"IServiceProvider")," \u5b9e\u4f8b\u5e76\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"CreateScope()")," \u521b\u5efa\u4e00\u4e2a\u4f5c\u7528\u57df\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8,12,17-21}",showLineNumbers:!0,"":!0,"{5,8,12,17-21}":!0},'public class ToDoEventSubscriber : IEventSubscriber\n{\n private readonly ILogger _logger;\n\n public ToDoEventSubscriber(IServiceProvider services\n , ILogger logger)\n {\n Services = services;\n _logger = logger;\n }\n\n public IServiceProvider Services { get; }\n\n [EventSubscribe("ToDo:Create")]\n public async Task CreateToDo(EventHandlerExecutingContext context)\n {\n // \u521b\u5efa\u65b0\u7684\u4f5c\u7528\u57df\n using var scope = Services.CreateScope();\n\n // \u89e3\u6790\u670d\u52a1\n var scopedProcessingService = scope.ServiceProvider.GetRequiredService();\n // ....\n }\n}\n')),(0,o.kt)("h2",{id:"229-\u8ba2\u9605\u6267\u884c\u4efb\u52a1\u610f\u5916\u5f02\u5e38"},"22.9 \u8ba2\u9605\u6267\u884c\u4efb\u52a1\u610f\u5916\u5f02\u5e38"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"services.AddEventBus(builder =>\n{\n // \u8ba2\u9605 EventBus \u672a\u6355\u83b7\u5f02\u5e38\n builder.UnobservedTaskExceptionHandler = (obj, args) =>\n {\n // ....\n };\n});\n")),(0,o.kt)("h2",{id:"2210-\u4e8b\u4ef6\u603b\u7ebf\u5de5\u5382"},"22.10 \u4e8b\u4ef6\u603b\u7ebf\u5de5\u5382"),(0,o.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 4.2.10 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,o.kt)("p",null,"\u5728\u8be5\u7248\u672c\u4e2d\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventBusFactory")," \u5de5\u5382\u670d\u52a1\uff0c\u53ef\u5728\u8fd0\u884c\u65f6\u52a8\u6001\u65b0\u589e\u6216\u5220\u9664\u8ba2\u9605\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,14-17,24}",showLineNumbers:!0,"{4,14-17,24}":!0},'public class TestEventBus : IDynamicApiController\n{\n private readonly IEventPublisher _eventPublisher;\n private readonly IEventBusFactory _eventBusFactory;\n public TestEventBus(IEventPublisher eventPublisher, IEventBusFactory eventBusFactory)\n {\n _eventPublisher = eventPublisher;\n _eventBusFactory = eventBusFactory;\n }\n\n // \u8fd0\u884c\u65f6\u52a8\u6001\u6dfb\u52a0\u4e00\u4e2a\u8ba2\u9605\u5668\n public async Task AddSubscriber()\n {\n await _eventBusFactory.Subscribe("xxx", async (ctx) =>\n {\n Console.WriteLine("\u6211\u662f\u52a8\u6001\u7684");\n await Task.CompletedTask;\n });\n }\n\n // \u8fd0\u884c\u65f6\u52a8\u6001\u5220\u9664\u4e00\u4e2a\u8ba2\u9605\u5668\n public async Task RemoveDynamic(string eventId)\n {\n await _eventBusFactory.Unsubscribe(eventId);\n }\n}\n')),(0,o.kt)("h2",{id:"2211-messagecenter-\u9759\u6001\u7c7b"},"22.11 ",(0,o.kt)("inlineCode",{parentName:"h2"},"MessageCenter")," \u9759\u6001\u7c7b"),(0,o.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 4.3.3 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,o.kt)("p",null,"\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 4.3.3")," \u7248\u672c\u65b0\u589e\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"MessageCenter")," \u9759\u6001\u7c7b\uff0c\u53ef\u5728\u4efb\u4f55\u5730\u65b9\u53d1\u9001\u4e8b\u4ef6\u6d88\u606f\u6216\u8ba2\u9605\u6d88\u606f\u3002"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,11}",showLineNumbers:!0,"{2,5,11}":!0},'// \u53d1\u9001\u6d88\u606f\uff08\u542b\u8bf8\u591a\u91cd\u8f7d\uff09\nawait MessageCenter.PublishAsync("messageId", new {});\n\n// \u52a8\u6001\u8ba2\u9605\u6d88\u606f\nMessageCenter.Subscribe("messageId", async (ctx) => {\n Console.WriteLine("\u6211\u662f\u52a8\u6001\u7684");\n await Task.CompletedTask;\n});\n\n// \u53d6\u6d88\u8ba2\u9605\nMessageCenter.Unsubscribe("messageId");\n')),(0,o.kt)("h2",{id:"2212-eventbusoptionsbuilder-\u914d\u7f6e"},"22.12 ",(0,o.kt)("inlineCode",{parentName:"h2"},"EventBusOptionsBuilder")," \u914d\u7f6e"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"EventBusOptionsBuilder")," \u662f ",(0,o.kt)("inlineCode",{parentName:"p"},"AddEventBus")," \u6784\u5efa\u670d\u52a1\u9009\u9879\uff0c\u8be5\u9009\u9879\u5305\u542b\u4ee5\u4e0b\u5c5e\u6027\u548c\u65b9\u6cd5\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u5c5e\u6027",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ChannelCapacity"),"\uff1a\u9ed8\u8ba4\u5185\u5b58\u901a\u9053\u5bb9\u91cf"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"UnobservedTaskExceptionHandler"),"\uff1a\u8ba2\u9605\u6267\u884c\u4efb\u52a1\u672a\u5bdf\u89c9\u5f02\u5e38"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"UseUtcTimestamp"),"\uff1a\u662f\u5426\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"li"},"UTC")," \u4e8b\u4ef6\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"false")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"FuzzyMatch"),"\uff1a\u662f\u5426\u5f00\u542f\u5168\u5c40\u6a21\u7cca\u5339\u914d\uff08\u6b63\u5219\u8868\u8fbe\u5f0f\uff09\u4e8b\u4ef6 ",(0,o.kt)("inlineCode",{parentName:"li"},"Id"),"\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"false")))),(0,o.kt)("li",{parentName:"ul"},"\u65b9\u6cd5",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"AddSubscriber"),"\uff1a\u6dfb\u52a0\u8ba2\u9605\u8005"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ReplacePublisher"),"\uff1a\u66ff\u6362\u53d1\u5e03\u8005"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ReplaceStorer(Func)"),"\uff1a\u66ff\u6362\u5b58\u50a8\u5668"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"AddMonitor"),"\uff1a\u6dfb\u52a0\u76d1\u89c6\u5668"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"AddExecutor"),"\uff1a\u6dfb\u52a0\u6267\u884c\u5668")))),(0,o.kt)("h2",{id:"2213-\u5982\u4f55\u5b9e\u73b0\u6570\u636e\u5e93\u4e8b\u52a1\u63a7\u5236"},"22.13 \u5982\u4f55\u5b9e\u73b0\u6570\u636e\u5e93\u4e8b\u52a1\u63a7\u5236"),(0,o.kt)("p",null,"\u76f8\u4fe1\u5f88\u591a\u670b\u53cb\u90fd\u4f7f\u7528\u4e86\u4e8b\u4ef6\u603b\u7ebf\u8fdb\u884c\u6570\u636e\u5e93\u64cd\u4f5c\uff0c\u4f46\u662f\u4e0d\u77e5\u9053\u5982\u4f55\u5b9e\u73b0\u4e8b\u52a1\u63a7\u5236\uff0c\u5b9e\u9645\u4e0a\u5e76\u4e0d\u96be\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,10,11,13,17}",showLineNumbers:!0,"{1,3,10,11,13,17}":!0},'await _eventPublisher.PublishAsync(eventId, new YourModel {\n OtherArgs = ...,\n Exception = ex // \u6709\u5f02\u5e38\u4f20\u5165\uff0c\u5426\u5219 null\n});\n\n[EventSubscribe("ToDo:Create")]\npublic async Task CreateToDo(EventHandlerExecutingContext context)\n{\n // \u5f00\u542f\u4e8b\u52a1....\n var model = context.Source.Payload as YourModel;\n if(model.Exception != null)\n {\n // \u56de\u6eda\u4e8b\u52a1\n }\n else\n {\n // \u63d0\u4ea4\u4e8b\u52a1\n }\n // \u7ed3\u675f\u4e8b\u52a1...\n\n await Task.CompletedTask;\n}\n')),(0,o.kt)("h2",{id:"2214-\u53cd\u9988\u4e0e\u5efa\u8bae"},"22.14 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}v.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/04b9380e.d0d2173b.js b/handbook/build/assets/js/04b9380e.d0d2173b.js deleted file mode 100644 index ded8b7363c..0000000000 --- a/handbook/build/assets/js/04b9380e.d0d2173b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[3867],{247:function(e,n,t){t.r(n),t.d(n,{assets:function(){return p},contentTitle:function(){return u},default:function(){return v},frontMatter:function(){return s},metadata:function(){return c},toc:function(){return m}});var r=t(3117),a=t(102),o=(t(7294),t(3905)),i=t(1402),l=["components"],s={id:"event-bus",title:"22. \u4e8b\u4ef6\u603b\u7ebf",sidebar_label:"22. \u4e8b\u4ef6\u603b\u7ebf\uff08New\uff09"},u=void 0,c={unversionedId:"event-bus",id:"event-bus",title:"22. \u4e8b\u4ef6\u603b\u7ebf",description:"",source:"@site/docs/event-bus.mdx",sourceDirName:".",slug:"/event-bus",permalink:"/furion/docs/event-bus",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/event-bus.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1661842230,formattedLastUpdatedAt:"Aug 30, 2022",frontMatter:{id:"event-bus",title:"22. \u4e8b\u4ef6\u603b\u7ebf",sidebar_label:"22. \u4e8b\u4ef6\u603b\u7ebf\uff08New\uff09"},sidebar:"docs",previous:{title:"21. \u5168\u7403\u5316\u548c\u672c\u5730\u5316\uff08\u591a\u8bed\u8a00\uff09",permalink:"/furion/docs/local-language"},next:{title:"23. JSON \u5e8f\u5217\u5316",permalink:"/furion/docs/json-serialization"}},p={},m=[{value:"22.1 \u5173\u4e8e\u4e8b\u4ef6\u603b\u7ebf",id:"221-\u5173\u4e8e\u4e8b\u4ef6\u603b\u7ebf",level:2},{value:"22.2 \u5feb\u901f\u5165\u95e8",id:"222-\u5feb\u901f\u5165\u95e8",level:2},{value:"22.3 \u81ea\u5b9a\u4e49\u4e8b\u4ef6\u6e90",id:"223-\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u6e90",level:2},{value:"22.4 \u81ea\u5b9a\u4e49\u4e8b\u4ef6\u6e90\u5b58\u50a8\u5668",id:"224-\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u6e90\u5b58\u50a8\u5668",level:2},{value:"22.4.1 RabbitMQ \u81ea\u5b9a\u4e49\u6307\u5357",id:"2241-rabbitmq-\u81ea\u5b9a\u4e49\u6307\u5357",level:3},{value:"22.5 \u81ea\u5b9a\u4e49\u4e8b\u4ef6\u53d1\u5e03\u8005",id:"225-\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u53d1\u5e03\u8005",level:2},{value:"22.6 \u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u76d1\u89c6\u5668",id:"226-\u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u76d1\u89c6\u5668",level:2},{value:"22.7 \u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u5668",id:"227-\u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u5668",level:2},{value:"22.8 \u4f7f\u7528\u6709\u4f5c\u7528\u57df\u7684\u670d\u52a1",id:"228-\u4f7f\u7528\u6709\u4f5c\u7528\u57df\u7684\u670d\u52a1",level:2},{value:"22.9 \u8ba2\u9605\u6267\u884c\u4efb\u52a1\u610f\u5916\u5f02\u5e38",id:"229-\u8ba2\u9605\u6267\u884c\u4efb\u52a1\u610f\u5916\u5f02\u5e38",level:2},{value:"22.10 \u4e8b\u4ef6\u603b\u7ebf\u5de5\u5382",id:"2210-\u4e8b\u4ef6\u603b\u7ebf\u5de5\u5382",level:2},{value:"22.11 MessageCenter \u9759\u6001\u7c7b",id:"2211-messagecenter-\u9759\u6001\u7c7b",level:2},{value:"22.12 EventBusOptionsBuilder \u914d\u7f6e",id:"2212-eventbusoptionsbuilder-\u914d\u7f6e",level:2},{value:"22.13 \u5982\u4f55\u5b9e\u73b0\u6570\u636e\u5e93\u4e8b\u52a1\u63a7\u5236",id:"2213-\u5982\u4f55\u5b9e\u73b0\u6570\u636e\u5e93\u4e8b\u52a1\u63a7\u5236",level:2},{value:"22.14 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"2214-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:m};function v(e){var n=e.components,t=(0,a.Z)(e,l);return(0,o.kt)("wrapper",(0,r.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{title:"v2.20 \u4ee5\u4e0b\u7248\u672c\u8bf4\u660e",type:"warning"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("strong",{parentName:"p"},"\u5728 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Furion v2.20+")," \u7248\u672c\u540e\u91c7\u7528 ",(0,o.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Jaina"},"Jaina")," \u4e8b\u4ef6\u603b\u7ebf\u66ff\u6362\u539f\u6709\u7684 ",(0,o.kt)("inlineCode",{parentName:"strong"},"EventBus")),"\uff0c",(0,o.kt)("a",{parentName:"p",href:"./event-bus-old"},"\u67e5\u770b\u65e7\u6587\u6863"))),(0,o.kt)("h2",{id:"221-\u5173\u4e8e\u4e8b\u4ef6\u603b\u7ebf"},"22.1 \u5173\u4e8e\u4e8b\u4ef6\u603b\u7ebf"),(0,o.kt)("p",null,"\u4e8b\u4ef6\u603b\u7ebf\u662f\u5bf9\u53d1\u5e03-\u8ba2\u9605\u6a21\u5f0f\u7684\u4e00\u79cd\u5b9e\u73b0\u3002\u5b83\u662f\u4e00\u79cd\u96c6\u4e2d\u5f0f\u4e8b\u4ef6\u5904\u7406\u673a\u5236\uff0c\u5141\u8bb8\u4e0d\u540c\u7684\u7ec4\u4ef6\u4e4b\u95f4\u8fdb\u884c\u5f7c\u6b64\u901a\u4fe1\u800c\u53c8\u4e0d\u9700\u8981\u76f8\u4e92\u4f9d\u8d56\uff0c\u8fbe\u5230\u4e00\u79cd\u89e3\u8026\u7684\u76ee\u7684\u3002"),(0,o.kt)("img",{src:(0,i.Z)("img/ebs.png")}),(0,o.kt)("h2",{id:"222-\u5feb\u901f\u5165\u95e8"},"22.2 \u5feb\u901f\u5165\u95e8"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"\u5b9a\u4e49\u4e8b\u4ef6\u8ba2\u9605\u8005 ",(0,o.kt)("inlineCode",{parentName:"li"},"ToDoEventSubscriber"),"\uff1a")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,10-11,19-21,28-30,32,36-38,44-48}",showLineNumbers:!0,"":!0,"{2,10-11,19-21,28-30,32,36-38,44-48}":!0},'// \u5b9e\u73b0 IEventSubscriber \u63a5\u53e3\npublic class ToDoEventSubscriber : IEventSubscriber\n{\n private readonly ILogger _logger;\n public ToDoEventSubscriber(ILogger logger)\n {\n _logger = logger;\n }\n\n [EventSubscribe("ToDo:Create")]\n public async Task CreateToDo(EventHandlerExecutingContext context)\n {\n var todo = context.Source;\n _logger.LogInformation("\u521b\u5efa\u4e00\u4e2a ToDo\uff1a{Name}", todo.Payload);\n await Task.CompletedTask;\n }\n\n // \u652f\u6301\u591a\u4e2a\n [EventSubscribe("ToDo:Create")]\n [EventSubscribe("ToDo:Update")]\n public async Task CreateOrUpdateToDo(EventHandlerExecutingContext context)\n {\n var todo = context.Source;\n _logger.LogInformation("\u521b\u5efa\u6216\u66f4\u65b0\u4e00\u4e2a ToDo\uff1a{Name}", todo.Payload);\n await Task.CompletedTask;\n }\n\n // \u652f\u6301\u679a\u4e3e\u7c7b\u578b\uff0cv3.4.3+ \u7248\u672c\u652f\u6301\n [EventSubscribe(YourEnum.Some)]\n public async Task EnumHandler(EventHandlerExecutingContext context)\n {\n var eventEnum = context.Source.EventId.ParseToEnum(); // \u5c06\u4e8b\u4ef6 Id \u8f6c\u6362\u6210\u679a\u4e3e\u5bf9\u8c61\n await Task.CompletedTask;\n }\n\n // \u652f\u6301\u6b63\u5219\u8868\u8fbe\u5f0f\u5339\u914d\uff0c4.2.10+ \u7248\u672c\u652f\u6301\n [EventSubscribe("(^1[3456789][0-9]{9}$)|((^[0-9]{3,4}\\\\-[0-9]{3,8}$)|(^[0-9]{3,8}$)|(^\\\\([0-9]{3,4}\\\\)[0-9]{3,8}$)|(^0{0,1}13[0-9]{9}$))", FuzzyMatch = true)]\n public async Task RegexHandler(EventHandlerExecutingContext context)\n {\n var eventId = context.Source.EventId;\n await Task.CompletedTask;\n }\n\n // \u652f\u6301\u591a\u79cd\u5f02\u5e38\u91cd\u8bd5\u914d\u7f6e\uff0c4.2.10+ \u7248\u672c\u652f\u6301\n [EventSubscribe("test:error", NumRetries = 3)]\n [EventSubscribe("test:error", NumRetries = 3, RetryTimeout = 1000)] // \u91cd\u8bd5\u95f4\u9694\u65f6\u95f4\n [EventSubscribe("test:error", NumRetries = 3, ExceptionTypes = new[] { typeof(ArgumentException) })] // \u7279\u5b9a\u7c7b\u578b\u5f02\u5e38\u624d\u91cd\u8bd5\n public async Task ExceptionHandler(EventHandlerExecutingContext context)\n {\n var eventId = context.Source.EventId;\n await Task.CompletedTask;\n }\n}\n')),(0,o.kt)("ol",{start:2},(0,o.kt)("li",{parentName:"ol"},"\u521b\u5efa\u63a7\u5236\u5668 ",(0,o.kt)("inlineCode",{parentName:"li"},"ToDoController"),"\uff0c\u4f9d\u8d56\u6ce8\u5165 ",(0,o.kt)("inlineCode",{parentName:"li"},"IEventPublisher")," \u670d\u52a1\uff1a")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,13,16-21}",showLineNumbers:!0,"":!0,"{4,13,16-21}":!0},'public class ToDoController : ControllerBase\n{\n // \u4f9d\u8d56\u6ce8\u5165\u4e8b\u4ef6\u53d1\u5e03\u8005 IEventPublisher\n private readonly IEventPublisher _eventPublisher;\n public ToDoController(IEventPublisher eventPublisher)\n {\n _eventPublisher = eventPublisher;\n }\n\n // \u53d1\u5e03 ToDo:Create \u6d88\u606f\n public async Task CreateDoTo(string name)\n {\n await _eventPublisher.PublishAsync(new ChannelEventSource("ToDo:Create", name));\n }\n\n // v3.4.3+ \u7248\u672c\u652f\u6301\u53d1\u9001\u6d88\u606f\u7b80\u5316\n public async Task CreateDoTo(string name)\n {\n await _eventPublisher.PublishAsync("ToDo:Create", name);\n // \u4e5f\u652f\u6301\u679a\u4e3e\n await _eventPublisher.PublishAsync(YourEnum.Some);\n }\n}\n')),(0,o.kt)("ol",{start:3},(0,o.kt)("li",{parentName:"ol"},"\u5728 ",(0,o.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"li"},"EventBus")," \u670d\u52a1\uff1a")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5}",showLineNumbers:!0,"":!0,"{2,5}":!0},"// \u6ce8\u518c EventBus \u670d\u52a1\nservices.AddEventBus(builder =>\n{\n // \u6ce8\u518c ToDo \u4e8b\u4ef6\u8ba2\u9605\u8005\n builder.AddSubscriber();\n\n // \u901a\u8fc7\u7c7b\u578b\u6ce8\u518c\uff0cFurion 4.2.1+ \u7248\u672c\n builder.AddSubscriber(typeof(ToDoEventSubscriber));\n\n // \u6279\u91cf\u6ce8\u518c\u4e8b\u4ef6\u8ba2\u9605\u8005\n builder.AddSubscribers(ass1, ass2, ....);\n});\n")),(0,o.kt)("admonition",{title:"\u61d2\u4eba\u63d0\u9192",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e2d\u53ef\u4ee5\u4e0d\u7528\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"builder.AddSubscriber()")," \u65b9\u5f0f\u4e00\u4e00\u6ce8\u518c\uff0c\u53ea\u9700\u8981\u5b9e\u73b0 ",(0,o.kt)("inlineCode",{parentName:"p"},"ISingleton")," \u63a5\u53e3\u5373\u53ef\uff0c\u5982\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"public class ToDoEventSubscriber : IEventSubscriber, ISingleton\n{\n}\n")),(0,o.kt)("p",{parentName:"admonition"},"\u8fd9\u6837\u5c31\u65e0\u9700\u5199 ",(0,o.kt)("del",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"del"},"builder.AddSubscriber();"))," \u4ee3\u7801\u4e86\uff0c\u53ea\u9700\u4fdd\u7559 ",(0,o.kt)("inlineCode",{parentName:"p"},"services.AddEventBus()")," \u670d\u52a1\u5373\u53ef\u3002")),(0,o.kt)("ol",{start:4},(0,o.kt)("li",{parentName:"ol"},"\u8fd0\u884c\u9879\u76ee\uff1a")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"info: Jaina.Samples.ToDoEventSubscriber[0]\n \u521b\u5efa\u4e00\u4e2a ToDo\uff1aJaina\n")),(0,o.kt)("h2",{id:"223-\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u6e90"},"22.3 \u81ea\u5b9a\u4e49\u4e8b\u4ef6\u6e90"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventSource")," \u4f5c\u4e3a\u6d88\u606f\u8f7d\u4f53\uff0c\u4efb\u4f55\u5b9e\u73b0\u8be5\u63a5\u53e3\u7684\u7c7b\u90fd\u53ef\u4ee5\u5145\u5f53\u6d88\u606f\u8f7d\u4f53\u3002"),(0,o.kt)("p",null,"\u5982\u9700\u81ea\u5b9a\u4e49\uff0c\u53ea\u9700\u5b9e\u73b0 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventSource")," \u63a5\u53e3\u5373\u53ef\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,14,19,24,29,35-37}",showLineNumbers:!0,"":!0,"{1,3,14,19,24,29,35-37}":!0},"public class ToDoEventSource : IEventSource\n{\n public ToDoEventSource()\n {\n }\n\n public ToDoEventSource(string eventId, string todoName)\n {\n EventId = eventId;\n ToDoName = todoName;\n }\n\n // \u81ea\u5b9a\u4e49\u5c5e\u6027\n public string ToDoName { get; set; }\n\n /// \n /// \u4e8b\u4ef6 Id\n /// \n public string EventId { get; set; }\n\n /// \n /// \u4e8b\u4ef6\u627f\u8f7d\uff08\u643a\u5e26\uff09\u6570\u636e\n /// \n public object Payload { get; set; }\n\n /// \n /// \u4e8b\u4ef6\u521b\u5efa\u65f6\u95f4\n /// \n public DateTime CreatedTime { get; set; } = DateTime.UtcNow;\n\n /// \n /// \u53d6\u6d88\u4efb\u52a1 Token\n /// \n /// \u7528\u4e8e\u53d6\u6d88\u672c\u6b21\u6d88\u606f\u5904\u7406\n [Newtonsoft.Json.JsonIgnore]\n [System.Text.Json.Serialization.JsonIgnore]\n public CancellationToken CancellationToken { get; set; }\n}\n")),(0,o.kt)("p",null,"\u4f7f\u7528\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await _eventPublisher.PublishAsync(new ToDoEventSource ("ToDo:Create", "\u6211\u7684 ToDo Name"));\n')),(0,o.kt)("h2",{id:"224-\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u6e90\u5b58\u50a8\u5668"},"22.4 \u81ea\u5b9a\u4e49\u4e8b\u4ef6\u6e90\u5b58\u50a8\u5668"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Fruion")," \u9ed8\u8ba4\u91c7\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"Channel")," \u4f5c\u4e3a\u4e8b\u4ef6\u6e90 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventSource")," \u5b58\u50a8\u5668\uff0c\u5f00\u53d1\u8005\u53ef\u4ee5\u4f7f\u7528\u4efb\u4f55\u6d88\u606f\u961f\u5217\u7ec4\u4ef6\u8fdb\u884c\u66ff\u6362\uff0c\u5982 ",(0,o.kt)("inlineCode",{parentName:"p"},"Kafka\u3001RabbitMQ\u3001ActiveMQ")," \u7b49\uff0c\u4e5f\u53ef\u4ee5\u4f7f\u7528\u90e8\u5206\u6570\u636e\u5e93 ",(0,o.kt)("inlineCode",{parentName:"p"},"Redis\u3001SQL Server\u3001MySql")," \u5b9e\u73b0\u3002"),(0,o.kt)("p",null,"\u5982\u9700\u81ea\u5b9a\u4e49\uff0c\u53ea\u9700\u5b9e\u73b0 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventSourceStorer")," \u63a5\u53e3\u5373\u53ef\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,11,17}",showLineNumbers:!0,"":!0,"{1,11,17}":!0},"public class RedisEventSourceStorer : IEventSourceStorer\n{\n private readonly IRedisClient _redisClient;\n\n public RedisEventSourceStorer(IRedisClient redisClient)\n {\n _redisClient = redisClient;\n }\n\n // \u5f80 Redis \u4e2d\u5199\u5165\u4e00\u6761\n public async ValueTask WriteAsync(IEventSource eventSource, CancellationToken cancellationToken)\n {\n await _redisClient.WriteAsync(...., cancellationToken);\n }\n\n // \u4ece Redis \u4e2d\u8bfb\u53d6\u4e00\u6761\n public async ValueTask ReadAsync(CancellationToken cancellationToken)\n {\n return await _redisClient.ReadAsync(...., cancellationToken);\n }\n}\n")),(0,o.kt)("p",null,"\u6700\u540e\uff0c\u5728\u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"p"},"EventBus")," \u670d\u52a1\u4e2d\u66ff\u6362\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventSourceStorer"),"\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4-8}",showLineNumbers:!0,"":!0,"{4-8}":!0},"services.AddEventBus(builder =>\n{\n // \u66ff\u6362\u4e8b\u4ef6\u6e90\u5b58\u50a8\u5668\n builder.ReplaceStorer(serviceProvider =>\n {\n var redisClient = serviceProvider.GetService();\n return new RedisEventSourceStorer(redisClient);\n });\n});\n")),(0,o.kt)("h3",{id:"2241-rabbitmq-\u81ea\u5b9a\u4e49\u6307\u5357"},"22.4.1 ",(0,o.kt)("inlineCode",{parentName:"h3"},"RabbitMQ")," \u81ea\u5b9a\u4e49\u6307\u5357"),(0,o.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 4.3.4 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,o.kt)("p",null,"\u7531\u4e8e\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"RabbitMQ")," \u4f5c\u4e3a\u4e8b\u4ef6\u603b\u7ebf\u5b58\u50a8\u5668\u7684\u6bd4\u8f83\u591a\uff0c\u6240\u4ee5\u8fd9\u91cc\u63d0\u4f9b\u4e86\u5b8c\u6574\u7684\u4f7f\u7528\u4f8b\u5b50\u3002"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"1. \u5b89\u88c5 ",(0,o.kt)("inlineCode",{parentName:"strong"},"RabbitMQ.Client")," \u62d3\u5c55\u5305")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"Install-Package RabbitMQ.Client -Version 6.4.0\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"2. \u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"strong"},"RabbitMQEventSourceStorer")," \u81ea\u5b9a\u4e49\u5b58\u50a8\u5668")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,41,60,66-78,99-103,116-117,125-126}",showLineNumbers:!0,"{13,41,60,66-78,99-103,116-117,125-126}":!0},'using Furion.EventBus;\nusing RabbitMQ.Client;\nusing RabbitMQ.Client.Events;\nusing System;\nusing System.Text;\nusing System.Text.Json;\nusing System.Threading;\nusing System.Threading.Channels;\nusing System.Threading.Tasks;\n\nnamespace Furion.Core;\n\npublic sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable\n{\n /// \n /// \u5185\u5b58\u901a\u9053\u4e8b\u4ef6\u6e90\u5b58\u50a8\u5668\n /// \n private readonly Channel _channel;\n\n /// \n /// \u901a\u9053\u5bf9\u8c61\n /// \n private readonly IModel _model;\n\n /// \n /// \u8fde\u63a5\u5bf9\u8c61\n /// \n private readonly IConnection _connection;\n\n /// \n /// \u8def\u7531\u952e\n /// \n private readonly string _routeKey;\n\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n /// \u8fde\u63a5\u5de5\u5382\n /// \u8def\u7531\u952e\n /// \u5b58\u50a8\u5668\u6700\u591a\u80fd\u591f\u5904\u7406\u591a\u5c11\u6d88\u606f\uff0c\u8d85\u8fc7\u8be5\u5bb9\u91cf\u8fdb\u5165\u7b49\u5f85\u5199\u5165\n public RabbitMQEventSourceStorer(ConnectionFactory factory, string routeKey, int capacity)\n {\n // \u914d\u7f6e\u901a\u9053\uff0c\u8bbe\u7f6e\u8d85\u51fa\u9ed8\u8ba4\u5bb9\u91cf\u540e\u8fdb\u5165\u7b49\u5f85\n var boundedChannelOptions = new BoundedChannelOptions(capacity)\n {\n FullMode = BoundedChannelFullMode.Wait\n };\n\n // \u521b\u5efa\u6709\u9650\u5bb9\u91cf\u901a\u9053\n _channel = Channel.CreateBounded(boundedChannelOptions);\n\n // \u521b\u5efa\u8fde\u63a5\n _connection = factory.CreateConnection();\n _routeKey = routeKey;\n\n // \u521b\u5efa\u901a\u9053\n _model = _connection.CreateModel();\n\n // \u58f0\u660e\u8def\u7531\u961f\u5217\n _model.QueueDeclare(routeKey, false, false, false, null);\n\n // \u521b\u5efa\u6d88\u606f\u8ba2\u9605\u8005\n var consumer = new EventingBasicConsumer(_model);\n\n // \u8ba2\u9605\u6d88\u606f\u5e76\u5199\u5165\u5185\u5b58 Channel\n consumer.Received += (ch, ea) =>\n {\n // \u8bfb\u53d6\u539f\u59cb\u6d88\u606f\n var stringEventSource = Encoding.UTF8.GetString(ea.Body.ToArray());\n\n // \u8f6c\u6362\u4e3a IEventSource\uff0c\u8fd9\u91cc\u53ef\u4ee5\u9009\u62e9\u81ea\u5df1\u559c\u6b22\u7684\u5e8f\u5217\u5316\u5de5\u5177\uff0c\u5982\u679c\u81ea\u5b9a\u4e49\u4e86 EventSource\uff0c\u6ce8\u610f\u5c5e\u6027\u662f\u53ef\u8bfb\u53ef\u5199\n var eventSource = JsonSerializer.Deserialize(stringEventSource);\n\n // \u5199\u5165\u5185\u5b58\u7ba1\u9053\u5b58\u50a8\u5668\n _channel.Writer.TryWrite(eventSource);\n\n // \u786e\u8ba4\u8be5\u6d88\u606f\u5df2\u88ab\u6d88\u8d39\n _model.BasicAck(ea.DeliveryTag, false);\n };\n\n // \u542f\u52a8\u6d88\u8d39\u8005 \u8bbe\u7f6e\u4e3a\u624b\u52a8\u5e94\u7b54\u6d88\u606f\n _model.BasicConsume(routeKey, false, consumer);\n }\n\n /// \n /// \u5c06\u4e8b\u4ef6\u6e90\u5199\u5165\u5b58\u50a8\u5668\n /// \n /// \u4e8b\u4ef6\u6e90\u5bf9\u8c61\n /// \u53d6\u6d88\u4efb\u52a1 Token\n /// \n public ValueTask WriteAsync(IEventSource eventSource, CancellationToken cancellationToken)\n {\n // \u7a7a\u68c0\u67e5\n if (eventSource == default)\n {\n throw new ArgumentNullException(nameof(eventSource));\n }\n\n // \u5e8f\u5217\u5316\uff0c\u8fd9\u91cc\u53ef\u4ee5\u9009\u62e9\u81ea\u5df1\u559c\u6b22\u7684\u5e8f\u5217\u5316\u5de5\u5177\n var data = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(eventSource));\n\n // \u53d1\u5e03\n _model.BasicPublish("", _routeKey, null, data);\n\n return ValueTask.CompletedTask;\n }\n\n /// \n /// \u4ece\u5b58\u50a8\u5668\u4e2d\u8bfb\u53d6\u4e00\u6761\u4e8b\u4ef6\u6e90\n /// \n /// \u53d6\u6d88\u4efb\u52a1 Token\n /// \u4e8b\u4ef6\u6e90\u5bf9\u8c61\n public async ValueTask ReadAsync(CancellationToken cancellationToken)\n {\n // \u8bfb\u53d6\u4e00\u6761\u4e8b\u4ef6\u6e90\n var eventSource = await _channel.Reader.ReadAsync(cancellationToken);\n return eventSource;\n }\n\n /// \n /// \u91ca\u653e\u975e\u6258\u7ba1\u8d44\u6e90\n /// \n public void Dispose()\n {\n _model.Dispose();\n _connection.Dispose();\n }\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"3. \u66ff\u6362\u9ed8\u8ba4\u4e8b\u4ef6\u5b58\u50a8\u5668")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4-8,11,14-16}",showLineNumbers:!0,"{1,4-8,11,14-16}":!0},'services.AddEventBus(options =>\n{\n // \u521b\u5efa\u8fde\u63a5\u5de5\u5382\n var factory = new ConnectionFactory\n {\n UserName = "admin",\n Password = "q1w2e3",\n };\n\n // \u521b\u5efa\u9ed8\u8ba4\u5185\u5b58\u901a\u9053\u4e8b\u4ef6\u6e90\u5bf9\u8c61\uff0c\u53ef\u81ea\u5b9a\u4e49\u961f\u5217\u8def\u7531key\uff0c\u6bd4\u5982\u8fd9\u91cc\u662f eventbus\n var rbmqEventSourceStorer = new RabbitMQEventSourceStorer(factory, "eventbus", 3000);\n\n // \u66ff\u6362\u9ed8\u8ba4\u4e8b\u4ef6\u603b\u7ebf\u5b58\u50a8\u5668\n options.ReplaceStorer(serviceProvider =>\n {\n return rbmqEventSourceStorer;\n });\n});\n')),(0,o.kt)("img",{src:(0,i.Z)("img/evs1.png")}),(0,o.kt)("h2",{id:"225-\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u53d1\u5e03\u8005"},"22.5 \u81ea\u5b9a\u4e49\u4e8b\u4ef6\u53d1\u5e03\u8005"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u9ed8\u8ba4\u5185\u7f6e\u57fa\u4e8e ",(0,o.kt)("inlineCode",{parentName:"p"},"Channel")," \u7684\u4e8b\u4ef6\u53d1\u5e03\u8005 ",(0,o.kt)("inlineCode",{parentName:"p"},"ChannelEventPublisher"),"\u3002"),(0,o.kt)("p",null,"\u5982\u9700\u81ea\u5b9a\u4e49\uff0c\u53ea\u9700\u5b9e\u73b0 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventPublisher")," \u63a5\u53e3\u5373\u53ef\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,10}",showLineNumbers:!0,"":!0,"{1,10}":!0},"public class ToDoEventPublisher : IEventPublisher\n{\n private readonly IEventSourceStorer _eventSourceStorer;\n\n public ChannelEventPublisher(IEventSourceStorer eventSourceStorer)\n {\n _eventSourceStorer = eventSourceStorer;\n }\n\n public async Task PublishAsync(IEventSource eventSource)\n {\n await _eventSourceStorer.WriteAsync(eventSource, eventSource.CancellationToken);\n }\n}\n")),(0,o.kt)("p",null,"\u6700\u540e\uff0c\u5728\u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"p"},"EventBus")," \u670d\u52a1\u4e2d\u66ff\u6362\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventPublisher"),"\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"services.AddEventBus(builder =>\n{\n // \u66ff\u6362\u4e8b\u4ef6\u6e90\u5b58\u50a8\u5668\n builder.ReplacePublisher();\n});\n")),(0,o.kt)("h2",{id:"226-\u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u76d1\u89c6\u5668"},"22.6 \u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u76d1\u89c6\u5668"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventHandlerMonitor")," \u76d1\u89c6\u5668\u63a5\u53e3\uff0c\u5b9e\u73b0\u8be5\u63a5\u53e3\u53ef\u4ee5\u76d1\u89c6\u6240\u6709\u8ba2\u9605\u4e8b\u4ef6\uff0c\u5305\u62ec ",(0,o.kt)("inlineCode",{parentName:"p"},"\u6267\u884c\u4e4b\u524d\u3001\u6267\u884c\u4e4b\u540e\uff0c\u6267\u884c\u5f02\u5e38\uff0c\u5171\u4eab\u4e0a\u4e0b\u6587\u6570\u636e"),"\u3002"),(0,o.kt)("p",null,"\u5982\u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"p"},"ToDoEventHandlerMonitor"),"\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,9,15}",showLineNumbers:!0,"":!0,"{1,9,15}":!0},'public class ToDoEventHandlerMonitor : IEventHandlerMonitor\n{\n private readonly ILogger _logger;\n public ToDoEventHandlerMonitor(ILogger logger)\n {\n _logger = logger;\n }\n\n public Task OnExecutingAsync(EventHandlerExecutingContext context)\n {\n _logger.LogInformation("\u6267\u884c\u4e4b\u524d\uff1a{EventId}", context.Source.EventId);\n return Task.CompletedTask;\n }\n\n public Task OnExecutedAsync(EventHandlerExecutedContext context)\n {\n _logger.LogInformation("\u6267\u884c\u4e4b\u540e\uff1a{EventId}", context.Source.EventId);\n\n if (context.Exception != null)\n {\n _logger.LogError(context.Exception, "\u6267\u884c\u51fa\u9519\u5566\uff1a{EventId}", context.Source.EventId);\n }\n\n return Task.CompletedTask;\n }\n}\n')),(0,o.kt)("p",null,"\u6700\u540e\uff0c\u5728\u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"p"},"EventBus")," \u670d\u52a1\u4e2d\u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"p"},"ToDoEventHandlerMonitor"),"\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"services.AddEventBus(builder =>\n{\n // \u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u76d1\u89c6\u5668\n builder.AddMonitor();\n});\n")),(0,o.kt)("h2",{id:"227-\u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u5668"},"22.7 \u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u5668"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventHandlerExecutor")," \u6267\u884c\u5668\u63a5\u53e3\uff0c\u53ef\u4ee5\u8ba9\u5f00\u53d1\u8005\u81ea\u5b9a\u4e49\u4e8b\u4ef6\u5904\u7406\u51fd\u6570\u6267\u884c\u7b56\u7565\uff0c\u5982 ",(0,o.kt)("inlineCode",{parentName:"p"},"\u8d85\u65f6\u63a7\u5236\uff0c\u5931\u8d25\u91cd\u8bd5\u3001\u7194\u65ad\u7b49\u7b49"),"\u3002"),(0,o.kt)("p",null,"\u5982\u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"p"},"RetryEventHandlerExecutor"),"\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3}",showLineNumbers:!0,"":!0,"{1,3}":!0},"public class RetryEventHandlerExecutor : IEventHandlerExecutor\n{\n public async Task ExecuteAsync(EventHandlerExecutingContext context, Func handler)\n {\n // \u5982\u679c\u6267\u884c\u5931\u8d25\uff0c\u6bcf\u9694 1s \u91cd\u8bd5\uff0c\u6700\u591a\u4e09\u6b21\n await Retry.InvokeAsync(async () => {\n await handler(context);\n }, 3, 1000);\n }\n}\n")),(0,o.kt)("p",null,"\u6700\u540e\uff0c\u5728\u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"p"},"EventBus")," \u670d\u52a1\u4e2d\u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"p"},"RetryEventHandlerExecutor"),"\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"services.AddEventBus(builder =>\n{\n // \u6dfb\u52a0\u4e8b\u4ef6\u6267\u884c\u5668\n builder.AddExecutor();\n});\n")),(0,o.kt)("h2",{id:"228-\u4f7f\u7528\u6709\u4f5c\u7528\u57df\u7684\u670d\u52a1"},"22.8 \u4f7f\u7528\u6709\u4f5c\u7528\u57df\u7684\u670d\u52a1"),(0,o.kt)("p",null,"\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e2d\uff0c ",(0,o.kt)("inlineCode",{parentName:"p"},"Event Bus")," \u6240\u6709\u670d\u52a1\u5747\u6ce8\u518c\u4e3a\u5355\u4f8b\uff0c\u5982\u9700\u4f7f\u7528\u4f5c\u7528\u57df\u670d\u52a1\uff08\u5355\u4f8b\u670d\u52a1\u53ef\u76f4\u63a5\u6ce8\u5165\uff09\uff0c\u53ef\u901a\u8fc7\u4f9d\u8d56\u6ce8\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"IServiceProvider")," \u5b9e\u4f8b\u5e76\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"CreateScope()")," \u521b\u5efa\u4e00\u4e2a\u4f5c\u7528\u57df\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8,12,17-21}",showLineNumbers:!0,"":!0,"{5,8,12,17-21}":!0},'public class ToDoEventSubscriber : IEventSubscriber\n{\n private readonly ILogger _logger;\n\n public ToDoEventSubscriber(IServiceProvider services\n , ILogger logger)\n {\n Services = services;\n _logger = logger;\n }\n\n public IServiceProvider Services { get; }\n\n [EventSubscribe("ToDo:Create")]\n public async Task CreateToDo(EventHandlerExecutingContext context)\n {\n // \u521b\u5efa\u65b0\u7684\u4f5c\u7528\u57df\n using var scope = Services.CreateScope();\n\n // \u89e3\u6790\u670d\u52a1\n var scopedProcessingService = scope.ServiceProvider.GetRequiredService();\n // ....\n }\n}\n')),(0,o.kt)("h2",{id:"229-\u8ba2\u9605\u6267\u884c\u4efb\u52a1\u610f\u5916\u5f02\u5e38"},"22.9 \u8ba2\u9605\u6267\u884c\u4efb\u52a1\u610f\u5916\u5f02\u5e38"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"services.AddEventBus(builder =>\n{\n // \u8ba2\u9605 EventBus \u672a\u6355\u83b7\u5f02\u5e38\n builder.UnobservedTaskExceptionHandler = (obj, args) =>\n {\n // ....\n };\n});\n")),(0,o.kt)("h2",{id:"2210-\u4e8b\u4ef6\u603b\u7ebf\u5de5\u5382"},"22.10 \u4e8b\u4ef6\u603b\u7ebf\u5de5\u5382"),(0,o.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 4.2.10 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,o.kt)("p",null,"\u5728\u8be5\u7248\u672c\u4e2d\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"IEventBusFactory")," \u5de5\u5382\u670d\u52a1\uff0c\u53ef\u5728\u8fd0\u884c\u65f6\u52a8\u6001\u65b0\u589e\u6216\u5220\u9664\u8ba2\u9605\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,14-17,24}",showLineNumbers:!0,"{4,14-17,24}":!0},'public class TestEventBus : IDynamicApiController\n{\n private readonly IEventPublisher _eventPublisher;\n private readonly IEventBusFactory _eventBusFactory;\n public TestEventBus(IEventPublisher eventPublisher, IEventBusFactory eventBusFactory)\n {\n _eventPublisher = eventPublisher;\n _eventBusFactory = eventBusFactory;\n }\n\n // \u8fd0\u884c\u65f6\u52a8\u6001\u6dfb\u52a0\u4e00\u4e2a\u8ba2\u9605\u5668\n public async Task AddSubscriber()\n {\n await _eventBusFactory.Subscribe("xxx", async (ctx) =>\n {\n Console.WriteLine("\u6211\u662f\u52a8\u6001\u7684");\n await Task.CompletedTask;\n });\n }\n\n // \u8fd0\u884c\u65f6\u52a8\u6001\u5220\u9664\u4e00\u4e2a\u8ba2\u9605\u5668\n public async Task RemoveDynamic(string eventId)\n {\n await _eventBusFactory.Unsubscribe(eventId);\n }\n}\n')),(0,o.kt)("h2",{id:"2211-messagecenter-\u9759\u6001\u7c7b"},"22.11 ",(0,o.kt)("inlineCode",{parentName:"h2"},"MessageCenter")," \u9759\u6001\u7c7b"),(0,o.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 4.3.3 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,o.kt)("p",null,"\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 4.3.3")," \u7248\u672c\u65b0\u589e\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"MessageCenter")," \u9759\u6001\u7c7b\uff0c\u53ef\u5728\u4efb\u4f55\u5730\u65b9\u53d1\u9001\u4e8b\u4ef6\u6d88\u606f\u6216\u8ba2\u9605\u6d88\u606f\u3002"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,11}",showLineNumbers:!0,"{2,5,11}":!0},'// \u53d1\u9001\u6d88\u606f\uff08\u542b\u8bf8\u591a\u91cd\u8f7d\uff09\nawait MessageCenter.PublishAsync("messageId", new {});\n\n// \u52a8\u6001\u8ba2\u9605\u6d88\u606f\nMessageCenter.Subscribe("messageId", async (ctx) => {\n Console.WriteLine("\u6211\u662f\u52a8\u6001\u7684");\n await Task.CompletedTask;\n});\n\n// \u53d6\u6d88\u8ba2\u9605\nMessageCenter.Unsubscribe("messageId");\n')),(0,o.kt)("h2",{id:"2212-eventbusoptionsbuilder-\u914d\u7f6e"},"22.12 ",(0,o.kt)("inlineCode",{parentName:"h2"},"EventBusOptionsBuilder")," \u914d\u7f6e"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"EventBusOptionsBuilder")," \u662f ",(0,o.kt)("inlineCode",{parentName:"p"},"AddEventBus")," \u6784\u5efa\u670d\u52a1\u9009\u9879\uff0c\u8be5\u9009\u9879\u5305\u542b\u4ee5\u4e0b\u5c5e\u6027\u548c\u65b9\u6cd5\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u5c5e\u6027",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ChannelCapacity"),"\uff1a\u9ed8\u8ba4\u5185\u5b58\u901a\u9053\u5bb9\u91cf"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"UnobservedTaskExceptionHandler"),"\uff1a\u8ba2\u9605\u6267\u884c\u4efb\u52a1\u672a\u5bdf\u89c9\u5f02\u5e38"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"UseUtcTimestamp"),"\uff1a\u662f\u5426\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"li"},"UTC")," \u4e8b\u4ef6\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"false")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"FuzzyMatch"),"\uff1a\u662f\u5426\u5f00\u542f\u5168\u5c40\u6a21\u7cca\u5339\u914d\uff08\u6b63\u5219\u8868\u8fbe\u5f0f\uff09\u4e8b\u4ef6 ",(0,o.kt)("inlineCode",{parentName:"li"},"Id"),"\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"false")))),(0,o.kt)("li",{parentName:"ul"},"\u65b9\u6cd5",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"AddSubscriber"),"\uff1a\u6dfb\u52a0\u8ba2\u9605\u8005"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ReplacePublisher"),"\uff1a\u66ff\u6362\u53d1\u5e03\u8005"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ReplaceStorer(Func)"),"\uff1a\u66ff\u6362\u5b58\u50a8\u5668"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"AddMonitor"),"\uff1a\u6dfb\u52a0\u76d1\u89c6\u5668"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"AddExecutor"),"\uff1a\u6dfb\u52a0\u6267\u884c\u5668")))),(0,o.kt)("h2",{id:"2213-\u5982\u4f55\u5b9e\u73b0\u6570\u636e\u5e93\u4e8b\u52a1\u63a7\u5236"},"22.13 \u5982\u4f55\u5b9e\u73b0\u6570\u636e\u5e93\u4e8b\u52a1\u63a7\u5236"),(0,o.kt)("p",null,"\u76f8\u4fe1\u5f88\u591a\u670b\u53cb\u90fd\u4f7f\u7528\u4e86\u4e8b\u4ef6\u603b\u7ebf\u8fdb\u884c\u6570\u636e\u5e93\u64cd\u4f5c\uff0c\u4f46\u662f\u4e0d\u77e5\u9053\u5982\u4f55\u5b9e\u73b0\u4e8b\u52a1\u63a7\u5236\uff0c\u5b9e\u9645\u4e0a\u5e76\u4e0d\u96be\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,10,11,13,17}",showLineNumbers:!0,"{1,3,10,11,13,17}":!0},'await _eventPublisher.PublishAsync(eventId, new YourModel {\n OtherArgs = ...,\n Exception = ex // \u6709\u5f02\u5e38\u4f20\u5165\uff0c\u5426\u5219 null\n});\n\n[EventSubscribe("ToDo:Create")]\npublic async Task CreateToDo(EventHandlerExecutingContext context)\n{\n // \u5f00\u542f\u4e8b\u52a1....\n var model = context.Source.Payload as YourModel;\n if(model.Exception != null)\n {\n // \u56de\u6eda\u4e8b\u52a1\n }\n else\n {\n // \u63d0\u4ea4\u4e8b\u52a1\n }\n // \u7ed3\u675f\u4e8b\u52a1...\n\n await Task.CompletedTask;\n}\n')),(0,o.kt)("h2",{id:"2214-\u53cd\u9988\u4e0e\u5efa\u8bae"},"22.14 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}v.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return c},kt:function(){return d}});var r=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function i(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var s=r.createContext({}),u=function(e){var n=r.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},c=function(e){var n=u(e.components);return r.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},m=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),m=u(t),d=a,v=m["".concat(s,".").concat(d)]||m[d]||p[d]||o;return t?r.createElement(v,i(i({ref:n},c),{},{components:t})):r.createElement(v,i({ref:n},c))}));function d(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var o=t.length,i=new Array(o);i[0]=m;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var u=2;uIDistributedCache",id:"1442-idistributedcache",level:3},{value:"14.4.3 \u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58",id:"1443-\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58",level:3},{value:"14.4.4 \u5206\u5e03\u5f0f SQL Server \u7f13\u5b58",id:"1444-\u5206\u5e03\u5f0f-sql-server-\u7f13\u5b58",level:3},{value:"14.4.5 \u5206\u5e03\u5f0f Redis \u7f13\u5b58",id:"1445-\u5206\u5e03\u5f0f-redis-\u7f13\u5b58",level:3},{value:"14.4.6 \u5206\u5e03\u5f0f NCache \u7f13\u5b58",id:"1446-\u5206\u5e03\u5f0f-ncache-\u7f13\u5b58",level:3},{value:"14.5 \u5206\u5e03\u5f0f\u7f13\u5b58\u4f7f\u7528",id:"145-\u5206\u5e03\u5f0f\u7f13\u5b58\u4f7f\u7528",level:2},{value:"14.6 \u5206\u5e03\u5f0f\u7f13\u5b58\u5efa\u8bae",id:"146-\u5206\u5e03\u5f0f\u7f13\u5b58\u5efa\u8bae",level:2},{value:"14.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"147-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:d};function u(e){var n=e.components,t=(0,i.Z)(e,o);return(0,r.kt)("wrapper",(0,a.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"141-\u4ec0\u4e48\u662f\u7f13\u5b58"},"14.1 \u4ec0\u4e48\u662f\u7f13\u5b58"),(0,r.kt)("p",null,"\u7f13\u5b58\u53ef\u4ee5\u51cf\u5c11\u751f\u6210\u5185\u5bb9\u6240\u9700\u7684\u5de5\u4f5c\uff0c\u4ece\u800c\u663e\u8457\u63d0\u9ad8\u5e94\u7528\u7a0b\u5e8f\u7684\u6027\u80fd\u548c\u53ef\u4f38\u7f29\u6027\u3002 ",(0,r.kt)("strong",{parentName:"p"},"\u7f13\u5b58\u9002\u7528\u4e8e\u4e0d\u7ecf\u5e38\u66f4\u6539\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u751f\u6210\u6210\u672c\u5f88\u9ad8"),"\u3002 \u901a\u8fc7\u7f13\u5b58\uff0c\u53ef\u6bd4\u4ece\u6570\u636e\u6e90\u8fd4\u56de\u6570\u636e\u7684\u526f\u672c\u901f\u5ea6\u5feb\u5f97\u591a\u3002 \u5e94\u8be5\u5bf9\u5e94\u7528\u8fdb\u884c\u7f16\u5199\u548c\u6d4b\u8bd5\uff0c\u4f7f\u5176\u4e0d\u8981\u6c38\u8fdc\u4f9d\u8d56\u4e8e\u7f13\u5b58\u7684\u6570\u636e\u3002"),(0,r.kt)("h2",{id:"142-\u7f13\u5b58\u7c7b\u578b"},"14.2 \u7f13\u5b58\u7c7b\u578b"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u5185\u5b58\u7f13\u5b58\uff1a\u987e\u540d\u601d\u4e49\uff0c\u5c31\u662f\u7f13\u5b58\u5728\u5e94\u7528\u90e8\u7f72\u6240\u5728\u670d\u52a1\u5668\u7684\u5185\u5b58\u4e2d"),(0,r.kt)("li",{parentName:"ul"},"\u5206\u5e03\u5f0f\u7f13\u5b58\uff1a\u5206\u5e03\u5f0f\u7f13\u5b58\u662f\u7531\u591a\u4e2a\u5e94\u7528\u670d\u52a1\u5668\u5171\u4eab\u7684\u7f13\u5b58"),(0,r.kt)("li",{parentName:"ul"},"\u54cd\u5e94\u7f13\u5b58\uff1a\u7f13\u5b58\u670d\u52a1\u5668\u7aef ",(0,r.kt)("inlineCode",{parentName:"li"},"Not Modified")," \u7684\u6570\u636e")),(0,r.kt)("h2",{id:"143-\u5185\u5b58\u7f13\u5b58\u4f7f\u7528"},"14.3 \u5185\u5b58\u7f13\u5b58\u4f7f\u7528"),(0,r.kt)("p",null,"\u5185\u5b58\u7f13\u5b58\u662f\u6700\u5e38\u7528\u7684\u7f13\u5b58\u65b9\u5f0f\uff0c\u5177\u6709\u5b58\u53d6\u5feb\uff0c\u6548\u7387\u9ad8\u7279\u70b9\u3002"),(0,r.kt)("p",null,"\u5185\u5b58\u7f13\u5b58\u901a\u8fc7\u6ce8\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"IMemoryCache")," \u65b9\u5f0f\u6ce8\u5165\u5373\u53ef\u3002"),(0,r.kt)("admonition",{title:"\u5907\u6ce8",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5185\u5b58\u7f13\u5b58\u670d\u52a1\u5df2\u7ecf\u9ed8\u8ba4\u6ce8\u518c\uff0c\u65e0\u9700\u624b\u52a8\u6ce8\u518c\u3002")),(0,r.kt)("h3",{id:"1431-\u57fa\u672c\u4f7f\u7528"},"14.3.1 \u57fa\u672c\u4f7f\u7528"),(0,r.kt)("p",null,"\u5982\uff0c\u7f13\u5b58\u5f53\u524d\u65f6\u95f4\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,21-24}",showLineNumbers:!0,"":!0,"{13,21-24}":!0},'using Furion.DynamicApiController;\nusing Microsoft.Extensions.Caching.Memory;\nusing System;\n\nnamespace Furion.Application\n{\n public class CacheServices : IDynamicApiController\n {\n private const string _timeCacheKey = "cache_time";\n\n private readonly IMemoryCache _memoryCache;\n\n public CacheServices(IMemoryCache memoryCache)\n {\n _memoryCache = memoryCache;\n }\n\n [ApiDescriptionSettings(KeepName = true)]\n public DateTimeOffset GetOrCreate()\n {\n return _memoryCache.GetOrCreate(_timeCacheKey, entry =>\n {\n return DateTimeOffset.UtcNow;\n });\n }\n }\n}\n')),(0,r.kt)("h3",{id:"1432-\u8bbe\u7f6e\u7f13\u5b58\u9009\u9879"},"14.3.2 \u8bbe\u7f6e\u7f13\u5b58\u9009\u9879"),(0,r.kt)("p",null,"\u5185\u5b58\u7f13\u5b58\u652f\u6301\u8bbe\u7f6e\u7f13\u5b58\u65f6\u95f4\u3001\u7f13\u5b58\u5927\u5c0f\u3001\u53ca\u7edd\u5bf9\u7f13\u5b58\u8fc7\u671f\u65f6\u95f4\u7b49"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"_memoryCache.GetOrCreate(_timeCacheKey, entry =>\n{\n entry.SlidingExpiration = TimeSpan.FromSeconds(3); // \u6ed1\u52a8\u7f13\u5b58\u65f6\u95f4\n return DateTimeOffset.UtcNow;\n});\n\nawait _memoryCache.GetOrCreateAsync(_timeCacheKey, async entry =>\n{\n // \u8fd9\u91cc\u53ef\u4ee5\u4f7f\u7528\u5f02\u6b65~~\n});\n")),(0,r.kt)("admonition",{title:"\u5173\u4e8e\u7f13\u5b58\u65f6\u95f4",type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"\u5177\u6709\u53ef\u8c03\u8fc7\u671f\u7684\u7f13\u5b58\u9879\u96c6\u5b58\u5728\u8fc7\u65f6\u7684\u98ce\u9669\u3002 \u5982\u679c\u8bbf\u95ee\u7684\u65f6\u95f4\u6bd4\u6ed1\u52a8\u8fc7\u671f\u65f6\u95f4\u95f4\u9694\u66f4\u9891\u7e41\uff0c\u5219\u8be5\u9879\u5c06\u6c38\u4e0d\u8fc7\u671f\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u5c06\u5f39\u6027\u8fc7\u671f\u4e0e\u7edd\u5bf9\u8fc7\u671f\u7ec4\u5408\u5728\u4e00\u8d77\uff0c\u4ee5\u4fdd\u8bc1\u9879\u76ee\u5728\u5176\u7edd\u5bf9\u8fc7\u671f\u65f6\u95f4\u901a\u8fc7\u540e\u8fc7\u671f\u3002 \u7edd\u5bf9\u8fc7\u671f\u4f1a\u5c06\u9879\u7684\u4e0a\u9650\u8bbe\u7f6e\u4e3a\u53ef\u7f13\u5b58\u9879\u7684\u65f6\u95f4\uff0c\u540c\u65f6\u4ecd\u5141\u8bb8\u9879\u5728\u53ef\u8c03\u6574\u8fc7\u671f\u65f6\u95f4\u95f4\u9694\u5185\u672a\u8bf7\u6c42\u65f6\u63d0\u524d\u8fc7\u671f\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u5982\u679c\u540c\u65f6\u6307\u5b9a\u4e86\u7edd\u5bf9\u8fc7\u671f\u548c\u53ef\u8c03\u8fc7\u671f\u65f6\u95f4\uff0c\u5219\u8fc7\u671f\u65f6\u95f4\u4ee5\u903b\u8f91\u65b9\u5f0f\u8fd0\u7b97\u3002 \u5982\u679c\u6ed1\u52a8\u8fc7\u671f\u65f6\u95f4\u95f4\u9694 \u6216 \u7edd\u5bf9\u8fc7\u671f\u65f6\u95f4\u901a\u8fc7\uff0c\u5219\u4ece\u7f13\u5b58\u4e2d\u9010\u51fa\u8be5\u9879\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u5982\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"_memoryCache.GetOrCreate(_timeCacheKey, entry =>\n{\n entry.SetSlidingExpiration(TimeSpan.FromSeconds(3));\n entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(20);\n return DateTime.Now;\n});\n")),(0,r.kt)("p",{parentName:"admonition"},"\u524d\u9762\u7684\u4ee3\u7801\u4fdd\u8bc1\u6570\u636e\u7684\u7f13\u5b58\u65f6\u95f4\u4e0d\u8d85\u8fc7\u7edd\u5bf9\u65f6\u95f4\u3002")),(0,r.kt)("h3",{id:"1433-\u624b\u52a8\u8bbe\u7f6e\u7f13\u5b58\u9009\u9879"},"14.3.3 \u624b\u52a8\u8bbe\u7f6e\u7f13\u5b58\u9009\u9879"),(0,r.kt)("p",null,"\u9664\u4e86\u4e0a\u9762\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Func")," \u65b9\u5f0f\u8bbe\u7f6e\u7f13\u5b58\u9009\u9879\uff0c\u6211\u4eec\u53ef\u4ee5\u624b\u52a8\u521b\u5efa\u5e76\u8bbe\u7f6e\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var cacheEntryOptions = new MemoryCacheEntryOptions()\n .SetSlidingExpiration(TimeSpan.FromSeconds(3));\n\n_memoryCache.Set(_timeCacheKey, DateTimeOffset.UtcNow, cacheEntryOptions);\n")),(0,r.kt)("h3",{id:"1434-\u7f13\u5b58\u4f9d\u8d56\u5173\u7cfb"},"14.3.4 \u7f13\u5b58\u4f9d\u8d56\u5173\u7cfb"),(0,r.kt)("p",null,"\u4e0b\u9762\u7684\u793a\u4f8b\u6f14\u793a\u5982\u4f55\u5728\u4f9d\u8d56\u6761\u76ee\u8fc7\u671f\u540e\u4f7f\u7f13\u5b58\u6761\u76ee\u8fc7\u671f\u3002 ",(0,r.kt)("inlineCode",{parentName:"p"},"CancellationChangeToken")," \u6dfb\u52a0\u5230\u7f13\u5b58\u7684\u9879\u3002 \u5f53 ",(0,r.kt)("inlineCode",{parentName:"p"},"Cancel")," \u5728\u4e0a\u8c03\u7528\u65f6 ",(0,r.kt)("inlineCode",{parentName:"p"},"CancellationTokenSource")," \uff0c\u5c06\u9010\u51fa\u4e24\u4e2a\u7f13\u5b58\u9879\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public IActionResult CreateDependentEntries()\n{\n var cts = new CancellationTokenSource();\n _cache.Set(CacheKeys.DependentCTS, cts);\n\n using (var entry = _cache.CreateEntry(CacheKeys.Parent))\n {\n // expire this entry if the dependant entry expires.\n entry.Value = DateTime.Now;\n entry.RegisterPostEvictionCallback(DependentEvictionCallback, this);\n\n _cache.Set(CacheKeys.Child,\n DateTime.Now,\n new CancellationChangeToken(cts.Token));\n }\n\n return RedirectToAction("GetDependentEntries");\n}\n\npublic IActionResult GetDependentEntries()\n{\n return View("Dependent", new DependentViewModel\n {\n ParentCachedTime = _cache.Get(CacheKeys.Parent),\n ChildCachedTime = _cache.Get(CacheKeys.Child),\n Message = _cache.Get(CacheKeys.DependentMessage)\n });\n}\n\npublic IActionResult RemoveChildEntry()\n{\n _cache.Get(CacheKeys.DependentCTS).Cancel();\n return RedirectToAction("GetDependentEntries");\n}\n\nprivate static void DependentEvictionCallback(object key, object value,\n EvictionReason reason, object state)\n{\n var message = $"Parent entry was evicted. Reason: {reason}.";\n ((HomeController)state)._cache.Set(CacheKeys.DependentMessage, message);\n}\n')),(0,r.kt)("p",null,"\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"CancellationTokenSource")," \u5141\u8bb8\u5c06\u591a\u4e2a\u7f13\u5b58\u6761\u76ee\u4f5c\u4e3a\u4e00\u4e2a\u7ec4\u9010\u51fa\u3002 ",(0,r.kt)("inlineCode",{parentName:"p"},"using")," \u5728\u4e0a\u9762\u7684\u4ee3\u7801\u4e2d\uff0c\u5728\u5757\u4e2d\u521b\u5efa\u7684\u7f13\u5b58\u6761\u76ee ",(0,r.kt)("inlineCode",{parentName:"p"},"using")," \u5c06\u7ee7\u627f\u89e6\u53d1\u5668\u548c\u8fc7\u671f\u8bbe\u7f6e\u3002"),(0,r.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"p"},"\u5185\u5b58\u4e2d\u7684\u7f13\u5b58")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/memory?view=aspnetcore-5.0"},"ASP.NET Core - \u5185\u5b58\u7f13\u5b58")," \u7ae0\u8282\u3002")),(0,r.kt)("h2",{id:"144-\u5206\u5e03\u5f0f\u7f13\u5b58"},"14.4 \u5206\u5e03\u5f0f\u7f13\u5b58"),(0,r.kt)("p",null,"\u5206\u5e03\u5f0f\u7f13\u5b58\u662f\u7531\u591a\u4e2a\u5e94\u7528\u670d\u52a1\u5668\u5171\u4eab\u7684\u7f13\u5b58\uff0c\u901a\u5e38\u4f5c\u4e3a\u5916\u90e8\u670d\u52a1\u5728\u8bbf\u95ee\u5b83\u7684\u5e94\u7528\u670d\u52a1\u5668\u4e0a\u7ef4\u62a4\u3002 \u5206\u5e03\u5f0f\u7f13\u5b58\u53ef\u4ee5\u63d0\u9ad8 ",(0,r.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u7a0b\u5e8f\u7684\u6027\u80fd\u548c\u53ef\u4f38\u7f29\u6027\uff0c\u5c24\u5176\u662f\u5728\u5e94\u7528\u7a0b\u5e8f\u7531\u4e91\u670d\u52a1\u6216\u670d\u52a1\u5668\u573a\u6258\u7ba1\u65f6\u3002"),(0,r.kt)("p",null,"\u4e0e\u5176\u4ed6\u7f13\u5b58\u65b9\u6848\u76f8\u6bd4\uff0c\u5206\u5e03\u5f0f\u7f13\u5b58\u5177\u6709\u591a\u9879\u4f18\u52bf\uff0c\u5176\u4e2d\u7f13\u5b58\u7684\u6570\u636e\u5b58\u50a8\u5728\u5355\u4e2a\u5e94\u7528\u670d\u52a1\u5668\u4e0a\u3002"),(0,r.kt)("p",null,"\u5f53\u5206\u5e03\u5f0f\u7f13\u5b58\u6570\u636e\u65f6\uff0c\u6570\u636e\u5c06\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"(\u4e00\u81f4\u6027) \u8de8\u591a\u4e2a \u670d\u52a1\u5668\u7684\u8bf7\u6c42"),(0,r.kt)("li",{parentName:"ul"},"\u5b58\u6d3b\u5728\u670d\u52a1\u5668\u91cd\u542f\u548c\u5e94\u7528\u90e8\u7f72\u4e4b\u95f4"),(0,r.kt)("li",{parentName:"ul"},"\u4e0d\u4f7f\u7528\u672c\u5730\u5185\u5b58")),(0,r.kt)("p",null,"\u5206\u5e03\u5f0f\u7f13\u5b58\u914d\u7f6e\u662f\u7279\u5b9a\u4e8e\u5b9e\u73b0\u7684\u3002 \u672c\u6587\u4ecb\u7ecd\u5982\u4f55\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"Redis")," \u5206\u5e03\u5f0f\u7f13\u5b58\u3002 \u7b2c\u4e09\u65b9\u5b9e\u73b0\u4e5f\u53ef\u7528\uff0c\u4f8b\u5982 GitHub \u4e0a\u7684 ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/Alachisoft/NCache"},"NCache")," (NCache) \u3002"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u65e0\u8bba\u9009\u62e9\u54ea\u79cd\u5b9e\u73b0\uff0c\u5e94\u7528\u90fd\u4f1a\u4f7f\u7528\u63a5\u53e3\u4e0e\u7f13\u5b58\u4ea4\u4e92 ",(0,r.kt)("inlineCode",{parentName:"strong"},"IDistributedCache")," \u3002")),(0,r.kt)("h3",{id:"1441-\u4f7f\u7528\u6761\u4ef6"},"14.4.1 \u4f7f\u7528\u6761\u4ef6"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u82e5\u8981\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"SQL Server")," \u5206\u5e03\u5f0f\u7f13\u5b58\uff0c\u5219\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Microsoft.Extensions.Caching.SqlServer")," \u5305"),(0,r.kt)("li",{parentName:"ul"},"\u82e5\u8981\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Redis")," \u5206\u5e03\u5f0f\u7f13\u5b58\uff0c\u5219\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Microsoft.Extensions.Caching.StackExchangeRedis")," \u5305"),(0,r.kt)("li",{parentName:"ul"},"\u82e5\u8981\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"NCache")," \u5206\u5e03\u5f0f\u7f13\u5b58\uff0c\u5219\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"NCache.Microsoft.Extensions.Caching.OpenSource")," \u5305")),(0,r.kt)("h3",{id:"1442-idistributedcache"},"14.4.2 ",(0,r.kt)("inlineCode",{parentName:"h3"},"IDistributedCache")),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"IDistributedCache")," \u63a5\u53e3\u63d0\u4f9b\u4ee5\u4e0b\u65b9\u6cd5\u6765\u5904\u7406\u5206\u5e03\u5f0f\u7f13\u5b58\u5b9e\u73b0\u4e2d\u7684\u9879\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Get/GetAsync"),"\uff1a\u63a5\u53d7\u5b57\u7b26\u4e32\u952e\uff0c\u5e76\u68c0\u7d22\u7f13\u5b58\u9879\u4f5c\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"byte[]")," \u6570\u7ec4\uff08\u5982\u679c\u5728\u7f13\u5b58\u4e2d\u627e\u5230\uff09"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Set/SetAsync"),"\uff1a\u4f7f\u7528\u5b57\u7b26\u4e32\u952e\u5c06\u9879 (\u4f5c\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"byte[]")," \u6570\u7ec4) \u6dfb\u52a0\u5230\u7f13\u5b58\u4e2d"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Refresh/RefreshAsync")," \uff1a\u6839\u636e\u9879\u7684\u952e\u5237\u65b0\u7f13\u5b58\u4e2d\u7684\u9879\uff0c\u91cd\u7f6e\u5176\u6ed1\u52a8\u8fc7\u671f\u8d85\u65f6\uff08\u5982\u679c\u6709\uff09"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Remove/RemoveAsync"),"\uff1a\u6839\u636e\u7f13\u5b58\u9879\u7684\u5b57\u7b26\u4e32\u952e\u5220\u9664\u7f13\u5b58\u9879")),(0,r.kt)("h3",{id:"1443-\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58"},"14.4.3 \u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58"),(0,r.kt)("p",null,"\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58\uff08",(0,r.kt)("inlineCode",{parentName:"p"},"AddDistributedMemoryCache"),"\uff09\u662f\u4e00\u4e2a\u6846\u67b6\u63d0\u4f9b\u7684\u5b9e\u73b0 ",(0,r.kt)("inlineCode",{parentName:"p"},"IDistributedCache")," \uff0c\u5b83\u5c06\u9879\u5b58\u50a8\u5728\u5185\u5b58\u4e2d\u3002 ",(0,r.kt)("strong",{parentName:"p"},"\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58\u4e0d\u662f\u5b9e\u9645\u7684\u5206\u5e03\u5f0f\u7f13\u5b58\uff0c\u7f13\u5b58\u9879\u7531\u5e94\u7528\u7a0b\u5e8f\u5b9e\u4f8b\u5b58\u50a8\u5728\u8fd0\u884c\u5e94\u7528\u7a0b\u5e8f\u7684\u670d\u52a1\u5668\u4e0a\u3002")),(0,r.kt)("p",null,"\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58\u4f18\u70b9\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u7528\u4e8e\u5f00\u53d1\u548c\u6d4b\u8bd5\u65b9\u6848\u3002"),(0,r.kt)("li",{parentName:"ul"},"\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u4f7f\u7528\u5355\u4e00\u670d\u52a1\u5668\u5e76\u4e14\u5185\u5b58\u6d88\u8017\u4e0d\u662f\u95ee\u9898\u3002 \u5b9e\u73b0\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58\u4f1a\u62bd\u8c61\u5316\u7f13\u5b58\u7684\u6570\u636e\u5b58\u50a8\u3002 \u5982\u679c\u9700\u8981\u591a\u4e2a\u8282\u70b9\u6216\u5bb9\u9519\uff0c\u53ef\u4ee5\u5728\u5c06\u6765\u5b9e\u73b0\u771f\u6b63\u7684\u5206\u5e03\u5f0f\u7f13\u5b58\u89e3\u51b3\u65b9\u6848\u3002")),(0,r.kt)("admonition",{title:"\u5907\u6ce8",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58\u670d\u52a1\u5df2\u7ecf\u9ed8\u8ba4\u6ce8\u518c\uff0c\u65e0\u9700\u624b\u52a8\u8c03\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"services.AddDistributedMemoryCache();")," \u6ce8\u518c\u3002")),(0,r.kt)("h3",{id:"1444-\u5206\u5e03\u5f0f-sql-server-\u7f13\u5b58"},"14.4.4 \u5206\u5e03\u5f0f SQL Server \u7f13\u5b58"),(0,r.kt)("p",null,"\u5206\u5e03\u5f0f ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u7f13\u5b58\u5b9e\u73b0 (",(0,r.kt)("inlineCode",{parentName:"p"},"AddDistributedSqlServerCache"),") \u5141\u8bb8\u5206\u5e03\u5f0f\u7f13\u5b58\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u6570\u636e\u5e93\u4f5c\u4e3a\u5176\u540e\u5907\u5b58\u50a8\u3002"),(0,r.kt)("p",null,"\u82e5\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u5b9e\u4f8b\u4e2d\u521b\u5efa ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u7f13\u5b58\u7684\u9879\u8868\uff0c\u53ef\u4ee5\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"sql-cache")," \u5de5\u5177\u3002 \u8be5\u5de5\u5177\u5c06\u521b\u5efa\u4e00\u4e2a\u8868\uff0c\u5176\u4e2d\u5305\u542b\u6307\u5b9a\u7684\u540d\u79f0\u548c\u67b6\u6784\u3002"),(0,r.kt)("p",null,"\u901a\u8fc7\u8fd0\u884c\u547d\u4ee4 ",(0,r.kt)("inlineCode",{parentName:"p"},"sql-cache create")," \u521b\u5efa\u4e00\u4e2a\u8868\uff0c\u63d0\u4f9b ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u5b9e\u4f8b (Data Source) \u3001\u6570\u636e\u5e93 (Initial Catalog) \u3001\u67b6\u6784 (\u4f8b\u5982) dbo \u548c\u8868\u540d\u79f0\u3002\u4f8b\u5982 ",(0,r.kt)("inlineCode",{parentName:"p"},"TestCache"),"\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},'dotnet sql-cache create "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache\n')),(0,r.kt)("p",null,"\u521b\u5efa\u6210\u529f\u540e\uff0c\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'services.AddDistributedSqlServerCache(options =>\n{\n options.ConnectionString =\n _config["DistCache_ConnectionString"];\n options.SchemaName = "dbo";\n options.TableName = "TestCache";\n});\n')),(0,r.kt)("h3",{id:"1445-\u5206\u5e03\u5f0f-redis-\u7f13\u5b58"},"14.4.5 \u5206\u5e03\u5f0f ",(0,r.kt)("inlineCode",{parentName:"h3"},"Redis")," \u7f13\u5b58"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Redis")," \u662f\u5185\u5b58\u4e2d\u6570\u636e\u5b58\u50a8\u7684\u5f00\u6e90\u6570\u636e\u5b58\u50a8\uff0c\u901a\u5e38\u7528\u4f5c\u5206\u5e03\u5f0f\u7f13\u5b58\u3002\u5728\u4f7f\u7528\u65f6\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"services.AddStackExchangeRedisCache()")," \u4e2d\u6ce8\u518c\u5373\u53ef\u3002"),(0,r.kt)("p",null,"\u8fd9\u91cc\u4e0d\u7ec6\u8bb2 ",(0,r.kt)("inlineCode",{parentName:"p"},"Redis")," \u76f8\u5173\u5185\u5bb9\uff0c\u540e\u7eed\u7ae0\u8282\u4f1a\u4f7f\u7528\u57fa\u672c\u4f8b\u5b50\u6f14\u793a\u3002"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Redis")," \u57fa\u672c\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'services.AddStackExchangeRedisCache(options =>\n{\n // \u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u8fd9\u91cc\u4e5f\u53ef\u4ee5\u8bfb\u53d6\u914d\u7f6e\u6587\u4ef6\n options.Configuration = "192.168.111.134,password=aW1HAyupRKmiZn3Q";\n // \u952e\u540d\u524d\u7f00\n options.InstanceName = "furion_";\n});\n')),(0,r.kt)("h3",{id:"1446-\u5206\u5e03\u5f0f-ncache-\u7f13\u5b58"},"14.4.6 \u5206\u5e03\u5f0f ",(0,r.kt)("inlineCode",{parentName:"h3"},"NCache")," \u7f13\u5b58"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"NCache")," \u662f\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},".Net Core")," \u4e2d\u4ee5\u672c\u673a\u65b9\u5f0f\u5f00\u53d1\u7684\u5f00\u6e90\u5185\u5b58\u4e2d\u5206\u5e03\u5f0f\u7f13\u5b58\u3002 ",(0,r.kt)("inlineCode",{parentName:"p"},"NCache")," \u5728\u672c\u5730\u5de5\u4f5c\u5e76\u914d\u7f6e\u4e3a\u5206\u5e03\u5f0f\u7f13\u5b58\u7fa4\u96c6\uff0c\u9002\u7528\u4e8e\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Azure")," \u6216\u5176\u4ed6\u6258\u7ba1\u5e73\u53f0\u4e0a\u8fd0\u884c\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u3002\n\u82e5\u8981\u5728\u672c\u5730\u8ba1\u7b97\u673a\u4e0a\u5b89\u88c5\u548c\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"NCache"),"\uff0c\u8bf7\u53c2\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://www.alachisoft.com/resources/docs/ncache-oss/getting-started-guide-windows/"},"\u9002\u7528\u4e8e Windows \u7684 NCache \u5165\u95e8\u6307\u5357"),"\u3002"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"NCache")," \u57fa\u672c\u914d\u7f6e\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u5b89\u88c5 ",(0,r.kt)("inlineCode",{parentName:"li"},"Alachisoft.NCache.OpenSource.SDK")," \u5305"),(0,r.kt)("li",{parentName:"ul"},"\u5728 ",(0,r.kt)("a",{parentName:"li",href:"https://www.alachisoft.com/resources/docs/ncache-oss/admin-guide/client-config.html"},"ncconf")," \u4e2d\u914d\u7f6e\u7f13\u5b58\u7fa4\u96c6"),(0,r.kt)("li",{parentName:"ul"},"\u6ce8\u518c ",(0,r.kt)("inlineCode",{parentName:"li"},"NCache")," \u670d\u52a1")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'services.AddNCacheDistributedCache(configuration =>\n{\n configuration.CacheName = "demoClusteredCache";\n configuration.EnableLogs = true;\n configuration.ExceptionsEnabled = true;\n});\n')),(0,r.kt)("h2",{id:"145-\u5206\u5e03\u5f0f\u7f13\u5b58\u4f7f\u7528"},"14.5 \u5206\u5e03\u5f0f\u7f13\u5b58\u4f7f\u7528"),(0,r.kt)("p",null,"\u82e5\u8981\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"IDistributedCache")," \u63a5\u53e3\uff0c\u8bf7 ",(0,r.kt)("inlineCode",{parentName:"p"},"IDistributedCache")," \u901a\u8fc7\u6784\u9020\u51fd\u6570\u4f9d\u8d56\u5173\u7cfb\u6ce8\u5165\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,16,30-33}",showLineNumbers:!0,"":!0,"{5,16,30-33}":!0},'public class IndexModel : PageModel\n{\n private readonly IDistributedCache _cache;\n\n public IndexModel(IDistributedCache cache)\n {\n _cache = cache;\n }\n\n public string CachedTimeUTC { get; set; }\n\n public async Task OnGetAsync()\n {\n CachedTimeUTC = "Cached Time Expired";\n // \u83b7\u53d6\u5206\u5e03\u5f0f\u7f13\u5b58\n var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");\n\n if (encodedCachedTimeUTC != null)\n {\n CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);\n }\n }\n\n public async Task OnPostResetCachedTime()\n {\n var currentTimeUTC = DateTime.UtcNow.ToString();\n byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);\n\n // \u8bbe\u7f6e\u5206\u5e03\u5f0f\u7f13\u5b58\n var options = new DistributedCacheEntryOptions()\n .SetSlidingExpiration(TimeSpan.FromSeconds(20));\n\n await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);\n\n return RedirectToPage();\n }\n}\n')),(0,r.kt)("h2",{id:"146-\u5206\u5e03\u5f0f\u7f13\u5b58\u5efa\u8bae"},"14.6 \u5206\u5e03\u5f0f\u7f13\u5b58\u5efa\u8bae"),(0,r.kt)("p",null,"\u786e\u5b9a ",(0,r.kt)("inlineCode",{parentName:"p"},"IDistributedCache")," \u6700\u9002\u5408\u4f60\u7684\u5e94\u7528\u7684\u5b9e\u73b0\u65f6\uff0c\u8bf7\u8003\u8651\u4ee5\u4e0b\u4e8b\u9879\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u73b0\u6709\u57fa\u7840\u7ed3\u6784"),(0,r.kt)("li",{parentName:"ul"},"\u6027\u80fd\u8981\u6c42"),(0,r.kt)("li",{parentName:"ul"},"\u6210\u672c"),(0,r.kt)("li",{parentName:"ul"},"\u56e2\u961f\u7ecf\u9a8c")),(0,r.kt)("p",null,"\u7f13\u5b58\u89e3\u51b3\u65b9\u6848\u901a\u5e38\u4f9d\u8d56\u4e8e\u5185\u5b58\u4e2d\u7684\u5b58\u50a8\u4ee5\u5feb\u901f\u68c0\u7d22\u7f13\u5b58\u7684\u6570\u636e\uff0c\u4f46\u662f\uff0c\u5185\u5b58\u662f\u6709\u9650\u7684\u8d44\u6e90\uff0c\u5e76\u4e14\u5f88\u6602\u8d35\u3002 \u4ec5\u5c06\u5e38\u7528\u6570\u636e\u5b58\u50a8\u5728\u7f13\u5b58\u4e2d\u3002"),(0,r.kt)("p",null,"\u901a\u5e38\uff0c",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"Redis")," \u7f13\u5b58\u63d0\u4f9b\u6bd4 ",(0,r.kt)("inlineCode",{parentName:"strong"},"SQL Server")," \u7f13\u5b58\u66f4\u9ad8\u7684\u541e\u5410\u91cf\u548c\u66f4\u4f4e\u7684\u5ef6\u8fdf\u3002")," \u4f46\u662f\uff0c\u901a\u5e38\u9700\u8981\u8fdb\u884c\u57fa\u51c6\u6d4b\u8bd5\u6765\u786e\u5b9a\u7f13\u5b58\u7b56\u7565\u7684\u6027\u80fd\u7279\u5f81\u3002"),(0,r.kt)("p",null,"\u5f53 ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u7528\u4f5c\u5206\u5e03\u5f0f\u7f13\u5b58\u540e\u5907\u5b58\u50a8\u65f6\uff0c\u5bf9\u7f13\u5b58\u4f7f\u7528\u540c\u4e00\u6570\u636e\u5e93\uff0c\u5e76\u4e14\u5e94\u7528\u7684\u666e\u901a\u6570\u636e\u5b58\u50a8\u548c\u68c0\u7d22\u4f1a\u5bf9\u8fd9\u4e24\u79cd\u60c5\u51b5\u7684\u6027\u80fd\u4ea7\u751f\u8d1f\u9762\u5f71\u54cd\u3002 \u5efa\u8bae\u4f7f\u7528\u5206\u5e03\u5f0f\u7f13\u5b58\u540e\u5907\u5b58\u50a8\u7684\u4e13\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u5b9e\u4f8b\u3002"),(0,r.kt)("h2",{id:"147-\u53cd\u9988\u4e0e\u5efa\u8bae"},"14.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,r.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,r.kt)("hr",null),(0,r.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"p"},"\u5206\u5e03\u5f0f\u7f13\u5b58")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/distributed?view=aspnetcore-5.0"},"ASP.NET Core - \u5206\u5e03\u5f0f\u7f13\u5b58")," \u7ae0\u8282\u3002")))}u.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return s},kt:function(){return u}});var a=t(7294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function o(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var c=a.createContext({}),p=function(e){var n=a.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},s=function(e){var n=p(e.components);return a.createElement(c.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,i=e.mdxType,r=e.originalType,c=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),m=p(t),u=i,k=m["".concat(c,".").concat(u)]||m[u]||d[u]||r;return t?a.createElement(k,o(o({ref:n},s),{},{components:t})):a.createElement(k,o({ref:n},s))}));function u(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var r=t.length,o=new Array(r);o[0]=m;var l={};for(var c in n)hasOwnProperty.call(n,c)&&(l[c]=n[c]);l.originalType=e,l.mdxType="string"==typeof e?e:i,o[1]=l;for(var p=2;p=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var c=a.createContext({}),p=function(e){var n=a.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},s=function(e){var n=p(e.components);return a.createElement(c.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,i=e.mdxType,r=e.originalType,c=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),m=p(t),u=i,k=m["".concat(c,".").concat(u)]||m[u]||d[u]||r;return t?a.createElement(k,o(o({ref:n},s),{},{components:t})):a.createElement(k,o({ref:n},s))}));function u(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var r=t.length,o=new Array(r);o[0]=m;var l={};for(var c in n)hasOwnProperty.call(n,c)&&(l[c]=n[c]);l.originalType=e,l.mdxType="string"==typeof e?e:i,o[1]=l;for(var p=2;pIDistributedCache",id:"1442-idistributedcache",level:3},{value:"14.4.3 \u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58",id:"1443-\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58",level:3},{value:"14.4.4 \u5206\u5e03\u5f0f SQL Server \u7f13\u5b58",id:"1444-\u5206\u5e03\u5f0f-sql-server-\u7f13\u5b58",level:3},{value:"14.4.5 \u5206\u5e03\u5f0f Redis \u7f13\u5b58",id:"1445-\u5206\u5e03\u5f0f-redis-\u7f13\u5b58",level:3},{value:"14.4.6 \u5206\u5e03\u5f0f NCache \u7f13\u5b58",id:"1446-\u5206\u5e03\u5f0f-ncache-\u7f13\u5b58",level:3},{value:"14.5 \u5206\u5e03\u5f0f\u7f13\u5b58\u4f7f\u7528",id:"145-\u5206\u5e03\u5f0f\u7f13\u5b58\u4f7f\u7528",level:2},{value:"14.6 \u5206\u5e03\u5f0f\u7f13\u5b58\u5efa\u8bae",id:"146-\u5206\u5e03\u5f0f\u7f13\u5b58\u5efa\u8bae",level:2},{value:"14.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"147-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:d};function u(e){var n=e.components,t=(0,i.Z)(e,o);return(0,r.kt)("wrapper",(0,a.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"141-\u4ec0\u4e48\u662f\u7f13\u5b58"},"14.1 \u4ec0\u4e48\u662f\u7f13\u5b58"),(0,r.kt)("p",null,"\u7f13\u5b58\u53ef\u4ee5\u51cf\u5c11\u751f\u6210\u5185\u5bb9\u6240\u9700\u7684\u5de5\u4f5c\uff0c\u4ece\u800c\u663e\u8457\u63d0\u9ad8\u5e94\u7528\u7a0b\u5e8f\u7684\u6027\u80fd\u548c\u53ef\u4f38\u7f29\u6027\u3002 ",(0,r.kt)("strong",{parentName:"p"},"\u7f13\u5b58\u9002\u7528\u4e8e\u4e0d\u7ecf\u5e38\u66f4\u6539\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u751f\u6210\u6210\u672c\u5f88\u9ad8"),"\u3002 \u901a\u8fc7\u7f13\u5b58\uff0c\u53ef\u6bd4\u4ece\u6570\u636e\u6e90\u8fd4\u56de\u6570\u636e\u7684\u526f\u672c\u901f\u5ea6\u5feb\u5f97\u591a\u3002 \u5e94\u8be5\u5bf9\u5e94\u7528\u8fdb\u884c\u7f16\u5199\u548c\u6d4b\u8bd5\uff0c\u4f7f\u5176\u4e0d\u8981\u6c38\u8fdc\u4f9d\u8d56\u4e8e\u7f13\u5b58\u7684\u6570\u636e\u3002"),(0,r.kt)("h2",{id:"142-\u7f13\u5b58\u7c7b\u578b"},"14.2 \u7f13\u5b58\u7c7b\u578b"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u5185\u5b58\u7f13\u5b58\uff1a\u987e\u540d\u601d\u4e49\uff0c\u5c31\u662f\u7f13\u5b58\u5728\u5e94\u7528\u90e8\u7f72\u6240\u5728\u670d\u52a1\u5668\u7684\u5185\u5b58\u4e2d"),(0,r.kt)("li",{parentName:"ul"},"\u5206\u5e03\u5f0f\u7f13\u5b58\uff1a\u5206\u5e03\u5f0f\u7f13\u5b58\u662f\u7531\u591a\u4e2a\u5e94\u7528\u670d\u52a1\u5668\u5171\u4eab\u7684\u7f13\u5b58"),(0,r.kt)("li",{parentName:"ul"},"\u54cd\u5e94\u7f13\u5b58\uff1a\u7f13\u5b58\u670d\u52a1\u5668\u7aef ",(0,r.kt)("inlineCode",{parentName:"li"},"Not Modified")," \u7684\u6570\u636e")),(0,r.kt)("h2",{id:"143-\u5185\u5b58\u7f13\u5b58\u4f7f\u7528"},"14.3 \u5185\u5b58\u7f13\u5b58\u4f7f\u7528"),(0,r.kt)("p",null,"\u5185\u5b58\u7f13\u5b58\u662f\u6700\u5e38\u7528\u7684\u7f13\u5b58\u65b9\u5f0f\uff0c\u5177\u6709\u5b58\u53d6\u5feb\uff0c\u6548\u7387\u9ad8\u7279\u70b9\u3002"),(0,r.kt)("p",null,"\u5185\u5b58\u7f13\u5b58\u901a\u8fc7\u6ce8\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"IMemoryCache")," \u65b9\u5f0f\u6ce8\u5165\u5373\u53ef\u3002"),(0,r.kt)("admonition",{title:"\u5907\u6ce8",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5185\u5b58\u7f13\u5b58\u670d\u52a1\u5df2\u7ecf\u9ed8\u8ba4\u6ce8\u518c\uff0c\u65e0\u9700\u624b\u52a8\u6ce8\u518c\u3002")),(0,r.kt)("h3",{id:"1431-\u57fa\u672c\u4f7f\u7528"},"14.3.1 \u57fa\u672c\u4f7f\u7528"),(0,r.kt)("p",null,"\u5982\uff0c\u7f13\u5b58\u5f53\u524d\u65f6\u95f4\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,21-24}",showLineNumbers:!0,"":!0,"{13,21-24}":!0},'using Furion.DynamicApiController;\nusing Microsoft.Extensions.Caching.Memory;\nusing System;\n\nnamespace Furion.Application\n{\n public class CacheServices : IDynamicApiController\n {\n private const string _timeCacheKey = "cache_time";\n\n private readonly IMemoryCache _memoryCache;\n\n public CacheServices(IMemoryCache memoryCache)\n {\n _memoryCache = memoryCache;\n }\n\n [ApiDescriptionSettings(KeepName = true)]\n public DateTimeOffset GetOrCreate()\n {\n return _memoryCache.GetOrCreate(_timeCacheKey, entry =>\n {\n return DateTimeOffset.UtcNow;\n });\n }\n }\n}\n')),(0,r.kt)("h3",{id:"1432-\u8bbe\u7f6e\u7f13\u5b58\u9009\u9879"},"14.3.2 \u8bbe\u7f6e\u7f13\u5b58\u9009\u9879"),(0,r.kt)("p",null,"\u5185\u5b58\u7f13\u5b58\u652f\u6301\u8bbe\u7f6e\u7f13\u5b58\u65f6\u95f4\u3001\u7f13\u5b58\u5927\u5c0f\u3001\u53ca\u7edd\u5bf9\u7f13\u5b58\u8fc7\u671f\u65f6\u95f4\u7b49"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"_memoryCache.GetOrCreate(_timeCacheKey, entry =>\n{\n entry.SlidingExpiration = TimeSpan.FromSeconds(3); // \u6ed1\u52a8\u7f13\u5b58\u65f6\u95f4\n return DateTimeOffset.UtcNow;\n});\n\nawait _memoryCache.GetOrCreateAsync(_timeCacheKey, async entry =>\n{\n // \u8fd9\u91cc\u53ef\u4ee5\u4f7f\u7528\u5f02\u6b65~~\n});\n")),(0,r.kt)("admonition",{title:"\u5173\u4e8e\u7f13\u5b58\u65f6\u95f4",type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"\u5177\u6709\u53ef\u8c03\u8fc7\u671f\u7684\u7f13\u5b58\u9879\u96c6\u5b58\u5728\u8fc7\u65f6\u7684\u98ce\u9669\u3002 \u5982\u679c\u8bbf\u95ee\u7684\u65f6\u95f4\u6bd4\u6ed1\u52a8\u8fc7\u671f\u65f6\u95f4\u95f4\u9694\u66f4\u9891\u7e41\uff0c\u5219\u8be5\u9879\u5c06\u6c38\u4e0d\u8fc7\u671f\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u5c06\u5f39\u6027\u8fc7\u671f\u4e0e\u7edd\u5bf9\u8fc7\u671f\u7ec4\u5408\u5728\u4e00\u8d77\uff0c\u4ee5\u4fdd\u8bc1\u9879\u76ee\u5728\u5176\u7edd\u5bf9\u8fc7\u671f\u65f6\u95f4\u901a\u8fc7\u540e\u8fc7\u671f\u3002 \u7edd\u5bf9\u8fc7\u671f\u4f1a\u5c06\u9879\u7684\u4e0a\u9650\u8bbe\u7f6e\u4e3a\u53ef\u7f13\u5b58\u9879\u7684\u65f6\u95f4\uff0c\u540c\u65f6\u4ecd\u5141\u8bb8\u9879\u5728\u53ef\u8c03\u6574\u8fc7\u671f\u65f6\u95f4\u95f4\u9694\u5185\u672a\u8bf7\u6c42\u65f6\u63d0\u524d\u8fc7\u671f\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u5982\u679c\u540c\u65f6\u6307\u5b9a\u4e86\u7edd\u5bf9\u8fc7\u671f\u548c\u53ef\u8c03\u8fc7\u671f\u65f6\u95f4\uff0c\u5219\u8fc7\u671f\u65f6\u95f4\u4ee5\u903b\u8f91\u65b9\u5f0f\u8fd0\u7b97\u3002 \u5982\u679c\u6ed1\u52a8\u8fc7\u671f\u65f6\u95f4\u95f4\u9694 \u6216 \u7edd\u5bf9\u8fc7\u671f\u65f6\u95f4\u901a\u8fc7\uff0c\u5219\u4ece\u7f13\u5b58\u4e2d\u9010\u51fa\u8be5\u9879\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u5982\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"_memoryCache.GetOrCreate(_timeCacheKey, entry =>\n{\n entry.SetSlidingExpiration(TimeSpan.FromSeconds(3));\n entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(20);\n return DateTime.Now;\n});\n")),(0,r.kt)("p",{parentName:"admonition"},"\u524d\u9762\u7684\u4ee3\u7801\u4fdd\u8bc1\u6570\u636e\u7684\u7f13\u5b58\u65f6\u95f4\u4e0d\u8d85\u8fc7\u7edd\u5bf9\u65f6\u95f4\u3002")),(0,r.kt)("h3",{id:"1433-\u624b\u52a8\u8bbe\u7f6e\u7f13\u5b58\u9009\u9879"},"14.3.3 \u624b\u52a8\u8bbe\u7f6e\u7f13\u5b58\u9009\u9879"),(0,r.kt)("p",null,"\u9664\u4e86\u4e0a\u9762\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Func")," \u65b9\u5f0f\u8bbe\u7f6e\u7f13\u5b58\u9009\u9879\uff0c\u6211\u4eec\u53ef\u4ee5\u624b\u52a8\u521b\u5efa\u5e76\u8bbe\u7f6e\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var cacheEntryOptions = new MemoryCacheEntryOptions()\n .SetSlidingExpiration(TimeSpan.FromSeconds(3));\n\n_memoryCache.Set(_timeCacheKey, DateTimeOffset.UtcNow, cacheEntryOptions);\n")),(0,r.kt)("h3",{id:"1434-\u7f13\u5b58\u4f9d\u8d56\u5173\u7cfb"},"14.3.4 \u7f13\u5b58\u4f9d\u8d56\u5173\u7cfb"),(0,r.kt)("p",null,"\u4e0b\u9762\u7684\u793a\u4f8b\u6f14\u793a\u5982\u4f55\u5728\u4f9d\u8d56\u6761\u76ee\u8fc7\u671f\u540e\u4f7f\u7f13\u5b58\u6761\u76ee\u8fc7\u671f\u3002 ",(0,r.kt)("inlineCode",{parentName:"p"},"CancellationChangeToken")," \u6dfb\u52a0\u5230\u7f13\u5b58\u7684\u9879\u3002 \u5f53 ",(0,r.kt)("inlineCode",{parentName:"p"},"Cancel")," \u5728\u4e0a\u8c03\u7528\u65f6 ",(0,r.kt)("inlineCode",{parentName:"p"},"CancellationTokenSource")," \uff0c\u5c06\u9010\u51fa\u4e24\u4e2a\u7f13\u5b58\u9879\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public IActionResult CreateDependentEntries()\n{\n var cts = new CancellationTokenSource();\n _cache.Set(CacheKeys.DependentCTS, cts);\n\n using (var entry = _cache.CreateEntry(CacheKeys.Parent))\n {\n // expire this entry if the dependant entry expires.\n entry.Value = DateTime.Now;\n entry.RegisterPostEvictionCallback(DependentEvictionCallback, this);\n\n _cache.Set(CacheKeys.Child,\n DateTime.Now,\n new CancellationChangeToken(cts.Token));\n }\n\n return RedirectToAction("GetDependentEntries");\n}\n\npublic IActionResult GetDependentEntries()\n{\n return View("Dependent", new DependentViewModel\n {\n ParentCachedTime = _cache.Get(CacheKeys.Parent),\n ChildCachedTime = _cache.Get(CacheKeys.Child),\n Message = _cache.Get(CacheKeys.DependentMessage)\n });\n}\n\npublic IActionResult RemoveChildEntry()\n{\n _cache.Get(CacheKeys.DependentCTS).Cancel();\n return RedirectToAction("GetDependentEntries");\n}\n\nprivate static void DependentEvictionCallback(object key, object value,\n EvictionReason reason, object state)\n{\n var message = $"Parent entry was evicted. Reason: {reason}.";\n ((HomeController)state)._cache.Set(CacheKeys.DependentMessage, message);\n}\n')),(0,r.kt)("p",null,"\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"CancellationTokenSource")," \u5141\u8bb8\u5c06\u591a\u4e2a\u7f13\u5b58\u6761\u76ee\u4f5c\u4e3a\u4e00\u4e2a\u7ec4\u9010\u51fa\u3002 ",(0,r.kt)("inlineCode",{parentName:"p"},"using")," \u5728\u4e0a\u9762\u7684\u4ee3\u7801\u4e2d\uff0c\u5728\u5757\u4e2d\u521b\u5efa\u7684\u7f13\u5b58\u6761\u76ee ",(0,r.kt)("inlineCode",{parentName:"p"},"using")," \u5c06\u7ee7\u627f\u89e6\u53d1\u5668\u548c\u8fc7\u671f\u8bbe\u7f6e\u3002"),(0,r.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"p"},"\u5185\u5b58\u4e2d\u7684\u7f13\u5b58")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/memory?view=aspnetcore-5.0"},"ASP.NET Core - \u5185\u5b58\u7f13\u5b58")," \u7ae0\u8282\u3002")),(0,r.kt)("h2",{id:"144-\u5206\u5e03\u5f0f\u7f13\u5b58"},"14.4 \u5206\u5e03\u5f0f\u7f13\u5b58"),(0,r.kt)("p",null,"\u5206\u5e03\u5f0f\u7f13\u5b58\u662f\u7531\u591a\u4e2a\u5e94\u7528\u670d\u52a1\u5668\u5171\u4eab\u7684\u7f13\u5b58\uff0c\u901a\u5e38\u4f5c\u4e3a\u5916\u90e8\u670d\u52a1\u5728\u8bbf\u95ee\u5b83\u7684\u5e94\u7528\u670d\u52a1\u5668\u4e0a\u7ef4\u62a4\u3002 \u5206\u5e03\u5f0f\u7f13\u5b58\u53ef\u4ee5\u63d0\u9ad8 ",(0,r.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u7a0b\u5e8f\u7684\u6027\u80fd\u548c\u53ef\u4f38\u7f29\u6027\uff0c\u5c24\u5176\u662f\u5728\u5e94\u7528\u7a0b\u5e8f\u7531\u4e91\u670d\u52a1\u6216\u670d\u52a1\u5668\u573a\u6258\u7ba1\u65f6\u3002"),(0,r.kt)("p",null,"\u4e0e\u5176\u4ed6\u7f13\u5b58\u65b9\u6848\u76f8\u6bd4\uff0c\u5206\u5e03\u5f0f\u7f13\u5b58\u5177\u6709\u591a\u9879\u4f18\u52bf\uff0c\u5176\u4e2d\u7f13\u5b58\u7684\u6570\u636e\u5b58\u50a8\u5728\u5355\u4e2a\u5e94\u7528\u670d\u52a1\u5668\u4e0a\u3002"),(0,r.kt)("p",null,"\u5f53\u5206\u5e03\u5f0f\u7f13\u5b58\u6570\u636e\u65f6\uff0c\u6570\u636e\u5c06\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"(\u4e00\u81f4\u6027) \u8de8\u591a\u4e2a \u670d\u52a1\u5668\u7684\u8bf7\u6c42"),(0,r.kt)("li",{parentName:"ul"},"\u5b58\u6d3b\u5728\u670d\u52a1\u5668\u91cd\u542f\u548c\u5e94\u7528\u90e8\u7f72\u4e4b\u95f4"),(0,r.kt)("li",{parentName:"ul"},"\u4e0d\u4f7f\u7528\u672c\u5730\u5185\u5b58")),(0,r.kt)("p",null,"\u5206\u5e03\u5f0f\u7f13\u5b58\u914d\u7f6e\u662f\u7279\u5b9a\u4e8e\u5b9e\u73b0\u7684\u3002 \u672c\u6587\u4ecb\u7ecd\u5982\u4f55\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"Redis")," \u5206\u5e03\u5f0f\u7f13\u5b58\u3002 \u7b2c\u4e09\u65b9\u5b9e\u73b0\u4e5f\u53ef\u7528\uff0c\u4f8b\u5982 GitHub \u4e0a\u7684 ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/Alachisoft/NCache"},"NCache")," (NCache) \u3002"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u65e0\u8bba\u9009\u62e9\u54ea\u79cd\u5b9e\u73b0\uff0c\u5e94\u7528\u90fd\u4f1a\u4f7f\u7528\u63a5\u53e3\u4e0e\u7f13\u5b58\u4ea4\u4e92 ",(0,r.kt)("inlineCode",{parentName:"strong"},"IDistributedCache")," \u3002")),(0,r.kt)("h3",{id:"1441-\u4f7f\u7528\u6761\u4ef6"},"14.4.1 \u4f7f\u7528\u6761\u4ef6"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u82e5\u8981\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"SQL Server")," \u5206\u5e03\u5f0f\u7f13\u5b58\uff0c\u5219\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Microsoft.Extensions.Caching.SqlServer")," \u5305"),(0,r.kt)("li",{parentName:"ul"},"\u82e5\u8981\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Redis")," \u5206\u5e03\u5f0f\u7f13\u5b58\uff0c\u5219\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Microsoft.Extensions.Caching.StackExchangeRedis")," \u5305"),(0,r.kt)("li",{parentName:"ul"},"\u82e5\u8981\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"NCache")," \u5206\u5e03\u5f0f\u7f13\u5b58\uff0c\u5219\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"NCache.Microsoft.Extensions.Caching.OpenSource")," \u5305")),(0,r.kt)("h3",{id:"1442-idistributedcache"},"14.4.2 ",(0,r.kt)("inlineCode",{parentName:"h3"},"IDistributedCache")),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"IDistributedCache")," \u63a5\u53e3\u63d0\u4f9b\u4ee5\u4e0b\u65b9\u6cd5\u6765\u5904\u7406\u5206\u5e03\u5f0f\u7f13\u5b58\u5b9e\u73b0\u4e2d\u7684\u9879\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Get/GetAsync"),"\uff1a\u63a5\u53d7\u5b57\u7b26\u4e32\u952e\uff0c\u5e76\u68c0\u7d22\u7f13\u5b58\u9879\u4f5c\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"byte[]")," \u6570\u7ec4\uff08\u5982\u679c\u5728\u7f13\u5b58\u4e2d\u627e\u5230\uff09"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Set/SetAsync"),"\uff1a\u4f7f\u7528\u5b57\u7b26\u4e32\u952e\u5c06\u9879 (\u4f5c\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"byte[]")," \u6570\u7ec4) \u6dfb\u52a0\u5230\u7f13\u5b58\u4e2d"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Refresh/RefreshAsync")," \uff1a\u6839\u636e\u9879\u7684\u952e\u5237\u65b0\u7f13\u5b58\u4e2d\u7684\u9879\uff0c\u91cd\u7f6e\u5176\u6ed1\u52a8\u8fc7\u671f\u8d85\u65f6\uff08\u5982\u679c\u6709\uff09"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Remove/RemoveAsync"),"\uff1a\u6839\u636e\u7f13\u5b58\u9879\u7684\u5b57\u7b26\u4e32\u952e\u5220\u9664\u7f13\u5b58\u9879")),(0,r.kt)("h3",{id:"1443-\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58"},"14.4.3 \u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58"),(0,r.kt)("p",null,"\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58\uff08",(0,r.kt)("inlineCode",{parentName:"p"},"AddDistributedMemoryCache"),"\uff09\u662f\u4e00\u4e2a\u6846\u67b6\u63d0\u4f9b\u7684\u5b9e\u73b0 ",(0,r.kt)("inlineCode",{parentName:"p"},"IDistributedCache")," \uff0c\u5b83\u5c06\u9879\u5b58\u50a8\u5728\u5185\u5b58\u4e2d\u3002 ",(0,r.kt)("strong",{parentName:"p"},"\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58\u4e0d\u662f\u5b9e\u9645\u7684\u5206\u5e03\u5f0f\u7f13\u5b58\uff0c\u7f13\u5b58\u9879\u7531\u5e94\u7528\u7a0b\u5e8f\u5b9e\u4f8b\u5b58\u50a8\u5728\u8fd0\u884c\u5e94\u7528\u7a0b\u5e8f\u7684\u670d\u52a1\u5668\u4e0a\u3002")),(0,r.kt)("p",null,"\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58\u4f18\u70b9\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u7528\u4e8e\u5f00\u53d1\u548c\u6d4b\u8bd5\u65b9\u6848\u3002"),(0,r.kt)("li",{parentName:"ul"},"\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u4f7f\u7528\u5355\u4e00\u670d\u52a1\u5668\u5e76\u4e14\u5185\u5b58\u6d88\u8017\u4e0d\u662f\u95ee\u9898\u3002 \u5b9e\u73b0\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58\u4f1a\u62bd\u8c61\u5316\u7f13\u5b58\u7684\u6570\u636e\u5b58\u50a8\u3002 \u5982\u679c\u9700\u8981\u591a\u4e2a\u8282\u70b9\u6216\u5bb9\u9519\uff0c\u53ef\u4ee5\u5728\u5c06\u6765\u5b9e\u73b0\u771f\u6b63\u7684\u5206\u5e03\u5f0f\u7f13\u5b58\u89e3\u51b3\u65b9\u6848\u3002")),(0,r.kt)("admonition",{title:"\u5907\u6ce8",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58\u670d\u52a1\u5df2\u7ecf\u9ed8\u8ba4\u6ce8\u518c\uff0c\u65e0\u9700\u624b\u52a8\u8c03\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"services.AddDistributedMemoryCache();")," \u6ce8\u518c\u3002")),(0,r.kt)("h3",{id:"1444-\u5206\u5e03\u5f0f-sql-server-\u7f13\u5b58"},"14.4.4 \u5206\u5e03\u5f0f SQL Server \u7f13\u5b58"),(0,r.kt)("p",null,"\u5206\u5e03\u5f0f ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u7f13\u5b58\u5b9e\u73b0 (",(0,r.kt)("inlineCode",{parentName:"p"},"AddDistributedSqlServerCache"),") \u5141\u8bb8\u5206\u5e03\u5f0f\u7f13\u5b58\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u6570\u636e\u5e93\u4f5c\u4e3a\u5176\u540e\u5907\u5b58\u50a8\u3002"),(0,r.kt)("p",null,"\u82e5\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u5b9e\u4f8b\u4e2d\u521b\u5efa ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u7f13\u5b58\u7684\u9879\u8868\uff0c\u53ef\u4ee5\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"sql-cache")," \u5de5\u5177\u3002 \u8be5\u5de5\u5177\u5c06\u521b\u5efa\u4e00\u4e2a\u8868\uff0c\u5176\u4e2d\u5305\u542b\u6307\u5b9a\u7684\u540d\u79f0\u548c\u67b6\u6784\u3002"),(0,r.kt)("p",null,"\u901a\u8fc7\u8fd0\u884c\u547d\u4ee4 ",(0,r.kt)("inlineCode",{parentName:"p"},"sql-cache create")," \u521b\u5efa\u4e00\u4e2a\u8868\uff0c\u63d0\u4f9b ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u5b9e\u4f8b (Data Source) \u3001\u6570\u636e\u5e93 (Initial Catalog) \u3001\u67b6\u6784 (\u4f8b\u5982) dbo \u548c\u8868\u540d\u79f0\u3002\u4f8b\u5982 ",(0,r.kt)("inlineCode",{parentName:"p"},"TestCache"),"\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},'dotnet sql-cache create "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache\n')),(0,r.kt)("p",null,"\u521b\u5efa\u6210\u529f\u540e\uff0c\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'services.AddDistributedSqlServerCache(options =>\n{\n options.ConnectionString =\n _config["DistCache_ConnectionString"];\n options.SchemaName = "dbo";\n options.TableName = "TestCache";\n});\n')),(0,r.kt)("h3",{id:"1445-\u5206\u5e03\u5f0f-redis-\u7f13\u5b58"},"14.4.5 \u5206\u5e03\u5f0f ",(0,r.kt)("inlineCode",{parentName:"h3"},"Redis")," \u7f13\u5b58"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Redis")," \u662f\u5185\u5b58\u4e2d\u6570\u636e\u5b58\u50a8\u7684\u5f00\u6e90\u6570\u636e\u5b58\u50a8\uff0c\u901a\u5e38\u7528\u4f5c\u5206\u5e03\u5f0f\u7f13\u5b58\u3002\u5728\u4f7f\u7528\u65f6\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"services.AddStackExchangeRedisCache()")," \u4e2d\u6ce8\u518c\u5373\u53ef\u3002"),(0,r.kt)("p",null,"\u8fd9\u91cc\u4e0d\u7ec6\u8bb2 ",(0,r.kt)("inlineCode",{parentName:"p"},"Redis")," \u76f8\u5173\u5185\u5bb9\uff0c\u540e\u7eed\u7ae0\u8282\u4f1a\u4f7f\u7528\u57fa\u672c\u4f8b\u5b50\u6f14\u793a\u3002"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Redis")," \u57fa\u672c\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'services.AddStackExchangeRedisCache(options =>\n{\n // \u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u8fd9\u91cc\u4e5f\u53ef\u4ee5\u8bfb\u53d6\u914d\u7f6e\u6587\u4ef6\n options.Configuration = "192.168.111.134,password=aW1HAyupRKmiZn3Q";\n // \u952e\u540d\u524d\u7f00\n options.InstanceName = "furion_";\n});\n')),(0,r.kt)("h3",{id:"1446-\u5206\u5e03\u5f0f-ncache-\u7f13\u5b58"},"14.4.6 \u5206\u5e03\u5f0f ",(0,r.kt)("inlineCode",{parentName:"h3"},"NCache")," \u7f13\u5b58"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"NCache")," \u662f\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},".Net Core")," \u4e2d\u4ee5\u672c\u673a\u65b9\u5f0f\u5f00\u53d1\u7684\u5f00\u6e90\u5185\u5b58\u4e2d\u5206\u5e03\u5f0f\u7f13\u5b58\u3002 ",(0,r.kt)("inlineCode",{parentName:"p"},"NCache")," \u5728\u672c\u5730\u5de5\u4f5c\u5e76\u914d\u7f6e\u4e3a\u5206\u5e03\u5f0f\u7f13\u5b58\u7fa4\u96c6\uff0c\u9002\u7528\u4e8e\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Azure")," \u6216\u5176\u4ed6\u6258\u7ba1\u5e73\u53f0\u4e0a\u8fd0\u884c\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u3002\n\u82e5\u8981\u5728\u672c\u5730\u8ba1\u7b97\u673a\u4e0a\u5b89\u88c5\u548c\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"NCache"),"\uff0c\u8bf7\u53c2\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://www.alachisoft.com/resources/docs/ncache-oss/getting-started-guide-windows/"},"\u9002\u7528\u4e8e Windows \u7684 NCache \u5165\u95e8\u6307\u5357"),"\u3002"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"NCache")," \u57fa\u672c\u914d\u7f6e\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u5b89\u88c5 ",(0,r.kt)("inlineCode",{parentName:"li"},"Alachisoft.NCache.OpenSource.SDK")," \u5305"),(0,r.kt)("li",{parentName:"ul"},"\u5728 ",(0,r.kt)("a",{parentName:"li",href:"https://www.alachisoft.com/resources/docs/ncache-oss/admin-guide/client-config.html"},"ncconf")," \u4e2d\u914d\u7f6e\u7f13\u5b58\u7fa4\u96c6"),(0,r.kt)("li",{parentName:"ul"},"\u6ce8\u518c ",(0,r.kt)("inlineCode",{parentName:"li"},"NCache")," \u670d\u52a1")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'services.AddNCacheDistributedCache(configuration =>\n{\n configuration.CacheName = "demoClusteredCache";\n configuration.EnableLogs = true;\n configuration.ExceptionsEnabled = true;\n});\n')),(0,r.kt)("h2",{id:"145-\u5206\u5e03\u5f0f\u7f13\u5b58\u4f7f\u7528"},"14.5 \u5206\u5e03\u5f0f\u7f13\u5b58\u4f7f\u7528"),(0,r.kt)("p",null,"\u82e5\u8981\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"IDistributedCache")," \u63a5\u53e3\uff0c\u8bf7 ",(0,r.kt)("inlineCode",{parentName:"p"},"IDistributedCache")," \u901a\u8fc7\u6784\u9020\u51fd\u6570\u4f9d\u8d56\u5173\u7cfb\u6ce8\u5165\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,16,30-33}",showLineNumbers:!0,"":!0,"{5,16,30-33}":!0},'public class IndexModel : PageModel\n{\n private readonly IDistributedCache _cache;\n\n public IndexModel(IDistributedCache cache)\n {\n _cache = cache;\n }\n\n public string CachedTimeUTC { get; set; }\n\n public async Task OnGetAsync()\n {\n CachedTimeUTC = "Cached Time Expired";\n // \u83b7\u53d6\u5206\u5e03\u5f0f\u7f13\u5b58\n var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");\n\n if (encodedCachedTimeUTC != null)\n {\n CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);\n }\n }\n\n public async Task OnPostResetCachedTime()\n {\n var currentTimeUTC = DateTime.UtcNow.ToString();\n byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);\n\n // \u8bbe\u7f6e\u5206\u5e03\u5f0f\u7f13\u5b58\n var options = new DistributedCacheEntryOptions()\n .SetSlidingExpiration(TimeSpan.FromSeconds(20));\n\n await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);\n\n return RedirectToPage();\n }\n}\n')),(0,r.kt)("h2",{id:"146-\u5206\u5e03\u5f0f\u7f13\u5b58\u5efa\u8bae"},"14.6 \u5206\u5e03\u5f0f\u7f13\u5b58\u5efa\u8bae"),(0,r.kt)("p",null,"\u786e\u5b9a ",(0,r.kt)("inlineCode",{parentName:"p"},"IDistributedCache")," \u6700\u9002\u5408\u4f60\u7684\u5e94\u7528\u7684\u5b9e\u73b0\u65f6\uff0c\u8bf7\u8003\u8651\u4ee5\u4e0b\u4e8b\u9879\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u73b0\u6709\u57fa\u7840\u7ed3\u6784"),(0,r.kt)("li",{parentName:"ul"},"\u6027\u80fd\u8981\u6c42"),(0,r.kt)("li",{parentName:"ul"},"\u6210\u672c"),(0,r.kt)("li",{parentName:"ul"},"\u56e2\u961f\u7ecf\u9a8c")),(0,r.kt)("p",null,"\u7f13\u5b58\u89e3\u51b3\u65b9\u6848\u901a\u5e38\u4f9d\u8d56\u4e8e\u5185\u5b58\u4e2d\u7684\u5b58\u50a8\u4ee5\u5feb\u901f\u68c0\u7d22\u7f13\u5b58\u7684\u6570\u636e\uff0c\u4f46\u662f\uff0c\u5185\u5b58\u662f\u6709\u9650\u7684\u8d44\u6e90\uff0c\u5e76\u4e14\u5f88\u6602\u8d35\u3002 \u4ec5\u5c06\u5e38\u7528\u6570\u636e\u5b58\u50a8\u5728\u7f13\u5b58\u4e2d\u3002"),(0,r.kt)("p",null,"\u901a\u5e38\uff0c",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"Redis")," \u7f13\u5b58\u63d0\u4f9b\u6bd4 ",(0,r.kt)("inlineCode",{parentName:"strong"},"SQL Server")," \u7f13\u5b58\u66f4\u9ad8\u7684\u541e\u5410\u91cf\u548c\u66f4\u4f4e\u7684\u5ef6\u8fdf\u3002")," \u4f46\u662f\uff0c\u901a\u5e38\u9700\u8981\u8fdb\u884c\u57fa\u51c6\u6d4b\u8bd5\u6765\u786e\u5b9a\u7f13\u5b58\u7b56\u7565\u7684\u6027\u80fd\u7279\u5f81\u3002"),(0,r.kt)("p",null,"\u5f53 ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u7528\u4f5c\u5206\u5e03\u5f0f\u7f13\u5b58\u540e\u5907\u5b58\u50a8\u65f6\uff0c\u5bf9\u7f13\u5b58\u4f7f\u7528\u540c\u4e00\u6570\u636e\u5e93\uff0c\u5e76\u4e14\u5e94\u7528\u7684\u666e\u901a\u6570\u636e\u5b58\u50a8\u548c\u68c0\u7d22\u4f1a\u5bf9\u8fd9\u4e24\u79cd\u60c5\u51b5\u7684\u6027\u80fd\u4ea7\u751f\u8d1f\u9762\u5f71\u54cd\u3002 \u5efa\u8bae\u4f7f\u7528\u5206\u5e03\u5f0f\u7f13\u5b58\u540e\u5907\u5b58\u50a8\u7684\u4e13\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"SQL Server")," \u5b9e\u4f8b\u3002"),(0,r.kt)("h2",{id:"147-\u53cd\u9988\u4e0e\u5efa\u8bae"},"14.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,r.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,r.kt)("hr",null),(0,r.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"p"},"\u5206\u5e03\u5f0f\u7f13\u5b58")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/distributed?view=aspnetcore-5.0"},"ASP.NET Core - \u5206\u5e03\u5f0f\u7f13\u5b58")," \u7ae0\u8282\u3002")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/093b1cf0.d0ea6525.js b/handbook/build/assets/js/093b1cf0.d0ea6525.js deleted file mode 100644 index 2ca8562850..0000000000 --- a/handbook/build/assets/js/093b1cf0.d0ea6525.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[5786],{1903:function(e,n,t){t.r(n),t.d(n,{assets:function(){return u},contentTitle:function(){return p},default:function(){return k},frontMatter:function(){return l},metadata:function(){return m},toc:function(){return c}});var r=t(3117),o=t(102),a=(t(7294),t(3905)),i=t(1402),s=["components"],l={id:"dbcontext-read-write",title:"9.27 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",sidebar_label:"9.27 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236"},p=void 0,m={unversionedId:"dbcontext-read-write",id:"dbcontext-read-write",title:"9.27 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",description:"",source:"@site/docs/dbcontext-read-write.mdx",sourceDirName:".",slug:"/dbcontext-read-write",permalink:"/furion/docs/dbcontext-read-write",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-read-write.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"dbcontext-read-write",title:"9.27 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",sidebar_label:"9.27 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236"},sidebar:"docs",previous:{title:"9.26 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143 (UnitOfWork)",permalink:"/furion/docs/tran"},next:{title:"9.28 \u5206\u8868\u5206\u5e93",permalink:"/furion/docs/split-db"}},u={},c=[{value:"9.27.1 \u8bfb\u5199\u5206\u79bb",id:"9271-\u8bfb\u5199\u5206\u79bb",level:2},{value:"9.27.1.1 \u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898",id:"92711-\u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898",level:3},{value:"9.27.1.2 \u6ce8\u610f\u4e8b\u9879",id:"92712-\u6ce8\u610f\u4e8b\u9879",level:3},{value:"9.27.2 \u5982\u4f55\u5b9e\u73b0",id:"9272-\u5982\u4f55\u5b9e\u73b0",level:2},{value:"9.27.2.1 \u521b\u5efa \u4e3b\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92721-\u521b\u5efa-\u4e3b\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:3},{value:"9.27.2.2 \u521b\u5efa \u4ece\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92722-\u521b\u5efa-\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:3},{value:"9.27.2.3 \u6ce8\u518c \u4e3b\u4ece\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92723-\u6ce8\u518c-\u4e3b\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:3},{value:"9.27.2.4 \u521b\u5efa Person \u5b9e\u4f53",id:"92724-\u521b\u5efa-person-\u5b9e\u4f53",level:3},{value:"9.27.2.5 \u5c06 Person \u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868",id:"92725-\u5c06-person-\u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868",level:3},{value:"9.27.2.6 \u56fa\u5b9a\u4e3b\u4ece\u5e93\u4f7f\u7528\u4f8b\u5b50",id:"92726-\u56fa\u5b9a\u4e3b\u4ece\u5e93\u4f7f\u7528\u4f8b\u5b50",level:3},{value:"9.27.2.7 \u968f\u673a\u6216 \u81ea\u5b9a\u4e49\u8fd4\u56de\u4ece\u5e93 \u2728",id:"92727-\u968f\u673a\u6216-\u81ea\u5b9a\u4e49\u8fd4\u56de\u4ece\u5e93-",level:3},{value:"9.27.3 \u4e3b\u4ece\u590d\u5236",id:"9273-\u4e3b\u4ece\u590d\u5236",level:2},{value:"9.27.4 \u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f",id:"9274-\u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f",level:2},{value:"9.27.4.1 \u540c\u6b65\u590d\u5236",id:"92741-\u540c\u6b65\u590d\u5236",level:3},{value:"9.27.4.2 \u5f02\u6b65\u590d\u5236",id:"92742-\u5f02\u6b65\u590d\u5236",level:3},{value:"9.27.4.3 \u534a\u540c\u6b65\u590d\u5236",id:"92743-\u534a\u540c\u6b65\u590d\u5236",level:3},{value:"9.27.5 SqlServer \u4e3b\u5e93\u914d\u7f6e",id:"9275-sqlserver-\u4e3b\u5e93\u914d\u7f6e",level:2},{value:"9.27.5.1 \u6dfb\u52a0 \u672c\u5730\u53d1\u5e03",id:"92751-\u6dfb\u52a0-\u672c\u5730\u53d1\u5e03",level:3},{value:"9.27.5.2 \u9009\u62e9 \u5206\u53d1\u670d\u52a1\u5668",id:"92752-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668",level:3},{value:"9.27.5.3 \u542f\u7528 \u4ee3\u7406",id:"92753-\u542f\u7528-\u4ee3\u7406",level:3},{value:"9.27.5.4 \u53d1\u5e03\u6570\u636e\u5e93",id:"92754-\u53d1\u5e03\u6570\u636e\u5e93",level:3},{value:"9.27.5.5 \u5feb\u7167\u53d1\u5e03",id:"92755-\u5feb\u7167\u53d1\u5e03",level:3},{value:"9.27.5.6 \u9009\u62e9\u53d1\u5e03\u9879\u76ee",id:"92756-\u9009\u62e9\u53d1\u5e03\u9879\u76ee",level:3},{value:"9.27.5.7 \u914d\u7f6e\u5206\u53d1\u8ba1\u5212",id:"92757-\u914d\u7f6e\u5206\u53d1\u8ba1\u5212",level:3},{value:"9.27.5.8 \u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e",id:"92758-\u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e",level:3},{value:"9.27.5.9 \u5b8c\u6210\u914d\u7f6e",id:"92759-\u5b8c\u6210\u914d\u7f6e",level:3},{value:"9.27.6 SqlServer \u4ece\u5e93\u914d\u7f6e",id:"9276-sqlserver-\u4ece\u5e93\u914d\u7f6e",level:2},{value:"9.27.6.1 \u6dfb\u52a0 \u672c\u5730\u8ba2\u9605",id:"92761-\u6dfb\u52a0-\u672c\u5730\u8ba2\u9605",level:3},{value:"9.27.6.2 \u9009\u62e9 \u5206\u53d1\u670d\u52a1\u5668",id:"92762-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668",level:3},{value:"9.27.6.3 \u9009\u62e9 \u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e",id:"92763-\u9009\u62e9-\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e",level:3},{value:"9.27.6.4 \u9009\u62e9 \u8ba2\u9605\u6570\u636e\u5e93",id:"92764-\u9009\u62e9-\u8ba2\u9605\u6570\u636e\u5e93",level:3},{value:"9.27.6.5 \u9009\u62e9 \u5206\u53d1\u5b89\u5168\u8bbe\u7f6e",id:"92765-\u9009\u62e9-\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e",level:3},{value:"9.27.6.6 \u9009\u62e9 \u540c\u6b65\u8ba1\u5212",id:"92766-\u9009\u62e9-\u540c\u6b65\u8ba1\u5212",level:3},{value:"9.27.6.7 \u5b8c\u6210\u8ba2\u9605",id:"92767-\u5b8c\u6210\u8ba2\u9605",level:3},{value:"9.27.7 \u5206\u53d1\u5b9a\u4e49\u76d1\u89c6",id:"9277-\u5206\u53d1\u5b9a\u4e49\u76d1\u89c6",level:2},{value:"9.27.8 \u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c",id:"9278-\u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c",level:2},{value:"9.27.9 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9279-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:c};function k(e){var n=e.components,t=(0,o.Z)(e,s);return(0,a.kt)("wrapper",(0,r.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"9271-\u8bfb\u5199\u5206\u79bb"},"9.27.1 \u8bfb\u5199\u5206\u79bb"),(0,a.kt)("p",null,"\u5176\u5b9e\u5c31\u662f\u5c06\u6570\u636e\u5e93\u5206\u4e3a\u4e86\u4e3b\u4ece\u5e93\uff0c\u4e00\u4e2a\u4e3b\u5e93\u7528\u4e8e\u5199\u6570\u636e\uff0c\u591a\u4e2a\u4ece\u5e93\u5b8c\u6210\u8bfb\u6570\u636e\u7684\u64cd\u4f5c\uff0c\u4e3b\u4ece\u5e93\u4e4b\u95f4\u901a\u8fc7\u67d0\u79cd\u673a\u5236\u8fdb\u884c\u6570\u636e\u7684\u540c\u6b65\uff0c\u662f\u4e00\u79cd\u5e38\u89c1\u7684\u6570\u636e\u5e93\u67b6\u6784\u3002"),(0,a.kt)("img",{src:(0,i.Z)("img/readwrite.png"),style:{height:300}}),(0,a.kt)("h3",{id:"92711-\u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898"},"9.27.1.1 \u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898"),(0,a.kt)("p",null,"\u5927\u591a\u6570\u4e92\u8054\u7f51\u4e1a\u52a1\uff0c\u5f80\u5f80\u8bfb\u591a\u5199\u5c11\uff0c\u8fd9\u65f6\u5019\uff0c\u6570\u636e\u5e93\u7684\u8bfb\u4f1a\u9996\u5148\u6210\u4e3a\u6570\u636e\u5e93\u7684\u74f6\u9888\uff0c\u8fd9\u65f6\uff0c\u5982\u679c\u6211\u4eec\u5e0c\u671b\u80fd\u591f\u7ebf\u6027\u7684\u63d0\u5347\u6570\u636e\u5e93\u7684\u8bfb\u6027\u80fd\uff0c\u6d88\u9664\u8bfb\u5199\u9501\u51b2\u7a81\u4ece\u800c\u63d0\u5347\u6570\u636e\u5e93\u7684\u5199\u6027\u80fd\uff0c\u90a3\u4e48\u5c31\u53ef\u4ee5\u4f7f\u7528\u201c\u5206\u7ec4\u67b6\u6784\u201d\uff08\u8bfb\u5199\u5206\u79bb\u67b6\u6784\uff09\u3002"),(0,a.kt)("p",null,"\u7528\u4e00\u53e5\u8bdd\u6982\u62ec\uff0c\u8bfb\u5199\u5206\u79bb\u662f\u7528\u6765\u89e3\u51b3\u6570\u636e\u5e93\u7684\u8bfb\u6027\u80fd\u74f6\u9888\u7684\u3002"),(0,a.kt)("h3",{id:"92712-\u6ce8\u610f\u4e8b\u9879"},"9.27.1.2 \u6ce8\u610f\u4e8b\u9879"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u6570\u636e\u5e93\u8fde\u63a5\u6c60\u8981\u8fdb\u884c\u533a\u5206\uff0c\u54ea\u4e9b\u662f\u8bfb\u8fde\u63a5\u6c60\uff0c\u54ea\u4e2a\u662f\u5199\u8fde\u63a5\u6c60\uff0c\u7814\u53d1\u7684\u96be\u5ea6\u4f1a\u589e\u52a0\uff1b"),(0,a.kt)("li",{parentName:"ul"},"\u4e3a\u4e86\u4fdd\u8bc1\u9ad8\u53ef\u7528\uff0c\u8bfb\u8fde\u63a5\u6c60\u8981\u80fd\u591f\u5b9e\u73b0\u6545\u969c\u81ea\u52a8\u8f6c\u79fb\uff1b"),(0,a.kt)("li",{parentName:"ul"},"\u4e3b\u4ece\u7684\u4e00\u81f4\u6027\u95ee\u9898\u9700\u8981\u8003\u8651\u3002")),(0,a.kt)("h2",{id:"9272-\u5982\u4f55\u5b9e\u73b0"},"9.27.2 \u5982\u4f55\u5b9e\u73b0"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u5728\u6570\u636e\u5e93\u6a21\u5757\u8bbe\u8ba1\u4e4b\u521d\uff0c\u5c31\u8003\u8651\u4e86\u8bfb\u5199\u5206\u79bb\u8fd9\u79cd\u60c5\u51b5\uff0c\u6240\u4ee5\u4ece\u5e95\u5c42\u5c31\u652f\u6301\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u53ca\u8bfb\u5199\u64cd\u4f5c\u65b9\u6cd5\u7ea6\u675f\u3002"),(0,a.kt)("p",null,"\u8bfb\u5199\u5206\u79bb\u64cd\u4f5c\u4e3b\u8981\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IMSRepository")," \u4ed3\u50a8\uff0c\u8be5\u4ed3\u50a8\u5df2\u7ecf\u4e3a\u5f00\u53d1\u8005\u63d0\u4f9b\u65b9\u4fbf\u7684\u64cd\u4f5c\u8c03\u7528\u3002\u5f53\u7136\u4e5f\u53ef\u4ee5\u4e0d\u4f7f\u7528\u8be5\u4ed3\u50a8\u3002"),(0,a.kt)("p",null,"\u4e0b\u9762\u5c31\u7ed9\u5927\u5bb6\u6f14\u793a\u5982\u4f55\u8bfb\u5199\u591a\u5e93\u8bfb\u5199\u64cd\u4f5c\u3002"),(0,a.kt)("h3",{id:"92721-\u521b\u5efa-\u4e3b\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.27.2.1 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u4e3b\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n /// \n /// \u4e3b\u5e93\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n /// \n [AppDbContext("MasterConnectionString")]\n public class MasterDbContext : AppDbContext\n {\n public MasterDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "ConnectionStrings": {\n "MasterConnectionString": "Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;"\n }\n}\n')),(0,a.kt)("h3",{id:"92722-\u521b\u5efa-\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.27.2.2 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u4ece\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11}",showLineNumbers:!0,"":!0,"{11}":!0},'using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n /// \n /// \u4ece\u5e93\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n /// \n [AppDbContext("SlaveConnectionString")]\n public class SlaveDbContext : AppDbContext\n {\n public SlaveDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u9664\u4e86\u9ed8\u8ba4\u6570\u636e\u5e93\u65e0\u9700\u81ea\u5b9a\u4e49 ",(0,a.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668"),"\uff0c\u5176\u4ed6\u6570\u636e\u5e93\u90fd\u9700\u8981\u6709\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002\u5982 ",(0,a.kt)("inlineCode",{parentName:"p"},"SlaveDbContextLocator"))),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u4ece\u5e93\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\uff1a")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8}",showLineNumbers:!0,"":!0,"{8}":!0},"using Furion.DatabaseAccessor;\n\nnamespace Furion.Core\n{\n /// \n /// \u4ece\u5e93\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\n /// \n public class SlaveDbContextLocator : IDbContextLocator\n {\n }\n}\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "ConnectionStrings": {\n "SlaveConnectionString": "Server=localhost;Database=FurSlave;User=sa;Password=000000;MultipleActiveResultSets=True;"\n }\n}\n')),(0,a.kt)("h3",{id:"92723-\u6ce8\u518c-\u4e3b\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.27.2.3 \u6ce8\u518c ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u4e3b\u4ece\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13-14}",showLineNumbers:!0,"":!0,"{13-14}":!0},"using Furion.Core;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppStartup(600)]\n public sealed class FurEntityFrameworkCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddDatabaseAccessor(options =>\n {\n services.AddDbPool();\n services.AddDbPool();\n });\n }\n }\n}\n")),(0,a.kt)("h3",{id:"92724-\u521b\u5efa-person-\u5b9e\u4f53"},"9.27.2.4 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h3"},"Person")," \u5b9e\u4f53"),(0,a.kt)("p",null,"\u7531\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"\u4e3b\u4ece\u5e93")," \u5177\u6709\u76f8\u540c\u7684\u6570\u636e\u5e93\u7ed3\u6784\uff0c\u6240\u4ee5\u5b9e\u4f53\u4e5f\u5fc5\u987b\u58f0\u660e ",(0,a.kt)("inlineCode",{parentName:"p"},"\u4e3b\u4ece\u5e93"),"\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7}",showLineNumbers:!0,"":!0,"{7}":!0},"using Furion.DatabaseAccessor;\nusing System.ComponentModel.DataAnnotations;\nusing System.ComponentModel.DataAnnotations.Schema;\n\nnamespace Furion.Core\n{\n public class Person : IEntity\n {\n /// \n /// \u4e3b\u952eId\n /// \n [Key]\n [DatabaseGenerated(DatabaseGeneratedOption.Identity)]\n public int Id { get; set; }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n\n /// \n /// \u5e74\u9f84\n /// \n public int Age { get; set; }\n }\n}\n")),(0,a.kt)("h3",{id:"92725-\u5c06-person-\u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868"},"9.27.2.5 \u5c06 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Person")," \u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u521b\u5efa\u4e3b\u5e93\u6570\u636e\u5e93\u8868\uff1a")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Add-Migration v0.0.1 -Context MasterDbContext\n")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Update-Database -Context MasterDbContext\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u521b\u5efa\u4ece\u5e93\u6570\u636e\u5e93\u8868\uff1a")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Add-Migration v0.0.1 -Context SlaveDbContext\n")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Update-Database -Context SlaveDbContext\n")),(0,a.kt)("img",{src:(0,i.Z)("img/readwrite1.png")}),(0,a.kt)("img",{src:(0,i.Z)("img/readwrite2.png")}),(0,a.kt)("h3",{id:"92726-\u56fa\u5b9a\u4e3b\u4ece\u5e93\u4f7f\u7528\u4f8b\u5b50"},"9.27.2.6 \u56fa\u5b9a\u4e3b\u4ece\u5e93\u4f7f\u7528\u4f8b\u5b50"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,19,31,40}",showLineNumbers:!0,"":!0,"{13,19,31,40}":!0},'using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing Furion.DynamicApiController;\nusing System.Collections.Generic;\n\nnamespace Furion.Application\n{\n public class PersonService : IDynamicApiController\n {\n /// \n /// \u53ef\u8c03\u914d\u4ed3\u50a8\uff08\u8bfb\u5199\u5206\u79bb\uff09\n /// \n private readonly IMSRepository _msRepository;\n\n /// \n /// \u6784\u9020\u51fd\u6570\u521d\u59cb\u5316\n /// \n /// \n public PersonService(IMSRepository msRepository)\n {\n _msRepository = msRepository;\n }\n\n /// \n /// \u65b0\u589e\u8d70\u4e3b\u5e93\n /// \n /// \n /// \n public void Insert(Person person)\n {\n _msRepository.Master().Insert(person);\n }\n\n /// \n /// \u67e5\u8be2\u8d70\u4ece\u5e93\n /// \n /// \n public List Get()\n {\n return _msRepository.Slave1().AsEnumerable().ToList();\n }\n }\n}\n')),(0,a.kt)("h3",{id:"92727-\u968f\u673a\u6216-\u81ea\u5b9a\u4e49\u8fd4\u56de\u4ece\u5e93-"},"9.27.2.7 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u968f\u673a"),"\u6216 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u81ea\u5b9a\u4e49"),"\u8fd4\u56de\u4ece\u5e93 \u2728"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 2.4.1 + ")," \u7248\u672c\u65b0\u589e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"IMSRepository")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"IMSRepository")," \u4ed3\u50a8\u7c7b\u578b\uff0c\u53ef\u4ee5\u83b7\u53d6\u968f\u673a\u4ed3\u50a8\u6216\u81ea\u5b9a\u4e49\u4ed3\u50a8\u3002\u4f7f\u7528\u4f8b\u5b50\u5982\u4e0b\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u914d\u7f6e \u4e3b\u5e93 ",(0,a.kt)("inlineCode",{parentName:"li"},"[AppDbContext]")," \u7279\u6027\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"SlaveDbContextLocators")," \u5c5e\u6027\uff0c\u53ef\u901a\u8fc7\u6784\u9020\u51fd\u6570\u6700\u540e\u53c2\u6570\u4f20\u5165\uff0c\u5982\uff1a")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6}",showLineNumbers:!0,"":!0,"{6}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite, typeof(\u4ece\u5e93\u5b9a\u4f4d\u56681), typeof(\u4ece\u5e93\u5b9a\u4f4d\u56682), typeof(\u4ece\u5e93\u5b9a\u4f4d\u56683))]\n public class MasterDbContext : AppDbContext\n {\n public MasterDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"li"},"IMSRepository")," \u6216 ",(0,a.kt)("inlineCode",{parentName:"li"},"IMSRepository"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,19,31,40,49-53}",showLineNumbers:!0,"":!0,"{13,19,31,40,49-53}":!0},'using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing Furion.DynamicApiController;\nusing System.Collections.Generic;\n\nnamespace Furion.Application\n{\n public class PersonService : IDynamicApiController\n {\n /// \n /// \u53ef\u8c03\u914d\u4ed3\u50a8\uff08\u8bfb\u5199\u5206\u79bb\uff09\n /// \n private readonly IMSRepository _msRepository; // \u4e0d\u6307\u5b9a\u5b9a\u4f4d\u5668\uff0c\u9ed8\u8ba4\u662f MasterDbContextLocator\n\n /// \n /// \u6784\u9020\u51fd\u6570\u521d\u59cb\u5316\n /// \n /// \n public PersonService(IMSRepository msRepository)\n {\n _msRepository = msRepository;\n }\n\n /// \n /// \u65b0\u589e\u8d70\u4e3b\u5e93\n /// \n /// \n /// \n public void Insert(Person person)\n {\n _msRepository.Master().Insert(person);\n }\n\n /// \n /// \u968f\u673a\u4ece\u5e93\n /// \n /// \n public List Get()\n {\n return _msRepository.Slave().AsEnumerable().ToList();\n }\n\n /// \n /// \u81ea\u5b9a\u4e49\u4ece\u5e93\n /// \n /// \n public List Get()\n {\n return _msRepository.Slave(() => {\n // \u8fd9\u91cc\u5199\u4f60\u7684\u903b\u8f91\u8fd4\u56de\u4ece\u5e93\u5b9a\u4f4d\u5668\n\n return \u4f60\u7684\u4ece\u5e93\u5b9a\u4f4d\u5668;\n }).AsEnumerable().ToList();\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"IMSRepository")," \u4e0d\u5e26\u6cdb\u578b\u9ed8\u8ba4\u6307\u7684\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"IMSRepository"),"\uff0c\u5982\u9700\u6cdb\u578b\u7248\u672c\uff0c\u5219\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IMSRepository<\u5b9a\u4f4d\u5668>"))),(0,a.kt)("h2",{id:"9273-\u4e3b\u4ece\u590d\u5236"},"9.27.3 \u4e3b\u4ece\u590d\u5236"),(0,a.kt)("p",null,"\u4e3b\u4ece\u590d\u5236\uff1a\u662f\u4e00\u79cd\u6570\u636e\u5907\u4efd\u7684\u65b9\u6848\u3002"),(0,a.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u662f\u4f7f\u7528\u4e24\u4e2a\u6216\u4e24\u4e2a\u4ee5\u4e0a\u76f8\u540c\u7684\u6570\u636e\u5e93\uff0c\u5c06\u4e00\u4e2a\u6570\u636e\u5e93\u5f53\u505a\u4e3b\u6570\u636e\u5e93\uff0c\u800c\u53e6\u4e00\u4e2a\u6570\u636e\u5e93\u5f53\u505a\u4ece\u6570\u636e\u5e93\u3002",(0,a.kt)("strong",{parentName:"p"},"\u5728\u4e3b\u6570\u636e\u5e93\u4e2d\u8fdb\u884c\u76f8\u5e94\u64cd\u4f5c\u65f6\uff0c\u4ece\u6570\u636e\u5e93\u8bb0\u5f55\u4e0b\u6240\u6709\u4e3b\u6570\u636e\u5e93\u7684\u64cd\u4f5c\uff0c\u4f7f\u5176\u4e8c\u8005\u4e00\u6a21\u4e00\u6837\u3002")),(0,a.kt)("h2",{id:"9274-\u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f"},"9.27.4 \u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f"),(0,a.kt)("h3",{id:"92741-\u540c\u6b65\u590d\u5236"},"9.27.4.1 \u540c\u6b65\u590d\u5236"),(0,a.kt)("p",null,"\u6240\u8c13\u7684\u540c\u6b65\u590d\u5236\uff0c\u610f\u601d\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"Master")," \u7684\u53d8\u5316\uff0c\u5fc5\u987b\u7b49\u5f85 ",(0,a.kt)("inlineCode",{parentName:"p"},"Slave-1\uff0cSlave-2\uff0c...\uff0cSlave-n")," \u5b8c\u6210\u540e\u624d\u80fd\u8fd4\u56de\u3002\n\u8fd9\u6837\uff0c\u663e\u7136\u4e0d\u53ef\u53d6\uff0c\u6bd4\u5982\uff0c\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u524d\u7aef\u9875\u9762\u4e0a\uff0c\u7528\u6237\u589e\u52a0\u4e86\u6761\u8bb0\u5f55\uff0c\u9700\u8981\u7b49\u5f85\u5f88\u957f\u65f6\u95f4\u3002"),(0,a.kt)("h3",{id:"92742-\u5f02\u6b65\u590d\u5236"},"9.27.4.2 \u5f02\u6b65\u590d\u5236"),(0,a.kt)("p",null,"\u5982\u540c AJAX \u8bf7\u6c42\u4e00\u6837\u3002",(0,a.kt)("inlineCode",{parentName:"p"},"Master")," \u53ea\u9700\u8981\u5b8c\u6210\u81ea\u5df1\u7684\u6570\u636e\u5e93\u64cd\u4f5c\u5373\u53ef\u3002\u81f3\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"Slaves")," \u662f\u5426\u6536\u5230\u4e8c\u8fdb\u5236\u65e5\u5fd7\uff0c\u662f\u5426\u5b8c\u6210\u64cd\u4f5c\uff0c\u4e0d\u7528\u5173\u5fc3\u3002",(0,a.kt)("strong",{parentName:"p"},"\uff08\u63a8\u8350\u65b9\u5f0f\uff09")),(0,a.kt)("h3",{id:"92743-\u534a\u540c\u6b65\u590d\u5236"},"9.27.4.3 \u534a\u540c\u6b65\u590d\u5236"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Master")," \u53ea\u4fdd\u8bc1 ",(0,a.kt)("inlineCode",{parentName:"p"},"Slaves")," \u4e2d\u7684\u4e00\u4e2a\u64cd\u4f5c\u6210\u529f\uff0c\u5c31\u8fd4\u56de\uff0c\u5176\u4ed6 ",(0,a.kt)("inlineCode",{parentName:"p"},"Slave")," \u4e0d\u7ba1\u3002"),(0,a.kt)("p",null,"\u4e0b\u9762\u5c06\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"SqlServer")," \u7b80\u5355\u914d\u7f6e\u4e3b\u4ece\u590d\u5236\u529f\u80fd\u3002"),(0,a.kt)("h2",{id:"9275-sqlserver-\u4e3b\u5e93\u914d\u7f6e"},"9.27.5 ",(0,a.kt)("inlineCode",{parentName:"h2"},"SqlServer")," \u4e3b\u5e93\u914d\u7f6e"),(0,a.kt)("h3",{id:"92751-\u6dfb\u52a0-\u672c\u5730\u53d1\u5e03"},"9.27.5.1 \u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u672c\u5730\u53d1\u5e03")),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy1.png")}),(0,a.kt)("h3",{id:"92752-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668"},"9.27.5.2 \u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u670d\u52a1\u5668")),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy2.png")}),(0,a.kt)("h3",{id:"92753-\u542f\u7528-\u4ee3\u7406"},"9.27.5.3 \u542f\u7528 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u4ee3\u7406")),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy3.png")}),(0,a.kt)("h3",{id:"92754-\u53d1\u5e03\u6570\u636e\u5e93"},"9.27.5.4 \u53d1\u5e03\u6570\u636e\u5e93"),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy4.png")}),(0,a.kt)("h3",{id:"92755-\u5feb\u7167\u53d1\u5e03"},"9.27.5.5 \u5feb\u7167\u53d1\u5e03"),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy5.png")}),(0,a.kt)("p",null,"\u5177\u4f53\u9009\u62e9\u4f55\u79cd\u53d1\u5e03\u7c7b\u578b\uff0c\u89c6\u5177\u4f53\u4e1a\u52a1\u573a\u666f\u800c\u5b9a\u3002"),(0,a.kt)("h3",{id:"92756-\u9009\u62e9\u53d1\u5e03\u9879\u76ee"},"9.27.5.6 \u9009\u62e9\u53d1\u5e03\u9879\u76ee"),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy6.png")}),(0,a.kt)("h3",{id:"92757-\u914d\u7f6e\u5206\u53d1\u8ba1\u5212"},"9.27.5.7 \u914d\u7f6e\u5206\u53d1\u8ba1\u5212"),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy7.png")}),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy8.png")}),(0,a.kt)("h3",{id:"92758-\u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e"},"9.27.5.8 \u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e"),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy9.png")}),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy10.png")}),(0,a.kt)("h3",{id:"92759-\u5b8c\u6210\u914d\u7f6e"},"9.27.5.9 \u5b8c\u6210\u914d\u7f6e"),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy11.png")}),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy12.png")}),(0,a.kt)("h2",{id:"9276-sqlserver-\u4ece\u5e93\u914d\u7f6e"},"9.27.6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"SqlServer")," \u4ece\u5e93\u914d\u7f6e"),(0,a.kt)("h3",{id:"92761-\u6dfb\u52a0-\u672c\u5730\u8ba2\u9605"},"9.27.6.1 \u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u672c\u5730\u8ba2\u9605")),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece1.png")}),(0,a.kt)("h3",{id:"92762-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668"},"9.27.6.2 \u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u670d\u52a1\u5668")),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece2.png")}),(0,a.kt)("h3",{id:"92763-\u9009\u62e9-\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e"},"9.27.6.3 \u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e")),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece3.png")}),(0,a.kt)("h3",{id:"92764-\u9009\u62e9-\u8ba2\u9605\u6570\u636e\u5e93"},"9.27.6.4 \u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u8ba2\u9605\u6570\u636e\u5e93")),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece4.png")}),(0,a.kt)("h3",{id:"92765-\u9009\u62e9-\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e"},"9.27.6.5 \u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e")),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece5.png")}),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece6.png")}),(0,a.kt)("h3",{id:"92766-\u9009\u62e9-\u540c\u6b65\u8ba1\u5212"},"9.27.6.6 \u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u540c\u6b65\u8ba1\u5212")),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece7.png")}),(0,a.kt)("h3",{id:"92767-\u5b8c\u6210\u8ba2\u9605"},"9.27.6.7 \u5b8c\u6210\u8ba2\u9605"),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece8.png")}),(0,a.kt)("h2",{id:"9277-\u5206\u53d1\u5b9a\u4e49\u76d1\u89c6"},"9.27.7 \u5206\u53d1\u5b9a\u4e49\u76d1\u89c6"),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece9.png")}),(0,a.kt)("h2",{id:"9278-\u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c"},"9.27.8 \u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c"),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece10.png")}),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece11.png")}),(0,a.kt)("admonition",{title:"\u7279\u522b\u7279\u6027",type:"important"},(0,a.kt)("p",{parentName:"admonition"},'\u4e3b\u4ece\u590d\u5236\u6709\u4e00\u5b9a\u8fdf\u5ef6\u6027\uff0c\u6240\u4ee5\u7cfb\u7edf\u8bbe\u8ba1\u8981\u6709\u4e00\u5b9a\u201c\u5bb9\u5fcd\u6027"\u3002')),(0,a.kt)("h2",{id:"9279-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.27.9 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}k.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return m},kt:function(){return d}});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function i(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var l=r.createContext({}),p=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},m=function(e){var n=p(e.components);return r.createElement(l.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},c=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),c=p(t),d=o,k=c["".concat(l,".").concat(d)]||c[d]||u[d]||a;return t?r.createElement(k,i(i({ref:n},m),{},{components:t})):r.createElement(k,i({ref:n},m))}));function d(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var a=t.length,i=new Array(a);i[0]=c;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:o,i[1]=s;for(var p=2;p=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var l=r.createContext({}),p=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},m=function(e){var n=p(e.components);return r.createElement(l.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},c=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),c=p(t),d=o,k=c["".concat(l,".").concat(d)]||c[d]||u[d]||a;return t?r.createElement(k,i(i({ref:n},m),{},{components:t})):r.createElement(k,i({ref:n},m))}));function d(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var a=t.length,i=new Array(a);i[0]=c;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:o,i[1]=s;for(var p=2;p\u4e3b\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92721-\u521b\u5efa-\u4e3b\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:3},{value:"9.27.2.2 \u521b\u5efa \u4ece\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92722-\u521b\u5efa-\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:3},{value:"9.27.2.3 \u6ce8\u518c \u4e3b\u4ece\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92723-\u6ce8\u518c-\u4e3b\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:3},{value:"9.27.2.4 \u521b\u5efa Person \u5b9e\u4f53",id:"92724-\u521b\u5efa-person-\u5b9e\u4f53",level:3},{value:"9.27.2.5 \u5c06 Person \u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868",id:"92725-\u5c06-person-\u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868",level:3},{value:"9.27.2.6 \u56fa\u5b9a\u4e3b\u4ece\u5e93\u4f7f\u7528\u4f8b\u5b50",id:"92726-\u56fa\u5b9a\u4e3b\u4ece\u5e93\u4f7f\u7528\u4f8b\u5b50",level:3},{value:"9.27.2.7 \u968f\u673a\u6216 \u81ea\u5b9a\u4e49\u8fd4\u56de\u4ece\u5e93 \u2728",id:"92727-\u968f\u673a\u6216-\u81ea\u5b9a\u4e49\u8fd4\u56de\u4ece\u5e93-",level:3},{value:"9.27.3 \u4e3b\u4ece\u590d\u5236",id:"9273-\u4e3b\u4ece\u590d\u5236",level:2},{value:"9.27.4 \u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f",id:"9274-\u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f",level:2},{value:"9.27.4.1 \u540c\u6b65\u590d\u5236",id:"92741-\u540c\u6b65\u590d\u5236",level:3},{value:"9.27.4.2 \u5f02\u6b65\u590d\u5236",id:"92742-\u5f02\u6b65\u590d\u5236",level:3},{value:"9.27.4.3 \u534a\u540c\u6b65\u590d\u5236",id:"92743-\u534a\u540c\u6b65\u590d\u5236",level:3},{value:"9.27.5 SqlServer \u4e3b\u5e93\u914d\u7f6e",id:"9275-sqlserver-\u4e3b\u5e93\u914d\u7f6e",level:2},{value:"9.27.5.1 \u6dfb\u52a0 \u672c\u5730\u53d1\u5e03",id:"92751-\u6dfb\u52a0-\u672c\u5730\u53d1\u5e03",level:3},{value:"9.27.5.2 \u9009\u62e9 \u5206\u53d1\u670d\u52a1\u5668",id:"92752-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668",level:3},{value:"9.27.5.3 \u542f\u7528 \u4ee3\u7406",id:"92753-\u542f\u7528-\u4ee3\u7406",level:3},{value:"9.27.5.4 \u53d1\u5e03\u6570\u636e\u5e93",id:"92754-\u53d1\u5e03\u6570\u636e\u5e93",level:3},{value:"9.27.5.5 \u5feb\u7167\u53d1\u5e03",id:"92755-\u5feb\u7167\u53d1\u5e03",level:3},{value:"9.27.5.6 \u9009\u62e9\u53d1\u5e03\u9879\u76ee",id:"92756-\u9009\u62e9\u53d1\u5e03\u9879\u76ee",level:3},{value:"9.27.5.7 \u914d\u7f6e\u5206\u53d1\u8ba1\u5212",id:"92757-\u914d\u7f6e\u5206\u53d1\u8ba1\u5212",level:3},{value:"9.27.5.8 \u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e",id:"92758-\u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e",level:3},{value:"9.27.5.9 \u5b8c\u6210\u914d\u7f6e",id:"92759-\u5b8c\u6210\u914d\u7f6e",level:3},{value:"9.27.6 SqlServer \u4ece\u5e93\u914d\u7f6e",id:"9276-sqlserver-\u4ece\u5e93\u914d\u7f6e",level:2},{value:"9.27.6.1 \u6dfb\u52a0 \u672c\u5730\u8ba2\u9605",id:"92761-\u6dfb\u52a0-\u672c\u5730\u8ba2\u9605",level:3},{value:"9.27.6.2 \u9009\u62e9 \u5206\u53d1\u670d\u52a1\u5668",id:"92762-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668",level:3},{value:"9.27.6.3 \u9009\u62e9 \u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e",id:"92763-\u9009\u62e9-\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e",level:3},{value:"9.27.6.4 \u9009\u62e9 \u8ba2\u9605\u6570\u636e\u5e93",id:"92764-\u9009\u62e9-\u8ba2\u9605\u6570\u636e\u5e93",level:3},{value:"9.27.6.5 \u9009\u62e9 \u5206\u53d1\u5b89\u5168\u8bbe\u7f6e",id:"92765-\u9009\u62e9-\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e",level:3},{value:"9.27.6.6 \u9009\u62e9 \u540c\u6b65\u8ba1\u5212",id:"92766-\u9009\u62e9-\u540c\u6b65\u8ba1\u5212",level:3},{value:"9.27.6.7 \u5b8c\u6210\u8ba2\u9605",id:"92767-\u5b8c\u6210\u8ba2\u9605",level:3},{value:"9.27.7 \u5206\u53d1\u5b9a\u4e49\u76d1\u89c6",id:"9277-\u5206\u53d1\u5b9a\u4e49\u76d1\u89c6",level:2},{value:"9.27.8 \u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c",id:"9278-\u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c",level:2},{value:"9.27.9 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9279-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:c};function k(e){var n=e.components,t=(0,o.Z)(e,s);return(0,a.kt)("wrapper",(0,r.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"9271-\u8bfb\u5199\u5206\u79bb"},"9.27.1 \u8bfb\u5199\u5206\u79bb"),(0,a.kt)("p",null,"\u5176\u5b9e\u5c31\u662f\u5c06\u6570\u636e\u5e93\u5206\u4e3a\u4e86\u4e3b\u4ece\u5e93\uff0c\u4e00\u4e2a\u4e3b\u5e93\u7528\u4e8e\u5199\u6570\u636e\uff0c\u591a\u4e2a\u4ece\u5e93\u5b8c\u6210\u8bfb\u6570\u636e\u7684\u64cd\u4f5c\uff0c\u4e3b\u4ece\u5e93\u4e4b\u95f4\u901a\u8fc7\u67d0\u79cd\u673a\u5236\u8fdb\u884c\u6570\u636e\u7684\u540c\u6b65\uff0c\u662f\u4e00\u79cd\u5e38\u89c1\u7684\u6570\u636e\u5e93\u67b6\u6784\u3002"),(0,a.kt)("img",{src:(0,i.Z)("img/readwrite.png"),style:{height:300}}),(0,a.kt)("h3",{id:"92711-\u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898"},"9.27.1.1 \u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898"),(0,a.kt)("p",null,"\u5927\u591a\u6570\u4e92\u8054\u7f51\u4e1a\u52a1\uff0c\u5f80\u5f80\u8bfb\u591a\u5199\u5c11\uff0c\u8fd9\u65f6\u5019\uff0c\u6570\u636e\u5e93\u7684\u8bfb\u4f1a\u9996\u5148\u6210\u4e3a\u6570\u636e\u5e93\u7684\u74f6\u9888\uff0c\u8fd9\u65f6\uff0c\u5982\u679c\u6211\u4eec\u5e0c\u671b\u80fd\u591f\u7ebf\u6027\u7684\u63d0\u5347\u6570\u636e\u5e93\u7684\u8bfb\u6027\u80fd\uff0c\u6d88\u9664\u8bfb\u5199\u9501\u51b2\u7a81\u4ece\u800c\u63d0\u5347\u6570\u636e\u5e93\u7684\u5199\u6027\u80fd\uff0c\u90a3\u4e48\u5c31\u53ef\u4ee5\u4f7f\u7528\u201c\u5206\u7ec4\u67b6\u6784\u201d\uff08\u8bfb\u5199\u5206\u79bb\u67b6\u6784\uff09\u3002"),(0,a.kt)("p",null,"\u7528\u4e00\u53e5\u8bdd\u6982\u62ec\uff0c\u8bfb\u5199\u5206\u79bb\u662f\u7528\u6765\u89e3\u51b3\u6570\u636e\u5e93\u7684\u8bfb\u6027\u80fd\u74f6\u9888\u7684\u3002"),(0,a.kt)("h3",{id:"92712-\u6ce8\u610f\u4e8b\u9879"},"9.27.1.2 \u6ce8\u610f\u4e8b\u9879"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u6570\u636e\u5e93\u8fde\u63a5\u6c60\u8981\u8fdb\u884c\u533a\u5206\uff0c\u54ea\u4e9b\u662f\u8bfb\u8fde\u63a5\u6c60\uff0c\u54ea\u4e2a\u662f\u5199\u8fde\u63a5\u6c60\uff0c\u7814\u53d1\u7684\u96be\u5ea6\u4f1a\u589e\u52a0\uff1b"),(0,a.kt)("li",{parentName:"ul"},"\u4e3a\u4e86\u4fdd\u8bc1\u9ad8\u53ef\u7528\uff0c\u8bfb\u8fde\u63a5\u6c60\u8981\u80fd\u591f\u5b9e\u73b0\u6545\u969c\u81ea\u52a8\u8f6c\u79fb\uff1b"),(0,a.kt)("li",{parentName:"ul"},"\u4e3b\u4ece\u7684\u4e00\u81f4\u6027\u95ee\u9898\u9700\u8981\u8003\u8651\u3002")),(0,a.kt)("h2",{id:"9272-\u5982\u4f55\u5b9e\u73b0"},"9.27.2 \u5982\u4f55\u5b9e\u73b0"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u5728\u6570\u636e\u5e93\u6a21\u5757\u8bbe\u8ba1\u4e4b\u521d\uff0c\u5c31\u8003\u8651\u4e86\u8bfb\u5199\u5206\u79bb\u8fd9\u79cd\u60c5\u51b5\uff0c\u6240\u4ee5\u4ece\u5e95\u5c42\u5c31\u652f\u6301\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u53ca\u8bfb\u5199\u64cd\u4f5c\u65b9\u6cd5\u7ea6\u675f\u3002"),(0,a.kt)("p",null,"\u8bfb\u5199\u5206\u79bb\u64cd\u4f5c\u4e3b\u8981\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IMSRepository")," \u4ed3\u50a8\uff0c\u8be5\u4ed3\u50a8\u5df2\u7ecf\u4e3a\u5f00\u53d1\u8005\u63d0\u4f9b\u65b9\u4fbf\u7684\u64cd\u4f5c\u8c03\u7528\u3002\u5f53\u7136\u4e5f\u53ef\u4ee5\u4e0d\u4f7f\u7528\u8be5\u4ed3\u50a8\u3002"),(0,a.kt)("p",null,"\u4e0b\u9762\u5c31\u7ed9\u5927\u5bb6\u6f14\u793a\u5982\u4f55\u8bfb\u5199\u591a\u5e93\u8bfb\u5199\u64cd\u4f5c\u3002"),(0,a.kt)("h3",{id:"92721-\u521b\u5efa-\u4e3b\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.27.2.1 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u4e3b\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n /// \n /// \u4e3b\u5e93\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n /// \n [AppDbContext("MasterConnectionString")]\n public class MasterDbContext : AppDbContext\n {\n public MasterDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "ConnectionStrings": {\n "MasterConnectionString": "Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;"\n }\n}\n')),(0,a.kt)("h3",{id:"92722-\u521b\u5efa-\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.27.2.2 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u4ece\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11}",showLineNumbers:!0,"":!0,"{11}":!0},'using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n /// \n /// \u4ece\u5e93\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n /// \n [AppDbContext("SlaveConnectionString")]\n public class SlaveDbContext : AppDbContext\n {\n public SlaveDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u9664\u4e86\u9ed8\u8ba4\u6570\u636e\u5e93\u65e0\u9700\u81ea\u5b9a\u4e49 ",(0,a.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668"),"\uff0c\u5176\u4ed6\u6570\u636e\u5e93\u90fd\u9700\u8981\u6709\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002\u5982 ",(0,a.kt)("inlineCode",{parentName:"p"},"SlaveDbContextLocator"))),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u4ece\u5e93\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\uff1a")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8}",showLineNumbers:!0,"":!0,"{8}":!0},"using Furion.DatabaseAccessor;\n\nnamespace Furion.Core\n{\n /// \n /// \u4ece\u5e93\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\n /// \n public class SlaveDbContextLocator : IDbContextLocator\n {\n }\n}\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "ConnectionStrings": {\n "SlaveConnectionString": "Server=localhost;Database=FurSlave;User=sa;Password=000000;MultipleActiveResultSets=True;"\n }\n}\n')),(0,a.kt)("h3",{id:"92723-\u6ce8\u518c-\u4e3b\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.27.2.3 \u6ce8\u518c ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u4e3b\u4ece\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13-14}",showLineNumbers:!0,"":!0,"{13-14}":!0},"using Furion.Core;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppStartup(600)]\n public sealed class FurEntityFrameworkCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddDatabaseAccessor(options =>\n {\n services.AddDbPool();\n services.AddDbPool();\n });\n }\n }\n}\n")),(0,a.kt)("h3",{id:"92724-\u521b\u5efa-person-\u5b9e\u4f53"},"9.27.2.4 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h3"},"Person")," \u5b9e\u4f53"),(0,a.kt)("p",null,"\u7531\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"\u4e3b\u4ece\u5e93")," \u5177\u6709\u76f8\u540c\u7684\u6570\u636e\u5e93\u7ed3\u6784\uff0c\u6240\u4ee5\u5b9e\u4f53\u4e5f\u5fc5\u987b\u58f0\u660e ",(0,a.kt)("inlineCode",{parentName:"p"},"\u4e3b\u4ece\u5e93"),"\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7}",showLineNumbers:!0,"":!0,"{7}":!0},"using Furion.DatabaseAccessor;\nusing System.ComponentModel.DataAnnotations;\nusing System.ComponentModel.DataAnnotations.Schema;\n\nnamespace Furion.Core\n{\n public class Person : IEntity\n {\n /// \n /// \u4e3b\u952eId\n /// \n [Key]\n [DatabaseGenerated(DatabaseGeneratedOption.Identity)]\n public int Id { get; set; }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n\n /// \n /// \u5e74\u9f84\n /// \n public int Age { get; set; }\n }\n}\n")),(0,a.kt)("h3",{id:"92725-\u5c06-person-\u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868"},"9.27.2.5 \u5c06 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Person")," \u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u521b\u5efa\u4e3b\u5e93\u6570\u636e\u5e93\u8868\uff1a")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Add-Migration v0.0.1 -Context MasterDbContext\n")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Update-Database -Context MasterDbContext\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u521b\u5efa\u4ece\u5e93\u6570\u636e\u5e93\u8868\uff1a")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Add-Migration v0.0.1 -Context SlaveDbContext\n")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Update-Database -Context SlaveDbContext\n")),(0,a.kt)("img",{src:(0,i.Z)("img/readwrite1.png")}),(0,a.kt)("img",{src:(0,i.Z)("img/readwrite2.png")}),(0,a.kt)("h3",{id:"92726-\u56fa\u5b9a\u4e3b\u4ece\u5e93\u4f7f\u7528\u4f8b\u5b50"},"9.27.2.6 \u56fa\u5b9a\u4e3b\u4ece\u5e93\u4f7f\u7528\u4f8b\u5b50"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,19,31,40}",showLineNumbers:!0,"":!0,"{13,19,31,40}":!0},'using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing Furion.DynamicApiController;\nusing System.Collections.Generic;\n\nnamespace Furion.Application\n{\n public class PersonService : IDynamicApiController\n {\n /// \n /// \u53ef\u8c03\u914d\u4ed3\u50a8\uff08\u8bfb\u5199\u5206\u79bb\uff09\n /// \n private readonly IMSRepository _msRepository;\n\n /// \n /// \u6784\u9020\u51fd\u6570\u521d\u59cb\u5316\n /// \n /// \n public PersonService(IMSRepository msRepository)\n {\n _msRepository = msRepository;\n }\n\n /// \n /// \u65b0\u589e\u8d70\u4e3b\u5e93\n /// \n /// \n /// \n public void Insert(Person person)\n {\n _msRepository.Master().Insert(person);\n }\n\n /// \n /// \u67e5\u8be2\u8d70\u4ece\u5e93\n /// \n /// \n public List Get()\n {\n return _msRepository.Slave1().AsEnumerable().ToList();\n }\n }\n}\n')),(0,a.kt)("h3",{id:"92727-\u968f\u673a\u6216-\u81ea\u5b9a\u4e49\u8fd4\u56de\u4ece\u5e93-"},"9.27.2.7 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u968f\u673a"),"\u6216 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u81ea\u5b9a\u4e49"),"\u8fd4\u56de\u4ece\u5e93 \u2728"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 2.4.1 + ")," \u7248\u672c\u65b0\u589e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"IMSRepository")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"IMSRepository")," \u4ed3\u50a8\u7c7b\u578b\uff0c\u53ef\u4ee5\u83b7\u53d6\u968f\u673a\u4ed3\u50a8\u6216\u81ea\u5b9a\u4e49\u4ed3\u50a8\u3002\u4f7f\u7528\u4f8b\u5b50\u5982\u4e0b\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u914d\u7f6e \u4e3b\u5e93 ",(0,a.kt)("inlineCode",{parentName:"li"},"[AppDbContext]")," \u7279\u6027\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"SlaveDbContextLocators")," \u5c5e\u6027\uff0c\u53ef\u901a\u8fc7\u6784\u9020\u51fd\u6570\u6700\u540e\u53c2\u6570\u4f20\u5165\uff0c\u5982\uff1a")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6}",showLineNumbers:!0,"":!0,"{6}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite, typeof(\u4ece\u5e93\u5b9a\u4f4d\u56681), typeof(\u4ece\u5e93\u5b9a\u4f4d\u56682), typeof(\u4ece\u5e93\u5b9a\u4f4d\u56683))]\n public class MasterDbContext : AppDbContext\n {\n public MasterDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"li"},"IMSRepository")," \u6216 ",(0,a.kt)("inlineCode",{parentName:"li"},"IMSRepository"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,19,31,40,49-53}",showLineNumbers:!0,"":!0,"{13,19,31,40,49-53}":!0},'using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing Furion.DynamicApiController;\nusing System.Collections.Generic;\n\nnamespace Furion.Application\n{\n public class PersonService : IDynamicApiController\n {\n /// \n /// \u53ef\u8c03\u914d\u4ed3\u50a8\uff08\u8bfb\u5199\u5206\u79bb\uff09\n /// \n private readonly IMSRepository _msRepository; // \u4e0d\u6307\u5b9a\u5b9a\u4f4d\u5668\uff0c\u9ed8\u8ba4\u662f MasterDbContextLocator\n\n /// \n /// \u6784\u9020\u51fd\u6570\u521d\u59cb\u5316\n /// \n /// \n public PersonService(IMSRepository msRepository)\n {\n _msRepository = msRepository;\n }\n\n /// \n /// \u65b0\u589e\u8d70\u4e3b\u5e93\n /// \n /// \n /// \n public void Insert(Person person)\n {\n _msRepository.Master().Insert(person);\n }\n\n /// \n /// \u968f\u673a\u4ece\u5e93\n /// \n /// \n public List Get()\n {\n return _msRepository.Slave().AsEnumerable().ToList();\n }\n\n /// \n /// \u81ea\u5b9a\u4e49\u4ece\u5e93\n /// \n /// \n public List Get()\n {\n return _msRepository.Slave(() => {\n // \u8fd9\u91cc\u5199\u4f60\u7684\u903b\u8f91\u8fd4\u56de\u4ece\u5e93\u5b9a\u4f4d\u5668\n\n return \u4f60\u7684\u4ece\u5e93\u5b9a\u4f4d\u5668;\n }).AsEnumerable().ToList();\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"IMSRepository")," \u4e0d\u5e26\u6cdb\u578b\u9ed8\u8ba4\u6307\u7684\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"IMSRepository"),"\uff0c\u5982\u9700\u6cdb\u578b\u7248\u672c\uff0c\u5219\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IMSRepository<\u5b9a\u4f4d\u5668>"))),(0,a.kt)("h2",{id:"9273-\u4e3b\u4ece\u590d\u5236"},"9.27.3 \u4e3b\u4ece\u590d\u5236"),(0,a.kt)("p",null,"\u4e3b\u4ece\u590d\u5236\uff1a\u662f\u4e00\u79cd\u6570\u636e\u5907\u4efd\u7684\u65b9\u6848\u3002"),(0,a.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u662f\u4f7f\u7528\u4e24\u4e2a\u6216\u4e24\u4e2a\u4ee5\u4e0a\u76f8\u540c\u7684\u6570\u636e\u5e93\uff0c\u5c06\u4e00\u4e2a\u6570\u636e\u5e93\u5f53\u505a\u4e3b\u6570\u636e\u5e93\uff0c\u800c\u53e6\u4e00\u4e2a\u6570\u636e\u5e93\u5f53\u505a\u4ece\u6570\u636e\u5e93\u3002",(0,a.kt)("strong",{parentName:"p"},"\u5728\u4e3b\u6570\u636e\u5e93\u4e2d\u8fdb\u884c\u76f8\u5e94\u64cd\u4f5c\u65f6\uff0c\u4ece\u6570\u636e\u5e93\u8bb0\u5f55\u4e0b\u6240\u6709\u4e3b\u6570\u636e\u5e93\u7684\u64cd\u4f5c\uff0c\u4f7f\u5176\u4e8c\u8005\u4e00\u6a21\u4e00\u6837\u3002")),(0,a.kt)("h2",{id:"9274-\u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f"},"9.27.4 \u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f"),(0,a.kt)("h3",{id:"92741-\u540c\u6b65\u590d\u5236"},"9.27.4.1 \u540c\u6b65\u590d\u5236"),(0,a.kt)("p",null,"\u6240\u8c13\u7684\u540c\u6b65\u590d\u5236\uff0c\u610f\u601d\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"Master")," \u7684\u53d8\u5316\uff0c\u5fc5\u987b\u7b49\u5f85 ",(0,a.kt)("inlineCode",{parentName:"p"},"Slave-1\uff0cSlave-2\uff0c...\uff0cSlave-n")," \u5b8c\u6210\u540e\u624d\u80fd\u8fd4\u56de\u3002\n\u8fd9\u6837\uff0c\u663e\u7136\u4e0d\u53ef\u53d6\uff0c\u6bd4\u5982\uff0c\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u524d\u7aef\u9875\u9762\u4e0a\uff0c\u7528\u6237\u589e\u52a0\u4e86\u6761\u8bb0\u5f55\uff0c\u9700\u8981\u7b49\u5f85\u5f88\u957f\u65f6\u95f4\u3002"),(0,a.kt)("h3",{id:"92742-\u5f02\u6b65\u590d\u5236"},"9.27.4.2 \u5f02\u6b65\u590d\u5236"),(0,a.kt)("p",null,"\u5982\u540c AJAX \u8bf7\u6c42\u4e00\u6837\u3002",(0,a.kt)("inlineCode",{parentName:"p"},"Master")," \u53ea\u9700\u8981\u5b8c\u6210\u81ea\u5df1\u7684\u6570\u636e\u5e93\u64cd\u4f5c\u5373\u53ef\u3002\u81f3\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"Slaves")," \u662f\u5426\u6536\u5230\u4e8c\u8fdb\u5236\u65e5\u5fd7\uff0c\u662f\u5426\u5b8c\u6210\u64cd\u4f5c\uff0c\u4e0d\u7528\u5173\u5fc3\u3002",(0,a.kt)("strong",{parentName:"p"},"\uff08\u63a8\u8350\u65b9\u5f0f\uff09")),(0,a.kt)("h3",{id:"92743-\u534a\u540c\u6b65\u590d\u5236"},"9.27.4.3 \u534a\u540c\u6b65\u590d\u5236"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Master")," \u53ea\u4fdd\u8bc1 ",(0,a.kt)("inlineCode",{parentName:"p"},"Slaves")," \u4e2d\u7684\u4e00\u4e2a\u64cd\u4f5c\u6210\u529f\uff0c\u5c31\u8fd4\u56de\uff0c\u5176\u4ed6 ",(0,a.kt)("inlineCode",{parentName:"p"},"Slave")," \u4e0d\u7ba1\u3002"),(0,a.kt)("p",null,"\u4e0b\u9762\u5c06\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"SqlServer")," \u7b80\u5355\u914d\u7f6e\u4e3b\u4ece\u590d\u5236\u529f\u80fd\u3002"),(0,a.kt)("h2",{id:"9275-sqlserver-\u4e3b\u5e93\u914d\u7f6e"},"9.27.5 ",(0,a.kt)("inlineCode",{parentName:"h2"},"SqlServer")," \u4e3b\u5e93\u914d\u7f6e"),(0,a.kt)("h3",{id:"92751-\u6dfb\u52a0-\u672c\u5730\u53d1\u5e03"},"9.27.5.1 \u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u672c\u5730\u53d1\u5e03")),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy1.png")}),(0,a.kt)("h3",{id:"92752-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668"},"9.27.5.2 \u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u670d\u52a1\u5668")),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy2.png")}),(0,a.kt)("h3",{id:"92753-\u542f\u7528-\u4ee3\u7406"},"9.27.5.3 \u542f\u7528 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u4ee3\u7406")),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy3.png")}),(0,a.kt)("h3",{id:"92754-\u53d1\u5e03\u6570\u636e\u5e93"},"9.27.5.4 \u53d1\u5e03\u6570\u636e\u5e93"),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy4.png")}),(0,a.kt)("h3",{id:"92755-\u5feb\u7167\u53d1\u5e03"},"9.27.5.5 \u5feb\u7167\u53d1\u5e03"),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy5.png")}),(0,a.kt)("p",null,"\u5177\u4f53\u9009\u62e9\u4f55\u79cd\u53d1\u5e03\u7c7b\u578b\uff0c\u89c6\u5177\u4f53\u4e1a\u52a1\u573a\u666f\u800c\u5b9a\u3002"),(0,a.kt)("h3",{id:"92756-\u9009\u62e9\u53d1\u5e03\u9879\u76ee"},"9.27.5.6 \u9009\u62e9\u53d1\u5e03\u9879\u76ee"),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy6.png")}),(0,a.kt)("h3",{id:"92757-\u914d\u7f6e\u5206\u53d1\u8ba1\u5212"},"9.27.5.7 \u914d\u7f6e\u5206\u53d1\u8ba1\u5212"),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy7.png")}),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy8.png")}),(0,a.kt)("h3",{id:"92758-\u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e"},"9.27.5.8 \u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e"),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy9.png")}),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy10.png")}),(0,a.kt)("h3",{id:"92759-\u5b8c\u6210\u914d\u7f6e"},"9.27.5.9 \u5b8c\u6210\u914d\u7f6e"),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy11.png")}),(0,a.kt)("img",{src:(0,i.Z)("img/dbcopy12.png")}),(0,a.kt)("h2",{id:"9276-sqlserver-\u4ece\u5e93\u914d\u7f6e"},"9.27.6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"SqlServer")," \u4ece\u5e93\u914d\u7f6e"),(0,a.kt)("h3",{id:"92761-\u6dfb\u52a0-\u672c\u5730\u8ba2\u9605"},"9.27.6.1 \u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u672c\u5730\u8ba2\u9605")),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece1.png")}),(0,a.kt)("h3",{id:"92762-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668"},"9.27.6.2 \u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u670d\u52a1\u5668")),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece2.png")}),(0,a.kt)("h3",{id:"92763-\u9009\u62e9-\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e"},"9.27.6.3 \u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e")),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece3.png")}),(0,a.kt)("h3",{id:"92764-\u9009\u62e9-\u8ba2\u9605\u6570\u636e\u5e93"},"9.27.6.4 \u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u8ba2\u9605\u6570\u636e\u5e93")),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece4.png")}),(0,a.kt)("h3",{id:"92765-\u9009\u62e9-\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e"},"9.27.6.5 \u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e")),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece5.png")}),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece6.png")}),(0,a.kt)("h3",{id:"92766-\u9009\u62e9-\u540c\u6b65\u8ba1\u5212"},"9.27.6.6 \u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u540c\u6b65\u8ba1\u5212")),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece7.png")}),(0,a.kt)("h3",{id:"92767-\u5b8c\u6210\u8ba2\u9605"},"9.27.6.7 \u5b8c\u6210\u8ba2\u9605"),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece8.png")}),(0,a.kt)("h2",{id:"9277-\u5206\u53d1\u5b9a\u4e49\u76d1\u89c6"},"9.27.7 \u5206\u53d1\u5b9a\u4e49\u76d1\u89c6"),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece9.png")}),(0,a.kt)("h2",{id:"9278-\u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c"},"9.27.8 \u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c"),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece10.png")}),(0,a.kt)("img",{src:(0,i.Z)("img/dbrece11.png")}),(0,a.kt)("admonition",{title:"\u7279\u522b\u7279\u6027",type:"important"},(0,a.kt)("p",{parentName:"admonition"},'\u4e3b\u4ece\u590d\u5236\u6709\u4e00\u5b9a\u8fdf\u5ef6\u6027\uff0c\u6240\u4ee5\u7cfb\u7edf\u8bbe\u8ba1\u8981\u6709\u4e00\u5b9a\u201c\u5bb9\u5fcd\u6027"\u3002')),(0,a.kt)("h2",{id:"9279-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.27.9 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/09bd0aa2.79620765.js b/handbook/build/assets/js/09bd0aa2.79620765.js deleted file mode 100644 index 6c28eac94e..0000000000 --- a/handbook/build/assets/js/09bd0aa2.79620765.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[9013],{9162:function(e,t,n){n.r(t),n.d(t,{assets:function(){return p},contentTitle:function(){return u},default:function(){return m},frontMatter:function(){return l},metadata:function(){return s},toc:function(){return c}});var r=n(3117),i=n(102),o=(n(7294),n(3905)),a=["components"],l={id:"dbcontext-filter",title:"9.23 \u5b9e\u4f53/\u5168\u5c40\u67e5\u8be2\u7b5b\u9009\u5668",sidebar_label:"9.23 \u5b9e\u4f53/\u5168\u5c40\u67e5\u8be2\u7b5b\u9009\u5668"},u=void 0,s={unversionedId:"dbcontext-filter",id:"dbcontext-filter",title:"9.23 \u5b9e\u4f53/\u5168\u5c40\u67e5\u8be2\u7b5b\u9009\u5668",description:"9.23.1 \u67e5\u8be2\u7b5b\u9009\u5668",source:"@site/docs/dbcontext-filter.mdx",sourceDirName:".",slug:"/dbcontext-filter",permalink:"/furion/docs/dbcontext-filter",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-filter.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"dbcontext-filter",title:"9.23 \u5b9e\u4f53/\u5168\u5c40\u67e5\u8be2\u7b5b\u9009\u5668",sidebar_label:"9.23 \u5b9e\u4f53/\u5168\u5c40\u67e5\u8be2\u7b5b\u9009\u5668"},sidebar:"docs",previous:{title:"9.22 \u5ba1\u8ba1\u65e5\u5fd7 (Audit)",permalink:"/furion/docs/dbcontext-audit"},next:{title:"9.24 \u6570\u636e\u5e93\u64cd\u4f5c\u62e6\u622a\u5668",permalink:"/furion/docs/dbcontext-Interceptor"}},p={},c=[{value:"9.23.1 \u67e5\u8be2\u7b5b\u9009\u5668",id:"9231-\u67e5\u8be2\u7b5b\u9009\u5668",level:2},{value:"9.23.2 \u591a\u79cd\u7b5b\u9009\u5668\u914d\u7f6e",id:"9232-\u591a\u79cd\u7b5b\u9009\u5668\u914d\u7f6e",level:2},{value:"9.23.2.1 \u5355\u8868\u7b5b\u9009\u5668",id:"92321-\u5355\u8868\u7b5b\u9009\u5668",level:3},{value:"9.23.2.2 \u5168\u5c40\u7b5b\u9009\u5668",id:"92322-\u5168\u5c40\u7b5b\u9009\u5668",level:3},{value:"9.23.3 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9233-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:c};function m(e){var t=e.components,n=(0,i.Z)(e,a);return(0,o.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"9231-\u67e5\u8be2\u7b5b\u9009\u5668"},"9.23.1 \u67e5\u8be2\u7b5b\u9009\u5668"),(0,o.kt)("p",null,"\u901a\u5e38\uff0c\u6211\u4eec\u7cfb\u7edf\u4e2d\u6709\u4e00\u4e9b\u7ef4\u62a4\u5b57\u6bb5\uff0c\u5982 ",(0,o.kt)("inlineCode",{parentName:"p"},"IsDeleted")," \u5b57\u6bb5\uff0c\u8fd9\u4e2a\u5b57\u6bb5\u7528\u6765\u6807\u8bc6\u7528\u6237\u5df2\u7ecf\u5220\u9664\u7684\u6570\u636e\uff0c\u90a3\u4e48\u6211\u4eec\u9700\u8981\u6bcf\u6b21\u67e5\u8be2\u6570\u636e\u7684\u65f6\u5019\u5e26\u4e0a\u8fd9\u4e2a\u5b57\u6bb5\uff0c\u907f\u514d\u67e5\u8be2\u51fa\u4e0d\u8be5\u51fa\u73b0\u7684\u6570\u636e\u3002"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u975e\u5e38\u7075\u6d3b\u65b9\u4fbf\u7684\u5168\u5c40\u67e5\u8be2\u7b5b\u9009\u5668\uff0c\u80fd\u591f\u5e94\u7528\u5230\u6bcf\u4e00\u6b21\u67e5\u8be2\u4e2d\u3002"),(0,o.kt)("h2",{id:"9232-\u591a\u79cd\u7b5b\u9009\u5668\u914d\u7f6e"},"9.23.2 \u591a\u79cd\u7b5b\u9009\u5668\u914d\u7f6e"),(0,o.kt)("h3",{id:"92321-\u5355\u8868\u7b5b\u9009\u5668"},"9.23.2.1 \u5355\u8868\u7b5b\u9009\u5668"),(0,o.kt)("p",null,"\u5355\u8868\u7b5b\u9009\u5668\u5c31\u662f\u53ea\u9488\u5bf9\u7279\u5b9a\u5b9e\u4f53\u8fdb\u884c\u7b5b\u9009\u64cd\u4f5c\uff0c\u4f7f\u7528\u7b80\u5355\uff0c\u53ea\u9700\u8981\u5728\u7ee7\u627f ",(0,o.kt)("inlineCode",{parentName:"p"},"IEntityTypeBuilder")," \u63a5\u53e3\u5e76\u5b9e\u73b0\u5373\u53ef\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8,24}",showLineNumbers:!0,"":!0,"{8,24}":!0},"using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\n\nnamespace Furion.Core\n{\n public class Person : Entity, IEntityTypeBuilder\n {\n public Person()\n {\n CreatedTime = DateTime.Now;\n IsDeleted = false;\n }\n\n public string Name { get; set; }\n\n public int Age { get; set; }\n\n public string Address { get; set; }\n\n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasQueryFilter(u => !u.IsDeleted);\n }\n }\n}\n")),(0,o.kt)("h3",{id:"92322-\u5168\u5c40\u7b5b\u9009\u5668"},"9.23.2.2 \u5168\u5c40\u7b5b\u9009\u5668"),(0,o.kt)("p",null,"\u5168\u5c40\u7b5b\u9009\u5668\u53ef\u4ee5\u914d\u7f6e\u6240\u6709\u5b9e\u4f53\u5e94\u7528\u7b5b\u9009\u5668\u4e2d\uff0c\u65e0\u9700\u4e00\u4e2a\u4e00\u4e2a\u53bb\u914d\u7f6e\u3002\u4f7f\u7528\u65b9\u6cd5\u7a0d\u5fae\u6709\u4e9b\u590d\u6742\uff0c\u9700\u8981\u52a8\u6001\u6784\u5efa ",(0,o.kt)("inlineCode",{parentName:"p"},"Lambda")," \u8868\u8fbe\u5f0f\u3002"),(0,o.kt)("p",null,"\u5b9e\u73b0\u5168\u5c40\u7b5b\u9009\u5668\u4f9d\u8d56\u4e8e ",(0,o.kt)("inlineCode",{parentName:"p"},"IModelBuilderFilter")," \u63a5\u53e3\uff0c\u8be5\u63a5\u53e3\u63d0\u4f9b\u4e24\u4e2a\u65b9\u6cd5\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"OnCreating"),"\uff1a\u5b9e\u4f53\u6784\u5efa\u4e4b\u524d"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"OnCreated"),"\uff1a\u5b9e\u4f53\u6784\u5efa\u4e4b\u540e")),(0,o.kt)("p",null,"\u901a\u8fc7\u5b9e\u73b0\u8fd9\u4e24\u4e2a\u65b9\u6cd5\u5373\u53ef\u914d\u7f6e\u5168\u5c40\u8fc7\u6ee4\u5668\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {10,18-19,21,24}",showLineNumbers:!0,"":!0,"{10,18-19,21,24}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Linq.Expressions;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurionDbContext : AppDbContext, IModelBuilderFilter\n {\n public FurionDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n // \u8bbe\u7f6e\u8f6f\u5220\u9664\u8868\u8fbe\u5f0f\n var fakeDeleteQueryFilterExpression = FakeDeleteQueryFilterExpression(entityBuilder, dbContext);\n if (fakeDeleteQueryFilterExpression == null) return;\n\n entityBuilder.HasQueryFilter(fakeDeleteQueryFilterExpression);\n }\n }\n}\n')),(0,o.kt)("admonition",{title:"\u5c0f\u5efa\u8bae",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u5bf9\u52a8\u6001\u6784\u5efa ",(0,o.kt)("inlineCode",{parentName:"p"},"LambdaExpression")," \u4e0d\u719f\u6089\u7684\u670b\u53cb\uff0c\u53ef\u4ee5\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"System.Linq.Dynamic.Core")," \u5305 ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/zzzprojects/System.Linq.Dynamic.Core"},"https://github.com/zzzprojects/System.Linq.Dynamic.Core"))),(0,o.kt)("h2",{id:"9233-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.23.3 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return p},kt:function(){return m}});var r=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var u=r.createContext({}),s=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p=function(e){var t=s(e.components);return r.createElement(u.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,o=e.originalType,u=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),d=s(n),m=i,f=d["".concat(u,".").concat(m)]||d[m]||c[m]||o;return n?r.createElement(f,a(a({ref:t},p),{},{components:n})):r.createElement(f,a({ref:t},p))}));function m(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=n.length,a=new Array(o);a[0]=d;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:i,a[1]=l;for(var s=2;s=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var u=r.createContext({}),s=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p=function(e){var t=s(e.components);return r.createElement(u.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,o=e.originalType,u=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),d=s(n),m=i,f=d["".concat(u,".").concat(m)]||d[m]||c[m]||o;return n?r.createElement(f,a(a({ref:t},p),{},{components:n})):r.createElement(f,a({ref:t},p))}));function m(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=n.length,a=new Array(o);a[0]=d;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:i,a[1]=l;for(var s=2;s")," \u63a5\u53e3\u5e76\u5b9e\u73b0\u5373\u53ef\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8,24}",showLineNumbers:!0,"":!0,"{8,24}":!0},"using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\n\nnamespace Furion.Core\n{\n public class Person : Entity, IEntityTypeBuilder\n {\n public Person()\n {\n CreatedTime = DateTime.Now;\n IsDeleted = false;\n }\n\n public string Name { get; set; }\n\n public int Age { get; set; }\n\n public string Address { get; set; }\n\n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasQueryFilter(u => !u.IsDeleted);\n }\n }\n}\n")),(0,o.kt)("h3",{id:"92322-\u5168\u5c40\u7b5b\u9009\u5668"},"9.23.2.2 \u5168\u5c40\u7b5b\u9009\u5668"),(0,o.kt)("p",null,"\u5168\u5c40\u7b5b\u9009\u5668\u53ef\u4ee5\u914d\u7f6e\u6240\u6709\u5b9e\u4f53\u5e94\u7528\u7b5b\u9009\u5668\u4e2d\uff0c\u65e0\u9700\u4e00\u4e2a\u4e00\u4e2a\u53bb\u914d\u7f6e\u3002\u4f7f\u7528\u65b9\u6cd5\u7a0d\u5fae\u6709\u4e9b\u590d\u6742\uff0c\u9700\u8981\u52a8\u6001\u6784\u5efa ",(0,o.kt)("inlineCode",{parentName:"p"},"Lambda")," \u8868\u8fbe\u5f0f\u3002"),(0,o.kt)("p",null,"\u5b9e\u73b0\u5168\u5c40\u7b5b\u9009\u5668\u4f9d\u8d56\u4e8e ",(0,o.kt)("inlineCode",{parentName:"p"},"IModelBuilderFilter")," \u63a5\u53e3\uff0c\u8be5\u63a5\u53e3\u63d0\u4f9b\u4e24\u4e2a\u65b9\u6cd5\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"OnCreating"),"\uff1a\u5b9e\u4f53\u6784\u5efa\u4e4b\u524d"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"OnCreated"),"\uff1a\u5b9e\u4f53\u6784\u5efa\u4e4b\u540e")),(0,o.kt)("p",null,"\u901a\u8fc7\u5b9e\u73b0\u8fd9\u4e24\u4e2a\u65b9\u6cd5\u5373\u53ef\u914d\u7f6e\u5168\u5c40\u8fc7\u6ee4\u5668\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {10,18-19,21,24}",showLineNumbers:!0,"":!0,"{10,18-19,21,24}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Linq.Expressions;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurionDbContext : AppDbContext, IModelBuilderFilter\n {\n public FurionDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n // \u8bbe\u7f6e\u8f6f\u5220\u9664\u8868\u8fbe\u5f0f\n var fakeDeleteQueryFilterExpression = FakeDeleteQueryFilterExpression(entityBuilder, dbContext);\n if (fakeDeleteQueryFilterExpression == null) return;\n\n entityBuilder.HasQueryFilter(fakeDeleteQueryFilterExpression);\n }\n }\n}\n')),(0,o.kt)("admonition",{title:"\u5c0f\u5efa\u8bae",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u5bf9\u52a8\u6001\u6784\u5efa ",(0,o.kt)("inlineCode",{parentName:"p"},"LambdaExpression")," \u4e0d\u719f\u6089\u7684\u670b\u53cb\uff0c\u53ef\u4ee5\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"System.Linq.Dynamic.Core")," \u5305 ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/zzzprojects/System.Linq.Dynamic.Core"},"https://github.com/zzzprojects/System.Linq.Dynamic.Core"))),(0,o.kt)("h2",{id:"9233-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.23.3 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/0baa6b13.47423144.js b/handbook/build/assets/js/0baa6b13.47423144.js new file mode 100644 index 0000000000..e50865a5c9 --- /dev/null +++ b/handbook/build/assets/js/0baa6b13.47423144.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[657],{3905:function(e,n,t){t.d(n,{Zo:function(){return p},kt:function(){return m}});var i=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function o(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var c=i.createContext({}),d=function(e){var n=i.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},p=function(e){var n=d(e.components);return i.createElement(c.Provider,{value:n},e.children)},s={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},u=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=d(t),m=r,k=u["".concat(c,".").concat(m)]||u[m]||s[m]||a;return t?i.createElement(k,o(o({ref:n},p),{},{components:t})):i.createElement(k,o({ref:n},p))}));function m(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,o=new Array(a);o[0]=u;var l={};for(var c in n)hasOwnProperty.call(n,c)&&(l[c]=n[c]);l.originalType=e,l.mdxType="string"==typeof e?e:r,o[1]=l;for(var d=2;dInject \u8bbe\u8ba1",id:"241-inject-\u8bbe\u8ba1",level:2},{value:"2.4.2 Inject \u65b9\u6cd5\u6709\u54ea\u4e9b",id:"242-inject-\u65b9\u6cd5\u6709\u54ea\u4e9b",level:2},{value:"2.4.3 \u5728 Program.cs \u4e2d\u4f7f\u7528",id:"243-\u5728-programcs-\u4e2d\u4f7f\u7528",level:2},{value:"2.4.3.1 Inject() \u65b9\u6cd5",id:"2431-inject-\u65b9\u6cd5",level:3},{value:"2.4.4 Startup.ConfigureServices \u4f7f\u7528",id:"244-startupconfigureservices-\u4f7f\u7528",level:2},{value:"2.4.4.1 AddInject() \u65b9\u6cd5",id:"2441-addinject-\u65b9\u6cd5",level:3},{value:"2.4.4.2 AddInjectBase() \u65b9\u6cd5",id:"2442-addinjectbase-\u65b9\u6cd5",level:3},{value:"2.4.4.3 AddInjectMini() \u65b9\u6cd5",id:"2443-addinjectmini-\u65b9\u6cd5",level:3},{value:"2.4.4.4 AddInjectWithUnifyResult() \u65b9\u6cd5",id:"2444-addinjectwithunifyresult-\u65b9\u6cd5",level:3},{value:"2.4.5 Startup.Configure \u4f7f\u7528",id:"245-startupconfigure-\u4f7f\u7528",level:2},{value:"2.4.5.1 UseInject() \u65b9\u6cd5",id:"2451-useinject-\u65b9\u6cd5",level:3},{value:"2.4.5.2 UseInjectBase() \u65b9\u6cd5",id:"2452-useinjectbase-\u65b9\u6cd5",level:3},{value:"2.4.6 \u914d\u7f6e Inject() \u9ed8\u8ba4\u6ce8\u518c\u670d\u52a1",id:"246-\u914d\u7f6e-inject-\u9ed8\u8ba4\u6ce8\u518c\u670d\u52a1",level:2},{value:"2.4.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"247-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],u={toc:s};function m(e){var n=e.components,t=(0,r.Z)(e,o);return(0,a.kt)("wrapper",(0,i.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"241-inject-\u8bbe\u8ba1"},"2.4.1 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Inject")," \u8bbe\u8ba1"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Inject [\u026an\u02c8d\u0292ekt]")," \u610f\u601d\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6ce8\u5165\uff0c\u6ce8\u5c04")," \u7684\u610f\u601d\uff0c\u5728\u8fd9\u91cc\u610f\u4e3a\u4f7f\u7528\u6700\u5c0f\u7684\u4fb5\u5165\u5f0f\u5bf9\u5e94\u7528\u8fdb\u884c\u673a\u80fd\u6539\u9020\u3002"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Inject()")," \u65b9\u6cd5\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u7684\u6700\u5c0f\u4fb5\u5165\u5f0f\u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u8ba9\u4efb\u4f55 ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," Web \u540e\u7aef\u9879\u76ee\u77ac\u95f4\u652f\u6301\u6240\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u7279\u6027\u3002"),(0,a.kt)("h2",{id:"242-inject-\u65b9\u6cd5\u6709\u54ea\u4e9b"},"2.4.2 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Inject")," \u65b9\u6cd5\u6709\u54ea\u4e9b"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Inject()"),"\uff1a\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"Program.cs")," \u4e2d\u6ce8\u518c"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"AddInject()"),"\uff1a\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"ConfigureServices")," \u4e2d\u6ce8\u518c"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"AddInjectBase()"),"\uff1a\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"ConfigureServices")," \u4e2d\u6ce8\u518c"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"AddInjectWithUnifyResult()/ AddInjectWithUnifyResult()"),"\uff1a\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"ConfigureServices")," \u4e2d\u6ce8\u518c"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"AddInjectMini()"),"\uff1a\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"li"},"Minimal API")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"UseInject()"),"\uff1a\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"Configure")," \u4e2d\u6ce8\u518c"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"UseInjectBase()"),"\uff1a\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"Configure")," \u4e2d\u6ce8\u518c")),(0,a.kt)("h2",{id:"243-\u5728-programcs-\u4e2d\u4f7f\u7528"},"2.4.3 \u5728 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Program.cs")," \u4e2d\u4f7f\u7528"),(0,a.kt)("h3",{id:"2431-inject-\u65b9\u6cd5"},"2.4.3.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Inject()")," \u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Inject()")," \u662f\u5728\u542f\u52a8\u7a0b\u5e8f ",(0,a.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u4f7f\u7528\u7684\uff0c\u96c6\u6210 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u552f\u4e00\u65b9\u6cd5\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {6,18} title="Furion.Web.Entry\\Program.cs"',showLineNumbers:!0,"":!0,"{6,18}":!0,title:'"Furion.Web.Entry\\Program.cs"'},"using Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Furion.Web.Entry\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args)\n {\n return Host.CreateDefaultBuilder(args)\n .ConfigureWebHostDefaults(webBuilder =>\n {\n webBuilder.Inject()\n .UseStartup();\n });\n }\n }\n}\n")),(0,a.kt)("h2",{id:"244-startupconfigureservices-\u4f7f\u7528"},"2.4.4 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Startup.ConfigureServices")," \u4f7f\u7528"),(0,a.kt)("h3",{id:"2441-addinject-\u65b9\u6cd5"},"2.4.4.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AddInject()")," \u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AddInject()")," \u65b9\u6cd5\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"ConfigureServices")," \u4e2d\u63d0\u4f9b\u6700\u57fa\u7840\u529f\u80fd\u7684\u6ce8\u518c\u3002"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AddInject()")," \u5305\u542b\u4ee5\u4e0b\u57fa\u7840\u529f\u80fd\u6ce8\u518c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddSpecificationDocuments([options])\n .AddDynamicApiControllers()\n .AddDataValidation()\n .AddFriendlyException();\n")),(0,a.kt)("p",null,"\u4f7f\u7528\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5,7,10}",showLineNumbers:!0,"":!0,"{3,5,7,10}":!0},"namespace Furion.Web.Entry\n{\n public class Startup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddInject(); // \u652f\u6301\u76f4\u63a5\u6ce8\u518c\uff08\u548c\u4e0b\u9762\u4ee3\u7801\u4e8c\u9009\u4e00\uff0c\u4e0d\u80fd\u540c\u65f6\u6ce8\u518c\u4e24\u6b21\uff09\n\n services.AddControllers()\n .AddInject(); // \u652f\u6301\u94fe\u5f0f\u6ce8\u518c\uff08\u548c\u4e0a\u9762\u4ee3\u7801\u4e8c\u9009\u4e00\uff0c\u4e0d\u80fd\u540c\u65f6\u6ce8\u518c\u4e24\u6b21\uff09\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n // \u5176\u4ed6\u4ee3\u7801\n }\n }\n}\n")),(0,a.kt)("h3",{id:"2442-addinjectbase-\u65b9\u6cd5"},"2.4.4.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AddInjectBase()")," \u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AddInjectBase()")," \u65b9\u6cd5\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"ConfigureServices")," \u4e2d\u63d0\u4f9b\u6700\u57fa\u7840\u529f\u80fd\u7684\u6ce8\u518c\u3002"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AddInjectBase()")," \u5305\u542b\u4ee5\u4e0b\u57fa\u7840\u529f\u80fd\u6ce8\u518c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddDataValidation()\n .AddFriendlyException();\n")),(0,a.kt)("p",null,"\u4f7f\u7528\u540c\u4e0a ",(0,a.kt)("inlineCode",{parentName:"p"},"AddInject()"),"\u3002"),(0,a.kt)("h3",{id:"2443-addinjectmini-\u65b9\u6cd5"},"2.4.4.3 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AddInjectMini()")," \u65b9\u6cd5"),(0,a.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 3.7.6 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,a.kt)("p",null,"\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET6")," \u6700\u65b0\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Minimal API")," \u6a21\u5f0f\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"builder.Services.AddInjectMini();\n")),(0,a.kt)("h3",{id:"2444-addinjectwithunifyresult-\u65b9\u6cd5"},"2.4.4.4 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AddInjectWithUnifyResult()")," \u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AddInjectWithUnifyResult()")," \u65b9\u6cd5\u5b9e\u9645\u4e0a\u7b49\u540c\u4e8e\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddInject([swaggerGen])\n .AddUnifyResult();\n")),(0,a.kt)("p",null,"\u4f7f\u7528\u540c\u4e0a ",(0,a.kt)("inlineCode",{parentName:"p"},"AddInject()"),"\u3002"),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u6240\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},".AddInject****()")," \u65b9\u6cd5\u4e0d\u80fd\u540c\u65f6\u6ce8\u518c\uff0c\u53ea\u80fd\u53d6\u5176\u4e00\u3002")),(0,a.kt)("h2",{id:"245-startupconfigure-\u4f7f\u7528"},"2.4.5 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Startup.Configure")," \u4f7f\u7528"),(0,a.kt)("h3",{id:"2451-useinject-\u65b9\u6cd5"},"2.4.5.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"UseInject()")," \u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"UseInject()")," \u65b9\u6cd5\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Configure")," \u4e2d\u63d0\u4f9b\u6700\u57fa\u7840\u529f\u80fd\u7684\u6ce8\u518c\u3002"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"UseInject()")," \u5305\u542b\u4ee5\u4e0b\u57fa\u7840\u529f\u80fd\u6ce8\u518c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"app.UseSpecificationDocuments();\n")),(0,a.kt)("p",null,"\u4f7f\u7528\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5,12}",showLineNumbers:!0,"":!0,"{3,5,12}":!0},"namespace Furion.Web.Entry\n{\n public class Startup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n // \u5176\u4ed6\u4ee3\u7801\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n app.UseInject(); // \u5305\u542b\u6700\u5c0f Swagger \u6ce8\u518c\n }\n }\n}\n")),(0,a.kt)("h3",{id:"2452-useinjectbase-\u65b9\u6cd5"},"2.4.5.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"UseInjectBase()")," \u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"UseInjectBase()")," \u65b9\u6cd5\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Configure")," \u4e2d\u63d0\u4f9b\u6700\u57fa\u7840\u529f\u80fd\u7684\u6ce8\u518c\u3002"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"UseInjectBase()")," \u5b9e\u9645\u4e0a\u662f\u4e2a\u7a7a\u65b9\u6cd5\uff0c\u4e3a\u4e86\u89c4\u8303\u5316\u4ee3\u7801\u7279\u610f\u5efa\u7acb\u7684\u3002"),(0,a.kt)("p",null,"\u4f7f\u7528\u540c\u4e0a ",(0,a.kt)("inlineCode",{parentName:"p"},"UseInject()"),"\u3002"),(0,a.kt)("h2",{id:"246-\u914d\u7f6e-inject-\u9ed8\u8ba4\u6ce8\u518c\u670d\u52a1"},"2.4.6 \u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"h2"},"Inject()")," \u9ed8\u8ba4\u6ce8\u518c\u670d\u52a1"),(0,a.kt)("p",null,"\u6240\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},".Inject")," \u65b9\u6cd5\u90fd\u53ef\u4ee5\u4f20\u5165\u59d4\u6258\uff0c\u901a\u8fc7\u59d4\u6258\u53ef\u4ee5\u8fdb\u4e00\u6b65\u53bb\u914d\u7f6e\u9ed8\u8ba4\u884c\u4e3a\u3002\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},".AddInject(options =>\n{\n options.DataValidation = (d) =>\n {\n d.GlobalEnabled = false;\n };\n\n // ....\n});\n")),(0,a.kt)("h2",{id:"247-\u53cd\u9988\u4e0e\u5efa\u8bae"},"2.4.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/0baa6b13.7c1d3edb.js b/handbook/build/assets/js/0baa6b13.7c1d3edb.js deleted file mode 100644 index cbe9d71684..0000000000 --- a/handbook/build/assets/js/0baa6b13.7c1d3edb.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[657],{6948:function(e,n,t){t.r(n),t.d(n,{assets:function(){return p},contentTitle:function(){return c},default:function(){return m},frontMatter:function(){return l},metadata:function(){return d},toc:function(){return s}});var i=t(3117),r=t(102),a=(t(7294),t(3905)),o=(t(1402),["components"]),l={id:"inject",title:"2.4 \u795e\u5947\u7684 Inject",sidebar_label:"2.4 \u795e\u5947\u7684 Inject"},c=void 0,d={unversionedId:"inject",id:"inject",title:"2.4 \u795e\u5947\u7684 Inject",description:"",source:"@site/docs/inject.mdx",sourceDirName:".",slug:"/inject",permalink:"/furion/docs/inject",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/inject.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1661910514,formattedLastUpdatedAt:"Aug 31, 2022",frontMatter:{id:"inject",title:"2.4 \u795e\u5947\u7684 Inject",sidebar_label:"2.4 \u795e\u5947\u7684 Inject"},sidebar:"docs",previous:{title:"2.3 \u624b\u52a8\u642d\u5efa\u5206\u5c42",permalink:"/furion/docs/reference"},next:{title:"2.5 .NET5 \u5347\u7ea7 .NET6",permalink:"/furion/docs/net5-to-net6"}},p={},s=[{value:"2.4.1 Inject \u8bbe\u8ba1",id:"241-inject-\u8bbe\u8ba1",level:2},{value:"2.4.2 Inject \u65b9\u6cd5\u6709\u54ea\u4e9b",id:"242-inject-\u65b9\u6cd5\u6709\u54ea\u4e9b",level:2},{value:"2.4.3 \u5728 Program.cs \u4e2d\u4f7f\u7528",id:"243-\u5728-programcs-\u4e2d\u4f7f\u7528",level:2},{value:"2.4.3.1 Inject() \u65b9\u6cd5",id:"2431-inject-\u65b9\u6cd5",level:3},{value:"2.4.4 Startup.ConfigureServices \u4f7f\u7528",id:"244-startupconfigureservices-\u4f7f\u7528",level:2},{value:"2.4.4.1 AddInject() \u65b9\u6cd5",id:"2441-addinject-\u65b9\u6cd5",level:3},{value:"2.4.4.2 AddInjectBase() \u65b9\u6cd5",id:"2442-addinjectbase-\u65b9\u6cd5",level:3},{value:"2.4.4.3 AddInjectMini() \u65b9\u6cd5",id:"2443-addinjectmini-\u65b9\u6cd5",level:3},{value:"2.4.4.4 AddInjectWithUnifyResult() \u65b9\u6cd5",id:"2444-addinjectwithunifyresult-\u65b9\u6cd5",level:3},{value:"2.4.5 Startup.Configure \u4f7f\u7528",id:"245-startupconfigure-\u4f7f\u7528",level:2},{value:"2.4.5.1 UseInject() \u65b9\u6cd5",id:"2451-useinject-\u65b9\u6cd5",level:3},{value:"2.4.5.2 UseInjectBase() \u65b9\u6cd5",id:"2452-useinjectbase-\u65b9\u6cd5",level:3},{value:"2.4.6 \u914d\u7f6e Inject() \u9ed8\u8ba4\u6ce8\u518c\u670d\u52a1",id:"246-\u914d\u7f6e-inject-\u9ed8\u8ba4\u6ce8\u518c\u670d\u52a1",level:2},{value:"2.4.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"247-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],u={toc:s};function m(e){var n=e.components,t=(0,r.Z)(e,o);return(0,a.kt)("wrapper",(0,i.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"241-inject-\u8bbe\u8ba1"},"2.4.1 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Inject")," \u8bbe\u8ba1"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Inject [\u026an\u02c8d\u0292ekt]")," \u610f\u601d\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6ce8\u5165\uff0c\u6ce8\u5c04")," \u7684\u610f\u601d\uff0c\u5728\u8fd9\u91cc\u610f\u4e3a\u4f7f\u7528\u6700\u5c0f\u7684\u4fb5\u5165\u5f0f\u5bf9\u5e94\u7528\u8fdb\u884c\u673a\u80fd\u6539\u9020\u3002"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Inject()")," \u65b9\u6cd5\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u7684\u6700\u5c0f\u4fb5\u5165\u5f0f\u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u8ba9\u4efb\u4f55 ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," Web \u540e\u7aef\u9879\u76ee\u77ac\u95f4\u652f\u6301\u6240\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u7279\u6027\u3002"),(0,a.kt)("h2",{id:"242-inject-\u65b9\u6cd5\u6709\u54ea\u4e9b"},"2.4.2 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Inject")," \u65b9\u6cd5\u6709\u54ea\u4e9b"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Inject()"),"\uff1a\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"Program.cs")," \u4e2d\u6ce8\u518c"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"AddInject()"),"\uff1a\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"ConfigureServices")," \u4e2d\u6ce8\u518c"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"AddInjectBase()"),"\uff1a\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"ConfigureServices")," \u4e2d\u6ce8\u518c"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"AddInjectWithUnifyResult()/ AddInjectWithUnifyResult()"),"\uff1a\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"ConfigureServices")," \u4e2d\u6ce8\u518c"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"AddInjectMini()"),"\uff1a\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"li"},"Minimal API")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"UseInject()"),"\uff1a\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"Configure")," \u4e2d\u6ce8\u518c"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"UseInjectBase()"),"\uff1a\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"Configure")," \u4e2d\u6ce8\u518c")),(0,a.kt)("h2",{id:"243-\u5728-programcs-\u4e2d\u4f7f\u7528"},"2.4.3 \u5728 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Program.cs")," \u4e2d\u4f7f\u7528"),(0,a.kt)("h3",{id:"2431-inject-\u65b9\u6cd5"},"2.4.3.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Inject()")," \u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Inject()")," \u662f\u5728\u542f\u52a8\u7a0b\u5e8f ",(0,a.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u4f7f\u7528\u7684\uff0c\u96c6\u6210 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u552f\u4e00\u65b9\u6cd5\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {6,18} title="Furion.Web.Entry\\Program.cs"',showLineNumbers:!0,"":!0,"{6,18}":!0,title:'"Furion.Web.Entry\\Program.cs"'},"using Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Furion.Web.Entry\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args)\n {\n return Host.CreateDefaultBuilder(args)\n .ConfigureWebHostDefaults(webBuilder =>\n {\n webBuilder.Inject()\n .UseStartup();\n });\n }\n }\n}\n")),(0,a.kt)("h2",{id:"244-startupconfigureservices-\u4f7f\u7528"},"2.4.4 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Startup.ConfigureServices")," \u4f7f\u7528"),(0,a.kt)("h3",{id:"2441-addinject-\u65b9\u6cd5"},"2.4.4.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AddInject()")," \u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AddInject()")," \u65b9\u6cd5\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"ConfigureServices")," \u4e2d\u63d0\u4f9b\u6700\u57fa\u7840\u529f\u80fd\u7684\u6ce8\u518c\u3002"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AddInject()")," \u5305\u542b\u4ee5\u4e0b\u57fa\u7840\u529f\u80fd\u6ce8\u518c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddSpecificationDocuments([options])\n .AddDynamicApiControllers()\n .AddDataValidation()\n .AddFriendlyException();\n")),(0,a.kt)("p",null,"\u4f7f\u7528\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5,7,10}",showLineNumbers:!0,"":!0,"{3,5,7,10}":!0},"namespace Furion.Web.Entry\n{\n public class Startup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddInject(); // \u652f\u6301\u76f4\u63a5\u6ce8\u518c\uff08\u548c\u4e0b\u9762\u4ee3\u7801\u4e8c\u9009\u4e00\uff0c\u4e0d\u80fd\u540c\u65f6\u6ce8\u518c\u4e24\u6b21\uff09\n\n services.AddControllers()\n .AddInject(); // \u652f\u6301\u94fe\u5f0f\u6ce8\u518c\uff08\u548c\u4e0a\u9762\u4ee3\u7801\u4e8c\u9009\u4e00\uff0c\u4e0d\u80fd\u540c\u65f6\u6ce8\u518c\u4e24\u6b21\uff09\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n // \u5176\u4ed6\u4ee3\u7801\n }\n }\n}\n")),(0,a.kt)("h3",{id:"2442-addinjectbase-\u65b9\u6cd5"},"2.4.4.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AddInjectBase()")," \u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AddInjectBase()")," \u65b9\u6cd5\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"ConfigureServices")," \u4e2d\u63d0\u4f9b\u6700\u57fa\u7840\u529f\u80fd\u7684\u6ce8\u518c\u3002"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AddInjectBase()")," \u5305\u542b\u4ee5\u4e0b\u57fa\u7840\u529f\u80fd\u6ce8\u518c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddDataValidation()\n .AddFriendlyException();\n")),(0,a.kt)("p",null,"\u4f7f\u7528\u540c\u4e0a ",(0,a.kt)("inlineCode",{parentName:"p"},"AddInject()"),"\u3002"),(0,a.kt)("h3",{id:"2443-addinjectmini-\u65b9\u6cd5"},"2.4.4.3 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AddInjectMini()")," \u65b9\u6cd5"),(0,a.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 3.7.6 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,a.kt)("p",null,"\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET6")," \u6700\u65b0\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Minimal API")," \u6a21\u5f0f\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"builder.Services.AddInjectMini();\n")),(0,a.kt)("h3",{id:"2444-addinjectwithunifyresult-\u65b9\u6cd5"},"2.4.4.4 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AddInjectWithUnifyResult()")," \u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AddInjectWithUnifyResult()")," \u65b9\u6cd5\u5b9e\u9645\u4e0a\u7b49\u540c\u4e8e\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddInject([swaggerGen])\n .AddUnifyResult();\n")),(0,a.kt)("p",null,"\u4f7f\u7528\u540c\u4e0a ",(0,a.kt)("inlineCode",{parentName:"p"},"AddInject()"),"\u3002"),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u6240\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},".AddInject****()")," \u65b9\u6cd5\u4e0d\u80fd\u540c\u65f6\u6ce8\u518c\uff0c\u53ea\u80fd\u53d6\u5176\u4e00\u3002")),(0,a.kt)("h2",{id:"245-startupconfigure-\u4f7f\u7528"},"2.4.5 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Startup.Configure")," \u4f7f\u7528"),(0,a.kt)("h3",{id:"2451-useinject-\u65b9\u6cd5"},"2.4.5.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"UseInject()")," \u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"UseInject()")," \u65b9\u6cd5\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Configure")," \u4e2d\u63d0\u4f9b\u6700\u57fa\u7840\u529f\u80fd\u7684\u6ce8\u518c\u3002"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"UseInject()")," \u5305\u542b\u4ee5\u4e0b\u57fa\u7840\u529f\u80fd\u6ce8\u518c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"app.UseSpecificationDocuments();\n")),(0,a.kt)("p",null,"\u4f7f\u7528\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5,12}",showLineNumbers:!0,"":!0,"{3,5,12}":!0},"namespace Furion.Web.Entry\n{\n public class Startup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n // \u5176\u4ed6\u4ee3\u7801\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n app.UseInject(); // \u5305\u542b\u6700\u5c0f Swagger \u6ce8\u518c\n }\n }\n}\n")),(0,a.kt)("h3",{id:"2452-useinjectbase-\u65b9\u6cd5"},"2.4.5.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"UseInjectBase()")," \u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"UseInjectBase()")," \u65b9\u6cd5\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Configure")," \u4e2d\u63d0\u4f9b\u6700\u57fa\u7840\u529f\u80fd\u7684\u6ce8\u518c\u3002"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"UseInjectBase()")," \u5b9e\u9645\u4e0a\u662f\u4e2a\u7a7a\u65b9\u6cd5\uff0c\u4e3a\u4e86\u89c4\u8303\u5316\u4ee3\u7801\u7279\u610f\u5efa\u7acb\u7684\u3002"),(0,a.kt)("p",null,"\u4f7f\u7528\u540c\u4e0a ",(0,a.kt)("inlineCode",{parentName:"p"},"UseInject()"),"\u3002"),(0,a.kt)("h2",{id:"246-\u914d\u7f6e-inject-\u9ed8\u8ba4\u6ce8\u518c\u670d\u52a1"},"2.4.6 \u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"h2"},"Inject()")," \u9ed8\u8ba4\u6ce8\u518c\u670d\u52a1"),(0,a.kt)("p",null,"\u6240\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},".Inject")," \u65b9\u6cd5\u90fd\u53ef\u4ee5\u4f20\u5165\u59d4\u6258\uff0c\u901a\u8fc7\u59d4\u6258\u53ef\u4ee5\u8fdb\u4e00\u6b65\u53bb\u914d\u7f6e\u9ed8\u8ba4\u884c\u4e3a\u3002\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},".AddInject(options =>\n{\n options.DataValidation = (d) =>\n {\n d.GlobalEnabled = false;\n };\n\n // ....\n});\n")),(0,a.kt)("h2",{id:"247-\u53cd\u9988\u4e0e\u5efa\u8bae"},"2.4.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return p},kt:function(){return m}});var i=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function o(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var c=i.createContext({}),d=function(e){var n=i.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},p=function(e){var n=d(e.components);return i.createElement(c.Provider,{value:n},e.children)},s={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},u=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=d(t),m=r,k=u["".concat(c,".").concat(m)]||u[m]||s[m]||a;return t?i.createElement(k,o(o({ref:n},p),{},{components:t})):i.createElement(k,o({ref:n},p))}));function m(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,o=new Array(a);o[0]=u;var l={};for(var c in n)hasOwnProperty.call(n,c)&&(l[c]=n[c]);l.originalType=e,l.mdxType="string"==typeof e?e:r,o[1]=l;for(var d=2;d child <"+("string"==typeof n.type?n.type:n.type.name)+'>: all children of the component should be , and every should have a unique "value" prop.')})),b=null!=g?g:f.map((function(n){var e=n.props;return{value:e.value,label:e.label,attributes:e.attributes}})),C=(0,r.l)(b,(function(n,e){return n.value===e.value}));if(C.length>0)throw new Error('Docusaurus error: Duplicate values "'+C.map((function(n){return n.value})).join(", ")+'" found in . Every value needs to be unique.');var O=null===d?d:null!=(e=null!=d?d:null==(t=f.find((function(n){return n.props.default})))?void 0:t.props.value)?e:f[0].props.value;if(null!==O&&!b.some((function(n){return n.value===O})))throw new Error('Docusaurus error: The has a defaultValue "'+O+'" but none of its children has the corresponding value. Available values are: '+b.map((function(n){return n.value})).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");var v=(0,l.U)(),h=v.tabGroupChoices,I=v.setTabGroupChoices,A=(0,o.useState)(O),y=A[0],T=A[1],w=[],E=(0,s.o5)().blockElementScrollPositionUntilNextRender;if(null!=k){var S=h[k];null!=S&&S!==y&&b.some((function(n){return n.value===S}))&&T(S)}var V=function(n){var e=n.currentTarget,t=w.indexOf(e),i=b[t].value;i!==y&&(E(e),T(i),null!=k&&I(k,String(i)))},L=function(n){var e,t=null;switch(n.key){case"ArrowRight":var i,o=w.indexOf(n.currentTarget)+1;t=null!=(i=w[o])?i:w[0];break;case"ArrowLeft":var a,p=w.indexOf(n.currentTarget)-1;t=null!=(a=w[p])?a:w[w.length-1]}null==(e=t)||e.focus()};return o.createElement("div",{className:(0,a.Z)("tabs-container",u)},o.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.Z)("tabs",{"tabs--block":c},N)},b.map((function(n){var e=n.value,t=n.label,p=n.attributes;return o.createElement("li",(0,i.Z)({role:"tab",tabIndex:y===e?0:-1,"aria-selected":y===e,key:e,ref:function(n){return w.push(n)},onKeyDown:L,onFocus:V,onClick:V},p,{className:(0,a.Z)("tabs__item",m,null==p?void 0:p.className,{"tabs__item--active":y===e})}),null!=t?t:e)}))),p?(0,o.cloneElement)(f.filter((function(n){return n.props.value===y}))[0],{className:"margin-top--md"}):o.createElement("div",{className:"margin-top--md"},f.map((function(n,e){return(0,o.cloneElement)(n,{key:e,hidden:n.props.value!==y})}))))}function d(n){var e=(0,p.Z)();return o.createElement(c,(0,i.Z)({key:String(e)},n))}},954:function(n,e,t){t.r(e),t.d(e,{assets:function(){return c},contentTitle:function(){return u},default:function(){return k},frontMatter:function(){return s},metadata:function(){return m},toc:function(){return d}});var i=t(3117),o=t(102),a=(t(7294),t(3905)),p=(t(1402),t(5559)),r=t(433),l=["components"],s={id:"options",title:"4.2 \u9009\u9879",sidebar_label:"4.2 \u9009\u9879"},u=void 0,m={unversionedId:"options",id:"options",title:"4.2 \u9009\u9879",description:"",source:"@site/docs/options.mdx",sourceDirName:".",slug:"/options",permalink:"/furion/docs/options",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/options.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1660201662,formattedLastUpdatedAt:"Aug 11, 2022",frontMatter:{id:"options",title:"4.2 \u9009\u9879",sidebar_label:"4.2 \u9009\u9879"},sidebar:"docs",previous:{title:"4.1 \u914d\u7f6e",permalink:"/furion/docs/configuration"},next:{title:"5.1 \u52a8\u6001 WebAPI",permalink:"/furion/docs/dynamic-api-controller"}},c={},d=[{value:"4.2.1 \u4ec0\u4e48\u662f\u9009\u9879",id:"421-\u4ec0\u4e48\u662f\u9009\u9879",level:2},{value:"4.2.2 \u4e0e\u914d\u7f6e\u7684\u533a\u522b",id:"422-\u4e0e\u914d\u7f6e\u7684\u533a\u522b",level:2},{value:"4.2.3 \u9009\u9879\u7684\u4f7f\u7528",id:"423-\u9009\u9879\u7684\u4f7f\u7528",level:2},{value:"4.2.3.1 \u914d\u7f6e appsettings.json \u4fe1\u606f",id:"4231-\u914d\u7f6e-appsettingsjson-\u4fe1\u606f",level:3},{value:"4.2.3.2 \u521b\u5efa AppInfoOptions \u5f3a\u7c7b\u578b\u7c7b",id:"4232-\u521b\u5efa-appinfooptions-\u5f3a\u7c7b\u578b\u7c7b",level:3},{value:"4.2.3.3 \u6ce8\u518c AppInfoOptions \u670d\u52a1",id:"4233-\u6ce8\u518c-appinfooptions-\u670d\u52a1",level:3},{value:"4.2.3.4 \u8bfb\u53d6 AppInfoOptions \u4fe1\u606f",id:"4234-\u8bfb\u53d6-appinfooptions-\u4fe1\u606f",level:3},{value:"4.2.3.5 \u5982\u4f55\u9009\u62e9\u8bfb\u53d6\u65b9\u5f0f",id:"4235-\u5982\u4f55\u9009\u62e9\u8bfb\u53d6\u65b9\u5f0f",level:3},{value:"4.2.4 \u9009\u9879\u63a5\u53e3\u8bf4\u660e",id:"424-\u9009\u9879\u63a5\u53e3\u8bf4\u660e",level:2},{value:"4.2.5 \u9009\u9879\u81ea\u5b9a\u4e49\u914d\u7f6e",id:"425-\u9009\u9879\u81ea\u5b9a\u4e49\u914d\u7f6e",level:2},{value:"4.2.5.1 \u9009\u9879\u67e5\u627e\u952e\u6d41\u7a0b",id:"4251-\u9009\u9879\u67e5\u627e\u952e\u6d41\u7a0b",level:3},{value:"4.2.6 [OptionsSettings] \u8bf4\u660e",id:"426-optionssettings-\u8bf4\u660e",level:2},{value:"4.2.7 \u9009\u9879\u9a8c\u8bc1",id:"427-\u9009\u9879\u9a8c\u8bc1",level:2},{value:"4.2.8 \u9009\u9879\u540e\u671f\u914d\u7f6e",id:"428-\u9009\u9879\u540e\u671f\u914d\u7f6e",level:2},{value:"4.2.9 \u9009\u9879\u66f4\u6539\u901a\u77e5\uff08\u70ed\u66f4\u65b0\uff09",id:"429-\u9009\u9879\u66f4\u6539\u901a\u77e5\u70ed\u66f4\u65b0",level:2},{value:"4.2.10 \u9009\u9879\u7684\u4f18\u7f3a\u70b9",id:"4210-\u9009\u9879\u7684\u4f18\u7f3a\u70b9",level:2},{value:"4.2.11 \u81ea\u5b9a\u4e49\u5c5e\u6027 Key \u6620\u5c04",id:"4211-\u81ea\u5b9a\u4e49\u5c5e\u6027-key-\u6620\u5c04",level:2},{value:"4.2.12 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"4212-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],g={toc:d};function k(n){var e=n.components,t=(0,o.Z)(n,l);return(0,a.kt)("wrapper",(0,i.Z)({},g,t,{components:e,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"421-\u4ec0\u4e48\u662f\u9009\u9879"},"4.2.1 \u4ec0\u4e48\u662f\u9009\u9879"),(0,a.kt)("p",null,"\u9009\u9879\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u63a8\u8350\u7684\u52a8\u6001\u8bfb\u53d6\u914d\u7f6e\u7684\u65b9\u5f0f\uff0c\u8fd9\u79cd\u65b9\u5f0f\u5c06\u914d\u7f6e\u6587\u4ef6\u6570\u636e\u7528\u4e00\u4e2a",(0,a.kt)("strong",{parentName:"p"},"\u5f3a\u7c7b\u578b"),"\u6765\u6258\u7ba1\uff0c\u80fd\u591f\u5b9e\u73b0\u914d\u7f6e\u9a8c\u8bc1\u3001\u9ed8\u8ba4\u503c\u914d\u7f6e\u3001\u5b9e\u65f6\u8bfb\u53d6\u7b49\u529f\u80fd\u3002"),(0,a.kt)("h2",{id:"422-\u4e0e\u914d\u7f6e\u7684\u533a\u522b"},"4.2.2 \u4e0e\u914d\u7f6e\u7684\u533a\u522b"),(0,a.kt)("p",null,"\u9009\u9879\u5b9e\u9645\u4e0a\u4e5f\u662f\u914d\u7f6e\uff0c\u4f46\u5728\u540e\u8005\u7684\u57fa\u7840\u4e0a\u6dfb\u52a0\u4e86\u914d\u7f6e\u9a8c\u8bc1\u3001\u9ed8\u8ba4\u503c/\u540e\u671f\u914d\u7f6e\u8bbe\u5b9a\u53ca\u63d0\u4f9b\u4e86\u591a\u79cd\u63a5\u53e3\u8bfb\u53d6\u914d\u7f6e\u4fe1\u606f\uff0c\u540c\u65f6\u8fd8\u652f\u6301\u4f9b\u914d\u7f6e\u66f4\u6539\u901a\u77e5\u7b49\u5f3a\u5927\u7075\u6d3b\u529f\u80fd\u3002"),(0,a.kt)("p",null,"\u6240\u4ee5\uff0c\u9664\u4e86\u4e00\u6b21\u6027\u8bfb\u53d6\u4f7f\u7528\u7684\u914d\u7f6e\u4ee5\u5916\uff0c\u90fd\u5e94\u8be5\u9009\u7528 ",(0,a.kt)("strong",{parentName:"p"},"\u9009\u9879")," \u66ff\u6362 ",(0,a.kt)("strong",{parentName:"p"},"\u914d\u7f6e"),"\u3002"),(0,a.kt)("admonition",{title:"\u77e5\u8bc6\u5bfc\u822a",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u6709\u5173\u914d\u7f6e\u8bf4\u660e\u53ef\u67e5\u770b\u300a",(0,a.kt)("a",{parentName:"p",href:"/furion/docs/configuration"},"4.1 \u914d\u7f6e"),"\u300b \u7ae0\u8282\u3002")),(0,a.kt)("h2",{id:"423-\u9009\u9879\u7684\u4f7f\u7528"},"4.2.3 \u9009\u9879\u7684\u4f7f\u7528"),(0,a.kt)("p",null,"\u5047\u8bbe\u6211\u4eec\u9700\u8981\u5728\u7cfb\u7edf\u8fd0\u884c\u65f6\u83b7\u53d6",(0,a.kt)("strong",{parentName:"p"},"\u7cfb\u7edf\u540d\u79f0\u3001\u7248\u672c\u53f7\u53ca\u7248\u6743\u4fe1\u606f"),"\uff0c\u8fd9\u4e9b\u4fe1\u606f\u53ef\u80fd\u968f\u65f6\u53d8\u5316\u800c\u4e14\u9700\u8981\u5728\u591a\u4e2a\u5730\u65b9\u4f7f\u7528\u3002\u8fd9\u65f6\u5c31\u9700\u8981\u5c06\u8fd9\u4e9b\u4fe1\u606f\u914d\u7f6e\u8d77\u6765\u3002\u5177\u4f53\u6b65\u9aa4\u5982\u4e0b\uff1a"),(0,a.kt)("h3",{id:"4231-\u914d\u7f6e-appsettingsjson-\u4fe1\u606f"},"4.2.3.1 \u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"h3"},"appsettings.json")," \u4fe1\u606f"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-6}",showLineNumbers:!0,"":!0,"{2-6}":!0},'{\n "AppInfo": {\n "Name": "Furion",\n "Version": "1.0.0",\n "Company": "Baiqian"\n }\n}\n')),(0,a.kt)("h3",{id:"4232-\u521b\u5efa-appinfooptions-\u5f3a\u7c7b\u578b\u7c7b"},"4.2.3.2 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h3"},"AppInfoOptions")," \u5f3a\u7c7b\u578b\u7c7b"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"":!0,"{1,5}":!0},"using Furion.ConfigurableOptions;\n\nnamespace Furion.Application\n{\n public class AppInfoOptions : IConfigurableOptions\n {\n public string Name { get; set; }\n public string Version { get; set; }\n public string Company { get; set; }\n }\n}\n")),(0,a.kt)("admonition",{title:"\u6e29\u99a8\u63d0\u793a",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u5efa\u8bae\u6240\u6709\u9009\u9879\u7c7b\u90fd\u5e94\u8be5\u4ee5 ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"Options"))," \u547d\u540d\u7ed3\u5c3e\u3002"),(0,a.kt)("p",{parentName:"admonition"},"\u53e6\u5916\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u7684\u6ce8\u518c\u9009\u9879\u670d\u52a1\u7684\u65b9\u6cd5\uff0c\u53ea\u9700\u8981\u7ee7\u627f ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"IConfigurableOptions"))," \u63a5\u53e3\u5373\u53ef\uff0c\u8be5\u63a5\u53e3\u4f4d\u4e8e ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"Furion.ConfigurableOptions"))," \u547d\u540d\u7a7a\u95f4\u4e0b\u3002")),(0,a.kt)("h3",{id:"4233-\u6ce8\u518c-appinfooptions-\u670d\u52a1"},"4.2.3.3 \u6ce8\u518c ",(0,a.kt)("inlineCode",{parentName:"h3"},"AppInfoOptions")," \u670d\u52a1"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u9009\u9879\u4e0d\u540c\u4e8e\u914d\u7f6e\uff0c\u9700\u5728\u5e94\u7528\u542f\u52a8\u65f6\u6ce8\u518c")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {12} title="Furion.Web.Core\\FurWebCoreStartup.cs"',showLineNumbers:!0,"":!0,"{12}":!0,title:'"Furion.Web.Core\\FurWebCoreStartup.cs"'},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.Web.Core\n{\n [AppStartup(800)]\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddConfigurableOptions();\n }\n }\n}\n")),(0,a.kt)("h3",{id:"4234-\u8bfb\u53d6-appinfooptions-\u4fe1\u606f"},"4.2.3.4 \u8bfb\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AppInfoOptions")," \u4fe1\u606f"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u63d0\u4f9b\u4e86\u591a\u79cd\u8bfb\u53d6\u65b9\u5f0f\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"li"},"App.GetOptions(path)")," \u8bfb\u53d6\uff08",(0,a.kt)("strong",{parentName:"li"},"\u4e0d\u63a8\u8350"),"\uff09"),(0,a.kt)("li",{parentName:"ul"},"\u901a\u8fc7\u4f9d\u8d56\u6ce8\u5165\u4ee5\u4e0b\u5b9e\u4f8b\u8bfb\u53d6\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IOptions")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IOptionsSnapshot")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IOptionsMonitor")))),(0,a.kt)("li",{parentName:"ul"},"\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"li"},"App")," \u9759\u6001\u7c7b\u63d0\u4f9b\u7684\u9759\u6001\u65b9\u6cd5\u83b7\u53d6\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"App.GetOptions()")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"App.GetOptionsMonitor()")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"App.GetOptionsSnapshot()"))))),(0,a.kt)(p.Z,{defaultValue:"App.GetOptions(path)",values:[{label:"App.GetOptions(path)",value:"App.GetOptions(path)"},{label:"\u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f",value:"\u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f"},{label:"App.GetOptions()",value:"App.GetOptions()"}],mdxType:"Tabs"},(0,a.kt)(r.Z,{value:"App.GetOptions(path)",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13-16}",showLineNumbers:!0,"":!0,"{13-16}":!0},'using Furion.Application;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n public class DefaultController : ControllerBase\n {\n [HttpGet]\n public string Get()\n {\n // \u4e0d\u63a8\u8350\u91c7\u7528\u6b64\u65b9\u5f0f\u8bfb\u53d6\uff0c\u8be5\u65b9\u5f0f\u4ec5\u5728 ConfigureServices \u542f\u52a8\u65f6\u4f7f\u7528\n var appInfo = App.GetConfig("AppInfo", true);\n return $@"\u540d\u79f0\uff1a{appInfo.Name}\uff0c\n \u7248\u672c\uff1a{appInfo.Version}\uff0c\n \u516c\u53f8\uff1a{appInfo.Company}";\n }\n }\n}\n'))),(0,a.kt)(r.Z,{value:"\u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,15-17,27-29,31-33,35-37}",showLineNumbers:!0,"":!0,"{3,15-17,27-29,31-33,35-37}":!0},'using Furion.Application;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.Extensions.Options;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n public class DefaultController : ControllerBase\n {\n private readonly AppInfoOptions options1;\n private readonly AppInfoOptions options2;\n private readonly AppInfoOptions options3;\n\n public DefaultController(\n IOptions options\n , IOptionsSnapshot optionsSnapshot\n , IOptionsMonitor optionsMonitor)\n {\n options1 = options.Value;\n options2 = optionsSnapshot.Value;\n options3 = optionsMonitor.CurrentValue;\n }\n\n [HttpGet]\n public string Get()\n {\n var info1 = $@"\u540d\u79f0\uff1a{options1.Name}\uff0c\n \u7248\u672c\uff1a{options1.Version}\uff0c\n \u516c\u53f8\uff1a{options1.Company}";\n\n var info2 = $@"\u540d\u79f0\uff1a{options2.Name}\uff0c\n \u7248\u672c\uff1a{options2.Version}\uff0c\n \u516c\u53f8\uff1a{options2.Company}";\n\n var info3 = $@"\u540d\u79f0\uff1a{options3.Name}\uff0c\n \u7248\u672c\uff1a{options3.Version}\uff0c\n \u516c\u53f8\uff1a{options3.Company}";\n\n return $"{info1}-{info2}-{info3}";\n }\n }\n}\n'))),(0,a.kt)(r.Z,{value:"App.GetOptions()",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {12-15,17-20,22-25}",showLineNumbers:!0,"":!0,"{12-15,17-20,22-25}":!0},'using Furion.Application;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n public class DefaultController : ControllerBase\n {\n [HttpGet]\n public string Get()\n {\n var options1 = App.GetOptions();\n var info1 = $@"\u540d\u79f0\uff1a{options1.Name}\uff0c\n \u7248\u672c\uff1a{options1.Version}\uff0c\n \u516c\u53f8\uff1a{options1.Company}";\n\n var options2 = App.GetOptionsSnapshot();\n var info2 = $@"\u540d\u79f0\uff1a{options2.Name}\uff0c\n \u7248\u672c\uff1a{options2.Version}\uff0c\n \u516c\u53f8\uff1a{options2.Company}";\n\n var options3 = App.GetOptionsMonitor();\n var info3 = $@"\u540d\u79f0\uff1a{options3.Name}\uff0c\n \u7248\u672c\uff1a{options3.Version}\uff0c\n \u516c\u53f8\uff1a{options3.Company}";\n\n return $"{info1}-{info2}-{info3}";\n }\n }\n}\n')))),(0,a.kt)("h3",{id:"4235-\u5982\u4f55\u9009\u62e9\u8bfb\u53d6\u65b9\u5f0f"},"4.2.3.5 \u5982\u4f55\u9009\u62e9\u8bfb\u53d6\u65b9\u5f0f"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5982\u679c\u9009\u9879\u9700\u8981\u5728\u591a\u4e2a\u5730\u65b9\u4f7f\u7528\uff0c\u5219\u65e0\u8bba\u4efb\u4f55\u65f6\u5019\u90fd\u4e0d\u63a8\u8350\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"li"},"App.GetOptions(path)")),(0,a.kt)("li",{parentName:"ul"},"\u5728\u53ef\u4f9d\u8d56\u6ce8\u5165\u7c7b\u4e2d\uff0c\u4f9d\u8d56\u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"li"},"IOptions[Snapshot|Monitor]")," \u8bfb\u53d6"),(0,a.kt)("li",{parentName:"ul"},"\u5728\u9759\u6001\u7c7b/\u975e\u4f9d\u8d56\u6ce8\u5165\u7c7b\u4e2d\uff0c\u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"li"},"App.GetOptions[Snapshot|Monitor]()")," \u8bfb\u53d6")),(0,a.kt)("h2",{id:"424-\u9009\u9879\u63a5\u53e3\u8bf4\u660e"},"4.2.4 \u9009\u9879\u63a5\u53e3\u8bf4\u660e"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u63d0\u4f9b\u4e86\u591a\u79cd\u8bfb\u53d6\u9009\u9879\u7684\u63a5\u53e3\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IOptions"),"\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u652f\u6301\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u5728\u5e94\u7528\u542f\u52a8\u540e\u8bfb\u53d6\u914d\u7f6e\u6570\u636e"),(0,a.kt)("li",{parentName:"ul"},"\u547d\u540d\u9009\u9879"))),(0,a.kt)("li",{parentName:"ul"},"\u6ce8\u518c\u4e3a\u5355\u4e00\u5b9e\u4f8b\u4e14\u53ef\u4ee5\u6ce8\u5165\u5230\u4efb\u4f55\u670d\u52a1\u751f\u5b58\u671f"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IOptionsSnapshot"),"\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u5728\u6bcf\u6b21\u8bf7\u6c42\u65f6\u5e94\u91cd\u65b0\u8ba1\u7b97\u9009\u9879\u7684\u65b9\u6848\u4e2d\u6709\u7528"),(0,a.kt)("li",{parentName:"ul"},"\u6ce8\u518c\u4e3a\u8303\u56f4\u5185\uff0c\u56e0\u6b64\u65e0\u6cd5\u6ce8\u5165\u5230\u5355\u4e00\u5b9e\u4f8b\u670d\u52a1"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u547d\u540d\u9009\u9879"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IOptionsMonitor"),"\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u7528\u4e8e\u68c0\u7d22\u9009\u9879\u5e76\u7ba1\u7406 TOptions \u5b9e\u4f8b\u7684\u9009\u9879\u901a\u77e5\u3002"),(0,a.kt)("li",{parentName:"ul"},"\u6ce8\u518c\u4e3a\u5355\u4e00\u5b9e\u4f8b\u4e14\u53ef\u4ee5\u6ce8\u5165\u5230\u4efb\u4f55\u670d\u52a1\u751f\u5b58\u671f\u3002"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u66f4\u6539\u901a\u77e5"),(0,a.kt)("li",{parentName:"ul"},"\u547d\u540d\u9009\u9879"),(0,a.kt)("li",{parentName:"ul"},"\u53ef\u91cd\u8f7d\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},"\u9009\u62e9\u6027\u9009\u9879\u5931\u6548 ",(0,a.kt)("inlineCode",{parentName:"li"},"(IOptionsMonitorCache)"))))))),(0,a.kt)("admonition",{title:"\u6ce8\u610f\u4e8b\u9879",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u5728\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IConfigurableOptionsListener")," \u76d1\u542c\u9009\u9879\u540e\uff0c\u5982\u8981\u83b7\u53d6\u6700\u65b0\u7684\u914d\u7f6e\u4fe1\u606f\uff0c\u8bf7\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"App.GetOptionsMonitor()")," \u800c\u4e0d\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"App.GetOptions()"),"\u3002")),(0,a.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u9009\u9879\u63a5\u53e3")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/options?view=aspnetcore-5.0#options-interfaces"},"ASP.NET Core - \u9009\u9879 - \u9009\u9879\u63a5\u53e3")," \u5c0f\u8282\u3002")),(0,a.kt)("h2",{id:"425-\u9009\u9879\u81ea\u5b9a\u4e49\u914d\u7f6e"},"4.2.5 \u9009\u9879\u81ea\u5b9a\u4e49\u914d\u7f6e"),(0,a.kt)("p",null,"\u6211\u4eec\u77e5\u9053\uff0c\u9009\u9879\u5b9e\u9645\u4e0a\u9700\u8981\u548c\u914d\u7f6e\u6587\u4ef6\u7279\u5b9a\u952e\u503c\u6302\u94a9\uff0c\u90a3 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u662f\u5982\u4f55\u51c6\u786e\u7684\u627e\u5230\u914d\u7f6e\u6587\u4ef6\u4e2d\u7684\u952e\u503c\u7684\u5462\uff1f"),(0,a.kt)("h3",{id:"4251-\u9009\u9879\u67e5\u627e\u952e\u6d41\u7a0b"},"4.2.5.1 \u9009\u9879\u67e5\u627e\u952e\u6d41\u7a0b"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u6ca1\u6709\u8d34 ",(0,a.kt)("inlineCode",{parentName:"strong"},"[OptionsSettings]")," \u7279\u6027"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"li"},"Options")," \u7ed3\u5c3e\uff0c\u5219\u53bb\u9664 ",(0,a.kt)("inlineCode",{parentName:"li"},"Options")," \u5b57\u7b26\u4e32"),(0,a.kt)("li",{parentName:"ul"},"\u5426\u5219\u8fd4\u56de ",(0,a.kt)("inlineCode",{parentName:"li"},"\u7c7b\u540d\u79f0")))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u8d34\u4e86 ",(0,a.kt)("inlineCode",{parentName:"strong"},"[OptionsSettings]")," \u7279\u6027"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u5982\u679c\u914d\u7f6e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"li"},"Path")," \u5c5e\u6027\uff0c\u5219\u8fd4\u56de ",(0,a.kt)("inlineCode",{parentName:"li"},"Path")," \u7684\u503c"),(0,a.kt)("li",{parentName:"ul"},"\u5426\u5219\u8fd4\u56de ",(0,a.kt)("inlineCode",{parentName:"li"},"\u7c7b\u540d\u79f0"))))),(0,a.kt)(p.Z,{defaultValue:"non-optionsettings",values:[{label:"\u65e0[OptionsSettings]",value:"non-optionsettings"},{label:"\u6709[OptionsSettings]",value:"has-optionsettings"}],mdxType:"Tabs"},(0,a.kt)(r.Z,{value:"non-optionsettings",mdxType:"TabItem"},(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"li"},"Options")," \u7ed3\u5c3e\uff0c\u5219\u952e\u540d\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"AppInfo"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"public class AppInfoOptions : IConfigurableOptions\n{\n public string Name { get; set; }\n public string Version { get; set; }\n public string Company { get; set; }\n}\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"li"},"Options")," \u7ed3\u5c3e\uff0c\u5219\u952e\u540d\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"AppInfoSettings"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"public class AppInfoSettings : IConfigurableOptions\n{\n public string Name { get; set; }\n public string Version { get; set; }\n public string Company { get; set; }\n}\n"))),(0,a.kt)(r.Z,{value:"has-optionsettings",mdxType:"TabItem"},(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u914d\u7f6e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"li"},"Path")," \u5c5e\u6027\uff0c\u5219\u952e\u540d\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"AppSettings:AppInfo"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'[OptionsSettings("AppSettings:AppInfo")]\npublic class AppInfoOptions : IConfigurableOptions\n{\n public string Name { get; set; }\n public string Version { get; set; }\n public string Company { get; set; }\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u6ca1\u6709\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"li"},"Path")," \u5c5e\u6027\uff0c\uff0c\u5219\u952e\u540d\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"AppInfoSettings"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"[OptionsSettings]\npublic class AppInfoSettings : IConfigurableOptions\n{\n public string Name { get; set; }\n public string Version { get; set; }\n public string Company { get; set; }\n}\n")))),(0,a.kt)("h2",{id:"426-optionssettings-\u8bf4\u660e"},"4.2.6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"[OptionsSettings]")," \u8bf4\u660e"),(0,a.kt)("p",null,"\u9009\u9879\u7c7b\u53ef\u4ee5\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"[OptionsSettings]")," \u6765\u914d\u7f6e\u67e5\u627e\u8def\u5f84\u503c\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Path"),"\uff1a\u5bf9\u5e94\u914d\u7f6e\u6587\u4ef6\u4e2d\u7684\u952e\uff0c\u652f\u6301 ",(0,a.kt)("strong",{parentName:"li"},"\u5206\u5c42\u952e")," \u5b57\u7b26\u4e32\uff0c\u53c2\u89c1\uff1a\u300a",(0,a.kt)("a",{parentName:"li",href:"configuration/#413-%E8%B7%AF%E5%BE%84%E7%AC%A6-%E6%9F%A5%E6%89%BE%E8%8A%82%E7%82%B9"},"4.1 \u914d\u7f6e - 4.1.3 \u8def\u5f84\u7b26 \u67e5\u627e\u8282\u70b9"),"\u300b"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"PostConfigureAll"),"\uff1a\u9009\u9879\u540e\u671f\u914d\u7f6e\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"false"),"\u3002",(0,a.kt)("a",{parentName:"li",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/options?view=aspnetcore-3.1#options-post-configuration"},"ASP.NET Core - \u9009\u9879 - \u9009\u9879\u540e\u671f\u914d\u7f6e"))),(0,a.kt)("h2",{id:"427-\u9009\u9879\u9a8c\u8bc1"},"4.2.7 \u9009\u9879\u9a8c\u8bc1"),(0,a.kt)("p",null,"\u9009\u9879\u652f\u6301\u9a8c\u8bc1\u914d\u7f6e\u6709\u6548\u6027\uff0c\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"services.AddConfigurableOptions()")," \u6ce8\u518c\u9009\u9879\u9ed8\u8ba4\u542f\u7528\u4e86\u9a8c\u8bc1\u652f\u6301\u3002"),(0,a.kt)("p",null,"\u5305\u62ec\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u7279\u6027\u65b9\u5f0f ",(0,a.kt)("inlineCode",{parentName:"li"},"DataAnnotations")),(0,a.kt)("li",{parentName:"ul"},"\u81ea\u5b9a\u4e49\u590d\u6742\u9a8c\u8bc1 ",(0,a.kt)("inlineCode",{parentName:"li"},"IValidateOptions"))),(0,a.kt)(p.Z,{defaultValue:"texin",values:[{label:"\u7279\u6027\u65b9\u5f0f",value:"texin"},{label:"\u590d\u6742\u9a8c\u8bc1",value:"fuza"}],mdxType:"Tabs"},(0,a.kt)(r.Z,{value:"texin",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,8,10,12}",showLineNumbers:!0,"":!0,"{2,8,10,12}":!0},'using Furion.ConfigurableOptions;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Furion.Application\n{\n public class AppInfoOptions : IConfigurableOptions\n {\n [Required(ErrorMessage = "\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a")]\n public string Name { get; set; }\n [Required, RegularExpression(@"^[0-9][0-9\\.]+[0-9]$", ErrorMessage = "\u4e0d\u662f\u6709\u6548\u7684\u7248\u672c\u53f7")]\n public string Version { get; set; }\n [Required, MaxLength(100)]\n public string Company { get; set; }\n }\n}\n'))),(0,a.kt)(r.Z,{value:"fuza",mdxType:"TabItem"},(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u81ea\u5b9a\u4e49\u9a8c\u8bc1\u7c7b ",(0,a.kt)("inlineCode",{parentName:"li"},"AppInfoValidation")," \u5e76\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"li"},"IValidateOptions")," \u63a5\u53e3\uff0c\u540c\u65f6\u5b9e\u73b0 ",(0,a.kt)("inlineCode",{parentName:"li"},"Validate")," \u65b9\u6cd5\u3002")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,6,8,12,15}",showLineNumbers:!0,"":!0,"{1,6,8,12,15}":!0},'using Microsoft.Extensions.Options;\nusing System.Text.RegularExpressions;\n\nnamespace Furion.Application\n{\n public class AppInfoValidation : IValidateOptions\n {\n public ValidateOptionsResult Validate(string name, AppInfoOptions options)\n {\n if (!Regex.IsMatch(options.Version, @"^[0-9][0-9\\.]+[0-9]$"))\n {\n return ValidateOptionsResult.Fail("\u4e0d\u662f\u6709\u6548\u7684\u7248\u672c\u53f7");\n }\n\n return ValidateOptionsResult.Success;\n }\n }\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u9009\u9879\u7c7b\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"li"},"IConfigurableOptions")," \u63a5\u53e3\uff0c\u5e76\u5b9e\u73b0\u8be5\u63a5\u53e3\u3002")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,16-18}",showLineNumbers:!0,"":!0,"{6,16-18}":!0},'using Furion.ConfigurableOptions;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Furion.Application\n{\n public class AppInfoOptions : IConfigurableOptions\n {\n [Required(ErrorMessage = "\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a")]\n public string Name { get; set; }\n [Required]\n public string Version { get; set; }\n [Required, MaxLength(100)]\n public string Company { get; set; }\n\n // \u9009\u9879\u540e\u671f\u914d\u7f6e\n public void PostConfigure(AppInfoOptions options, IConfiguration configuration)\n {\n }\n }\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5b8c\u6574\u4ee3\u7801\u5982\u4e0b\uff1a")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,9,19,25,27,31,34}",showLineNumbers:!0,"":!0,"{4,9,19,25,27,31,34}":!0},'using Furion.ConfigurableOptions;\nusing Microsoft.Extensions.Options;\nusing System.ComponentModel.DataAnnotations;\nusing System.Text.RegularExpressions;\n\nnamespace Furion.Application\n{\n // \u7ee7\u627f IConfigurableOptions \u63a5\u53e3\n public class AppInfoOptions : IConfigurableOptions\n {\n [Required(ErrorMessage = "\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a")]\n public string Name { get; set; }\n [Required]\n public string Version { get; set; }\n [Required, MaxLength(100)]\n public string Company { get; set; }\n\n // \u9009\u9879\u540e\u671f\u914d\u7f6e\n public void PostConfigure(AppInfoOptions options)\n {\n }\n }\n\n // \u521b\u5efa\u81ea\u5b9a\u4e49\u9a8c\u8bc1\u7c7b\n public class AppInfoValidation : IValidateOptions\n {\n public ValidateOptionsResult Validate(string name, AppInfoOptions options)\n {\n if (!Regex.IsMatch(options.Version, @"^[0-9][0-9\\.]+[0-9]$"))\n {\n return ValidateOptionsResult.Fail("\u4e0d\u662f\u6709\u6548\u7684\u7248\u672c\u53f7");\n }\n\n return ValidateOptionsResult.Success;\n }\n }\n}\n')))),(0,a.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"IConfigurableOptions"))," \u7ee7\u627f\u81ea ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"IConfigurableOptions")),"\uff0c\u4e5f\u5c31\u662f\u81ea\u5b9a\u4e49\u590d\u6742\u9a8c\u8bc1\u9ed8\u8ba4\u5177\u6709 ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"PostConfigure(TOptions options)"))," \u9009\u9879\u540e\u671f\u914d\u7f6e\u65b9\u6cd5\u3002\u5173\u4e8e\u300a",(0,a.kt)("a",{parentName:"p",href:"#428-%E9%80%89%E9%A1%B9%E5%90%8E%E6%9C%9F%E9%85%8D%E7%BD%AE"},"4.2.8 \u9009\u9879\u540e\u671f\u914d\u7f6e"),"\u300b\u5c06\u5728\u4e0b\u4e00\u5c0f\u8282\u8bf4\u660e\u3002")),(0,a.kt)("h2",{id:"428-\u9009\u9879\u540e\u671f\u914d\u7f6e"},"4.2.8 \u9009\u9879\u540e\u671f\u914d\u7f6e"),(0,a.kt)("p",null,"\u9009\u9879\u540e\u671f\u914d\u7f6e\u901a\u4fd7\u4e00\u70b9\u6765\u8bf4\uff0c\u53ef\u4ee5\u5728\u8fd0\u884c\u65f6\u89e3\u6790\u503c\u6216\u8bbe\u5b9a\u9ed8\u8ba4\u503c/\u540e\u671f\u914d\u7f6e\u7b49\u3002"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u914d\u7f6e\u9009\u9879\u540e\u671f\u914d\u7f6e\u5f88\u7b80\u5355\uff0c\u53ea\u9700\u8981\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"p"},"IConfigurableOptions")," \u63a5\u53e3\u5e76\u5b9e\u73b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"PostConfigure(TOptions options)")," \u65b9\u6cd5\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,16-21}",showLineNumbers:!0,"":!0,"{7,16-21}":!0},'using Furion.ConfigurableOptions;\nusing Microsoft.Extensions.Configuration;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Furion.Application\n{\n public class AppInfoOptions : IConfigurableOptions\n {\n [Required(ErrorMessage = "\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a")]\n public string Name { get; set; }\n [Required]\n public string Version { get; set; }\n [Required, MaxLength(100)]\n public string Company { get; set; }\n\n public void PostConfigure(AppInfoOptions options, IConfiguration configuration)\n {\n options.Name ??= "Furion";\n options.Version ??= "1.0.0";\n options.Company ??= "Baiqian";\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"IConfigurableOptions"))," \u7ee7\u627f\u81ea ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"IConfigurableOptions")),"\uff0c\u4e5f\u5c31\u662f\u81ea\u5b9a\u4e49\u590d\u6742\u9a8c\u8bc1\u9ed8\u8ba4\u5177\u6709 ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"PostConfigure(TOptions options, IConfiguration configuration)"))," \u9009\u9879\u540e\u671f\u914d\u7f6e\u65b9\u6cd5\u3002")),(0,a.kt)("h2",{id:"429-\u9009\u9879\u66f4\u6539\u901a\u77e5\u70ed\u66f4\u65b0"},"4.2.9 \u9009\u9879\u66f4\u6539\u901a\u77e5\uff08",(0,a.kt)("inlineCode",{parentName:"h2"},"\u70ed\u66f4\u65b0"),"\uff09"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u975e\u5e38\u7b80\u5355\u4e14\u7075\u6d3b\u7684\u65b9\u5f0f\u76d1\u542c\u9009\u9879\u66f4\u6539\uff0c\u4e5f\u5c31\u662f ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"appsettings.json")," \u6216 \u81ea\u5b9a\u4e49\u914d\u7f6e\u6587\u4ef6\u53d1\u751f\u4efb\u4f55\u66f4\u6539\u90fd\u4f1a\u89e6\u53d1\u5904\u7406\u65b9\u6cd5"),"\u3002"),(0,a.kt)("p",null,"\u4f7f\u7528\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700\u8981\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"p"},"IConfigurableOptionsListener")," \u63a5\u53e3\u5e76\u5b9e\u73b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"void OnListener(TOptions options, IConfiguration configuration)")," \u65b9\u6cd5\u5373\u53ef\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,11-15}",showLineNumbers:!0,"":!0,"{5,11-15}":!0},"using Furion.ConfigurableOptions;\n\nnamespace Furion.Application\n{\n public class AppInfoOptions : IConfigurableOptionsListener\n {\n public string Name { get; set; }\n public string Version { get; set; }\n public string Company { get; set; }\n\n public void OnListener(AppInfoOptions options, IConfiguration configuration)\n {\n var name = options.Name; // \u5b9e\u65f6\u7684\u6700\u65b0\u503c\n var version = options.Version; // \u5b9e\u65f6\u7684\u6700\u65b0\u503c\n }\n\n public void PostConfigure(AppInfoOptions options, IConfiguration configuration)\n {\n }\n }\n}\n")),(0,a.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"IConfigurableOptionsListener"))," \u7ee7\u627f\u81ea ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"IConfigurableOptions")),"\u3002")),(0,a.kt)("h2",{id:"4210-\u9009\u9879\u7684\u4f18\u7f3a\u70b9"},"4.2.10 \u9009\u9879\u7684\u4f18\u7f3a\u70b9"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u4f18\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u5f3a\u7c7b\u578b\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},"\u63d0\u4f9b\u591a\u79cd\u8bfb\u53d6\u65b9\u5f0f"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u70ed\u52a0\u8f7d"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u8bbe\u7f6e\u9ed8\u8ba4\u503c/\u540e\u671f\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u5728\u8fd0\u884c\u73af\u5883\u4e2d\u52a8\u6001\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u9a8c\u8bc1\u914d\u7f6e\u6709\u6548\u6027"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u66f4\u6539\u901a\u77e5"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u547d\u540d\u9009\u9879"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u7f3a\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u9700\u8981\u5b9a\u4e49\u5bf9\u5e94\u7c7b\u578b"),(0,a.kt)("li",{parentName:"ul"},"\u9700\u8981\u5728\u542f\u52a8\u65f6\u6ce8\u518c")))),(0,a.kt)("h2",{id:"4211-\u81ea\u5b9a\u4e49\u5c5e\u6027-key-\u6620\u5c04"},"4.2.11 \u81ea\u5b9a\u4e49\u5c5e\u6027 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Key")," \u6620\u5c04"),(0,a.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion v3.4.3+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,a.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u4e2d\u914d\u7f6e\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Key")," \u548c\u9009\u9879\u5b9a\u4e49\u7684\u5c5e\u6027\u540d\u4e0d\u4e00\u6837\uff0c\u8fd9\u65f6\u5019\u5c31\u9700\u8981\u7528\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"[MapSettings]")," \u7279\u6027\u5373\u53ef\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {4}",showLineNumbers:!0,"{4}":!0},'"AppInfo": {\n "Name": "Furion",\n "Version": "1.0.0",\n "Company_Name": "Baiqian"\n}\n')),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6-7}",showLineNumbers:!0,"{6-7}":!0},'public class AppInfoOptions : IConfigurableOptions\n{\n public string Name { get; set; }\n public string Version { get; set; }\n\n [MapSettings("Company_Name")]\n public string Company { get; set; }\n}\n')),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"[MapSettings]")," \u914d\u7f6e\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Key")," \u4f1a\u81ea\u5b9a\u5e94\u7528\u9009\u9879\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Key")," \u4f5c\u4e3a\u8d77\u59cb\u70b9\uff0c\u5982\u5b9e\u9645\u4e0a ",(0,a.kt)("inlineCode",{parentName:"p"},"Company")," \u5c5e\u6027\u5bf9\u5e94\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Key")," \u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"AppInfo:Company_Name"),"\u3002")),(0,a.kt)("h2",{id:"4212-\u53cd\u9988\u4e0e\u5efa\u8bae"},"4.2.12 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,a.kt)("hr",null),(0,a.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u9009\u9879")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/options?view=aspnetcore-5.0"},"ASP.NET Core - \u9009\u9879")," \u7ae0\u8282\u3002")))}k.isMDXComponent=!0},3905:function(n,e,t){t.d(e,{Zo:function(){return u},kt:function(){return d}});var i=t(7294);function o(n,e,t){return e in n?Object.defineProperty(n,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):n[e]=t,n}function a(n,e){var t=Object.keys(n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(n);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),t.push.apply(t,i)}return t}function p(n){for(var e=1;e=0||(o[t]=n[t]);return o}(n,e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(n);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(n,t)&&(o[t]=n[t])}return o}var l=i.createContext({}),s=function(n){var e=i.useContext(l),t=e;return n&&(t="function"==typeof n?n(e):p(p({},e),n)),t},u=function(n){var e=s(n.components);return i.createElement(l.Provider,{value:e},n.children)},m={inlineCode:"code",wrapper:function(n){var e=n.children;return i.createElement(i.Fragment,{},e)}},c=i.forwardRef((function(n,e){var t=n.components,o=n.mdxType,a=n.originalType,l=n.parentName,u=r(n,["components","mdxType","originalType","parentName"]),c=s(t),d=o,g=c["".concat(l,".").concat(d)]||c[d]||m[d]||a;return t?i.createElement(g,p(p({ref:e},u),{},{components:t})):i.createElement(g,p({ref:e},u))}));function d(n,e){var t=arguments,o=e&&e.mdxType;if("string"==typeof n||o){var a=t.length,p=new Array(a);p[0]=c;var r={};for(var l in e)hasOwnProperty.call(e,l)&&(r[l]=e[l]);r.originalType=n,r.mdxType="string"==typeof n?n:o,p[1]=r;for(var s=2;s=0||(o[t]=n[t]);return o}(n,e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(n);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(n,t)&&(o[t]=n[t])}return o}var l=i.createContext({}),s=function(n){var e=i.useContext(l),t=e;return n&&(t="function"==typeof n?n(e):p(p({},e),n)),t},u=function(n){var e=s(n.components);return i.createElement(l.Provider,{value:e},n.children)},m={inlineCode:"code",wrapper:function(n){var e=n.children;return i.createElement(i.Fragment,{},e)}},c=i.forwardRef((function(n,e){var t=n.components,o=n.mdxType,a=n.originalType,l=n.parentName,u=r(n,["components","mdxType","originalType","parentName"]),c=s(t),d=o,g=c["".concat(l,".").concat(d)]||c[d]||m[d]||a;return t?i.createElement(g,p(p({ref:e},u),{},{components:t})):i.createElement(g,p({ref:e},u))}));function d(n,e){var t=arguments,o=e&&e.mdxType;if("string"==typeof n||o){var a=t.length,p=new Array(a);p[0]=c;var r={};for(var l in e)hasOwnProperty.call(e,l)&&(r[l]=e[l]);r.originalType=n,r.mdxType="string"==typeof n?n:o,p[1]=r;for(var s=2;s child <"+("string"==typeof n.type?n.type:n.type.name)+'>: all children of the component should be , and every should have a unique "value" prop.')})),b=null!=g?g:f.map((function(n){var e=n.props;return{value:e.value,label:e.label,attributes:e.attributes}})),C=(0,r.l)(b,(function(n,e){return n.value===e.value}));if(C.length>0)throw new Error('Docusaurus error: Duplicate values "'+C.map((function(n){return n.value})).join(", ")+'" found in . Every value needs to be unique.');var O=null===d?d:null!=(e=null!=d?d:null==(t=f.find((function(n){return n.props.default})))?void 0:t.props.value)?e:f[0].props.value;if(null!==O&&!b.some((function(n){return n.value===O})))throw new Error('Docusaurus error: The has a defaultValue "'+O+'" but none of its children has the corresponding value. Available values are: '+b.map((function(n){return n.value})).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");var v=(0,l.U)(),h=v.tabGroupChoices,I=v.setTabGroupChoices,A=(0,o.useState)(O),y=A[0],T=A[1],w=[],E=(0,s.o5)().blockElementScrollPositionUntilNextRender;if(null!=k){var S=h[k];null!=S&&S!==y&&b.some((function(n){return n.value===S}))&&T(S)}var V=function(n){var e=n.currentTarget,t=w.indexOf(e),i=b[t].value;i!==y&&(E(e),T(i),null!=k&&I(k,String(i)))},L=function(n){var e,t=null;switch(n.key){case"ArrowRight":var i,o=w.indexOf(n.currentTarget)+1;t=null!=(i=w[o])?i:w[0];break;case"ArrowLeft":var a,p=w.indexOf(n.currentTarget)-1;t=null!=(a=w[p])?a:w[w.length-1]}null==(e=t)||e.focus()};return o.createElement("div",{className:(0,a.Z)("tabs-container",u)},o.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.Z)("tabs",{"tabs--block":c},N)},b.map((function(n){var e=n.value,t=n.label,p=n.attributes;return o.createElement("li",(0,i.Z)({role:"tab",tabIndex:y===e?0:-1,"aria-selected":y===e,key:e,ref:function(n){return w.push(n)},onKeyDown:L,onFocus:V,onClick:V},p,{className:(0,a.Z)("tabs__item",m,null==p?void 0:p.className,{"tabs__item--active":y===e})}),null!=t?t:e)}))),p?(0,o.cloneElement)(f.filter((function(n){return n.props.value===y}))[0],{className:"margin-top--md"}):o.createElement("div",{className:"margin-top--md"},f.map((function(n,e){return(0,o.cloneElement)(n,{key:e,hidden:n.props.value!==y})}))))}function d(n){var e=(0,p.Z)();return o.createElement(c,(0,i.Z)({key:String(e)},n))}},6486:function(n,e,t){t.r(e),t.d(e,{assets:function(){return c},contentTitle:function(){return u},default:function(){return k},frontMatter:function(){return s},metadata:function(){return m},toc:function(){return d}});var i=t(3117),o=t(102),a=(t(7294),t(3905)),p=(t(4996),t(5488)),r=t(5162),l=["components"],s={id:"options",title:"4.2 \u9009\u9879",sidebar_label:"4.2 \u9009\u9879"},u=void 0,m={unversionedId:"options",id:"options",title:"4.2 \u9009\u9879",description:"",source:"@site/docs/options.mdx",sourceDirName:".",slug:"/options",permalink:"/furion/docs/options",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/options.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1660201662,formattedLastUpdatedAt:"Aug 11, 2022",frontMatter:{id:"options",title:"4.2 \u9009\u9879",sidebar_label:"4.2 \u9009\u9879"},sidebar:"docs",previous:{title:"4.1 \u914d\u7f6e",permalink:"/furion/docs/configuration"},next:{title:"5.1 \u52a8\u6001 WebAPI",permalink:"/furion/docs/dynamic-api-controller"}},c={},d=[{value:"4.2.1 \u4ec0\u4e48\u662f\u9009\u9879",id:"421-\u4ec0\u4e48\u662f\u9009\u9879",level:2},{value:"4.2.2 \u4e0e\u914d\u7f6e\u7684\u533a\u522b",id:"422-\u4e0e\u914d\u7f6e\u7684\u533a\u522b",level:2},{value:"4.2.3 \u9009\u9879\u7684\u4f7f\u7528",id:"423-\u9009\u9879\u7684\u4f7f\u7528",level:2},{value:"4.2.3.1 \u914d\u7f6e appsettings.json \u4fe1\u606f",id:"4231-\u914d\u7f6e-appsettingsjson-\u4fe1\u606f",level:3},{value:"4.2.3.2 \u521b\u5efa AppInfoOptions \u5f3a\u7c7b\u578b\u7c7b",id:"4232-\u521b\u5efa-appinfooptions-\u5f3a\u7c7b\u578b\u7c7b",level:3},{value:"4.2.3.3 \u6ce8\u518c AppInfoOptions \u670d\u52a1",id:"4233-\u6ce8\u518c-appinfooptions-\u670d\u52a1",level:3},{value:"4.2.3.4 \u8bfb\u53d6 AppInfoOptions \u4fe1\u606f",id:"4234-\u8bfb\u53d6-appinfooptions-\u4fe1\u606f",level:3},{value:"4.2.3.5 \u5982\u4f55\u9009\u62e9\u8bfb\u53d6\u65b9\u5f0f",id:"4235-\u5982\u4f55\u9009\u62e9\u8bfb\u53d6\u65b9\u5f0f",level:3},{value:"4.2.4 \u9009\u9879\u63a5\u53e3\u8bf4\u660e",id:"424-\u9009\u9879\u63a5\u53e3\u8bf4\u660e",level:2},{value:"4.2.5 \u9009\u9879\u81ea\u5b9a\u4e49\u914d\u7f6e",id:"425-\u9009\u9879\u81ea\u5b9a\u4e49\u914d\u7f6e",level:2},{value:"4.2.5.1 \u9009\u9879\u67e5\u627e\u952e\u6d41\u7a0b",id:"4251-\u9009\u9879\u67e5\u627e\u952e\u6d41\u7a0b",level:3},{value:"4.2.6 [OptionsSettings] \u8bf4\u660e",id:"426-optionssettings-\u8bf4\u660e",level:2},{value:"4.2.7 \u9009\u9879\u9a8c\u8bc1",id:"427-\u9009\u9879\u9a8c\u8bc1",level:2},{value:"4.2.8 \u9009\u9879\u540e\u671f\u914d\u7f6e",id:"428-\u9009\u9879\u540e\u671f\u914d\u7f6e",level:2},{value:"4.2.9 \u9009\u9879\u66f4\u6539\u901a\u77e5\uff08\u70ed\u66f4\u65b0\uff09",id:"429-\u9009\u9879\u66f4\u6539\u901a\u77e5\u70ed\u66f4\u65b0",level:2},{value:"4.2.10 \u9009\u9879\u7684\u4f18\u7f3a\u70b9",id:"4210-\u9009\u9879\u7684\u4f18\u7f3a\u70b9",level:2},{value:"4.2.11 \u81ea\u5b9a\u4e49\u5c5e\u6027 Key \u6620\u5c04",id:"4211-\u81ea\u5b9a\u4e49\u5c5e\u6027-key-\u6620\u5c04",level:2},{value:"4.2.12 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"4212-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],g={toc:d};function k(n){var e=n.components,t=(0,o.Z)(n,l);return(0,a.kt)("wrapper",(0,i.Z)({},g,t,{components:e,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"421-\u4ec0\u4e48\u662f\u9009\u9879"},"4.2.1 \u4ec0\u4e48\u662f\u9009\u9879"),(0,a.kt)("p",null,"\u9009\u9879\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u63a8\u8350\u7684\u52a8\u6001\u8bfb\u53d6\u914d\u7f6e\u7684\u65b9\u5f0f\uff0c\u8fd9\u79cd\u65b9\u5f0f\u5c06\u914d\u7f6e\u6587\u4ef6\u6570\u636e\u7528\u4e00\u4e2a",(0,a.kt)("strong",{parentName:"p"},"\u5f3a\u7c7b\u578b"),"\u6765\u6258\u7ba1\uff0c\u80fd\u591f\u5b9e\u73b0\u914d\u7f6e\u9a8c\u8bc1\u3001\u9ed8\u8ba4\u503c\u914d\u7f6e\u3001\u5b9e\u65f6\u8bfb\u53d6\u7b49\u529f\u80fd\u3002"),(0,a.kt)("h2",{id:"422-\u4e0e\u914d\u7f6e\u7684\u533a\u522b"},"4.2.2 \u4e0e\u914d\u7f6e\u7684\u533a\u522b"),(0,a.kt)("p",null,"\u9009\u9879\u5b9e\u9645\u4e0a\u4e5f\u662f\u914d\u7f6e\uff0c\u4f46\u5728\u540e\u8005\u7684\u57fa\u7840\u4e0a\u6dfb\u52a0\u4e86\u914d\u7f6e\u9a8c\u8bc1\u3001\u9ed8\u8ba4\u503c/\u540e\u671f\u914d\u7f6e\u8bbe\u5b9a\u53ca\u63d0\u4f9b\u4e86\u591a\u79cd\u63a5\u53e3\u8bfb\u53d6\u914d\u7f6e\u4fe1\u606f\uff0c\u540c\u65f6\u8fd8\u652f\u6301\u4f9b\u914d\u7f6e\u66f4\u6539\u901a\u77e5\u7b49\u5f3a\u5927\u7075\u6d3b\u529f\u80fd\u3002"),(0,a.kt)("p",null,"\u6240\u4ee5\uff0c\u9664\u4e86\u4e00\u6b21\u6027\u8bfb\u53d6\u4f7f\u7528\u7684\u914d\u7f6e\u4ee5\u5916\uff0c\u90fd\u5e94\u8be5\u9009\u7528 ",(0,a.kt)("strong",{parentName:"p"},"\u9009\u9879")," \u66ff\u6362 ",(0,a.kt)("strong",{parentName:"p"},"\u914d\u7f6e"),"\u3002"),(0,a.kt)("admonition",{title:"\u77e5\u8bc6\u5bfc\u822a",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u6709\u5173\u914d\u7f6e\u8bf4\u660e\u53ef\u67e5\u770b\u300a",(0,a.kt)("a",{parentName:"p",href:"/furion/docs/configuration"},"4.1 \u914d\u7f6e"),"\u300b \u7ae0\u8282\u3002")),(0,a.kt)("h2",{id:"423-\u9009\u9879\u7684\u4f7f\u7528"},"4.2.3 \u9009\u9879\u7684\u4f7f\u7528"),(0,a.kt)("p",null,"\u5047\u8bbe\u6211\u4eec\u9700\u8981\u5728\u7cfb\u7edf\u8fd0\u884c\u65f6\u83b7\u53d6",(0,a.kt)("strong",{parentName:"p"},"\u7cfb\u7edf\u540d\u79f0\u3001\u7248\u672c\u53f7\u53ca\u7248\u6743\u4fe1\u606f"),"\uff0c\u8fd9\u4e9b\u4fe1\u606f\u53ef\u80fd\u968f\u65f6\u53d8\u5316\u800c\u4e14\u9700\u8981\u5728\u591a\u4e2a\u5730\u65b9\u4f7f\u7528\u3002\u8fd9\u65f6\u5c31\u9700\u8981\u5c06\u8fd9\u4e9b\u4fe1\u606f\u914d\u7f6e\u8d77\u6765\u3002\u5177\u4f53\u6b65\u9aa4\u5982\u4e0b\uff1a"),(0,a.kt)("h3",{id:"4231-\u914d\u7f6e-appsettingsjson-\u4fe1\u606f"},"4.2.3.1 \u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"h3"},"appsettings.json")," \u4fe1\u606f"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-6}",showLineNumbers:!0,"":!0,"{2-6}":!0},'{\n "AppInfo": {\n "Name": "Furion",\n "Version": "1.0.0",\n "Company": "Baiqian"\n }\n}\n')),(0,a.kt)("h3",{id:"4232-\u521b\u5efa-appinfooptions-\u5f3a\u7c7b\u578b\u7c7b"},"4.2.3.2 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h3"},"AppInfoOptions")," \u5f3a\u7c7b\u578b\u7c7b"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"":!0,"{1,5}":!0},"using Furion.ConfigurableOptions;\n\nnamespace Furion.Application\n{\n public class AppInfoOptions : IConfigurableOptions\n {\n public string Name { get; set; }\n public string Version { get; set; }\n public string Company { get; set; }\n }\n}\n")),(0,a.kt)("admonition",{title:"\u6e29\u99a8\u63d0\u793a",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u5efa\u8bae\u6240\u6709\u9009\u9879\u7c7b\u90fd\u5e94\u8be5\u4ee5 ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"Options"))," \u547d\u540d\u7ed3\u5c3e\u3002"),(0,a.kt)("p",{parentName:"admonition"},"\u53e6\u5916\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u7684\u6ce8\u518c\u9009\u9879\u670d\u52a1\u7684\u65b9\u6cd5\uff0c\u53ea\u9700\u8981\u7ee7\u627f ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"IConfigurableOptions"))," \u63a5\u53e3\u5373\u53ef\uff0c\u8be5\u63a5\u53e3\u4f4d\u4e8e ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"Furion.ConfigurableOptions"))," \u547d\u540d\u7a7a\u95f4\u4e0b\u3002")),(0,a.kt)("h3",{id:"4233-\u6ce8\u518c-appinfooptions-\u670d\u52a1"},"4.2.3.3 \u6ce8\u518c ",(0,a.kt)("inlineCode",{parentName:"h3"},"AppInfoOptions")," \u670d\u52a1"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u9009\u9879\u4e0d\u540c\u4e8e\u914d\u7f6e\uff0c\u9700\u5728\u5e94\u7528\u542f\u52a8\u65f6\u6ce8\u518c")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {12} title="Furion.Web.Core\\FurWebCoreStartup.cs"',showLineNumbers:!0,"":!0,"{12}":!0,title:'"Furion.Web.Core\\FurWebCoreStartup.cs"'},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.Web.Core\n{\n [AppStartup(800)]\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddConfigurableOptions();\n }\n }\n}\n")),(0,a.kt)("h3",{id:"4234-\u8bfb\u53d6-appinfooptions-\u4fe1\u606f"},"4.2.3.4 \u8bfb\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AppInfoOptions")," \u4fe1\u606f"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u63d0\u4f9b\u4e86\u591a\u79cd\u8bfb\u53d6\u65b9\u5f0f\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"li"},"App.GetOptions(path)")," \u8bfb\u53d6\uff08",(0,a.kt)("strong",{parentName:"li"},"\u4e0d\u63a8\u8350"),"\uff09"),(0,a.kt)("li",{parentName:"ul"},"\u901a\u8fc7\u4f9d\u8d56\u6ce8\u5165\u4ee5\u4e0b\u5b9e\u4f8b\u8bfb\u53d6\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IOptions")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IOptionsSnapshot")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IOptionsMonitor")))),(0,a.kt)("li",{parentName:"ul"},"\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"li"},"App")," \u9759\u6001\u7c7b\u63d0\u4f9b\u7684\u9759\u6001\u65b9\u6cd5\u83b7\u53d6\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"App.GetOptions()")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"App.GetOptionsMonitor()")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"App.GetOptionsSnapshot()"))))),(0,a.kt)(p.Z,{defaultValue:"App.GetOptions(path)",values:[{label:"App.GetOptions(path)",value:"App.GetOptions(path)"},{label:"\u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f",value:"\u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f"},{label:"App.GetOptions()",value:"App.GetOptions()"}],mdxType:"Tabs"},(0,a.kt)(r.Z,{value:"App.GetOptions(path)",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13-16}",showLineNumbers:!0,"":!0,"{13-16}":!0},'using Furion.Application;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n public class DefaultController : ControllerBase\n {\n [HttpGet]\n public string Get()\n {\n // \u4e0d\u63a8\u8350\u91c7\u7528\u6b64\u65b9\u5f0f\u8bfb\u53d6\uff0c\u8be5\u65b9\u5f0f\u4ec5\u5728 ConfigureServices \u542f\u52a8\u65f6\u4f7f\u7528\n var appInfo = App.GetConfig("AppInfo", true);\n return $@"\u540d\u79f0\uff1a{appInfo.Name}\uff0c\n \u7248\u672c\uff1a{appInfo.Version}\uff0c\n \u516c\u53f8\uff1a{appInfo.Company}";\n }\n }\n}\n'))),(0,a.kt)(r.Z,{value:"\u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,15-17,27-29,31-33,35-37}",showLineNumbers:!0,"":!0,"{3,15-17,27-29,31-33,35-37}":!0},'using Furion.Application;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.Extensions.Options;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n public class DefaultController : ControllerBase\n {\n private readonly AppInfoOptions options1;\n private readonly AppInfoOptions options2;\n private readonly AppInfoOptions options3;\n\n public DefaultController(\n IOptions options\n , IOptionsSnapshot optionsSnapshot\n , IOptionsMonitor optionsMonitor)\n {\n options1 = options.Value;\n options2 = optionsSnapshot.Value;\n options3 = optionsMonitor.CurrentValue;\n }\n\n [HttpGet]\n public string Get()\n {\n var info1 = $@"\u540d\u79f0\uff1a{options1.Name}\uff0c\n \u7248\u672c\uff1a{options1.Version}\uff0c\n \u516c\u53f8\uff1a{options1.Company}";\n\n var info2 = $@"\u540d\u79f0\uff1a{options2.Name}\uff0c\n \u7248\u672c\uff1a{options2.Version}\uff0c\n \u516c\u53f8\uff1a{options2.Company}";\n\n var info3 = $@"\u540d\u79f0\uff1a{options3.Name}\uff0c\n \u7248\u672c\uff1a{options3.Version}\uff0c\n \u516c\u53f8\uff1a{options3.Company}";\n\n return $"{info1}-{info2}-{info3}";\n }\n }\n}\n'))),(0,a.kt)(r.Z,{value:"App.GetOptions()",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {12-15,17-20,22-25}",showLineNumbers:!0,"":!0,"{12-15,17-20,22-25}":!0},'using Furion.Application;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n public class DefaultController : ControllerBase\n {\n [HttpGet]\n public string Get()\n {\n var options1 = App.GetOptions();\n var info1 = $@"\u540d\u79f0\uff1a{options1.Name}\uff0c\n \u7248\u672c\uff1a{options1.Version}\uff0c\n \u516c\u53f8\uff1a{options1.Company}";\n\n var options2 = App.GetOptionsSnapshot();\n var info2 = $@"\u540d\u79f0\uff1a{options2.Name}\uff0c\n \u7248\u672c\uff1a{options2.Version}\uff0c\n \u516c\u53f8\uff1a{options2.Company}";\n\n var options3 = App.GetOptionsMonitor();\n var info3 = $@"\u540d\u79f0\uff1a{options3.Name}\uff0c\n \u7248\u672c\uff1a{options3.Version}\uff0c\n \u516c\u53f8\uff1a{options3.Company}";\n\n return $"{info1}-{info2}-{info3}";\n }\n }\n}\n')))),(0,a.kt)("h3",{id:"4235-\u5982\u4f55\u9009\u62e9\u8bfb\u53d6\u65b9\u5f0f"},"4.2.3.5 \u5982\u4f55\u9009\u62e9\u8bfb\u53d6\u65b9\u5f0f"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5982\u679c\u9009\u9879\u9700\u8981\u5728\u591a\u4e2a\u5730\u65b9\u4f7f\u7528\uff0c\u5219\u65e0\u8bba\u4efb\u4f55\u65f6\u5019\u90fd\u4e0d\u63a8\u8350\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"li"},"App.GetOptions(path)")),(0,a.kt)("li",{parentName:"ul"},"\u5728\u53ef\u4f9d\u8d56\u6ce8\u5165\u7c7b\u4e2d\uff0c\u4f9d\u8d56\u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"li"},"IOptions[Snapshot|Monitor]")," \u8bfb\u53d6"),(0,a.kt)("li",{parentName:"ul"},"\u5728\u9759\u6001\u7c7b/\u975e\u4f9d\u8d56\u6ce8\u5165\u7c7b\u4e2d\uff0c\u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"li"},"App.GetOptions[Snapshot|Monitor]()")," \u8bfb\u53d6")),(0,a.kt)("h2",{id:"424-\u9009\u9879\u63a5\u53e3\u8bf4\u660e"},"4.2.4 \u9009\u9879\u63a5\u53e3\u8bf4\u660e"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u63d0\u4f9b\u4e86\u591a\u79cd\u8bfb\u53d6\u9009\u9879\u7684\u63a5\u53e3\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IOptions"),"\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u652f\u6301\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u5728\u5e94\u7528\u542f\u52a8\u540e\u8bfb\u53d6\u914d\u7f6e\u6570\u636e"),(0,a.kt)("li",{parentName:"ul"},"\u547d\u540d\u9009\u9879"))),(0,a.kt)("li",{parentName:"ul"},"\u6ce8\u518c\u4e3a\u5355\u4e00\u5b9e\u4f8b\u4e14\u53ef\u4ee5\u6ce8\u5165\u5230\u4efb\u4f55\u670d\u52a1\u751f\u5b58\u671f"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IOptionsSnapshot"),"\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u5728\u6bcf\u6b21\u8bf7\u6c42\u65f6\u5e94\u91cd\u65b0\u8ba1\u7b97\u9009\u9879\u7684\u65b9\u6848\u4e2d\u6709\u7528"),(0,a.kt)("li",{parentName:"ul"},"\u6ce8\u518c\u4e3a\u8303\u56f4\u5185\uff0c\u56e0\u6b64\u65e0\u6cd5\u6ce8\u5165\u5230\u5355\u4e00\u5b9e\u4f8b\u670d\u52a1"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u547d\u540d\u9009\u9879"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IOptionsMonitor"),"\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u7528\u4e8e\u68c0\u7d22\u9009\u9879\u5e76\u7ba1\u7406 TOptions \u5b9e\u4f8b\u7684\u9009\u9879\u901a\u77e5\u3002"),(0,a.kt)("li",{parentName:"ul"},"\u6ce8\u518c\u4e3a\u5355\u4e00\u5b9e\u4f8b\u4e14\u53ef\u4ee5\u6ce8\u5165\u5230\u4efb\u4f55\u670d\u52a1\u751f\u5b58\u671f\u3002"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u66f4\u6539\u901a\u77e5"),(0,a.kt)("li",{parentName:"ul"},"\u547d\u540d\u9009\u9879"),(0,a.kt)("li",{parentName:"ul"},"\u53ef\u91cd\u8f7d\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},"\u9009\u62e9\u6027\u9009\u9879\u5931\u6548 ",(0,a.kt)("inlineCode",{parentName:"li"},"(IOptionsMonitorCache)"))))))),(0,a.kt)("admonition",{title:"\u6ce8\u610f\u4e8b\u9879",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u5728\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IConfigurableOptionsListener")," \u76d1\u542c\u9009\u9879\u540e\uff0c\u5982\u8981\u83b7\u53d6\u6700\u65b0\u7684\u914d\u7f6e\u4fe1\u606f\uff0c\u8bf7\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"App.GetOptionsMonitor()")," \u800c\u4e0d\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"App.GetOptions()"),"\u3002")),(0,a.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u9009\u9879\u63a5\u53e3")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/options?view=aspnetcore-5.0#options-interfaces"},"ASP.NET Core - \u9009\u9879 - \u9009\u9879\u63a5\u53e3")," \u5c0f\u8282\u3002")),(0,a.kt)("h2",{id:"425-\u9009\u9879\u81ea\u5b9a\u4e49\u914d\u7f6e"},"4.2.5 \u9009\u9879\u81ea\u5b9a\u4e49\u914d\u7f6e"),(0,a.kt)("p",null,"\u6211\u4eec\u77e5\u9053\uff0c\u9009\u9879\u5b9e\u9645\u4e0a\u9700\u8981\u548c\u914d\u7f6e\u6587\u4ef6\u7279\u5b9a\u952e\u503c\u6302\u94a9\uff0c\u90a3 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u662f\u5982\u4f55\u51c6\u786e\u7684\u627e\u5230\u914d\u7f6e\u6587\u4ef6\u4e2d\u7684\u952e\u503c\u7684\u5462\uff1f"),(0,a.kt)("h3",{id:"4251-\u9009\u9879\u67e5\u627e\u952e\u6d41\u7a0b"},"4.2.5.1 \u9009\u9879\u67e5\u627e\u952e\u6d41\u7a0b"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u6ca1\u6709\u8d34 ",(0,a.kt)("inlineCode",{parentName:"strong"},"[OptionsSettings]")," \u7279\u6027"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"li"},"Options")," \u7ed3\u5c3e\uff0c\u5219\u53bb\u9664 ",(0,a.kt)("inlineCode",{parentName:"li"},"Options")," \u5b57\u7b26\u4e32"),(0,a.kt)("li",{parentName:"ul"},"\u5426\u5219\u8fd4\u56de ",(0,a.kt)("inlineCode",{parentName:"li"},"\u7c7b\u540d\u79f0")))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u8d34\u4e86 ",(0,a.kt)("inlineCode",{parentName:"strong"},"[OptionsSettings]")," \u7279\u6027"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u5982\u679c\u914d\u7f6e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"li"},"Path")," \u5c5e\u6027\uff0c\u5219\u8fd4\u56de ",(0,a.kt)("inlineCode",{parentName:"li"},"Path")," \u7684\u503c"),(0,a.kt)("li",{parentName:"ul"},"\u5426\u5219\u8fd4\u56de ",(0,a.kt)("inlineCode",{parentName:"li"},"\u7c7b\u540d\u79f0"))))),(0,a.kt)(p.Z,{defaultValue:"non-optionsettings",values:[{label:"\u65e0[OptionsSettings]",value:"non-optionsettings"},{label:"\u6709[OptionsSettings]",value:"has-optionsettings"}],mdxType:"Tabs"},(0,a.kt)(r.Z,{value:"non-optionsettings",mdxType:"TabItem"},(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"li"},"Options")," \u7ed3\u5c3e\uff0c\u5219\u952e\u540d\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"AppInfo"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"public class AppInfoOptions : IConfigurableOptions\n{\n public string Name { get; set; }\n public string Version { get; set; }\n public string Company { get; set; }\n}\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"li"},"Options")," \u7ed3\u5c3e\uff0c\u5219\u952e\u540d\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"AppInfoSettings"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"public class AppInfoSettings : IConfigurableOptions\n{\n public string Name { get; set; }\n public string Version { get; set; }\n public string Company { get; set; }\n}\n"))),(0,a.kt)(r.Z,{value:"has-optionsettings",mdxType:"TabItem"},(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u914d\u7f6e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"li"},"Path")," \u5c5e\u6027\uff0c\u5219\u952e\u540d\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"AppSettings:AppInfo"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'[OptionsSettings("AppSettings:AppInfo")]\npublic class AppInfoOptions : IConfigurableOptions\n{\n public string Name { get; set; }\n public string Version { get; set; }\n public string Company { get; set; }\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u6ca1\u6709\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"li"},"Path")," \u5c5e\u6027\uff0c\uff0c\u5219\u952e\u540d\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"AppInfoSettings"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"[OptionsSettings]\npublic class AppInfoSettings : IConfigurableOptions\n{\n public string Name { get; set; }\n public string Version { get; set; }\n public string Company { get; set; }\n}\n")))),(0,a.kt)("h2",{id:"426-optionssettings-\u8bf4\u660e"},"4.2.6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"[OptionsSettings]")," \u8bf4\u660e"),(0,a.kt)("p",null,"\u9009\u9879\u7c7b\u53ef\u4ee5\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"[OptionsSettings]")," \u6765\u914d\u7f6e\u67e5\u627e\u8def\u5f84\u503c\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Path"),"\uff1a\u5bf9\u5e94\u914d\u7f6e\u6587\u4ef6\u4e2d\u7684\u952e\uff0c\u652f\u6301 ",(0,a.kt)("strong",{parentName:"li"},"\u5206\u5c42\u952e")," \u5b57\u7b26\u4e32\uff0c\u53c2\u89c1\uff1a\u300a",(0,a.kt)("a",{parentName:"li",href:"configuration/#413-%E8%B7%AF%E5%BE%84%E7%AC%A6-%E6%9F%A5%E6%89%BE%E8%8A%82%E7%82%B9"},"4.1 \u914d\u7f6e - 4.1.3 \u8def\u5f84\u7b26 \u67e5\u627e\u8282\u70b9"),"\u300b"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"PostConfigureAll"),"\uff1a\u9009\u9879\u540e\u671f\u914d\u7f6e\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"false"),"\u3002",(0,a.kt)("a",{parentName:"li",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/options?view=aspnetcore-3.1#options-post-configuration"},"ASP.NET Core - \u9009\u9879 - \u9009\u9879\u540e\u671f\u914d\u7f6e"))),(0,a.kt)("h2",{id:"427-\u9009\u9879\u9a8c\u8bc1"},"4.2.7 \u9009\u9879\u9a8c\u8bc1"),(0,a.kt)("p",null,"\u9009\u9879\u652f\u6301\u9a8c\u8bc1\u914d\u7f6e\u6709\u6548\u6027\uff0c\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"services.AddConfigurableOptions()")," \u6ce8\u518c\u9009\u9879\u9ed8\u8ba4\u542f\u7528\u4e86\u9a8c\u8bc1\u652f\u6301\u3002"),(0,a.kt)("p",null,"\u5305\u62ec\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u7279\u6027\u65b9\u5f0f ",(0,a.kt)("inlineCode",{parentName:"li"},"DataAnnotations")),(0,a.kt)("li",{parentName:"ul"},"\u81ea\u5b9a\u4e49\u590d\u6742\u9a8c\u8bc1 ",(0,a.kt)("inlineCode",{parentName:"li"},"IValidateOptions"))),(0,a.kt)(p.Z,{defaultValue:"texin",values:[{label:"\u7279\u6027\u65b9\u5f0f",value:"texin"},{label:"\u590d\u6742\u9a8c\u8bc1",value:"fuza"}],mdxType:"Tabs"},(0,a.kt)(r.Z,{value:"texin",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,8,10,12}",showLineNumbers:!0,"":!0,"{2,8,10,12}":!0},'using Furion.ConfigurableOptions;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Furion.Application\n{\n public class AppInfoOptions : IConfigurableOptions\n {\n [Required(ErrorMessage = "\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a")]\n public string Name { get; set; }\n [Required, RegularExpression(@"^[0-9][0-9\\.]+[0-9]$", ErrorMessage = "\u4e0d\u662f\u6709\u6548\u7684\u7248\u672c\u53f7")]\n public string Version { get; set; }\n [Required, MaxLength(100)]\n public string Company { get; set; }\n }\n}\n'))),(0,a.kt)(r.Z,{value:"fuza",mdxType:"TabItem"},(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u81ea\u5b9a\u4e49\u9a8c\u8bc1\u7c7b ",(0,a.kt)("inlineCode",{parentName:"li"},"AppInfoValidation")," \u5e76\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"li"},"IValidateOptions")," \u63a5\u53e3\uff0c\u540c\u65f6\u5b9e\u73b0 ",(0,a.kt)("inlineCode",{parentName:"li"},"Validate")," \u65b9\u6cd5\u3002")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,6,8,12,15}",showLineNumbers:!0,"":!0,"{1,6,8,12,15}":!0},'using Microsoft.Extensions.Options;\nusing System.Text.RegularExpressions;\n\nnamespace Furion.Application\n{\n public class AppInfoValidation : IValidateOptions\n {\n public ValidateOptionsResult Validate(string name, AppInfoOptions options)\n {\n if (!Regex.IsMatch(options.Version, @"^[0-9][0-9\\.]+[0-9]$"))\n {\n return ValidateOptionsResult.Fail("\u4e0d\u662f\u6709\u6548\u7684\u7248\u672c\u53f7");\n }\n\n return ValidateOptionsResult.Success;\n }\n }\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u9009\u9879\u7c7b\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"li"},"IConfigurableOptions")," \u63a5\u53e3\uff0c\u5e76\u5b9e\u73b0\u8be5\u63a5\u53e3\u3002")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,16-18}",showLineNumbers:!0,"":!0,"{6,16-18}":!0},'using Furion.ConfigurableOptions;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Furion.Application\n{\n public class AppInfoOptions : IConfigurableOptions\n {\n [Required(ErrorMessage = "\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a")]\n public string Name { get; set; }\n [Required]\n public string Version { get; set; }\n [Required, MaxLength(100)]\n public string Company { get; set; }\n\n // \u9009\u9879\u540e\u671f\u914d\u7f6e\n public void PostConfigure(AppInfoOptions options, IConfiguration configuration)\n {\n }\n }\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5b8c\u6574\u4ee3\u7801\u5982\u4e0b\uff1a")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,9,19,25,27,31,34}",showLineNumbers:!0,"":!0,"{4,9,19,25,27,31,34}":!0},'using Furion.ConfigurableOptions;\nusing Microsoft.Extensions.Options;\nusing System.ComponentModel.DataAnnotations;\nusing System.Text.RegularExpressions;\n\nnamespace Furion.Application\n{\n // \u7ee7\u627f IConfigurableOptions \u63a5\u53e3\n public class AppInfoOptions : IConfigurableOptions\n {\n [Required(ErrorMessage = "\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a")]\n public string Name { get; set; }\n [Required]\n public string Version { get; set; }\n [Required, MaxLength(100)]\n public string Company { get; set; }\n\n // \u9009\u9879\u540e\u671f\u914d\u7f6e\n public void PostConfigure(AppInfoOptions options)\n {\n }\n }\n\n // \u521b\u5efa\u81ea\u5b9a\u4e49\u9a8c\u8bc1\u7c7b\n public class AppInfoValidation : IValidateOptions\n {\n public ValidateOptionsResult Validate(string name, AppInfoOptions options)\n {\n if (!Regex.IsMatch(options.Version, @"^[0-9][0-9\\.]+[0-9]$"))\n {\n return ValidateOptionsResult.Fail("\u4e0d\u662f\u6709\u6548\u7684\u7248\u672c\u53f7");\n }\n\n return ValidateOptionsResult.Success;\n }\n }\n}\n')))),(0,a.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"IConfigurableOptions"))," \u7ee7\u627f\u81ea ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"IConfigurableOptions")),"\uff0c\u4e5f\u5c31\u662f\u81ea\u5b9a\u4e49\u590d\u6742\u9a8c\u8bc1\u9ed8\u8ba4\u5177\u6709 ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"PostConfigure(TOptions options)"))," \u9009\u9879\u540e\u671f\u914d\u7f6e\u65b9\u6cd5\u3002\u5173\u4e8e\u300a",(0,a.kt)("a",{parentName:"p",href:"#428-%E9%80%89%E9%A1%B9%E5%90%8E%E6%9C%9F%E9%85%8D%E7%BD%AE"},"4.2.8 \u9009\u9879\u540e\u671f\u914d\u7f6e"),"\u300b\u5c06\u5728\u4e0b\u4e00\u5c0f\u8282\u8bf4\u660e\u3002")),(0,a.kt)("h2",{id:"428-\u9009\u9879\u540e\u671f\u914d\u7f6e"},"4.2.8 \u9009\u9879\u540e\u671f\u914d\u7f6e"),(0,a.kt)("p",null,"\u9009\u9879\u540e\u671f\u914d\u7f6e\u901a\u4fd7\u4e00\u70b9\u6765\u8bf4\uff0c\u53ef\u4ee5\u5728\u8fd0\u884c\u65f6\u89e3\u6790\u503c\u6216\u8bbe\u5b9a\u9ed8\u8ba4\u503c/\u540e\u671f\u914d\u7f6e\u7b49\u3002"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u914d\u7f6e\u9009\u9879\u540e\u671f\u914d\u7f6e\u5f88\u7b80\u5355\uff0c\u53ea\u9700\u8981\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"p"},"IConfigurableOptions")," \u63a5\u53e3\u5e76\u5b9e\u73b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"PostConfigure(TOptions options)")," \u65b9\u6cd5\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,16-21}",showLineNumbers:!0,"":!0,"{7,16-21}":!0},'using Furion.ConfigurableOptions;\nusing Microsoft.Extensions.Configuration;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Furion.Application\n{\n public class AppInfoOptions : IConfigurableOptions\n {\n [Required(ErrorMessage = "\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a")]\n public string Name { get; set; }\n [Required]\n public string Version { get; set; }\n [Required, MaxLength(100)]\n public string Company { get; set; }\n\n public void PostConfigure(AppInfoOptions options, IConfiguration configuration)\n {\n options.Name ??= "Furion";\n options.Version ??= "1.0.0";\n options.Company ??= "Baiqian";\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"IConfigurableOptions"))," \u7ee7\u627f\u81ea ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"IConfigurableOptions")),"\uff0c\u4e5f\u5c31\u662f\u81ea\u5b9a\u4e49\u590d\u6742\u9a8c\u8bc1\u9ed8\u8ba4\u5177\u6709 ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"PostConfigure(TOptions options, IConfiguration configuration)"))," \u9009\u9879\u540e\u671f\u914d\u7f6e\u65b9\u6cd5\u3002")),(0,a.kt)("h2",{id:"429-\u9009\u9879\u66f4\u6539\u901a\u77e5\u70ed\u66f4\u65b0"},"4.2.9 \u9009\u9879\u66f4\u6539\u901a\u77e5\uff08",(0,a.kt)("inlineCode",{parentName:"h2"},"\u70ed\u66f4\u65b0"),"\uff09"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u975e\u5e38\u7b80\u5355\u4e14\u7075\u6d3b\u7684\u65b9\u5f0f\u76d1\u542c\u9009\u9879\u66f4\u6539\uff0c\u4e5f\u5c31\u662f ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"appsettings.json")," \u6216 \u81ea\u5b9a\u4e49\u914d\u7f6e\u6587\u4ef6\u53d1\u751f\u4efb\u4f55\u66f4\u6539\u90fd\u4f1a\u89e6\u53d1\u5904\u7406\u65b9\u6cd5"),"\u3002"),(0,a.kt)("p",null,"\u4f7f\u7528\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700\u8981\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"p"},"IConfigurableOptionsListener")," \u63a5\u53e3\u5e76\u5b9e\u73b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"void OnListener(TOptions options, IConfiguration configuration)")," \u65b9\u6cd5\u5373\u53ef\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,11-15}",showLineNumbers:!0,"":!0,"{5,11-15}":!0},"using Furion.ConfigurableOptions;\n\nnamespace Furion.Application\n{\n public class AppInfoOptions : IConfigurableOptionsListener\n {\n public string Name { get; set; }\n public string Version { get; set; }\n public string Company { get; set; }\n\n public void OnListener(AppInfoOptions options, IConfiguration configuration)\n {\n var name = options.Name; // \u5b9e\u65f6\u7684\u6700\u65b0\u503c\n var version = options.Version; // \u5b9e\u65f6\u7684\u6700\u65b0\u503c\n }\n\n public void PostConfigure(AppInfoOptions options, IConfiguration configuration)\n {\n }\n }\n}\n")),(0,a.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"IConfigurableOptionsListener"))," \u7ee7\u627f\u81ea ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"IConfigurableOptions")),"\u3002")),(0,a.kt)("h2",{id:"4210-\u9009\u9879\u7684\u4f18\u7f3a\u70b9"},"4.2.10 \u9009\u9879\u7684\u4f18\u7f3a\u70b9"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u4f18\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u5f3a\u7c7b\u578b\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},"\u63d0\u4f9b\u591a\u79cd\u8bfb\u53d6\u65b9\u5f0f"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u70ed\u52a0\u8f7d"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u8bbe\u7f6e\u9ed8\u8ba4\u503c/\u540e\u671f\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u5728\u8fd0\u884c\u73af\u5883\u4e2d\u52a8\u6001\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u9a8c\u8bc1\u914d\u7f6e\u6709\u6548\u6027"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u66f4\u6539\u901a\u77e5"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u547d\u540d\u9009\u9879"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u7f3a\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u9700\u8981\u5b9a\u4e49\u5bf9\u5e94\u7c7b\u578b"),(0,a.kt)("li",{parentName:"ul"},"\u9700\u8981\u5728\u542f\u52a8\u65f6\u6ce8\u518c")))),(0,a.kt)("h2",{id:"4211-\u81ea\u5b9a\u4e49\u5c5e\u6027-key-\u6620\u5c04"},"4.2.11 \u81ea\u5b9a\u4e49\u5c5e\u6027 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Key")," \u6620\u5c04"),(0,a.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion v3.4.3+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,a.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u4e2d\u914d\u7f6e\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Key")," \u548c\u9009\u9879\u5b9a\u4e49\u7684\u5c5e\u6027\u540d\u4e0d\u4e00\u6837\uff0c\u8fd9\u65f6\u5019\u5c31\u9700\u8981\u7528\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"[MapSettings]")," \u7279\u6027\u5373\u53ef\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {4}",showLineNumbers:!0,"{4}":!0},'"AppInfo": {\n "Name": "Furion",\n "Version": "1.0.0",\n "Company_Name": "Baiqian"\n}\n')),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6-7}",showLineNumbers:!0,"{6-7}":!0},'public class AppInfoOptions : IConfigurableOptions\n{\n public string Name { get; set; }\n public string Version { get; set; }\n\n [MapSettings("Company_Name")]\n public string Company { get; set; }\n}\n')),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"[MapSettings]")," \u914d\u7f6e\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Key")," \u4f1a\u81ea\u5b9a\u5e94\u7528\u9009\u9879\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Key")," \u4f5c\u4e3a\u8d77\u59cb\u70b9\uff0c\u5982\u5b9e\u9645\u4e0a ",(0,a.kt)("inlineCode",{parentName:"p"},"Company")," \u5c5e\u6027\u5bf9\u5e94\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Key")," \u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"AppInfo:Company_Name"),"\u3002")),(0,a.kt)("h2",{id:"4212-\u53cd\u9988\u4e0e\u5efa\u8bae"},"4.2.12 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,a.kt)("hr",null),(0,a.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u9009\u9879")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/options?view=aspnetcore-5.0"},"ASP.NET Core - \u9009\u9879")," \u7ae0\u8282\u3002")))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/0ff68343.1e411abb.js b/handbook/build/assets/js/0ff68343.1e411abb.js new file mode 100644 index 0000000000..378b82963d --- /dev/null +++ b/handbook/build/assets/js/0ff68343.1e411abb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[2019],{3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return c}});var i=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function l(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=i.createContext({}),m=function(e){var t=i.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},s=function(e){var t=m(e.components);return i.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},d=i.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,p=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=m(n),c=a,k=d["".concat(p,".").concat(c)]||d[c]||u[c]||r;return n?i.createElement(k,l(l({ref:t},s),{},{components:n})):i.createElement(k,l({ref:t},s))}));function c(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,l=new Array(r);l[0]=d;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var m=2;m getall \u4f1a\u88ab\u590d\u5199\u4e3a `[HttpHead]`\n [ "other", "PUT" ] // => \u65b0\u589e\u4e00\u6761\u65b0\u89c4\u5219\uff0c\u6bd4\u5982\uff0c\u4e00 `[other]` \u5f00\u5934\u4f1a\u8f6c\u6362\u4e3a `[HttpPut]` \u8bf7\u6c42\n ]\n }\n')))))),(0,r.kt)("h2",{id:"53-\u914d\u7f6e\u793a\u4f8b"},"5.3 \u914d\u7f6e\u793a\u4f8b"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "DynamicApiControllerSettings": {\n "SupportedMvcController": true\n }\n}\n')))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/0ff68343.9f62d4ed.js b/handbook/build/assets/js/0ff68343.9f62d4ed.js deleted file mode 100644 index df7f8cd96e..0000000000 --- a/handbook/build/assets/js/0ff68343.9f62d4ed.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[2019],{2399:function(e,t,n){n.r(t),n.d(t,{assets:function(){return s},contentTitle:function(){return p},default:function(){return c},frontMatter:function(){return o},metadata:function(){return m},toc:function(){return u}});var i=n(3117),a=n(102),r=(n(7294),n(3905)),l=["components"],o={id:"dynamicapicontrollersettings",title:"5. \u52a8\u6001API\u914d\u7f6e",sidebar_label:"5. \u52a8\u6001API\u914d\u7f6e"},p=void 0,m={unversionedId:"settings/dynamicapicontrollersettings",id:"settings/dynamicapicontrollersettings",title:"5. \u52a8\u6001API\u914d\u7f6e",description:"\u5982\u9700\u7f16\u5199\u914d\u7f6e\u7684\u65f6\u5019\u63d0\u4f9b\u667a\u80fd\u63d0\u793a\u548c\u6821\u9a8c\uff0c\u53ef\u67e5\u770b \u30102.7 JSON Schema \u4f7f\u7528\u3011",source:"@site/docs/settings/dynamicapicontrollersettings.mdx",sourceDirName:"settings",slug:"/settings/dynamicapicontrollersettings",permalink:"/furion/docs/settings/dynamicapicontrollersettings",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/settings/dynamicapicontrollersettings.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1656403543,formattedLastUpdatedAt:"Jun 28, 2022",frontMatter:{id:"dynamicapicontrollersettings",title:"5. \u52a8\u6001API\u914d\u7f6e",sidebar_label:"5. \u52a8\u6001API\u914d\u7f6e"},sidebar:"settings",previous:{title:"4. \u4f9d\u8d56\u6ce8\u5165\u914d\u7f6e",permalink:"/furion/docs/settings/dependencyinjectionsettings"},next:{title:"6. \u53cb\u597d\u5f02\u5e38\u914d\u7f6e",permalink:"/furion/docs/settings/friendlyexceptionsettings"}},s={},u=[{value:"5.1 \u5173\u4e8e\u914d\u7f6e",id:"51-\u5173\u4e8e\u914d\u7f6e",level:2},{value:"5.2 \u914d\u7f6e\u4fe1\u606f",id:"52-\u914d\u7f6e\u4fe1\u606f",level:2},{value:"5.3 \u914d\u7f6e\u793a\u4f8b",id:"53-\u914d\u7f6e\u793a\u4f8b",level:2}],d={toc:u};function c(e){var t=e.components,n=(0,a.Z)(e,l);return(0,r.kt)("wrapper",(0,i.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("admonition",{title:"\u914d\u7f6e\u667a\u80fd\u63d0\u793a\u548c\u6821\u9a8c",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"\u5982\u9700\u7f16\u5199\u914d\u7f6e\u7684\u65f6\u5019\u63d0\u4f9b\u667a\u80fd\u63d0\u793a\u548c\u6821\u9a8c\uff0c\u53ef\u67e5\u770b \u3010",(0,r.kt)("a",{parentName:"p",href:"../jsonschema"},"2.7 JSON Schema \u4f7f\u7528"),"\u3011"),(0,r.kt)("p",{parentName:"admonition"},"\u53ea\u9700\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u5934\u90e8\u6dfb\u52a0\u4e0b\u5217\u914d\u7f6e\u5373\u53ef\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},'{\n "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"\n}\n'))),(0,r.kt)("h2",{id:"51-\u5173\u4e8e\u914d\u7f6e"},"5.1 \u5173\u4e8e\u914d\u7f6e"),(0,r.kt)("p",null,"\u52a8\u6001 API \u914d\u7f6e\u6307\u7684\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u52a8\u6001 API \u914d\u7f6e\u9009\u9879\u3002"),(0,r.kt)("h2",{id:"52-\u914d\u7f6e\u4fe1\u606f"},"5.2 \u914d\u7f6e\u4fe1\u606f"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DynamicApiControllerSettings"),"\uff1a\u914d\u7f6e\u6839\u8282\u70b9",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DefaultRoutePrefix"),"\uff1a\u9ed8\u8ba4\u8def\u7531\u524d\u7f00\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"api")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DefaultHttpMethod"),"\uff1a\u9ed8\u8ba4\u8bf7\u6c42\u8c13\u8bcd\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"POST")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DefaultModule"),"\uff1a\u9ed8\u8ba4\u6a21\u5757\u540d\u79f0\uff08\u533a\u57df\uff09\uff0c\u53ef\u7528\u4f5c\u63a5\u53e3\u7248\u672c\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"v1")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"LowercaseRoute"),"\uff1a\u5c0f\u5199\u8def\u7531\u683c\u5f0f\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AsLowerCamelCase"),"\uff1a\u542f\u7528\u5c0f\u9a7c\u5cf0\u547d\u540d\uff08\u9996\u5b57\u6bcd\u5c0f\u5199\uff09\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"KeepVerb"),"\uff1a\u662f\u5426\u4fdd\u7559\u52a8\u4f5c\u8c13\u8bcd\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"false")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"KeepName"),"\uff1a\u662f\u5426\u4fdd\u7559\u9ed8\u8ba4\u540d\u79f0\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"fasle")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"CamelCaseSeparator"),"\uff1a\u9a86\u9a7c\uff08\u9a7c\u5cf0\uff09\u547d\u540d\u5206\u9694\u7b26\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"-")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"VersionSeparator"),"\uff1a\u7248\u672c\u5206\u9694\u7b26\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"@")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ModelToQuery"),"\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"GET/HEAD")," \u8bf7\u6c42\u5c06 ",(0,r.kt)("inlineCode",{parentName:"li"},"\u7c7b\u7c7b\u578b\u53c2\u6570\u8f6c\u67e5\u8be2\u53c2\u6570"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SupportedMvcController"),"\uff1a\u662f\u5426\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Mvc Controller")," \u52a8\u6001\u914d\u7f6e\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"UrlParameterization"),"\uff1a\u8def\u7531\u53c2\u6570\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"[FromQuery]")," \u5316\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false"),"\uff08",(0,r.kt)("inlineCode",{parentName:"li"},"[FromRoute]")," \u65b9\u5f0f\uff09"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DefaultArea"),"\uff1a\u914d\u7f6e\u9ed8\u8ba4\u533a\u57df\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"null")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ForceWithRoutePrefix"),"\uff1a\u914d\u7f6e\u662f\u5426\u5f3a\u5236\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"DefaultRoutePrefix"),"\uff0c\u5f53\u63a7\u5236\u5668\u81ea\u5b9a\u4e49\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"[Route]")," \u6709\u6548\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u4ec5\u9650 v3.4.1+\u7248\u672c\u6709\u6548")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AbandonControllerAffixes"),"\uff1a\u9ed8\u8ba4\u53bb\u9664\u63a7\u5236\u5668\u540d\u79f0\u524d\u540e\u7f00\u5217\u8868\u540d\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string[]"),"\uff0c\u9ed8\u8ba4\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppServices")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppService")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ApiController")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Controller")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Services")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Service")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AbandonActionAffixes"),"\uff1a\u9ed8\u8ba4\u53bb\u9664\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u524d\u540e\u7f00\u5217\u8868\u540d\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string[]"),"\uff0c\u9ed8\u8ba4\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Async")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"VerbToHttpMethods"),"\uff1a\u590d\u5199\u9ed8\u8ba4\u65b9\u6cd5\u540d\u8f6c ",(0,r.kt)("inlineCode",{parentName:"li"},"[HttpMethod]")," \u89c4\u5219\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string[][]")," \u4e8c\u7ef4\u6570\u7ec4\u7c7b\u578b\uff0c\u5185\u7f6e\u5339\u914d\u89c4\u5219\u4e3a\uff1a",(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'["post"] = "POST",\n["add"] = "POST",\n["create"] = "POST",\n["insert"] = "POST",\n["submit"] = "POST",\n["get"] = "GET",\n["find"] = "GET",\n["fetch"] = "GET",\n["query"] = "GET",\n["getlist"] = "GET",\n["getall"] = "GET",\n["put"] = "PUT",\n["update"] = "PUT",\n["delete"] = "DELETE",\n["remove"] = "DELETE",\n["clear"] = "DELETE",\n["patch"] = "PATCH"\n')),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"\u590d\u5199\u793a\u4f8b")),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'"DynamicApiControllerSettings": {\n "VerbToHttpMethods": [\n [ "getall", "HEAD" ], // => getall \u4f1a\u88ab\u590d\u5199\u4e3a `[HttpHead]`\n [ "other", "PUT" ] // => \u65b0\u589e\u4e00\u6761\u65b0\u89c4\u5219\uff0c\u6bd4\u5982\uff0c\u4e00 `[other]` \u5f00\u5934\u4f1a\u8f6c\u6362\u4e3a `[HttpPut]` \u8bf7\u6c42\n ]\n }\n')))))),(0,r.kt)("h2",{id:"53-\u914d\u7f6e\u793a\u4f8b"},"5.3 \u914d\u7f6e\u793a\u4f8b"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "DynamicApiControllerSettings": {\n "SupportedMvcController": true\n }\n}\n')))}c.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return c}});var i=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function l(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=i.createContext({}),m=function(e){var t=i.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},s=function(e){var t=m(e.components);return i.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},d=i.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,p=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=m(n),c=a,k=d["".concat(p,".").concat(c)]||d[c]||u[c]||r;return n?i.createElement(k,l(l({ref:t},s),{},{components:n})):i.createElement(k,l({ref:t},s))}));function c(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,l=new Array(r);l[0]=d;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var m=2;mVisual Studio \u4e2d\u914d\u7f6e\u8def\u5f84",id:"2923-\u5728-visual-studio-\u4e2d\u914d\u7f6e\u8def\u5f84",level:3},{value:"2.9.2.4 \u9009\u62e9\u6d4b\u8bd5\u7248\u5b89\u88c5\u6216\u66f4\u65b0",id:"2924-\u9009\u62e9\u6d4b\u8bd5\u7248\u5b89\u88c5\u6216\u66f4\u65b0",level:3},{value:"2.9.3 Visual Studio \u8c03\u8bd5 Nuget \u5305",id:"293-visual-studio-\u8c03\u8bd5-nuget-\u5305",level:2},{value:"2.9.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"294-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],g={toc:d};function m(e){var t=e.components,n=(0,i.Z)(e,u);return(0,o.kt)("wrapper",(0,r.Z)({},g,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"291-\u5173\u4e8e\u672c\u5730\u6d4b\u8bd5\u5305"},"2.9.1 \u5173\u4e8e\u672c\u5730\u6d4b\u8bd5\u5305"),(0,o.kt)("p",null,"\u6b63\u5e38\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u90fd\u662f\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5728\u7ebf\u5e73\u53f0\uff08Visual Studio \u5185\u7f6e\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5305\u7ba1\u7406\u5668\uff09\u5b89\u88c5\u62d3\u5c55\u4f9d\u8d56\uff0c",(0,o.kt)("strong",{parentName:"p"},"\u4f46\u6709\u65f6\u5019\u6211\u4eec\u4e0d\u5e0c\u671b\u53d1\u5e03\u5230 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Nuget")," \u5e73\u53f0\u6216\u8005\u53ea\u60f3\u5728\u672c\u5730\u4f7f\u7528\u53c8\u6216\u8005\u5148\u5728\u672c\u5730\u6d4b\u8bd5\u901a\u8fc7\u518d\u53d1\u5e03\u3002")),(0,o.kt)("p",null,"\u8fd9\u6837\u505a\u7684\u597d\u5904\u662f\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u53ef\u4ee5\u6709\u6548\u4fdd\u62a4\u516c\u53f8\u6838\u5fc3\u4ee3\u7801"),(0,o.kt)("li",{parentName:"ul"},"\u65b9\u4fbf\u5f00\u6e90\u9879\u76ee\u6d4b\u8bd5")),(0,o.kt)("h2",{id:"292-\u5982\u4f55\u914d\u7f6e"},"2.9.2 \u5982\u4f55\u914d\u7f6e"),(0,o.kt)("h3",{id:"2921-\u6d4b\u8bd5\u5305\u547d\u540d\u89c4\u5219"},"2.9.2.1 \u6d4b\u8bd5\u5305\u547d\u540d\u89c4\u5219"),(0,o.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u4f1a\u6839\u636e ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion.\u7248\u672c\u53f7-beta.Issue\u7f16\u53f7")," \u89c4\u5219\u751f\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},".nupkg")," \u548c ",(0,o.kt)("inlineCode",{parentName:"p"},".snupkg")," \u5305\uff0c\u524d\u8005\u662f\u4e0d\u5305\u542b\u8c03\u8bd5\u7684\u65e0\u7b26\u53f7 ",(0,o.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5305\uff0c\u540e\u8005\u5219\u662f\u8c03\u8bd5\u7b26\u53f7\u5305\uff08\u65b9\u4fbf ",(0,o.kt)("inlineCode",{parentName:"p"},"IDE")," \u8c03\u8bd5\u7528\u7684\uff09\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-showLineNumbers",metastring:'title="D:\\Furion_Nuget_Test_Packages"',title:'"D:\\Furion_Nuget_Test_Packages"'},"Furion.4.2.3-beta-I5MM3O.nupkg\nFurion.4.2.3-beta-I5MM3O.snupkg\n")),(0,o.kt)("p",null,"\u5176\u4e2d ",(0,o.kt)("inlineCode",{parentName:"p"},"I5MM3O")," \u5bf9\u5e94\u7684\u6b63\u662f ",(0,o.kt)("inlineCode",{parentName:"p"},"Issue")," \u7684\u7f16\u53f7\uff1a",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/I5MM3O"},"https://gitee.com/dotnetchina/Furion/issues/I5MM3O")),(0,o.kt)("h3",{id:"2922-\u914d\u7f6e\u672c\u5730\u5305\u8def\u5f84"},"2.9.2.2 \u914d\u7f6e\u672c\u5730\u5305\u8def\u5f84"),(0,o.kt)("p",null,"\u6709\u4e86\u8fd9\u4e24\u4e2a\u5305\u4e4b\u540e\uff0c\u5c31\u53ef\u4ee5\u5728\u672c\u5730\u78c1\u76d8\u4e2d\u521b\u5efa\u6587\u4ef6\u5939\u5e76\u653e\u8fdb\u53bb\uff0c\u5982 ",(0,o.kt)("inlineCode",{parentName:"p"},"D:\\Furion_Nuget_Test_Packages"),"\u3002"),(0,o.kt)("img",{src:(0,a.Z)("img/ng1.png")}),(0,o.kt)("h3",{id:"2923-\u5728-visual-studio-\u4e2d\u914d\u7f6e\u8def\u5f84"},"2.9.2.3 \u5728 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Visual Studio")," \u4e2d\u914d\u7f6e\u8def\u5f84"),(0,o.kt)("img",{src:(0,a.Z)("img/ng2.png")}),(0,o.kt)("img",{src:(0,a.Z)("img/ng3.png")}),(0,o.kt)("img",{src:(0,a.Z)("img/ng4.png")}),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u547d\u4ee4\u884c\u64cd\u4f5c",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4e0d\u4f7f\u7528\u53ef\u89c6\u5316 ",(0,o.kt)("inlineCode",{parentName:"p"},"IDE")," \u914d\u7f6e\uff0c\u53ef\u901a\u8fc7\u4e0b\u5217\u547d\u4ee4\u884c\u914d\u7f6e\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'dotnet restore "YourProject.Web.Entry/YourProject.Web.Entry.csproj" -s "D:\\Furion_Nuget_Test_Packages";\ndotnet restore "YourProject.Web.Entry/YourProject.Web.Entry.csproj" -s "https://api.nuget.org/v3/index.json";\n'))),(0,o.kt)("h3",{id:"2924-\u9009\u62e9\u6d4b\u8bd5\u7248\u5b89\u88c5\u6216\u66f4\u65b0"},"2.9.2.4 \u9009\u62e9\u6d4b\u8bd5\u7248\u5b89\u88c5\u6216\u66f4\u65b0"),(0,o.kt)("img",{src:(0,a.Z)("img/ng5.png")}),(0,o.kt)("img",{src:(0,a.Z)("img/ng6.png")}),(0,o.kt)("img",{src:(0,a.Z)("img/ng7.png")}),(0,o.kt)("br",null),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u6d4b\u8bd5\u901a\u8fc7\u540e\u53ef\u4ee5\u5220\u9664\u4e4b\u524d\u7684\u914d\u7f6e\u5373\u53ef"),"\uff0c\u5982\uff1a"),(0,o.kt)("img",{src:(0,a.Z)("img/ng8.png")}),(0,o.kt)("h2",{id:"293-visual-studio-\u8c03\u8bd5-nuget-\u5305"},"2.9.3 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Visual Studio")," \u8c03\u8bd5 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Nuget")," \u5305"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},".snupkg")," \u5305\uff0c\u5728\u5b89\u88c5 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u7684\u65f6\u5019\u81ea\u52a8\u4e0b\u8f7d\u5230\u672c\u5730\uff0c\u5982\u9700\u542f\u7528\u6e90\u7801\u8c03\u8bd5\uff0c\u53ea\u9700\u8981\u542f\u7528\u4ee5\u4e0b\u914d\u7f6e\u5373\u53ef\uff1a"),(0,o.kt)("img",{src:(0,a.Z)("img/vs10.png")}),(0,o.kt)("p",null,"\u542f\u7528\u4e4b\u540e\u91cd\u65b0\u7f16\u8bd1\u89e3\u51b3\u65b9\u6848\u5c31\u53ef\u4ee5\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"F12")," \u8df3\u8f6c\u5230\u6e90\u4ee3\u7801\u533a\u5e76\u8c03\u8bd5\u6e90\u4ee3\u7801\u4e86\u3002"),(0,o.kt)("h2",{id:"294-\u53cd\u9988\u4e0e\u5efa\u8bae"},"2.9.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return g}});var r=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var l=r.createContext({}),p=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},s=function(e){var t=p(e.components);return r.createElement(l.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,s=u(e,["components","mdxType","originalType","parentName"]),d=p(n),g=i,m=d["".concat(l,".").concat(g)]||d[g]||c[g]||o;return n?r.createElement(m,a(a({ref:t},s),{},{components:n})):r.createElement(m,a({ref:t},s))}));function g(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=n.length,a=new Array(o);a[0]=d;var u={};for(var l in t)hasOwnProperty.call(t,l)&&(u[l]=t[l]);u.originalType=e,u.mdxType="string"==typeof e?e:i,a[1]=u;for(var p=2;p=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var l=r.createContext({}),p=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},s=function(e){var t=p(e.components);return r.createElement(l.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,s=u(e,["components","mdxType","originalType","parentName"]),d=p(n),g=i,m=d["".concat(l,".").concat(g)]||d[g]||c[g]||o;return n?r.createElement(m,a(a({ref:t},s),{},{components:n})):r.createElement(m,a({ref:t},s))}));function g(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=n.length,a=new Array(o);a[0]=d;var u={};for(var l in t)hasOwnProperty.call(t,l)&&(u[l]=t[l]);u.originalType=e,u.mdxType="string"==typeof e?e:i,a[1]=u;for(var p=2;pVisual Studio \u4e2d\u914d\u7f6e\u8def\u5f84",id:"2923-\u5728-visual-studio-\u4e2d\u914d\u7f6e\u8def\u5f84",level:3},{value:"2.9.2.4 \u9009\u62e9\u6d4b\u8bd5\u7248\u5b89\u88c5\u6216\u66f4\u65b0",id:"2924-\u9009\u62e9\u6d4b\u8bd5\u7248\u5b89\u88c5\u6216\u66f4\u65b0",level:3},{value:"2.9.3 Visual Studio \u8c03\u8bd5 Nuget \u5305",id:"293-visual-studio-\u8c03\u8bd5-nuget-\u5305",level:2},{value:"2.9.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"294-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],g={toc:d};function m(e){var t=e.components,n=(0,i.Z)(e,u);return(0,o.kt)("wrapper",(0,r.Z)({},g,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"291-\u5173\u4e8e\u672c\u5730\u6d4b\u8bd5\u5305"},"2.9.1 \u5173\u4e8e\u672c\u5730\u6d4b\u8bd5\u5305"),(0,o.kt)("p",null,"\u6b63\u5e38\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u90fd\u662f\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5728\u7ebf\u5e73\u53f0\uff08Visual Studio \u5185\u7f6e\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5305\u7ba1\u7406\u5668\uff09\u5b89\u88c5\u62d3\u5c55\u4f9d\u8d56\uff0c",(0,o.kt)("strong",{parentName:"p"},"\u4f46\u6709\u65f6\u5019\u6211\u4eec\u4e0d\u5e0c\u671b\u53d1\u5e03\u5230 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Nuget")," \u5e73\u53f0\u6216\u8005\u53ea\u60f3\u5728\u672c\u5730\u4f7f\u7528\u53c8\u6216\u8005\u5148\u5728\u672c\u5730\u6d4b\u8bd5\u901a\u8fc7\u518d\u53d1\u5e03\u3002")),(0,o.kt)("p",null,"\u8fd9\u6837\u505a\u7684\u597d\u5904\u662f\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u53ef\u4ee5\u6709\u6548\u4fdd\u62a4\u516c\u53f8\u6838\u5fc3\u4ee3\u7801"),(0,o.kt)("li",{parentName:"ul"},"\u65b9\u4fbf\u5f00\u6e90\u9879\u76ee\u6d4b\u8bd5")),(0,o.kt)("h2",{id:"292-\u5982\u4f55\u914d\u7f6e"},"2.9.2 \u5982\u4f55\u914d\u7f6e"),(0,o.kt)("h3",{id:"2921-\u6d4b\u8bd5\u5305\u547d\u540d\u89c4\u5219"},"2.9.2.1 \u6d4b\u8bd5\u5305\u547d\u540d\u89c4\u5219"),(0,o.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u4f1a\u6839\u636e ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion.\u7248\u672c\u53f7-beta.Issue\u7f16\u53f7")," \u89c4\u5219\u751f\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},".nupkg")," \u548c ",(0,o.kt)("inlineCode",{parentName:"p"},".snupkg")," \u5305\uff0c\u524d\u8005\u662f\u4e0d\u5305\u542b\u8c03\u8bd5\u7684\u65e0\u7b26\u53f7 ",(0,o.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5305\uff0c\u540e\u8005\u5219\u662f\u8c03\u8bd5\u7b26\u53f7\u5305\uff08\u65b9\u4fbf ",(0,o.kt)("inlineCode",{parentName:"p"},"IDE")," \u8c03\u8bd5\u7528\u7684\uff09\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-showLineNumbers",metastring:'title="D:\\Furion_Nuget_Test_Packages"',title:'"D:\\Furion_Nuget_Test_Packages"'},"Furion.4.2.3-beta-I5MM3O.nupkg\nFurion.4.2.3-beta-I5MM3O.snupkg\n")),(0,o.kt)("p",null,"\u5176\u4e2d ",(0,o.kt)("inlineCode",{parentName:"p"},"I5MM3O")," \u5bf9\u5e94\u7684\u6b63\u662f ",(0,o.kt)("inlineCode",{parentName:"p"},"Issue")," \u7684\u7f16\u53f7\uff1a",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/I5MM3O"},"https://gitee.com/dotnetchina/Furion/issues/I5MM3O")),(0,o.kt)("h3",{id:"2922-\u914d\u7f6e\u672c\u5730\u5305\u8def\u5f84"},"2.9.2.2 \u914d\u7f6e\u672c\u5730\u5305\u8def\u5f84"),(0,o.kt)("p",null,"\u6709\u4e86\u8fd9\u4e24\u4e2a\u5305\u4e4b\u540e\uff0c\u5c31\u53ef\u4ee5\u5728\u672c\u5730\u78c1\u76d8\u4e2d\u521b\u5efa\u6587\u4ef6\u5939\u5e76\u653e\u8fdb\u53bb\uff0c\u5982 ",(0,o.kt)("inlineCode",{parentName:"p"},"D:\\Furion_Nuget_Test_Packages"),"\u3002"),(0,o.kt)("img",{src:(0,a.Z)("img/ng1.png")}),(0,o.kt)("h3",{id:"2923-\u5728-visual-studio-\u4e2d\u914d\u7f6e\u8def\u5f84"},"2.9.2.3 \u5728 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Visual Studio")," \u4e2d\u914d\u7f6e\u8def\u5f84"),(0,o.kt)("img",{src:(0,a.Z)("img/ng2.png")}),(0,o.kt)("img",{src:(0,a.Z)("img/ng3.png")}),(0,o.kt)("img",{src:(0,a.Z)("img/ng4.png")}),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u547d\u4ee4\u884c\u64cd\u4f5c",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4e0d\u4f7f\u7528\u53ef\u89c6\u5316 ",(0,o.kt)("inlineCode",{parentName:"p"},"IDE")," \u914d\u7f6e\uff0c\u53ef\u901a\u8fc7\u4e0b\u5217\u547d\u4ee4\u884c\u914d\u7f6e\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'dotnet restore "YourProject.Web.Entry/YourProject.Web.Entry.csproj" -s "D:\\Furion_Nuget_Test_Packages";\ndotnet restore "YourProject.Web.Entry/YourProject.Web.Entry.csproj" -s "https://api.nuget.org/v3/index.json";\n'))),(0,o.kt)("h3",{id:"2924-\u9009\u62e9\u6d4b\u8bd5\u7248\u5b89\u88c5\u6216\u66f4\u65b0"},"2.9.2.4 \u9009\u62e9\u6d4b\u8bd5\u7248\u5b89\u88c5\u6216\u66f4\u65b0"),(0,o.kt)("img",{src:(0,a.Z)("img/ng5.png")}),(0,o.kt)("img",{src:(0,a.Z)("img/ng6.png")}),(0,o.kt)("img",{src:(0,a.Z)("img/ng7.png")}),(0,o.kt)("br",null),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u6d4b\u8bd5\u901a\u8fc7\u540e\u53ef\u4ee5\u5220\u9664\u4e4b\u524d\u7684\u914d\u7f6e\u5373\u53ef"),"\uff0c\u5982\uff1a"),(0,o.kt)("img",{src:(0,a.Z)("img/ng8.png")}),(0,o.kt)("h2",{id:"293-visual-studio-\u8c03\u8bd5-nuget-\u5305"},"2.9.3 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Visual Studio")," \u8c03\u8bd5 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Nuget")," \u5305"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},".snupkg")," \u5305\uff0c\u5728\u5b89\u88c5 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u7684\u65f6\u5019\u81ea\u52a8\u4e0b\u8f7d\u5230\u672c\u5730\uff0c\u5982\u9700\u542f\u7528\u6e90\u7801\u8c03\u8bd5\uff0c\u53ea\u9700\u8981\u542f\u7528\u4ee5\u4e0b\u914d\u7f6e\u5373\u53ef\uff1a"),(0,o.kt)("img",{src:(0,a.Z)("img/vs10.png")}),(0,o.kt)("p",null,"\u542f\u7528\u4e4b\u540e\u91cd\u65b0\u7f16\u8bd1\u89e3\u51b3\u65b9\u6848\u5c31\u53ef\u4ee5\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"F12")," \u8df3\u8f6c\u5230\u6e90\u4ee3\u7801\u533a\u5e76\u8c03\u8bd5\u6e90\u4ee3\u7801\u4e86\u3002"),(0,o.kt)("h2",{id:"294-\u53cd\u9988\u4e0e\u5efa\u8bae"},"2.9.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/14cdac51.abde07cc.js b/handbook/build/assets/js/14cdac51.abde07cc.js deleted file mode 100644 index e2cf08e5b8..0000000000 --- a/handbook/build/assets/js/14cdac51.abde07cc.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4474],{7533:function(e,t,n){n.r(t),n.d(t,{assets:function(){return p},contentTitle:function(){return s},default:function(){return C},frontMatter:function(){return l},metadata:function(){return c},toc:function(){return m}});var o=n(3117),a=n(102),r=(n(7294),n(3905)),i=["components"],l={id:"entity",title:"9.3 \u6570\u636e\u5e93\u5b9e\u4f53",sidebar_label:"9.3 \u6570\u636e\u5e93\u5b9e\u4f53"},s=void 0,c={unversionedId:"entity",id:"entity",title:"9.3 \u6570\u636e\u5e93\u5b9e\u4f53",description:"\u4e00\u65e6\u5b9a\u4e49\u4e86\u5b9e\u4f53\u6216\u6539\u53d8\u4e86\u5b9e\u4f53\u7ed3\u6784\u6216\u5b9e\u4f53\u914d\u7f6e\uff0c\u9700\u8981\u91cd\u65b0\u6267\u884c Add-Migration \u548c Update-Database \u547d\u4ee4\u3002",source:"@site/docs/entity.mdx",sourceDirName:".",slug:"/entity",permalink:"/furion/docs/entity",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/entity.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1655361651,formattedLastUpdatedAt:"Jun 16, 2022",frontMatter:{id:"entity",title:"9.3 \u6570\u636e\u5e93\u5b9e\u4f53",sidebar_label:"9.3 \u6570\u636e\u5e93\u5b9e\u4f53"},sidebar:"docs",previous:{title:"9.2 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668",permalink:"/furion/docs/dbcontext-locator"},next:{title:"9.4 \u4ed3\u50a8\u6a21\u5f0f (Repository)",permalink:"/furion/docs/dbcontext-repository"}},p={},m=[{value:"9.3.1 \u6570\u636e\u5e93\u5b9e\u4f53",id:"931-\u6570\u636e\u5e93\u5b9e\u4f53",level:2},{value:"9.3.2 \u5982\u4f55\u5b9a\u4e49\u5b9e\u4f53",id:"932-\u5982\u4f55\u5b9a\u4e49\u5b9e\u4f53",level:2},{value:"9.3.2.1 \u5b9e\u4f53\u7ee7\u627f\u9009\u7528\u539f\u5219",id:"9321-\u5b9e\u4f53\u7ee7\u627f\u9009\u7528\u539f\u5219",level:3},{value:"9.3.2.2 IEntity \u793a\u8303\uff1a",id:"9322-ientity-\u793a\u8303",level:3},{value:"9.3.2.3 EntityBase \u793a\u8303\uff1a",id:"9323-entitybase-\u793a\u8303",level:3},{value:"9.3.2.4 Entity \u793a\u8303\uff1a",id:"9324-entity-\u793a\u8303",level:3},{value:"9.3.2.5 EntityNotKey \u793a\u8303\uff1a",id:"9325-entitynotkey-\u793a\u8303",level:3},{value:"9.3.3 \u81ea\u5b9a\u4e49\u516c\u5171\u5b9e\u4f53",id:"933-\u81ea\u5b9a\u4e49\u516c\u5171\u5b9e\u4f53",level:2},{value:"9.3.4 \u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e",id:"934-\u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e",level:2},{value:"9.3.4.1 \u5728\u6570\u636e\u5e93\u5b9e\u4f53\u4e2d\u914d\u7f6e",id:"9341-\u5728\u6570\u636e\u5e93\u5b9e\u4f53\u4e2d\u914d\u7f6e",level:3},{value:"9.3.4.2 \u5728\u4efb\u4f55\u5b9e\u4f8b\u7c7b\u4e2d\u914d\u7f6e",id:"9342-\u5728\u4efb\u4f55\u5b9e\u4f8b\u7c7b\u4e2d\u914d\u7f6e",level:3},{value:"9.3.5 \u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e\u8bf4\u660e",id:"935-\u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e\u8bf4\u660e",level:2},{value:"9.3.6 \u914d\u7f6e\u5217\u540d\u53ca\u5217\u7c7b\u578b",id:"936-\u914d\u7f6e\u5217\u540d\u53ca\u5217\u7c7b\u578b",level:2},{value:"9.3.7 \u914d\u7f6e\u6570\u636e\u5e93\u8868\u540d\u548c Schema",id:"937-\u914d\u7f6e\u6570\u636e\u5e93\u8868\u540d\u548c-schema",level:2},{value:"9.3.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"938-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],u={toc:m};function C(e){var t=e.components,n=(0,a.Z)(e,i);return(0,r.kt)("wrapper",(0,o.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("admonition",{title:"\u7279\u522b\u63d0\u9192",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4e00\u65e6\u5b9a\u4e49\u4e86\u5b9e\u4f53\u6216\u6539\u53d8\u4e86\u5b9e\u4f53\u7ed3\u6784\u6216\u5b9e\u4f53\u914d\u7f6e\uff0c\u9700\u8981\u91cd\u65b0\u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"p"},"Add-Migration")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"Update-Database")," \u547d\u4ee4\u3002")),(0,r.kt)("h2",{id:"931-\u6570\u636e\u5e93\u5b9e\u4f53"},"9.3.1 \u6570\u636e\u5e93\u5b9e\u4f53"),(0,r.kt)("p",null,"\u5728\u9762\u5411\u5bf9\u8c61\u5f00\u53d1\u601d\u60f3\u4e2d\uff0c\u6700\u91cd\u8981\u5c24\u4e3a",(0,r.kt)("strong",{parentName:"p"},"\u5bf9\u8c61"),"\u4e8c\u5b57\uff0c\u5728 .NET \u5f00\u53d1\u8fc7\u53bb\uff0c\u64cd\u4f5c\u6570\u636e\u5e93\u5f80\u5f80\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"DataTable")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"DataSet")," \u6765\u63a5\u6536\u6570\u636e\u5e93\u8fd4\u56de\u7ed3\u679c\u96c6\uff0c\u800c\u64cd\u4f5c\u6570\u636e\u5e93\u4e5f\u79bb\u4e0d\u5f00\u624b\u5199 ",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u8bed\u53e5\u3002"),(0,r.kt)("p",null,"\u5728\u8fc7\u53bb\u9762\u5411\u8fc7\u7a0b\u548c\u5e94\u7528\u4e0d\u53d1\u8fbe\u7684\u65f6\u4ee3\uff0c\u8fd9\u4e9b\u64cd\u4f5c\u786e\u5b9e\u597d\u4f7f\u3002\u7136\u540e\u968f\u7740\u4e2d\u56fd\u4e92\u8054\u7f51\u7f51\u6c11\u7684\u6fc0\u589e\uff0c\u7535\u5b50\u5316\u65f6\u4ee3\u7684\u5230\u6765\uff0c\u5404\u884c\u5404\u4e1a\u5bf9\u5e94\u7528\u9700\u6c42\u4e5f\u8fbe\u5230\u4e86\u524d\u6240\u672a\u6709\u7684\u91cf\u7ea7\u3002"),(0,r.kt)("p",null,"\u6240\u4ee5\uff0c\u5728\u8fc7\u53bb\u624b\u5199 ",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u7684\u65f6\u4ee3\u5404\u79cd\u95ee\u9898\u663e\u9732\u65e0\u7591\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u7a0b\u5e8f\u5458\u80fd\u529b\u53c2\u5dee\u4e0d\u9f50\uff0c\u5199\u51fa\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u6027\u80fd\u81ea\u7136\u4e5f\u5929\u5dee\u5730\u522b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u5c5e\u4e8e\u5b57\u7b26\u4e32\u786c\u7f16\u7a0b\uff0c\u540e\u671f\u7ef4\u62a4\u96be\u4e0a\u52a0\u96be"),(0,r.kt)("li",{parentName:"ul"},"\u8bb8\u591a\u5355\u8868\u751a\u81f3\u591a\u8868\u7ed3\u6784\u4e00\u81f4\uff0c\u51fa\u73b0\u5927\u91cf\u91cd\u590d ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u4ee3\u7801"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u672c\u8eab\u5728\u4e0d\u540c\u7684\u6570\u636e\u5e93\u63d0\u4f9b\u5668\u4e2d\u5199\u6cd5\u6709\u5dee\uff0c\u540e\u7eed\u8fc1\u79fb\u5934\u75db\u4e0d\u5df2")),(0,r.kt)("p",null,"\u5f53\u7136\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u662f\u65f6\u4ee3\u7684\u4ea7\u7269\uff0c\u6211\u4eec\u4e5f\u79bb\u4e0d\u5f00 ",(0,r.kt)("inlineCode",{parentName:"p"},"sql"),"\uff0c\u4f46\u5bf9\u4e8e\u5927\u591a\u6570\u7a0b\u5e8f\u5458\u548c\u9879\u76ee\u6765\u8bf4\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u672a\u5fc5\u80fd\u591f\u5e26\u7ed9\u4ed6\u4eec\u591a\u5927\u7684\u6548\u76ca\u3002"),(0,r.kt)("p",null,"\u6240\u4ee5\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"ORM")," \u5c31\u8bde\u751f\u4e86\uff0c\u6240\u8c13\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"ORM")," \u5c31\u662f\u5bf9\u8c61\u5173\u7cfb\u6620\u5c04\uff0c\u82f1\u6587\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"Object Relational Mapping"),"\uff0c\u7b80\u5355\u70b9\u8bf4\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"ORM")," \u6839\u636e\u7279\u6709\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"POCO \u8d2b\u8840\u6a21\u578b")," \u89c4\u5219\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u8bed\u53e5\u3002\u5927\u5927\u907f\u514d\u4e86\u91cd\u590d ",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u80fd\u529b\u53c2\u5dee\u4e0d\u9f50\u7b49\u95ee\u9898\u3002\uff08\u5f53\u7136 ",(0,r.kt)("inlineCode",{parentName:"p"},"ORM")," \u4f5c\u8005 ",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u80fd\u529b\u4e5f\u4f1a\u5f71\u54cd\u6700\u7ec8\u6027\u80fd\uff09"),(0,r.kt)("p",null,"\u4e0a\u9762\u6240\u8bf4\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"POCO")," \u8d2b\u8840\u6a21\u578b\u6b63\u662f\u6211\u4eec\u672c\u7ae0\u8282\u7684 ",(0,r.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u5b9e\u4f53"),"\u3002"),(0,r.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u6570\u636e\u5e93\u5b9e\u4f53\u5c31\u662f\u6570\u636e\u5e93\u8868\u7684\u7c7b\u8868\u73b0\uff0c\u901a\u8fc7\u4e00\u5b9a\u7684\u89c4\u5219\u4f7f\u8fd9\u4e2a\u7c7b\u80fd\u591f\u4e00\u4e00\u5bf9\u5e94\u8868\u7ed3\u6784\u3002\u901a\u5e38\u8fd9\u6837\u7684\u7c7b\u4e5f\u79f0\u4e3a\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"POCO")," \u8d2b\u8840\u6a21\u578b\uff0c\u4e5f\u5c31\u662f\u53ea\u6709\u5b9a\u4e49\uff0c\u6ca1\u6709\u884c\u4e3a\u3002"),(0,r.kt)("h2",{id:"932-\u5982\u4f55\u5b9a\u4e49\u5b9e\u4f53"},"9.3.2 \u5982\u4f55\u5b9a\u4e49\u5b9e\u4f53"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u591a\u79cd\u5b9a\u4e49\u5b9e\u4f53\u7684\u63a5\u53e3\u4f9d\u8d56\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"IEntity"),"\uff1a\u5b9e\u4f53\u57fa\u63a5\u53e3\uff0c\u662f\u6240\u6709\u5b9e\u4f53\u7684\u57fa\u63a5\u53e3"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"IEntityNotKey"),"\uff1a\u65e0\u952e\u5b9e\u4f53\u63a5\u53e3\uff0c\u4e5f\u5c31\u662f\u89c6\u56fe\u3001\u5b58\u50a8\u8fc7\u7a0b\u3001\u51fd\u6570\u4f9d\u8d56\u63a5\u53e3"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EntityBase"),"\uff1a\u5b9e\u4f53\u57fa\u62bd\u8c61\u7c7b\uff0c\u5185\u7f6e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"Id"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"TenantId")," \u5b57\u6bb5"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Entity"),"\uff1a\u5b9e\u4f53\u901a\u7528\u62bd\u8c61\u7c7b\uff0c\u7ee7\u627f\u81ea ",(0,r.kt)("inlineCode",{parentName:"li"},"EntityBase"),"\uff0c\u540c\u65f6\u5185\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"CreatedTime"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"UpdatedTime")," \u5b57\u6bb5"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EntityNotKey"),"\uff1a\u65e0\u952e\u5b9e\u4f53\u62bd\u8c61\u7c7b\uff0c\u89c6\u56fe\u3001\u5b58\u50a8\u8fc7\u7a0b\u3001\u51fd\u6570\u4f9d\u8d56\u62bd\u8c61\u7c7b")),(0,r.kt)("admonition",{title:"\u5b9e\u4f53\u5b9a\u4e49\u4f4d\u7f6e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u6709\u7ea6\u5b9a\uff0c\u5b9e\u4f53\u7edf\u4e00\u5b9a\u4e49\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Core")," \u5c42\u3002")),(0,r.kt)("h3",{id:"9321-\u5b9e\u4f53\u7ee7\u627f\u9009\u7528\u539f\u5219"},"9.3.2.1 \u5b9e\u4f53\u7ee7\u627f\u9009\u7528\u539f\u5219"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u5982\u679c\u4f60\u4e0d\u9700\u8981 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u4e3a\u5b9e\u4f53\u6dfb\u52a0\u4efb\u4f55\u5185\u7f6e\u7279\u6027\uff0c\u9009\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntity"),"\uff0c\u65e0\u952e\u5b9e\u4f53\u9009\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntityNotKey")),(0,r.kt)("li",{parentName:"ul"},"\u5982\u679c\u4f60\u53ea\u9700\u8981 ",(0,r.kt)("inlineCode",{parentName:"li"},"Id")," \u5c5e\u6027\uff0c\u9009\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"EntityBase")),(0,r.kt)("li",{parentName:"ul"},"\u5982\u679c\u4f60\u9700\u8981 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u4e3a\u4f60\u81ea\u52a8\u6dfb\u52a0\u5e38\u7528\u5b57\u6bb5\uff0c\u5219\u9009\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Entity")),(0,r.kt)("li",{parentName:"ul"},"\u5982\u679c\u4f60\u9700\u8981\u89c6\u56fe\u3001\u5b58\u50a8\u8fc7\u7a0b\u3001\u51fd\u6570\u53ef\u4ee5\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"DbSet")," \u64cd\u4f5c\uff0c\u5219\u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"li"},"EntityNotKey"))),(0,r.kt)("h3",{id:"9322-ientity-\u793a\u8303"},"9.3.2.2 ",(0,r.kt)("inlineCode",{parentName:"h3"},"IEntity")," \u793a\u8303\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"":!0,"{1,5}":!0},"using Furion.DatabaseAccessor;\n\nnamespace Furion.Core\n{\n public class User : IEntity\n {\n /// \n /// \u624b\u5de5\u5b9a\u4e49 Id\n /// \n public int Id { get; set; }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n }\n}\n")),(0,r.kt)("h3",{id:"9323-entitybase-\u793a\u8303"},"9.3.2.3 ",(0,r.kt)("inlineCode",{parentName:"h3"},"EntityBase")," \u793a\u8303\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"":!0,"{1,5}":!0},"using Furion.DatabaseAccessor;\n\nnamespace Furion.Core\n{\n public class User : EntityBase\n {\n // \u65e0\u9700\u5b9a\u4e49 Id \u5c5e\u6027\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n }\n}\n")),(0,r.kt)("h3",{id:"9324-entity-\u793a\u8303"},"9.3.2.4 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Entity")," \u793a\u8303\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"":!0,"{1,5}":!0},"using Furion.DatabaseAccessor;\n\nnamespace Furion.Core\n{\n public class User : Entity\n {\n // \u65e0\u9700\u5b9a\u4e49 Id \u5c5e\u6027\n // \u5e76\u81ea\u52a8\u6dfb\u52a0 CreatedTime\uff0cUpdatedTime \u5c5e\u6027\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n }\n}\n")),(0,r.kt)("h3",{id:"9325-entitynotkey-\u793a\u8303"},"9.3.2.5 ",(0,r.kt)("inlineCode",{parentName:"h3"},"EntityNotKey")," \u793a\u8303\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,7-9}",showLineNumbers:!0,"":!0,"{1,5,7-9}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Core\n{\n public class UserView : EntityNotKey\n {\n public UserView() : base("\u89c6\u56fe\u540d\u79f0")\n {\n }\n\n /// \n /// Id\n /// \n public int Id { get; set; }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n }\n}\n')),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u6570\u636e\u5e93\u5b9e\u4f53\u5fc5\u987b\u76f4\u63a5\u6216\u95f4\u63a5\u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"p"},"IEntity")," \u624d\u80fd\u8fdb\u884c\u4ed3\u50a8\u7b49\u64cd\u4f5c\u3002")),(0,r.kt)("h2",{id:"933-\u81ea\u5b9a\u4e49\u516c\u5171\u5b9e\u4f53"},"9.3.3 \u81ea\u5b9a\u4e49\u516c\u5171\u5b9e\u4f53"),(0,r.kt)("p",null,"\u5728\u5b9e\u9645\u9879\u76ee\u5f00\u53d1\u4e2d\uff0c\u6211\u4eec\u901a\u5e38\u6bcf\u4e2a\u5e94\u7528\u7684\u6570\u636e\u5e93\u8868\u90fd\u6709\u4e00\u4e9b\u516c\u5171\u7684\u7c7b\uff0c\u6bd4\u5982\u521b\u5efa\u4eba\uff0c\u521b\u5efa\u65f6\u95f4\u7b49\uff0c\u8fd9\u4e2a\u65f6\u5019\u6211\u4eec\u5c31\u9700\u8981\u81ea\u5b9a\u4e49\u516c\u5171\u5b9e\u4f53\u7c7b\u4e86\u3002"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u521b\u5efa\u516c\u5171\u5b9e\u4f53\u7c7b\u9700\u8981\u6ee1\u8db3\u4ee5\u4e0b\u6761\u4ef6\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u516c\u5171\u5b9e\u4f53\u7c7b",(0,r.kt)("strong",{parentName:"li"},"\u5fc5\u987b\u662f\u516c\u5f00\u4e14\u662f\u62bd\u8c61\u7c7b")),(0,r.kt)("li",{parentName:"ul"},"\u516c\u5171\u5b9e\u4f53\u7c7b\u5fc5\u987b\u542b\u6709\u65e0\u53c2\u6784\u9020\u51fd\u6570"),(0,r.kt)("li",{parentName:"ul"},"\u516c\u5171\u5b9e\u4f53\u7c7b\u5fc5\u987b\u63d0\u4f9b\u6570\u636e\u5e93\u5b9a\u4f4d\u5668\u7684\u652f\u6301")),(0,r.kt)("p",null,"\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {83-91}",showLineNumbers:!0,"":!0,"{83-91}":!0},"using System;\nusing System.ComponentModel.DataAnnotations;\nusing System.ComponentModel.DataAnnotations.Schema;\n\nnamespace Your.Namespace\n{\n public abstract class CommonEntity : CommonEntity\n {\n }\n\n public abstract class CommonEntity : CommonEntity\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n where TDbContextLocator2 : class, IDbContextLocator\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n where TDbContextLocator2 : class, IDbContextLocator\n where TDbContextLocator3 : class, IDbContextLocator\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n where TDbContextLocator2 : class, IDbContextLocator\n where TDbContextLocator3 : class, IDbContextLocator\n where TDbContextLocator4 : class, IDbContextLocator\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n where TDbContextLocator2 : class, IDbContextLocator\n where TDbContextLocator3 : class, IDbContextLocator\n where TDbContextLocator4 : class, IDbContextLocator\n where TDbContextLocator5 : class, IDbContextLocator\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n where TDbContextLocator2 : class, IDbContextLocator\n where TDbContextLocator3 : class, IDbContextLocator\n where TDbContextLocator4 : class, IDbContextLocator\n where TDbContextLocator5 : class, IDbContextLocator\n where TDbContextLocator6 : class, IDbContextLocator\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n where TDbContextLocator2 : class, IDbContextLocator\n where TDbContextLocator3 : class, IDbContextLocator\n where TDbContextLocator4 : class, IDbContextLocator\n where TDbContextLocator5 : class, IDbContextLocator\n where TDbContextLocator6 : class, IDbContextLocator\n where TDbContextLocator7 : class, IDbContextLocator\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n where TDbContextLocator2 : class, IDbContextLocator\n where TDbContextLocator3 : class, IDbContextLocator\n where TDbContextLocator4 : class, IDbContextLocator\n where TDbContextLocator5 : class, IDbContextLocator\n where TDbContextLocator6 : class, IDbContextLocator\n where TDbContextLocator7 : class, IDbContextLocator\n where TDbContextLocator8 : class, IDbContextLocator\n {\n }\n\n public abstract class PrivateCommonEntity : IPrivateEntity\n {\n // \u6ce8\u610f\u662f\u5728\u8fd9\u91cc\u5b9a\u4e49\u4f60\u7684\u516c\u5171\u5b9e\u4f53\n public virtual TKey Id { get; set; }\n\n public virtual DateTime CreatedTime { get; set; }\n\n // \u66f4\u591a\u5c5e\u6027\u5b9a\u4e49\n }\n}\n")),(0,r.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u901a\u8fc7\u4e0a\u9762\u7684\u683c\u5f0f\u5b9a\u4e49\u53ef\u4ee5\u5b8c\u7f8e\u7684\u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\uff0c\u5efa\u8bae\u91c7\u7528\u8fd9\u79cd\u683c\u5f0f\uff0c\u800c\u4e14\u6240\u6709\u7684\u516c\u5171\u5c5e\u6027\u90fd\u5e94\u8be5\u5b9a\u4e49\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"PrivateXXXX")," ",(0,r.kt)("inlineCode",{parentName:"p"},"\u79c1"),"\u6709\u7c7b\u4e2d\u3002")),(0,r.kt)("h2",{id:"934-\u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e"},"9.3.4 \u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e"),(0,r.kt)("p",null,"\u5728\u8fc7\u53bb\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"EF Core")," \u9879\u76ee\u5f00\u53d1\u4e2d\uff0c\u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e\u9700\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"OnModelCreating")," \u4e2d\u914d\u7f6e\u3002",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e3a\u4e86\u7b80\u5316\u914d\u7f6e\u548c\u63d0\u9ad8\u5f00\u53d1\u6548\u7387\uff0c\u62bd\u8c61\u51fa\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"IEntityTypeBuilder")," \u63a5\u53e3\u3002"),(0,r.kt)("p",null,"\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"IEntityTypeBuilder")," \u63a5\u53e3\uff0c\u6211\u4eec\u65e0\u9700\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"OnModelCreating")," \u4e2d\u914d\u7f6e\uff0c\u53ef\u5728\u4efb\u610f\u5730\u65b9\u914d\u7f6e\u3002"),(0,r.kt)("h3",{id:"9341-\u5728\u6570\u636e\u5e93\u5b9e\u4f53\u4e2d\u914d\u7f6e"},"9.3.4.1 \u5728\u6570\u636e\u5e93\u5b9e\u4f53\u4e2d\u914d\u7f6e"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,20-25}",showLineNumbers:!0,"":!0,"{1,5,20-25}":!0},"using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\n\nnamespace Furion.Core\n{\n public class User : Entity, IEntityTypeBuilder\n {\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n\n /// \n /// \u5e74\u9f84\n /// \n public int Age { get; set; }\n\n // \u914d\u7f6e\u6570\u636e\u5e93\u5b9e\u4f53\n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasKey(u => u.Id);\n entityBuilder.HasIndex(u => u.Name);\n }\n }\n}\n")),(0,r.kt)("h3",{id:"9342-\u5728\u4efb\u4f55\u5b9e\u4f8b\u7c7b\u4e2d\u914d\u7f6e"},"9.3.4.2 \u5728\u4efb\u4f55\u5b9e\u4f8b\u7c7b\u4e2d\u914d\u7f6e"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,8,10-14}",showLineNumbers:!0,"":!0,"{1,8,10-14}":!0},"using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\n\nnamespace Furion.Core\n{\n public class SomeClass : IEntityTypeBuilder\n {\n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasKey(u => u.Id);\n entityBuilder.HasIndex(u => u.Name);\n }\n }\n}\n")),(0,r.kt)("p",null,"\u5982\u4e0a\u9762\u4f8b\u5b50\uff0c\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"SomeClass")," \u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"User")," \u6570\u636e\u5e93\u5b9e\u4f53\u3002"),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"note"},(0,r.kt)("p",{parentName:"admonition"}," ",(0,r.kt)("inlineCode",{parentName:"p"},"SomeClass"),"\u5fc5\u987b\u58f0\u660e\u4e3a",(0,r.kt)("inlineCode",{parentName:"p"},"public"),"\uff0c\u5426\u5219\u65e0\u6cd5\u81ea\u52a8\u6ce8\u518c\u3002")),(0,r.kt)("admonition",{title:"\u66f4\u591a\u77e5\u8bc6",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u5982\u9700\u4e86\u89e3\u5b9e\u4f53\u914d\u7f6e\u652f\u6301\u54ea\u4e9b\u914d\u7f6e\u53ef\u67e5\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/ef/core/modeling/"},"\u3010EFCore - \u521b\u5efa\u6a21\u578b\u3011")," \u7ae0\u8282\u3002")),(0,r.kt)("h2",{id:"935-\u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e\u8bf4\u660e"},"9.3.5 \u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e\u8bf4\u660e"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4f1a\u81ea\u52a8\u626b\u63cf\u6240\u6709\u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"p"},"IEntity")," \u63a5\u53e3\u7684\u7c7b\u8fdb\u884c ",(0,r.kt)("inlineCode",{parentName:"p"},"DbSet")," \u6ce8\u518c\uff0c\u4e5f\u5c31\u662f\u5b9e\u73b0\u81ea\u52a8\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"OnModelCreating"),"\u3002"),(0,r.kt)("p",null,"\u5982\u679c\u9700\u8981\u8df3\u8fc7\u81ea\u52a8\u6ce8\u518c\uff0c\u53ea\u9700\u8981\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[Manual]")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"[SuppressSniffer]")," \u7279\u6027\u5373\u53ef\u3002\u4e00\u65e6\u8d34\u4e86\u6b64\u7279\u6027\uff0c\u90a3\u4e48\u5c31\u9700\u8981\u624b\u52a8\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"OnModelCreating")),(0,r.kt)("h2",{id:"936-\u914d\u7f6e\u5217\u540d\u53ca\u5217\u7c7b\u578b"},"9.3.6 \u914d\u7f6e\u5217\u540d\u53ca\u5217\u7c7b\u578b"),(0,r.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u624b\u52a8\u8bbe\u7f6e\u5217\u540d\u6216\u5217\u7c7b\u578b\uff0c\u6bd4\u5982 ",(0,r.kt)("inlineCode",{parentName:"p"},"decimal(18,2)"),"\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u5728\u5c5e\u6027\u4e0a\u9762\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},'[Column("\u5217\u540d", TypeName="decimal(18,2)")]')," \u5373\u53ef\u3002"),(0,r.kt)("h2",{id:"937-\u914d\u7f6e\u6570\u636e\u5e93\u8868\u540d\u548c-schema"},"9.3.7 \u914d\u7f6e\u6570\u636e\u5e93\u8868\u540d\u548c ",(0,r.kt)("inlineCode",{parentName:"h2"},"Schema")),(0,r.kt)("p",null,"\u53ef\u4ee5\u901a\u8fc7\u5728\u5b9e\u4f53\u7c7b\u578b\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},'[Table("\u8868\u540d", "dbo")]')," \u914d\u7f6e\u3002"),(0,r.kt)("h2",{id:"938-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.3.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,r.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}C.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return p},kt:function(){return C}});var o=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=o.createContext({}),c=function(e){var t=o.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return o.createElement(s.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},u=o.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=c(n),C=a,d=u["".concat(s,".").concat(C)]||u[C]||m[C]||r;return n?o.createElement(d,i(i({ref:t},p),{},{components:n})):o.createElement(d,i({ref:t},p))}));function C(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,i=new Array(r);i[0]=u;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;c=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=o.createContext({}),c=function(e){var t=o.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return o.createElement(s.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},u=o.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=c(n),C=a,d=u["".concat(s,".").concat(C)]||u[C]||m[C]||r;return n?o.createElement(d,i(i({ref:t},p),{},{components:n})):o.createElement(d,i({ref:t},p))}));function C(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,i=new Array(r);i[0]=u;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;cIEntity \u793a\u8303\uff1a",id:"9322-ientity-\u793a\u8303",level:3},{value:"9.3.2.3 EntityBase \u793a\u8303\uff1a",id:"9323-entitybase-\u793a\u8303",level:3},{value:"9.3.2.4 Entity \u793a\u8303\uff1a",id:"9324-entity-\u793a\u8303",level:3},{value:"9.3.2.5 EntityNotKey \u793a\u8303\uff1a",id:"9325-entitynotkey-\u793a\u8303",level:3},{value:"9.3.3 \u81ea\u5b9a\u4e49\u516c\u5171\u5b9e\u4f53",id:"933-\u81ea\u5b9a\u4e49\u516c\u5171\u5b9e\u4f53",level:2},{value:"9.3.4 \u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e",id:"934-\u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e",level:2},{value:"9.3.4.1 \u5728\u6570\u636e\u5e93\u5b9e\u4f53\u4e2d\u914d\u7f6e",id:"9341-\u5728\u6570\u636e\u5e93\u5b9e\u4f53\u4e2d\u914d\u7f6e",level:3},{value:"9.3.4.2 \u5728\u4efb\u4f55\u5b9e\u4f8b\u7c7b\u4e2d\u914d\u7f6e",id:"9342-\u5728\u4efb\u4f55\u5b9e\u4f8b\u7c7b\u4e2d\u914d\u7f6e",level:3},{value:"9.3.5 \u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e\u8bf4\u660e",id:"935-\u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e\u8bf4\u660e",level:2},{value:"9.3.6 \u914d\u7f6e\u5217\u540d\u53ca\u5217\u7c7b\u578b",id:"936-\u914d\u7f6e\u5217\u540d\u53ca\u5217\u7c7b\u578b",level:2},{value:"9.3.7 \u914d\u7f6e\u6570\u636e\u5e93\u8868\u540d\u548c Schema",id:"937-\u914d\u7f6e\u6570\u636e\u5e93\u8868\u540d\u548c-schema",level:2},{value:"9.3.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"938-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],u={toc:m};function C(e){var t=e.components,n=(0,a.Z)(e,i);return(0,r.kt)("wrapper",(0,o.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("admonition",{title:"\u7279\u522b\u63d0\u9192",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4e00\u65e6\u5b9a\u4e49\u4e86\u5b9e\u4f53\u6216\u6539\u53d8\u4e86\u5b9e\u4f53\u7ed3\u6784\u6216\u5b9e\u4f53\u914d\u7f6e\uff0c\u9700\u8981\u91cd\u65b0\u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"p"},"Add-Migration")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"Update-Database")," \u547d\u4ee4\u3002")),(0,r.kt)("h2",{id:"931-\u6570\u636e\u5e93\u5b9e\u4f53"},"9.3.1 \u6570\u636e\u5e93\u5b9e\u4f53"),(0,r.kt)("p",null,"\u5728\u9762\u5411\u5bf9\u8c61\u5f00\u53d1\u601d\u60f3\u4e2d\uff0c\u6700\u91cd\u8981\u5c24\u4e3a",(0,r.kt)("strong",{parentName:"p"},"\u5bf9\u8c61"),"\u4e8c\u5b57\uff0c\u5728 .NET \u5f00\u53d1\u8fc7\u53bb\uff0c\u64cd\u4f5c\u6570\u636e\u5e93\u5f80\u5f80\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"DataTable")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"DataSet")," \u6765\u63a5\u6536\u6570\u636e\u5e93\u8fd4\u56de\u7ed3\u679c\u96c6\uff0c\u800c\u64cd\u4f5c\u6570\u636e\u5e93\u4e5f\u79bb\u4e0d\u5f00\u624b\u5199 ",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u8bed\u53e5\u3002"),(0,r.kt)("p",null,"\u5728\u8fc7\u53bb\u9762\u5411\u8fc7\u7a0b\u548c\u5e94\u7528\u4e0d\u53d1\u8fbe\u7684\u65f6\u4ee3\uff0c\u8fd9\u4e9b\u64cd\u4f5c\u786e\u5b9e\u597d\u4f7f\u3002\u7136\u540e\u968f\u7740\u4e2d\u56fd\u4e92\u8054\u7f51\u7f51\u6c11\u7684\u6fc0\u589e\uff0c\u7535\u5b50\u5316\u65f6\u4ee3\u7684\u5230\u6765\uff0c\u5404\u884c\u5404\u4e1a\u5bf9\u5e94\u7528\u9700\u6c42\u4e5f\u8fbe\u5230\u4e86\u524d\u6240\u672a\u6709\u7684\u91cf\u7ea7\u3002"),(0,r.kt)("p",null,"\u6240\u4ee5\uff0c\u5728\u8fc7\u53bb\u624b\u5199 ",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u7684\u65f6\u4ee3\u5404\u79cd\u95ee\u9898\u663e\u9732\u65e0\u7591\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u7a0b\u5e8f\u5458\u80fd\u529b\u53c2\u5dee\u4e0d\u9f50\uff0c\u5199\u51fa\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u6027\u80fd\u81ea\u7136\u4e5f\u5929\u5dee\u5730\u522b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u5c5e\u4e8e\u5b57\u7b26\u4e32\u786c\u7f16\u7a0b\uff0c\u540e\u671f\u7ef4\u62a4\u96be\u4e0a\u52a0\u96be"),(0,r.kt)("li",{parentName:"ul"},"\u8bb8\u591a\u5355\u8868\u751a\u81f3\u591a\u8868\u7ed3\u6784\u4e00\u81f4\uff0c\u51fa\u73b0\u5927\u91cf\u91cd\u590d ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u4ee3\u7801"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u672c\u8eab\u5728\u4e0d\u540c\u7684\u6570\u636e\u5e93\u63d0\u4f9b\u5668\u4e2d\u5199\u6cd5\u6709\u5dee\uff0c\u540e\u7eed\u8fc1\u79fb\u5934\u75db\u4e0d\u5df2")),(0,r.kt)("p",null,"\u5f53\u7136\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u662f\u65f6\u4ee3\u7684\u4ea7\u7269\uff0c\u6211\u4eec\u4e5f\u79bb\u4e0d\u5f00 ",(0,r.kt)("inlineCode",{parentName:"p"},"sql"),"\uff0c\u4f46\u5bf9\u4e8e\u5927\u591a\u6570\u7a0b\u5e8f\u5458\u548c\u9879\u76ee\u6765\u8bf4\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u672a\u5fc5\u80fd\u591f\u5e26\u7ed9\u4ed6\u4eec\u591a\u5927\u7684\u6548\u76ca\u3002"),(0,r.kt)("p",null,"\u6240\u4ee5\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"ORM")," \u5c31\u8bde\u751f\u4e86\uff0c\u6240\u8c13\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"ORM")," \u5c31\u662f\u5bf9\u8c61\u5173\u7cfb\u6620\u5c04\uff0c\u82f1\u6587\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"Object Relational Mapping"),"\uff0c\u7b80\u5355\u70b9\u8bf4\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"ORM")," \u6839\u636e\u7279\u6709\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"POCO \u8d2b\u8840\u6a21\u578b")," \u89c4\u5219\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u8bed\u53e5\u3002\u5927\u5927\u907f\u514d\u4e86\u91cd\u590d ",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u80fd\u529b\u53c2\u5dee\u4e0d\u9f50\u7b49\u95ee\u9898\u3002\uff08\u5f53\u7136 ",(0,r.kt)("inlineCode",{parentName:"p"},"ORM")," \u4f5c\u8005 ",(0,r.kt)("inlineCode",{parentName:"p"},"sql")," \u80fd\u529b\u4e5f\u4f1a\u5f71\u54cd\u6700\u7ec8\u6027\u80fd\uff09"),(0,r.kt)("p",null,"\u4e0a\u9762\u6240\u8bf4\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"POCO")," \u8d2b\u8840\u6a21\u578b\u6b63\u662f\u6211\u4eec\u672c\u7ae0\u8282\u7684 ",(0,r.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u5b9e\u4f53"),"\u3002"),(0,r.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u6570\u636e\u5e93\u5b9e\u4f53\u5c31\u662f\u6570\u636e\u5e93\u8868\u7684\u7c7b\u8868\u73b0\uff0c\u901a\u8fc7\u4e00\u5b9a\u7684\u89c4\u5219\u4f7f\u8fd9\u4e2a\u7c7b\u80fd\u591f\u4e00\u4e00\u5bf9\u5e94\u8868\u7ed3\u6784\u3002\u901a\u5e38\u8fd9\u6837\u7684\u7c7b\u4e5f\u79f0\u4e3a\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"POCO")," \u8d2b\u8840\u6a21\u578b\uff0c\u4e5f\u5c31\u662f\u53ea\u6709\u5b9a\u4e49\uff0c\u6ca1\u6709\u884c\u4e3a\u3002"),(0,r.kt)("h2",{id:"932-\u5982\u4f55\u5b9a\u4e49\u5b9e\u4f53"},"9.3.2 \u5982\u4f55\u5b9a\u4e49\u5b9e\u4f53"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u591a\u79cd\u5b9a\u4e49\u5b9e\u4f53\u7684\u63a5\u53e3\u4f9d\u8d56\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"IEntity"),"\uff1a\u5b9e\u4f53\u57fa\u63a5\u53e3\uff0c\u662f\u6240\u6709\u5b9e\u4f53\u7684\u57fa\u63a5\u53e3"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"IEntityNotKey"),"\uff1a\u65e0\u952e\u5b9e\u4f53\u63a5\u53e3\uff0c\u4e5f\u5c31\u662f\u89c6\u56fe\u3001\u5b58\u50a8\u8fc7\u7a0b\u3001\u51fd\u6570\u4f9d\u8d56\u63a5\u53e3"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EntityBase"),"\uff1a\u5b9e\u4f53\u57fa\u62bd\u8c61\u7c7b\uff0c\u5185\u7f6e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"Id"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"TenantId")," \u5b57\u6bb5"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Entity"),"\uff1a\u5b9e\u4f53\u901a\u7528\u62bd\u8c61\u7c7b\uff0c\u7ee7\u627f\u81ea ",(0,r.kt)("inlineCode",{parentName:"li"},"EntityBase"),"\uff0c\u540c\u65f6\u5185\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"CreatedTime"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"UpdatedTime")," \u5b57\u6bb5"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EntityNotKey"),"\uff1a\u65e0\u952e\u5b9e\u4f53\u62bd\u8c61\u7c7b\uff0c\u89c6\u56fe\u3001\u5b58\u50a8\u8fc7\u7a0b\u3001\u51fd\u6570\u4f9d\u8d56\u62bd\u8c61\u7c7b")),(0,r.kt)("admonition",{title:"\u5b9e\u4f53\u5b9a\u4e49\u4f4d\u7f6e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u6709\u7ea6\u5b9a\uff0c\u5b9e\u4f53\u7edf\u4e00\u5b9a\u4e49\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Core")," \u5c42\u3002")),(0,r.kt)("h3",{id:"9321-\u5b9e\u4f53\u7ee7\u627f\u9009\u7528\u539f\u5219"},"9.3.2.1 \u5b9e\u4f53\u7ee7\u627f\u9009\u7528\u539f\u5219"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u5982\u679c\u4f60\u4e0d\u9700\u8981 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u4e3a\u5b9e\u4f53\u6dfb\u52a0\u4efb\u4f55\u5185\u7f6e\u7279\u6027\uff0c\u9009\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntity"),"\uff0c\u65e0\u952e\u5b9e\u4f53\u9009\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntityNotKey")),(0,r.kt)("li",{parentName:"ul"},"\u5982\u679c\u4f60\u53ea\u9700\u8981 ",(0,r.kt)("inlineCode",{parentName:"li"},"Id")," \u5c5e\u6027\uff0c\u9009\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"EntityBase")),(0,r.kt)("li",{parentName:"ul"},"\u5982\u679c\u4f60\u9700\u8981 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u4e3a\u4f60\u81ea\u52a8\u6dfb\u52a0\u5e38\u7528\u5b57\u6bb5\uff0c\u5219\u9009\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Entity")),(0,r.kt)("li",{parentName:"ul"},"\u5982\u679c\u4f60\u9700\u8981\u89c6\u56fe\u3001\u5b58\u50a8\u8fc7\u7a0b\u3001\u51fd\u6570\u53ef\u4ee5\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"DbSet")," \u64cd\u4f5c\uff0c\u5219\u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"li"},"EntityNotKey"))),(0,r.kt)("h3",{id:"9322-ientity-\u793a\u8303"},"9.3.2.2 ",(0,r.kt)("inlineCode",{parentName:"h3"},"IEntity")," \u793a\u8303\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"":!0,"{1,5}":!0},"using Furion.DatabaseAccessor;\n\nnamespace Furion.Core\n{\n public class User : IEntity\n {\n /// \n /// \u624b\u5de5\u5b9a\u4e49 Id\n /// \n public int Id { get; set; }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n }\n}\n")),(0,r.kt)("h3",{id:"9323-entitybase-\u793a\u8303"},"9.3.2.3 ",(0,r.kt)("inlineCode",{parentName:"h3"},"EntityBase")," \u793a\u8303\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"":!0,"{1,5}":!0},"using Furion.DatabaseAccessor;\n\nnamespace Furion.Core\n{\n public class User : EntityBase\n {\n // \u65e0\u9700\u5b9a\u4e49 Id \u5c5e\u6027\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n }\n}\n")),(0,r.kt)("h3",{id:"9324-entity-\u793a\u8303"},"9.3.2.4 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Entity")," \u793a\u8303\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"":!0,"{1,5}":!0},"using Furion.DatabaseAccessor;\n\nnamespace Furion.Core\n{\n public class User : Entity\n {\n // \u65e0\u9700\u5b9a\u4e49 Id \u5c5e\u6027\n // \u5e76\u81ea\u52a8\u6dfb\u52a0 CreatedTime\uff0cUpdatedTime \u5c5e\u6027\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n }\n}\n")),(0,r.kt)("h3",{id:"9325-entitynotkey-\u793a\u8303"},"9.3.2.5 ",(0,r.kt)("inlineCode",{parentName:"h3"},"EntityNotKey")," \u793a\u8303\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,7-9}",showLineNumbers:!0,"":!0,"{1,5,7-9}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Core\n{\n public class UserView : EntityNotKey\n {\n public UserView() : base("\u89c6\u56fe\u540d\u79f0")\n {\n }\n\n /// \n /// Id\n /// \n public int Id { get; set; }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n }\n}\n')),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u6570\u636e\u5e93\u5b9e\u4f53\u5fc5\u987b\u76f4\u63a5\u6216\u95f4\u63a5\u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"p"},"IEntity")," \u624d\u80fd\u8fdb\u884c\u4ed3\u50a8\u7b49\u64cd\u4f5c\u3002")),(0,r.kt)("h2",{id:"933-\u81ea\u5b9a\u4e49\u516c\u5171\u5b9e\u4f53"},"9.3.3 \u81ea\u5b9a\u4e49\u516c\u5171\u5b9e\u4f53"),(0,r.kt)("p",null,"\u5728\u5b9e\u9645\u9879\u76ee\u5f00\u53d1\u4e2d\uff0c\u6211\u4eec\u901a\u5e38\u6bcf\u4e2a\u5e94\u7528\u7684\u6570\u636e\u5e93\u8868\u90fd\u6709\u4e00\u4e9b\u516c\u5171\u7684\u7c7b\uff0c\u6bd4\u5982\u521b\u5efa\u4eba\uff0c\u521b\u5efa\u65f6\u95f4\u7b49\uff0c\u8fd9\u4e2a\u65f6\u5019\u6211\u4eec\u5c31\u9700\u8981\u81ea\u5b9a\u4e49\u516c\u5171\u5b9e\u4f53\u7c7b\u4e86\u3002"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u521b\u5efa\u516c\u5171\u5b9e\u4f53\u7c7b\u9700\u8981\u6ee1\u8db3\u4ee5\u4e0b\u6761\u4ef6\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u516c\u5171\u5b9e\u4f53\u7c7b",(0,r.kt)("strong",{parentName:"li"},"\u5fc5\u987b\u662f\u516c\u5f00\u4e14\u662f\u62bd\u8c61\u7c7b")),(0,r.kt)("li",{parentName:"ul"},"\u516c\u5171\u5b9e\u4f53\u7c7b\u5fc5\u987b\u542b\u6709\u65e0\u53c2\u6784\u9020\u51fd\u6570"),(0,r.kt)("li",{parentName:"ul"},"\u516c\u5171\u5b9e\u4f53\u7c7b\u5fc5\u987b\u63d0\u4f9b\u6570\u636e\u5e93\u5b9a\u4f4d\u5668\u7684\u652f\u6301")),(0,r.kt)("p",null,"\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {83-91}",showLineNumbers:!0,"":!0,"{83-91}":!0},"using System;\nusing System.ComponentModel.DataAnnotations;\nusing System.ComponentModel.DataAnnotations.Schema;\n\nnamespace Your.Namespace\n{\n public abstract class CommonEntity : CommonEntity\n {\n }\n\n public abstract class CommonEntity : CommonEntity\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n where TDbContextLocator2 : class, IDbContextLocator\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n where TDbContextLocator2 : class, IDbContextLocator\n where TDbContextLocator3 : class, IDbContextLocator\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n where TDbContextLocator2 : class, IDbContextLocator\n where TDbContextLocator3 : class, IDbContextLocator\n where TDbContextLocator4 : class, IDbContextLocator\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n where TDbContextLocator2 : class, IDbContextLocator\n where TDbContextLocator3 : class, IDbContextLocator\n where TDbContextLocator4 : class, IDbContextLocator\n where TDbContextLocator5 : class, IDbContextLocator\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n where TDbContextLocator2 : class, IDbContextLocator\n where TDbContextLocator3 : class, IDbContextLocator\n where TDbContextLocator4 : class, IDbContextLocator\n where TDbContextLocator5 : class, IDbContextLocator\n where TDbContextLocator6 : class, IDbContextLocator\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n where TDbContextLocator2 : class, IDbContextLocator\n where TDbContextLocator3 : class, IDbContextLocator\n where TDbContextLocator4 : class, IDbContextLocator\n where TDbContextLocator5 : class, IDbContextLocator\n where TDbContextLocator6 : class, IDbContextLocator\n where TDbContextLocator7 : class, IDbContextLocator\n {\n }\n\n public abstract class CommonEntity : PrivateCommonEntity\n where TDbContextLocator1 : class, IDbContextLocator\n where TDbContextLocator2 : class, IDbContextLocator\n where TDbContextLocator3 : class, IDbContextLocator\n where TDbContextLocator4 : class, IDbContextLocator\n where TDbContextLocator5 : class, IDbContextLocator\n where TDbContextLocator6 : class, IDbContextLocator\n where TDbContextLocator7 : class, IDbContextLocator\n where TDbContextLocator8 : class, IDbContextLocator\n {\n }\n\n public abstract class PrivateCommonEntity : IPrivateEntity\n {\n // \u6ce8\u610f\u662f\u5728\u8fd9\u91cc\u5b9a\u4e49\u4f60\u7684\u516c\u5171\u5b9e\u4f53\n public virtual TKey Id { get; set; }\n\n public virtual DateTime CreatedTime { get; set; }\n\n // \u66f4\u591a\u5c5e\u6027\u5b9a\u4e49\n }\n}\n")),(0,r.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u901a\u8fc7\u4e0a\u9762\u7684\u683c\u5f0f\u5b9a\u4e49\u53ef\u4ee5\u5b8c\u7f8e\u7684\u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\uff0c\u5efa\u8bae\u91c7\u7528\u8fd9\u79cd\u683c\u5f0f\uff0c\u800c\u4e14\u6240\u6709\u7684\u516c\u5171\u5c5e\u6027\u90fd\u5e94\u8be5\u5b9a\u4e49\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"PrivateXXXX")," ",(0,r.kt)("inlineCode",{parentName:"p"},"\u79c1"),"\u6709\u7c7b\u4e2d\u3002")),(0,r.kt)("h2",{id:"934-\u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e"},"9.3.4 \u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e"),(0,r.kt)("p",null,"\u5728\u8fc7\u53bb\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"EF Core")," \u9879\u76ee\u5f00\u53d1\u4e2d\uff0c\u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e\u9700\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"OnModelCreating")," \u4e2d\u914d\u7f6e\u3002",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e3a\u4e86\u7b80\u5316\u914d\u7f6e\u548c\u63d0\u9ad8\u5f00\u53d1\u6548\u7387\uff0c\u62bd\u8c61\u51fa\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"IEntityTypeBuilder")," \u63a5\u53e3\u3002"),(0,r.kt)("p",null,"\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"IEntityTypeBuilder")," \u63a5\u53e3\uff0c\u6211\u4eec\u65e0\u9700\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"OnModelCreating")," \u4e2d\u914d\u7f6e\uff0c\u53ef\u5728\u4efb\u610f\u5730\u65b9\u914d\u7f6e\u3002"),(0,r.kt)("h3",{id:"9341-\u5728\u6570\u636e\u5e93\u5b9e\u4f53\u4e2d\u914d\u7f6e"},"9.3.4.1 \u5728\u6570\u636e\u5e93\u5b9e\u4f53\u4e2d\u914d\u7f6e"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,20-25}",showLineNumbers:!0,"":!0,"{1,5,20-25}":!0},"using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\n\nnamespace Furion.Core\n{\n public class User : Entity, IEntityTypeBuilder\n {\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n\n /// \n /// \u5e74\u9f84\n /// \n public int Age { get; set; }\n\n // \u914d\u7f6e\u6570\u636e\u5e93\u5b9e\u4f53\n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasKey(u => u.Id);\n entityBuilder.HasIndex(u => u.Name);\n }\n }\n}\n")),(0,r.kt)("h3",{id:"9342-\u5728\u4efb\u4f55\u5b9e\u4f8b\u7c7b\u4e2d\u914d\u7f6e"},"9.3.4.2 \u5728\u4efb\u4f55\u5b9e\u4f8b\u7c7b\u4e2d\u914d\u7f6e"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,8,10-14}",showLineNumbers:!0,"":!0,"{1,8,10-14}":!0},"using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\n\nnamespace Furion.Core\n{\n public class SomeClass : IEntityTypeBuilder\n {\n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasKey(u => u.Id);\n entityBuilder.HasIndex(u => u.Name);\n }\n }\n}\n")),(0,r.kt)("p",null,"\u5982\u4e0a\u9762\u4f8b\u5b50\uff0c\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"SomeClass")," \u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"User")," \u6570\u636e\u5e93\u5b9e\u4f53\u3002"),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"note"},(0,r.kt)("p",{parentName:"admonition"}," ",(0,r.kt)("inlineCode",{parentName:"p"},"SomeClass"),"\u5fc5\u987b\u58f0\u660e\u4e3a",(0,r.kt)("inlineCode",{parentName:"p"},"public"),"\uff0c\u5426\u5219\u65e0\u6cd5\u81ea\u52a8\u6ce8\u518c\u3002")),(0,r.kt)("admonition",{title:"\u66f4\u591a\u77e5\u8bc6",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u5982\u9700\u4e86\u89e3\u5b9e\u4f53\u914d\u7f6e\u652f\u6301\u54ea\u4e9b\u914d\u7f6e\u53ef\u67e5\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/ef/core/modeling/"},"\u3010EFCore - \u521b\u5efa\u6a21\u578b\u3011")," \u7ae0\u8282\u3002")),(0,r.kt)("h2",{id:"935-\u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e\u8bf4\u660e"},"9.3.5 \u6570\u636e\u5e93\u5b9e\u4f53\u914d\u7f6e\u8bf4\u660e"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4f1a\u81ea\u52a8\u626b\u63cf\u6240\u6709\u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"p"},"IEntity")," \u63a5\u53e3\u7684\u7c7b\u8fdb\u884c ",(0,r.kt)("inlineCode",{parentName:"p"},"DbSet")," \u6ce8\u518c\uff0c\u4e5f\u5c31\u662f\u5b9e\u73b0\u81ea\u52a8\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"OnModelCreating"),"\u3002"),(0,r.kt)("p",null,"\u5982\u679c\u9700\u8981\u8df3\u8fc7\u81ea\u52a8\u6ce8\u518c\uff0c\u53ea\u9700\u8981\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[Manual]")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"[SuppressSniffer]")," \u7279\u6027\u5373\u53ef\u3002\u4e00\u65e6\u8d34\u4e86\u6b64\u7279\u6027\uff0c\u90a3\u4e48\u5c31\u9700\u8981\u624b\u52a8\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"OnModelCreating")),(0,r.kt)("h2",{id:"936-\u914d\u7f6e\u5217\u540d\u53ca\u5217\u7c7b\u578b"},"9.3.6 \u914d\u7f6e\u5217\u540d\u53ca\u5217\u7c7b\u578b"),(0,r.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u624b\u52a8\u8bbe\u7f6e\u5217\u540d\u6216\u5217\u7c7b\u578b\uff0c\u6bd4\u5982 ",(0,r.kt)("inlineCode",{parentName:"p"},"decimal(18,2)"),"\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u5728\u5c5e\u6027\u4e0a\u9762\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},'[Column("\u5217\u540d", TypeName="decimal(18,2)")]')," \u5373\u53ef\u3002"),(0,r.kt)("h2",{id:"937-\u914d\u7f6e\u6570\u636e\u5e93\u8868\u540d\u548c-schema"},"9.3.7 \u914d\u7f6e\u6570\u636e\u5e93\u8868\u540d\u548c ",(0,r.kt)("inlineCode",{parentName:"h2"},"Schema")),(0,r.kt)("p",null,"\u53ef\u4ee5\u901a\u8fc7\u5728\u5b9e\u4f53\u7c7b\u578b\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},'[Table("\u8868\u540d", "dbo")]')," \u914d\u7f6e\u3002"),(0,r.kt)("h2",{id:"938-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.3.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,r.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}C.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/17896441.08aa0b1c.js b/handbook/build/assets/js/17896441.08aa0b1c.js deleted file mode 100644 index 52ea352009..0000000000 --- a/handbook/build/assets/js/17896441.08aa0b1c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[7918],{4613:function(e,t,n){n.d(t,{Z:function(){return m}});var a=n(3117),l=n(102),i=n(7294),c=n(6010),s=n(1351),r="tableOfContents_jeP5",o=n(1402),u=["className"];function m(e){var t=e.className,n=(0,l.Z)(e,u);return i.createElement("div",{className:(0,c.Z)(r,"thin-scrollbar",t)},i.createElement(h,null),i.createElement(s.Z,(0,a.Z)({},n,{linkClassName:"table-of-contents__link toc-highlight",linkActiveClassName:"table-of-contents__link--active"})))}function h(){return i.createElement("a",{href:"https://gitee.com/dotnetchina",target:"_blank",style:{display:"block",position:"relative"},title:"\u4e86\u89e3 dotNET China \u7ec4\u7ec7"},i.createElement("img",{src:(0,o.Z)("img/chinadotnet.png"),style:{display:"block",width:"90%",margin:"0 auto"}}))}}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/17896441.d648632e.js b/handbook/build/assets/js/17896441.d648632e.js new file mode 100644 index 0000000000..1f1bb32b9c --- /dev/null +++ b/handbook/build/assets/js/17896441.d648632e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[7918],{541:function(e,t,n){n.d(t,{Z:function(){return m}});var a=n(3117),l=n(102),i=n(7294),c=n(6010),s=n(3743),r="tableOfContents_jeP5",o=n(4996),u=["className"];function m(e){var t=e.className,n=(0,l.Z)(e,u);return i.createElement("div",{className:(0,c.Z)(r,"thin-scrollbar",t)},i.createElement(h,null),i.createElement(s.Z,(0,a.Z)({},n,{linkClassName:"table-of-contents__link toc-highlight",linkActiveClassName:"table-of-contents__link--active"})))}function h(){return i.createElement("a",{href:"https://gitee.com/dotnetchina",target:"_blank",style:{display:"block",position:"relative"},title:"\u4e86\u89e3 dotNET China \u7ec4\u7ec7"},i.createElement("img",{src:(0,o.Z)("img/chinadotnet.png"),style:{display:"block",width:"90%",margin:"0 auto"}}))}}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/1a4e3797.b4a26642.js b/handbook/build/assets/js/1a4e3797.b4a26642.js deleted file mode 100644 index 2d380af639..0000000000 --- a/handbook/build/assets/js/1a4e3797.b4a26642.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see 1a4e3797.b4a26642.js.LICENSE.txt */ -(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[7920],{7331:function(e){function t(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function r(e){return"function"==typeof e}function n(e){return"object"==typeof e&&null!==e}function i(e){return void 0===e}e.exports=t,t.prototype._events=void 0,t.prototype._maxListeners=void 0,t.defaultMaxListeners=10,t.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||isNaN(e))throw TypeError("n must be a positive number");return this._maxListeners=e,this},t.prototype.emit=function(e){var t,a,s,c,u,o;if(this._events||(this._events={}),"error"===e&&(!this._events.error||n(this._events.error)&&!this._events.error.length)){if((t=arguments[1])instanceof Error)throw t;var f=new Error('Uncaught, unspecified "error" event. ('+t+")");throw f.context=t,f}if(i(a=this._events[e]))return!1;if(r(a))switch(arguments.length){case 1:a.call(this);break;case 2:a.call(this,arguments[1]);break;case 3:a.call(this,arguments[1],arguments[2]);break;default:c=Array.prototype.slice.call(arguments,1),a.apply(this,c)}else if(n(a))for(c=Array.prototype.slice.call(arguments,1),s=(o=a.slice()).length,u=0;u0&&this._events[e].length>s&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),"function"==typeof console.trace&&console.trace()),this},t.prototype.on=t.prototype.addListener,t.prototype.once=function(e,t){if(!r(t))throw TypeError("listener must be a function");var n=!1;function i(){this.removeListener(e,i),n||(n=!0,t.apply(this,arguments))}return i.listener=t,this.on(e,i),this},t.prototype.removeListener=function(e,t){var i,a,s,c;if(!r(t))throw TypeError("listener must be a function");if(!this._events||!this._events[e])return this;if(s=(i=this._events[e]).length,a=-1,i===t||r(i.listener)&&i.listener===t)delete this._events[e],this._events.removeListener&&this.emit("removeListener",e,t);else if(n(i)){for(c=s;c-- >0;)if(i[c]===t||i[c].listener&&i[c].listener===t){a=c;break}if(a<0)return this;1===i.length?(i.length=0,delete this._events[e]):i.splice(a,1),this._events.removeListener&&this.emit("removeListener",e,t)}return this},t.prototype.removeAllListeners=function(e){var t,n;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[e]&&delete this._events[e],this;if(0===arguments.length){for(t in this._events)"removeListener"!==t&&this.removeAllListeners(t);return this.removeAllListeners("removeListener"),this._events={},this}if(r(n=this._events[e]))this.removeListener(e,n);else if(n)for(;n.length;)this.removeListener(e,n[n.length-1]);return delete this._events[e],this},t.prototype.listeners=function(e){return this._events&&this._events[e]?r(this._events[e])?[this._events[e]]:this._events[e].slice():[]},t.prototype.listenerCount=function(e){if(this._events){var t=this._events[e];if(r(t))return 1;if(t)return t.length}return 0},t.listenerCount=function(e,t){return e.listenerCount(t)}},7880:function(e,t,r){"use strict";r.d(t,{c:function(){return o}});var n=r(7294),i=r(6832),a=["zero","one","two","few","many","other"];function s(e){return a.filter((function(t){return e.includes(t)}))}var c={locale:"en",pluralForms:s(["one","other"]),select:function(e){return 1===e?"one":"other"}};function u(){var e=(0,i.Z)().i18n.currentLocale;return(0,n.useMemo)((function(){try{return t=e,r=new Intl.PluralRules(t),{locale:t,pluralForms:s(r.resolvedOptions().pluralCategories),select:function(e){return r.select(e)}}}catch(n){return console.error('Failed to use Intl.PluralRules for locale "'+e+'".\nDocusaurus will fallback to the default (English) implementation.\nError: '+n.message+"\n"),c}var t,r}),[e])}function o(){var e=u();return{selectMessage:function(t,r){return function(e,t,r){var n=e.split("|");if(1===n.length)return n[0];n.length>r.pluralForms.length&&console.error("For locale="+r.locale+", a maximum of "+r.pluralForms.length+" plural forms are expected ("+r.pluralForms.join(",")+"), but the message contains "+n.length+": "+e);var i=r.select(t),a=r.pluralForms.indexOf(i);return n[Math.min(a,n.length-1)]}(r,t,e)}}}},4073:function(e,t,r){"use strict";r.r(t),r.d(t,{default:function(){return q}});var n=r(7294);function i(e){var t,r,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t1}));return n.createElement("div",{className:a("col","col--3","padding-left--none",T)},r.map((function(e){var i=e[0],a=e[1],s=r.length>1?i+": ":"";return n.createElement("select",{key:i,onChange:function(e){return t.setSearchVersion(i,e.target.value)},defaultValue:t.searchVersions[i],className:_},a.versions.map((function(e,t){return n.createElement("option",{key:t,label:""+s+e.label,value:e.name})})))})))}function I(){var e,t,r,i,s,u,p=(0,R.Z)(),_=p.siteConfig.themeConfig,T=p.i18n.currentLocale,I=_.algolia,q=I.appId,V=I.apiKey,L=I.indexName,B=I.externalUrlRegex,z=(e=(0,m.c)().selectMessage,function(t){return e(t,(0,b.I)({id:"theme.SearchPage.documentsFound.plurals",description:'Pluralized label for "{count} documents found". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',message:"One document found|{count} documents found"},{count:t}))}),M=(t=(0,F._r)(),r=(0,n.useState)((function(){return Object.entries(t).reduce((function(e,t){var r,n=t[0],i=t[1];return Object.assign({},e,((r={})[n]=i.versions[0].name,r))}),{})})),i=r[0],s=r[1],u=Object.values(t).some((function(e){return e.versions.length>1})),{allDocsData:t,versioningEnabled:u,searchVersions:i,setSearchVersion:function(e,t){return s((function(r){var n;return Object.assign({},r,((n={})[e]=t,n))}))}}),J=(0,g.O)(),U=J.searchQuery,W=J.setSearchQuery,Z={items:[],query:null,totalResults:null,totalPages:null,lastPage:null,hasMore:null,loading:null},X=(0,n.useReducer)((function(e,t){switch(t.type){case"reset":return Z;case"loading":return Object.assign({},e,{loading:!0});case"update":return U!==t.value.query?e:Object.assign({},t.value,{items:0===t.value.lastPage?t.value.items:e.items.concat(t.value.items)});case"advance":var r=e.totalPages>e.lastPage+1;return Object.assign({},e,{lastPage:r?e.lastPage+1:e.lastPage,hasMore:r});default:return e}}),Z),K=X[0],G=X[1],$=c()(q,V),Y=o()($,L,{hitsPerPage:15,advancedSyntax:!0,disjunctiveFacets:["language","docusaurus_tag"]});Y.on("result",(function(e){var t=e.results,r=t.query,n=t.hits,i=t.page,a=t.nbHits,s=t.nbPages;if(""!==r&&Array.isArray(n)){var c=function(e){return e.replace(/algolia-docsearch-suggestion--highlight/g,"search-result-match")},u=n.map((function(e){var t=e.url,r=e._highlightResult.hierarchy,n=e._snippetResult,i=void 0===n?{}:n,a=new URL(t),s=Object.keys(r).map((function(e){return c(r[e].value)}));return{title:s.pop(),url:(0,d.F)(B,a.href)?a.href:a.pathname+a.hash,summary:i.content?c(i.content.value)+"...":"",breadcrumbs:s}}));G({type:"update",value:{items:u,query:r,totalResults:a,totalPages:s,lastPage:i,hasMore:s>i+1,loading:!1}})}else G({type:"reset"})}));var ee=(0,n.useState)(null),te=ee[0],re=ee[1],ne=(0,n.useRef)(0),ie=(0,n.useRef)(l.Z.canUseIntersectionObserver&&new IntersectionObserver((function(e){var t=e[0],r=t.isIntersecting,n=t.boundingClientRect.y;r&&ne.current>n&&G({type:"advance"}),ne.current=n}),{threshold:1})),ae=function(){return U?(0,b.I)({id:"theme.SearchPage.existingResultsTitle",message:'Search results for "{query}"',description:"The search page title for non-empty query"},{query:U}):(0,b.I)({id:"theme.SearchPage.emptyResultsTitle",message:"Search the documentation",description:"The search page title for empty query"})},se=(0,v.zX)((function(e){void 0===e&&(e=0),Y.addDisjunctiveFacetRefinement("docusaurus_tag","default"),Y.addDisjunctiveFacetRefinement("language",T),Object.entries(M.searchVersions).forEach((function(e){var t=e[0],r=e[1];Y.addDisjunctiveFacetRefinement("docusaurus_tag","docs-"+t+"-"+r)})),Y.setQuery(U).setPage(e).search()}));return(0,n.useEffect)((function(){if(te){var e=ie.current;return e?(e.observe(te),function(){return e.unobserve(te)}):function(){return!0}}}),[te]),(0,n.useEffect)((function(){G({type:"reset"}),U&&(G({type:"loading"}),setTimeout((function(){se()}),300))}),[U,M.searchVersions,se]),(0,n.useEffect)((function(){K.lastPage&&0!==K.lastPage&&se(K.lastPage)}),[se,K.lastPage]),n.createElement(P.Z,null,n.createElement(f.Z,null,n.createElement("title",null,(0,y.p)(ae())),n.createElement("meta",{property:"robots",content:"noindex, follow"})),n.createElement("div",{className:"container margin-vert--lg"},n.createElement("h1",null,ae()),n.createElement("form",{className:"row",onSubmit:function(e){return e.preventDefault()}},n.createElement("div",{className:a("col",S,{"col--9":M.versioningEnabled,"col--12":!M.versioningEnabled})},n.createElement("input",{type:"search",name:"q",className:j,placeholder:(0,b.I)({id:"theme.SearchPage.inputPlaceholder",message:"Type your search here",description:"The placeholder for search page input"}),"aria-label":(0,b.I)({id:"theme.SearchPage.inputLabel",message:"Search",description:"The ARIA label for search page input"}),onChange:function(e){return W(e.target.value)},value:U,autoComplete:"off",autoFocus:!0})),M.versioningEnabled&&n.createElement(D,{docsSearchVersionsHelpers:M})),n.createElement("div",{className:"row"},n.createElement("div",{className:a("col","col--8",E)},!!K.totalResults&&z(K.totalResults)),n.createElement("div",{className:a("col","col--4","text--right",Q)},n.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://www.algolia.com/","aria-label":(0,b.I)({id:"theme.SearchPage.algoliaLabel",message:"Search by Algolia",description:"The ARIA label for Algolia mention"})},n.createElement("svg",{viewBox:"0 0 168 24",className:x},n.createElement("g",{fill:"none"},n.createElement("path",{className:O,d:"M120.925 18.804c-4.386.02-4.386-3.54-4.386-4.106l-.007-13.336 2.675-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-10.846-2.18c.821 0 1.43-.047 1.855-.129v-2.719a6.334 6.334 0 0 0-1.574-.199 5.7 5.7 0 0 0-.897.069 2.699 2.699 0 0 0-.814.24c-.24.116-.439.28-.582.491-.15.212-.219.335-.219.656 0 .628.219.991.616 1.23s.938.362 1.615.362zm-.233-9.7c.883 0 1.629.109 2.231.328.602.218 1.088.525 1.444.915.363.396.609.922.76 1.483.157.56.232 1.175.232 1.85v6.874a32.5 32.5 0 0 1-1.868.314c-.834.123-1.772.185-2.813.185-.69 0-1.327-.069-1.895-.198a4.001 4.001 0 0 1-1.471-.636 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.803 0-.656.13-1.073.384-1.525a3.24 3.24 0 0 1 1.047-1.106c.445-.287.95-.492 1.532-.615a8.8 8.8 0 0 1 1.82-.185 8.404 8.404 0 0 1 1.972.24v-.438c0-.307-.035-.6-.11-.874a1.88 1.88 0 0 0-.384-.73 1.784 1.784 0 0 0-.724-.493 3.164 3.164 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.735 7.735 0 0 0-1.26.307l-.321-2.192c.335-.117.834-.233 1.478-.349a10.98 10.98 0 0 1 2.073-.178zm52.842 9.626c.822 0 1.43-.048 1.854-.13V13.7a6.347 6.347 0 0 0-1.574-.199c-.294 0-.595.021-.896.069a2.7 2.7 0 0 0-.814.24 1.46 1.46 0 0 0-.582.491c-.15.212-.218.335-.218.656 0 .628.218.991.615 1.23.404.245.938.362 1.615.362zm-.226-9.694c.883 0 1.629.108 2.231.327.602.219 1.088.526 1.444.915.355.39.609.923.759 1.483a6.8 6.8 0 0 1 .233 1.852v6.873c-.41.088-1.034.19-1.868.314-.834.123-1.772.184-2.813.184-.69 0-1.327-.068-1.895-.198a4.001 4.001 0 0 1-1.471-.635 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.804 0-.656.13-1.073.384-1.524.26-.45.608-.82 1.047-1.107.445-.286.95-.491 1.532-.614a8.803 8.803 0 0 1 2.751-.13c.329.034.671.096 1.04.185v-.437a3.3 3.3 0 0 0-.109-.875 1.873 1.873 0 0 0-.384-.731 1.784 1.784 0 0 0-.724-.492 3.165 3.165 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.75 7.75 0 0 0-1.26.307l-.321-2.193c.335-.116.834-.232 1.478-.348a11.633 11.633 0 0 1 2.073-.177zm-8.034-1.271a1.626 1.626 0 0 1-1.628-1.62c0-.895.725-1.62 1.628-1.62.904 0 1.63.725 1.63 1.62 0 .895-.733 1.62-1.63 1.62zm1.348 13.22h-2.689V7.27l2.69-.423v11.956zm-4.714 0c-4.386.02-4.386-3.54-4.386-4.107l-.008-13.336 2.676-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-8.698-5.903c0-1.156-.253-2.119-.746-2.788-.493-.677-1.183-1.01-2.067-1.01-.882 0-1.574.333-2.065 1.01-.493.676-.733 1.632-.733 2.788 0 1.168.246 1.953.74 2.63.492.683 1.183 1.018 2.066 1.018.882 0 1.574-.342 2.067-1.019.492-.683.738-1.46.738-2.63zm2.737-.007c0 .902-.13 1.584-.397 2.33a5.52 5.52 0 0 1-1.128 1.906 4.986 4.986 0 0 1-1.752 1.223c-.685.286-1.739.45-2.265.45-.528-.006-1.574-.157-2.252-.45a5.096 5.096 0 0 1-1.744-1.223c-.487-.527-.863-1.162-1.137-1.906a6.345 6.345 0 0 1-.41-2.33c0-.902.123-1.77.397-2.508a5.554 5.554 0 0 1 1.15-1.892 5.133 5.133 0 0 1 1.75-1.216c.679-.287 1.425-.423 2.232-.423.808 0 1.553.142 2.237.423a4.88 4.88 0 0 1 1.753 1.216 5.644 5.644 0 0 1 1.135 1.892c.287.738.431 1.606.431 2.508zm-20.138 0c0 1.12.246 2.363.738 2.882.493.52 1.13.78 1.91.78.424 0 .828-.062 1.204-.178.377-.116.677-.253.917-.417V9.33a10.476 10.476 0 0 0-1.766-.226c-.971-.028-1.71.37-2.23 1.004-.513.636-.773 1.75-.773 2.788zm7.438 5.274c0 1.824-.466 3.156-1.404 4.004-.936.846-2.367 1.27-4.296 1.27-.705 0-2.17-.137-3.34-.396l.431-2.118c.98.205 2.272.26 2.95.26 1.074 0 1.84-.219 2.299-.656.459-.437.684-1.086.684-1.948v-.437a8.07 8.07 0 0 1-1.047.397c-.43.13-.93.198-1.492.198-.739 0-1.41-.116-2.018-.349a4.206 4.206 0 0 1-1.567-1.025c-.431-.45-.774-1.017-1.013-1.694-.24-.677-.363-1.885-.363-2.773 0-.834.13-1.88.384-2.577.26-.696.629-1.298 1.129-1.796.493-.498 1.095-.881 1.8-1.162a6.605 6.605 0 0 1 2.428-.457c.87 0 1.67.109 2.45.24.78.129 1.444.265 1.985.415V18.17zM6.972 6.677v1.627c-.712-.446-1.52-.67-2.425-.67-.585 0-1.045.13-1.38.391a1.24 1.24 0 0 0-.502 1.03c0 .425.164.765.494 1.02.33.256.835.532 1.516.83.447.192.795.356 1.045.495.25.138.537.332.862.582.324.25.563.548.718.894.154.345.23.741.23 1.188 0 .947-.334 1.691-1.004 2.234-.67.542-1.537.814-2.601.814-1.18 0-2.16-.229-2.936-.686v-1.708c.84.628 1.814.942 2.92.942.585 0 1.048-.136 1.388-.407.34-.271.51-.646.51-1.125 0-.287-.1-.55-.302-.79-.203-.24-.42-.42-.655-.542-.234-.123-.585-.29-1.053-.503a61.27 61.27 0 0 1-.582-.271 13.67 13.67 0 0 1-.55-.287 4.275 4.275 0 0 1-.567-.351 6.92 6.92 0 0 1-.455-.4c-.18-.17-.31-.34-.39-.51-.08-.17-.155-.37-.224-.598a2.553 2.553 0 0 1-.104-.742c0-.915.333-1.638.998-2.17.664-.532 1.523-.798 2.576-.798.968 0 1.793.17 2.473.51zm7.468 5.696v-.287c-.022-.607-.187-1.088-.495-1.444-.309-.357-.75-.535-1.324-.535-.532 0-.99.194-1.373.583-.382.388-.622.949-.717 1.683h3.909zm1.005 2.792v1.404c-.596.34-1.383.51-2.362.51-1.255 0-2.255-.377-3-1.132-.744-.755-1.116-1.744-1.116-2.968 0-1.297.34-2.316 1.021-3.055.68-.74 1.548-1.11 2.6-1.11 1.033 0 1.852.323 2.458.966.606.644.91 1.572.91 2.784 0 .33-.033.676-.096 1.038h-5.314c.107.702.405 1.239.894 1.611.49.372 1.106.558 1.85.558.862 0 1.58-.202 2.155-.606zm6.605-1.77h-1.212c-.596 0-1.045.116-1.349.35-.303.234-.454.532-.454.894 0 .372.117.664.35.877.235.213.575.32 1.022.32.51 0 .912-.142 1.204-.424.293-.281.44-.651.44-1.108v-.91zm-4.068-2.554V9.325c.627-.361 1.457-.542 2.489-.542 2.116 0 3.175 1.026 3.175 3.08V17h-1.548v-.957c-.415.68-1.143 1.02-2.186 1.02-.766 0-1.38-.22-1.843-.661-.462-.442-.694-1.003-.694-1.684 0-.776.293-1.38.878-1.81.585-.431 1.404-.647 2.457-.647h1.34V11.8c0-.554-.133-.971-.399-1.253-.266-.282-.707-.423-1.324-.423a4.07 4.07 0 0 0-2.345.718zm9.333-1.93v1.42c.394-1 1.101-1.5 2.123-1.5.148 0 .313.016.494.048v1.531a1.885 1.885 0 0 0-.75-.143c-.542 0-.989.24-1.34.718-.351.479-.527 1.048-.527 1.707V17h-1.563V8.91h1.563zm5.01 4.084c.022.82.272 1.492.75 2.019.479.526 1.15.79 2.01.79.639 0 1.235-.176 1.788-.527v1.404c-.521.319-1.186.479-1.995.479-1.265 0-2.276-.4-3.031-1.197-.755-.798-1.133-1.792-1.133-2.984 0-1.16.38-2.151 1.14-2.975.761-.825 1.79-1.237 3.088-1.237.702 0 1.346.149 1.93.447v1.436a3.242 3.242 0 0 0-1.77-.495c-.84 0-1.513.266-2.019.798-.505.532-.758 1.213-.758 2.042zM40.24 5.72v4.579c.458-1 1.293-1.5 2.505-1.5.787 0 1.42.245 1.899.734.479.49.718 1.17.718 2.042V17h-1.564v-5.106c0-.553-.14-.98-.422-1.284-.282-.303-.652-.455-1.11-.455-.531 0-1.002.202-1.411.606-.41.405-.615 1.022-.615 1.851V17h-1.563V5.72h1.563zm14.966 10.02c.596 0 1.096-.253 1.5-.758.404-.506.606-1.157.606-1.955 0-.915-.202-1.62-.606-2.114-.404-.495-.92-.742-1.548-.742-.553 0-1.05.224-1.491.67-.442.447-.662 1.133-.662 2.058 0 .958.212 1.67.638 2.138.425.469.946.703 1.563.703zM53.004 5.72v4.42c.574-.894 1.388-1.341 2.44-1.341 1.022 0 1.857.383 2.506 1.149.649.766.973 1.781.973 3.047 0 1.138-.309 2.109-.925 2.912-.617.803-1.463 1.205-2.537 1.205-1.075 0-1.894-.447-2.457-1.34V17h-1.58V5.72h1.58zm9.908 11.104l-3.223-7.913h1.739l1.005 2.632 1.26 3.415c.096-.32.48-1.458 1.15-3.415l.909-2.632h1.66l-2.92 7.866c-.777 2.074-1.963 3.11-3.559 3.11a2.92 2.92 0 0 1-.734-.079v-1.34c.17.042.351.064.543.064 1.032 0 1.755-.57 2.17-1.708z"}),n.createElement("path",{fill:"#5468FF",d:"M78.988.938h16.594a2.968 2.968 0 0 1 2.966 2.966V20.5a2.967 2.967 0 0 1-2.966 2.964H78.988a2.967 2.967 0 0 1-2.966-2.964V3.897A2.961 2.961 0 0 1 78.988.938z"}),n.createElement("path",{fill:"white",d:"M89.632 5.967v-.772a.978.978 0 0 0-.978-.977h-2.28a.978.978 0 0 0-.978.977v.793c0 .088.082.15.171.13a7.127 7.127 0 0 1 1.984-.28c.65 0 1.295.088 1.917.259.082.02.164-.04.164-.13m-6.248 1.01l-.39-.389a.977.977 0 0 0-1.382 0l-.465.465a.973.973 0 0 0 0 1.38l.383.383c.062.061.15.047.205-.014.226-.307.472-.601.746-.874.281-.28.568-.526.883-.751.068-.042.075-.137.02-.2m4.16 2.453v3.341c0 .096.104.165.192.117l2.97-1.537c.068-.034.089-.117.055-.184a3.695 3.695 0 0 0-3.08-1.866c-.068 0-.136.054-.136.13m0 8.048a4.489 4.489 0 0 1-4.49-4.482 4.488 4.488 0 0 1 4.49-4.482 4.488 4.488 0 0 1 4.489 4.482 4.484 4.484 0 0 1-4.49 4.482m0-10.85a6.363 6.363 0 1 0 0 12.729 6.37 6.37 0 0 0 6.372-6.368 6.358 6.358 0 0 0-6.371-6.36"})))))),K.items.length>0?n.createElement("main",null,K.items.map((function(e,t){var r=e.title,i=e.url,s=e.summary,c=e.breadcrumbs;return n.createElement("article",{key:t,className:w},n.createElement("h2",{className:N},n.createElement(h.Z,{to:i,dangerouslySetInnerHTML:{__html:r}})),c.length>0&&n.createElement("nav",{"aria-label":"breadcrumbs"},n.createElement("ul",{className:a("breadcrumbs",A)},c.map((function(e,t){return n.createElement("li",{key:t,className:"breadcrumbs__item",dangerouslySetInnerHTML:{__html:e}})})))),s&&n.createElement("p",{className:H,dangerouslySetInnerHTML:{__html:s}}))}))):[U&&!K.loading&&n.createElement("p",{key:"no-results"},n.createElement(b.Z,{id:"theme.SearchPage.noResultsText",description:"The paragraph for empty search result"},"No results were found")),!!K.loading&&n.createElement("div",{key:"spinner",className:C})],K.hasMore&&n.createElement("div",{className:k,ref:re},n.createElement(b.Z,{id:"theme.SearchPage.fetchingNewResults",description:"The paragraph for fetching new search results"},"Fetching new results..."))))}function q(){return n.createElement(p.FG,{className:"search-page-wrapper"},n.createElement(I,null))}},5702:function(e,t,r){"use strict";var n=r(8185),i=r(6479),a=r(2956);function s(e,t,r){return new n(e,t,r)}s.version=r(4392),s.AlgoliaSearchHelper=n,s.SearchParameters=i,s.SearchResults=a,e.exports=s},2213:function(e,t,r){"use strict";var n=r(7331);function i(e,t){this.main=e,this.fn=t,this.lastResults=null}r(3412)(i,n),i.prototype.detach=function(){this.removeAllListeners(),this.main.detachDerivedHelper(this)},i.prototype.getModifiedState=function(e){return this.fn(e)},e.exports=i},5396:function(e,t,r){"use strict";var n=r(8937),i=r(9906),a=r(9613),s={addRefinement:function(e,t,r){if(s.isRefined(e,t,r))return e;var i=""+r,a=e[t]?e[t].concat(i):[i],c={};return c[t]=a,n({},c,e)},removeRefinement:function(e,t,r){if(void 0===r)return s.clearRefinement(e,(function(e,r){return t===r}));var n=""+r;return s.clearRefinement(e,(function(e,r){return t===r&&n===e}))},toggleRefinement:function(e,t,r){if(void 0===r)throw new Error("toggleRefinement should be used with a value");return s.isRefined(e,t,r)?s.removeRefinement(e,t,r):s.addRefinement(e,t,r)},clearRefinement:function(e,t,r){if(void 0===t)return a(e)?{}:e;if("string"==typeof t)return i(e,[t]);if("function"==typeof t){var n=!1,s=Object.keys(e).reduce((function(i,a){var s=e[a]||[],c=s.filter((function(e){return!t(e,a,r)}));return c.length!==s.length&&(n=!0),i[a]=c,i}),{});return n?s:e}},isRefined:function(e,t,r){var n=!!e[t]&&e[t].length>0;if(void 0===r||!n)return n;var i=""+r;return-1!==e[t].indexOf(i)}};e.exports=s},6479:function(e,t,r){"use strict";var n=r(7952),i=r(8937),a=r(4720),s=r(4458),c=r(2629),u=r(9906),o=r(9613),f=r(56),h=r(5396);function l(e,t){return Array.isArray(e)&&Array.isArray(t)?e.length===t.length&&e.every((function(e,r){return l(t[r],e)})):e===t}function m(e){var t=e?m._parseNumbers(e):{};void 0===t.userToken||f(t.userToken)||console.warn("[algoliasearch-helper] The `userToken` parameter is invalid. This can lead to wrong analytics.\n - Format: [a-zA-Z0-9_-]{1,64}"),this.facets=t.facets||[],this.disjunctiveFacets=t.disjunctiveFacets||[],this.hierarchicalFacets=t.hierarchicalFacets||[],this.facetsRefinements=t.facetsRefinements||{},this.facetsExcludes=t.facetsExcludes||{},this.disjunctiveFacetsRefinements=t.disjunctiveFacetsRefinements||{},this.numericRefinements=t.numericRefinements||{},this.tagRefinements=t.tagRefinements||[],this.hierarchicalFacetsRefinements=t.hierarchicalFacetsRefinements||{};var r=this;Object.keys(t).forEach((function(e){var n=-1!==m.PARAMETERS.indexOf(e),i=void 0!==t[e];!n&&i&&(r[e]=t[e])}))}m.PARAMETERS=Object.keys(new m),m._parseNumbers=function(e){if(e instanceof m)return e;var t={};if(["aroundPrecision","aroundRadius","getRankingInfo","minWordSizefor2Typos","minWordSizefor1Typo","page","maxValuesPerFacet","distinct","minimumAroundRadius","hitsPerPage","minProximity"].forEach((function(r){var n=e[r];if("string"==typeof n){var i=parseFloat(n);t[r]=isNaN(i)?n:i}})),Array.isArray(e.insideBoundingBox)&&(t.insideBoundingBox=e.insideBoundingBox.map((function(e){return Array.isArray(e)?e.map((function(e){return parseFloat(e)})):e}))),e.numericRefinements){var r={};Object.keys(e.numericRefinements).forEach((function(t){var n=e.numericRefinements[t]||{};r[t]={},Object.keys(n).forEach((function(e){var i=n[e].map((function(e){return Array.isArray(e)?e.map((function(e){return"string"==typeof e?parseFloat(e):e})):"string"==typeof e?parseFloat(e):e}));r[t][e]=i}))})),t.numericRefinements=r}return n({},e,t)},m.make=function(e){var t=new m(e);return(e.hierarchicalFacets||[]).forEach((function(e){if(e.rootPath){var r=t.getHierarchicalRefinement(e.name);r.length>0&&0!==r[0].indexOf(e.rootPath)&&(t=t.clearRefinements(e.name)),0===(r=t.getHierarchicalRefinement(e.name)).length&&(t=t.toggleHierarchicalFacetRefinement(e.name,e.rootPath))}})),t},m.validate=function(e,t){var r=t||{};return e.tagFilters&&r.tagRefinements&&r.tagRefinements.length>0?new Error("[Tags] Cannot switch from the managed tag API to the advanced API. It is probably an error, if it is really what you want, you should first clear the tags with clearTags method."):e.tagRefinements.length>0&&r.tagFilters?new Error("[Tags] Cannot switch from the advanced tag API to the managed API. It is probably an error, if it is not, you should first clear the tags with clearTags method."):e.numericFilters&&r.numericRefinements&&o(r.numericRefinements)?new Error("[Numeric filters] Can't switch from the advanced to the managed API. It is probably an error, if this is really what you want, you have to first clear the numeric filters."):o(e.numericRefinements)&&r.numericFilters?new Error("[Numeric filters] Can't switch from the managed API to the advanced. It is probably an error, if this is really what you want, you have to first clear the numeric filters."):null},m.prototype={constructor:m,clearRefinements:function(e){var t={numericRefinements:this._clearNumericRefinements(e),facetsRefinements:h.clearRefinement(this.facetsRefinements,e,"conjunctiveFacet"),facetsExcludes:h.clearRefinement(this.facetsExcludes,e,"exclude"),disjunctiveFacetsRefinements:h.clearRefinement(this.disjunctiveFacetsRefinements,e,"disjunctiveFacet"),hierarchicalFacetsRefinements:h.clearRefinement(this.hierarchicalFacetsRefinements,e,"hierarchicalFacet")};return t.numericRefinements===this.numericRefinements&&t.facetsRefinements===this.facetsRefinements&&t.facetsExcludes===this.facetsExcludes&&t.disjunctiveFacetsRefinements===this.disjunctiveFacetsRefinements&&t.hierarchicalFacetsRefinements===this.hierarchicalFacetsRefinements?this:this.setQueryParameters(t)},clearTags:function(){return void 0===this.tagFilters&&0===this.tagRefinements.length?this:this.setQueryParameters({tagFilters:void 0,tagRefinements:[]})},setIndex:function(e){return e===this.index?this:this.setQueryParameters({index:e})},setQuery:function(e){return e===this.query?this:this.setQueryParameters({query:e})},setPage:function(e){return e===this.page?this:this.setQueryParameters({page:e})},setFacets:function(e){return this.setQueryParameters({facets:e})},setDisjunctiveFacets:function(e){return this.setQueryParameters({disjunctiveFacets:e})},setHitsPerPage:function(e){return this.hitsPerPage===e?this:this.setQueryParameters({hitsPerPage:e})},setTypoTolerance:function(e){return this.typoTolerance===e?this:this.setQueryParameters({typoTolerance:e})},addNumericRefinement:function(e,t,r){var i=c(r);if(this.isNumericRefined(e,t,i))return this;var a=n({},this.numericRefinements);return a[e]=n({},a[e]),a[e][t]?(a[e][t]=a[e][t].slice(),a[e][t].push(i)):a[e][t]=[i],this.setQueryParameters({numericRefinements:a})},getConjunctiveRefinements:function(e){return this.isConjunctiveFacet(e)&&this.facetsRefinements[e]||[]},getDisjunctiveRefinements:function(e){return this.isDisjunctiveFacet(e)&&this.disjunctiveFacetsRefinements[e]||[]},getHierarchicalRefinement:function(e){return this.hierarchicalFacetsRefinements[e]||[]},getExcludeRefinements:function(e){return this.isConjunctiveFacet(e)&&this.facetsExcludes[e]||[]},removeNumericRefinement:function(e,t,r){return void 0!==r?this.isNumericRefined(e,t,r)?this.setQueryParameters({numericRefinements:this._clearNumericRefinements((function(n,i){return i===e&&n.op===t&&l(n.val,c(r))}))}):this:void 0!==t?this.isNumericRefined(e,t)?this.setQueryParameters({numericRefinements:this._clearNumericRefinements((function(r,n){return n===e&&r.op===t}))}):this:this.isNumericRefined(e)?this.setQueryParameters({numericRefinements:this._clearNumericRefinements((function(t,r){return r===e}))}):this},getNumericRefinements:function(e){return this.numericRefinements[e]||{}},getNumericRefinement:function(e,t){return this.numericRefinements[e]&&this.numericRefinements[e][t]},_clearNumericRefinements:function(e){if(void 0===e)return o(this.numericRefinements)?{}:this.numericRefinements;if("string"==typeof e)return u(this.numericRefinements,[e]);if("function"==typeof e){var t=!1,r=this.numericRefinements,n=Object.keys(r).reduce((function(n,i){var a=r[i],s={};return a=a||{},Object.keys(a).forEach((function(r){var n=a[r]||[],c=[];n.forEach((function(t){e({val:t,op:r},i,"numeric")||c.push(t)})),c.length!==n.length&&(t=!0),s[r]=c})),n[i]=s,n}),{});return t?n:this.numericRefinements}},addFacet:function(e){return this.isConjunctiveFacet(e)?this:this.setQueryParameters({facets:this.facets.concat([e])})},addDisjunctiveFacet:function(e){return this.isDisjunctiveFacet(e)?this:this.setQueryParameters({disjunctiveFacets:this.disjunctiveFacets.concat([e])})},addHierarchicalFacet:function(e){if(this.isHierarchicalFacet(e.name))throw new Error("Cannot declare two hierarchical facets with the same name: `"+e.name+"`");return this.setQueryParameters({hierarchicalFacets:this.hierarchicalFacets.concat([e])})},addFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return h.isRefined(this.facetsRefinements,e,t)?this:this.setQueryParameters({facetsRefinements:h.addRefinement(this.facetsRefinements,e,t)})},addExcludeRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return h.isRefined(this.facetsExcludes,e,t)?this:this.setQueryParameters({facetsExcludes:h.addRefinement(this.facetsExcludes,e,t)})},addDisjunctiveFacetRefinement:function(e,t){if(!this.isDisjunctiveFacet(e))throw new Error(e+" is not defined in the disjunctiveFacets attribute of the helper configuration");return h.isRefined(this.disjunctiveFacetsRefinements,e,t)?this:this.setQueryParameters({disjunctiveFacetsRefinements:h.addRefinement(this.disjunctiveFacetsRefinements,e,t)})},addTagRefinement:function(e){if(this.isTagRefined(e))return this;var t={tagRefinements:this.tagRefinements.concat(e)};return this.setQueryParameters(t)},removeFacet:function(e){return this.isConjunctiveFacet(e)?this.clearRefinements(e).setQueryParameters({facets:this.facets.filter((function(t){return t!==e}))}):this},removeDisjunctiveFacet:function(e){return this.isDisjunctiveFacet(e)?this.clearRefinements(e).setQueryParameters({disjunctiveFacets:this.disjunctiveFacets.filter((function(t){return t!==e}))}):this},removeHierarchicalFacet:function(e){return this.isHierarchicalFacet(e)?this.clearRefinements(e).setQueryParameters({hierarchicalFacets:this.hierarchicalFacets.filter((function(t){return t.name!==e}))}):this},removeFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return h.isRefined(this.facetsRefinements,e,t)?this.setQueryParameters({facetsRefinements:h.removeRefinement(this.facetsRefinements,e,t)}):this},removeExcludeRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return h.isRefined(this.facetsExcludes,e,t)?this.setQueryParameters({facetsExcludes:h.removeRefinement(this.facetsExcludes,e,t)}):this},removeDisjunctiveFacetRefinement:function(e,t){if(!this.isDisjunctiveFacet(e))throw new Error(e+" is not defined in the disjunctiveFacets attribute of the helper configuration");return h.isRefined(this.disjunctiveFacetsRefinements,e,t)?this.setQueryParameters({disjunctiveFacetsRefinements:h.removeRefinement(this.disjunctiveFacetsRefinements,e,t)}):this},removeTagRefinement:function(e){if(!this.isTagRefined(e))return this;var t={tagRefinements:this.tagRefinements.filter((function(t){return t!==e}))};return this.setQueryParameters(t)},toggleRefinement:function(e,t){return this.toggleFacetRefinement(e,t)},toggleFacetRefinement:function(e,t){if(this.isHierarchicalFacet(e))return this.toggleHierarchicalFacetRefinement(e,t);if(this.isConjunctiveFacet(e))return this.toggleConjunctiveFacetRefinement(e,t);if(this.isDisjunctiveFacet(e))return this.toggleDisjunctiveFacetRefinement(e,t);throw new Error("Cannot refine the undeclared facet "+e+"; it should be added to the helper options facets, disjunctiveFacets or hierarchicalFacets")},toggleConjunctiveFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return this.setQueryParameters({facetsRefinements:h.toggleRefinement(this.facetsRefinements,e,t)})},toggleExcludeFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return this.setQueryParameters({facetsExcludes:h.toggleRefinement(this.facetsExcludes,e,t)})},toggleDisjunctiveFacetRefinement:function(e,t){if(!this.isDisjunctiveFacet(e))throw new Error(e+" is not defined in the disjunctiveFacets attribute of the helper configuration");return this.setQueryParameters({disjunctiveFacetsRefinements:h.toggleRefinement(this.disjunctiveFacetsRefinements,e,t)})},toggleHierarchicalFacetRefinement:function(e,t){if(!this.isHierarchicalFacet(e))throw new Error(e+" is not defined in the hierarchicalFacets attribute of the helper configuration");var r=this._getHierarchicalFacetSeparator(this.getHierarchicalFacetByName(e)),n={};return void 0!==this.hierarchicalFacetsRefinements[e]&&this.hierarchicalFacetsRefinements[e].length>0&&(this.hierarchicalFacetsRefinements[e][0]===t||0===this.hierarchicalFacetsRefinements[e][0].indexOf(t+r))?-1===t.indexOf(r)?n[e]=[]:n[e]=[t.slice(0,t.lastIndexOf(r))]:n[e]=[t],this.setQueryParameters({hierarchicalFacetsRefinements:i({},n,this.hierarchicalFacetsRefinements)})},addHierarchicalFacetRefinement:function(e,t){if(this.isHierarchicalFacetRefined(e))throw new Error(e+" is already refined.");if(!this.isHierarchicalFacet(e))throw new Error(e+" is not defined in the hierarchicalFacets attribute of the helper configuration.");var r={};return r[e]=[t],this.setQueryParameters({hierarchicalFacetsRefinements:i({},r,this.hierarchicalFacetsRefinements)})},removeHierarchicalFacetRefinement:function(e){if(!this.isHierarchicalFacetRefined(e))return this;var t={};return t[e]=[],this.setQueryParameters({hierarchicalFacetsRefinements:i({},t,this.hierarchicalFacetsRefinements)})},toggleTagRefinement:function(e){return this.isTagRefined(e)?this.removeTagRefinement(e):this.addTagRefinement(e)},isDisjunctiveFacet:function(e){return this.disjunctiveFacets.indexOf(e)>-1},isHierarchicalFacet:function(e){return void 0!==this.getHierarchicalFacetByName(e)},isConjunctiveFacet:function(e){return this.facets.indexOf(e)>-1},isFacetRefined:function(e,t){return!!this.isConjunctiveFacet(e)&&h.isRefined(this.facetsRefinements,e,t)},isExcludeRefined:function(e,t){return!!this.isConjunctiveFacet(e)&&h.isRefined(this.facetsExcludes,e,t)},isDisjunctiveFacetRefined:function(e,t){return!!this.isDisjunctiveFacet(e)&&h.isRefined(this.disjunctiveFacetsRefinements,e,t)},isHierarchicalFacetRefined:function(e,t){if(!this.isHierarchicalFacet(e))return!1;var r=this.getHierarchicalRefinement(e);return t?-1!==r.indexOf(t):r.length>0},isNumericRefined:function(e,t,r){if(void 0===r&&void 0===t)return!!this.numericRefinements[e];var n=this.numericRefinements[e]&&void 0!==this.numericRefinements[e][t];if(void 0===r||!n)return n;var i,a,u=c(r),o=void 0!==(i=this.numericRefinements[e][t],a=u,s(i,(function(e){return l(e,a)})));return n&&o},isTagRefined:function(e){return-1!==this.tagRefinements.indexOf(e)},getRefinedDisjunctiveFacets:function(){var e=this,t=a(Object.keys(this.numericRefinements).filter((function(t){return Object.keys(e.numericRefinements[t]).length>0})),this.disjunctiveFacets);return Object.keys(this.disjunctiveFacetsRefinements).filter((function(t){return e.disjunctiveFacetsRefinements[t].length>0})).concat(t).concat(this.getRefinedHierarchicalFacets())},getRefinedHierarchicalFacets:function(){var e=this;return a(this.hierarchicalFacets.map((function(e){return e.name})),Object.keys(this.hierarchicalFacetsRefinements).filter((function(t){return e.hierarchicalFacetsRefinements[t].length>0})))},getUnrefinedDisjunctiveFacets:function(){var e=this.getRefinedDisjunctiveFacets();return this.disjunctiveFacets.filter((function(t){return-1===e.indexOf(t)}))},managedParameters:["index","facets","disjunctiveFacets","facetsRefinements","hierarchicalFacets","facetsExcludes","disjunctiveFacetsRefinements","numericRefinements","tagRefinements","hierarchicalFacetsRefinements"],getQueryParams:function(){var e=this.managedParameters,t={},r=this;return Object.keys(this).forEach((function(n){var i=r[n];-1===e.indexOf(n)&&void 0!==i&&(t[n]=i)})),t},setQueryParameter:function(e,t){if(this[e]===t)return this;var r={};return r[e]=t,this.setQueryParameters(r)},setQueryParameters:function(e){if(!e)return this;var t=m.validate(this,e);if(t)throw t;var r=this,n=m._parseNumbers(e),i=Object.keys(this).reduce((function(e,t){return e[t]=r[t],e}),{}),a=Object.keys(n).reduce((function(e,t){var r=void 0!==e[t],i=void 0!==n[t];return r&&!i?u(e,[t]):(i&&(e[t]=n[t]),e)}),i);return new this.constructor(a)},resetPage:function(){return void 0===this.page?this:this.setPage(0)},_getHierarchicalFacetSortBy:function(e){return e.sortBy||["isRefined:desc","name:asc"]},_getHierarchicalFacetSeparator:function(e){return e.separator||" > "},_getHierarchicalRootPath:function(e){return e.rootPath||null},_getHierarchicalShowParentLevel:function(e){return"boolean"!=typeof e.showParentLevel||e.showParentLevel},getHierarchicalFacetByName:function(e){return s(this.hierarchicalFacets,(function(t){return t.name===e}))},getHierarchicalFacetBreadcrumb:function(e){if(!this.isHierarchicalFacet(e))return[];var t=this.getHierarchicalRefinement(e)[0];if(!t)return[];var r=this._getHierarchicalFacetSeparator(this.getHierarchicalFacetByName(e));return t.split(r).map((function(e){return e.trim()}))},toString:function(){return JSON.stringify(this,null,2)}},e.exports=m},9677:function(e,t,r){"use strict";e.exports=function(e){return function(t,r){var s=e.hierarchicalFacets[r],o=e.hierarchicalFacetsRefinements[s.name]&&e.hierarchicalFacetsRefinements[s.name][0]||"",f=e._getHierarchicalFacetSeparator(s),h=e._getHierarchicalRootPath(s),l=e._getHierarchicalShowParentLevel(s),m=a(e._getHierarchicalFacetSortBy(s)),d=t.every((function(e){return e.exhaustive})),v=function(e,t,r,a,s){return function(o,f,h){var l=o;if(h>0){var m=0;for(l=o;m-1})));if(s){var f=s.attributes.indexOf(t),l=u(e.hierarchicalFacets,(function(e){return e.name===s.name}));o.hierarchicalFacets[l][f]={attribute:t,data:i,exhaustive:a.exhaustiveFacetsCount}}else{var m,d=-1!==e.disjunctiveFacets.indexOf(t),g=-1!==e.facets.indexOf(t);d&&(m=p[t],o.disjunctiveFacets[m]={name:t,data:i,exhaustive:a.exhaustiveFacetsCount},v(o.disjunctiveFacets[m],a.facets_stats,t)),g&&(m=h[t],o.facets[m]={name:t,data:i,exhaustive:a.exhaustiveFacetsCount},v(o.facets[m],a.facets_stats,t))}})),this.hierarchicalFacets=s(this.hierarchicalFacets),f.forEach((function(r){var s=t[g],c=s&&s.facets?s.facets:{},f=e.getHierarchicalFacetByName(r);Object.keys(c).forEach((function(t){var r,h=c[t];if(f){r=u(e.hierarchicalFacets,(function(e){return e.name===f.name}));var m=u(o.hierarchicalFacets[r],(function(e){return e.attribute===t}));if(-1===m)return;o.hierarchicalFacets[r][m].data=n({},o.hierarchicalFacets[r][m].data,h)}else{r=p[t];var d=a.facets&&a.facets[t]||{};o.disjunctiveFacets[r]={name:t,data:i({},h,d),exhaustive:s.exhaustiveFacetsCount},v(o.disjunctiveFacets[r],s.facets_stats,t),e.disjunctiveFacetsRefinements[t]&&e.disjunctiveFacetsRefinements[t].forEach((function(n){!o.disjunctiveFacets[r].data[n]&&e.disjunctiveFacetsRefinements[t].indexOf(l(n))>-1&&(o.disjunctiveFacets[r].data[n]=0)}))}})),g++})),e.getRefinedHierarchicalFacets().forEach((function(r){var n=e.getHierarchicalFacetByName(r),a=e._getHierarchicalFacetSeparator(n),s=e.getHierarchicalRefinement(r);0===s.length||s[0].split(a).length<2||t.slice(g).forEach((function(t){var r=t&&t.facets?t.facets:{};Object.keys(r).forEach((function(t){var c=r[t],f=u(e.hierarchicalFacets,(function(e){return e.name===n.name})),h=u(o.hierarchicalFacets[f],(function(e){return e.attribute===t}));if(-1!==h){var l={};if(s.length>0){var m=s[0].split(a)[0];l[m]=o.hierarchicalFacets[f][h].data[m]}o.hierarchicalFacets[f][h].data=i(l,c,o.hierarchicalFacets[f][h].data)}})),g++}))})),Object.keys(e.facetsExcludes).forEach((function(t){var r=e.facetsExcludes[t],n=h[t];o.facets[n]={name:t,data:a.facets[t],exhaustive:a.exhaustiveFacetsCount},r.forEach((function(e){o.facets[n]=o.facets[n]||{name:t},o.facets[n].data=o.facets[n].data||{},o.facets[n].data[e]=0}))})),this.hierarchicalFacets=this.hierarchicalFacets.map(m(e)),this.facets=s(this.facets),this.disjunctiveFacets=s(this.disjunctiveFacets),this._state=e}function g(e,t,r,n){if(n=n||0,Array.isArray(t))return e(t,r[n]);if(!t.data||0===t.data.length)return t;var a=t.data.map((function(t){return g(e,t,r,n+1)})),s=e(a,r[n]);return i({data:s},t)}function y(e,t){var r=c(e,(function(e){return e.name===t}));return r&&r.stats}function R(e,t,r,n,i){var a=c(i,(function(e){return e.name===r})),s=a&&a.data&&a.data[n]?a.data[n]:0,u=a&&a.exhaustive||!1;return{type:t,attributeName:r,name:n,count:s,exhaustive:u}}p.prototype.getFacetByName=function(e){function t(t){return t.name===e}return c(this.facets,t)||c(this.disjunctiveFacets,t)||c(this.hierarchicalFacets,t)},p.DEFAULT_SORT=["isRefined:desc","count:desc","name:asc"],p.prototype.getFacetValues=function(e,t){var r=function(e,t){function r(e){return e.name===t}if(e._state.isConjunctiveFacet(t)){var n=c(e.facets,r);return n?Object.keys(n.data).map((function(r){var i=h(r);return{name:r,escapedValue:i,count:n.data[r],isRefined:e._state.isFacetRefined(t,i),isExcluded:e._state.isExcludeRefined(t,r)}})):[]}if(e._state.isDisjunctiveFacet(t)){var i=c(e.disjunctiveFacets,r);return i?Object.keys(i.data).map((function(r){var n=h(r);return{name:r,escapedValue:n,count:i.data[r],isRefined:e._state.isDisjunctiveFacetRefined(t,n)}})):[]}if(e._state.isHierarchicalFacet(t))return c(e.hierarchicalFacets,r)}(this,e);if(r){var n,s=i({},t,{sortBy:p.DEFAULT_SORT,facetOrdering:!(t&&t.sortBy)}),u=this;if(Array.isArray(r))n=[e];else n=u._state.getHierarchicalFacetByName(r.name).attributes;return g((function(e,t){if(s.facetOrdering){var r=function(e,t){return e.renderingContent&&e.renderingContent.facetOrdering&&e.renderingContent.facetOrdering.values&&e.renderingContent.facetOrdering.values[t]}(u,t);if(Boolean(r))return function(e,t){var r=[],n=[],i=(t.order||[]).reduce((function(e,t,r){return e[t]=r,e}),{});e.forEach((function(e){var t=e.path||e.name;void 0!==i[t]?r[i[t]]=e:n.push(e)})),r=r.filter((function(e){return e}));var s,c=t.sortRemainingBy;return"hidden"===c?r:(s="alpha"===c?[["path","name"],["asc","asc"]]:[["count"],["desc"]],r.concat(a(n,s[0],s[1])))}(e,r)}if(Array.isArray(s.sortBy)){var n=o(s.sortBy,p.DEFAULT_SORT);return a(e,n[0],n[1])}if("function"==typeof s.sortBy)return function(e,t){return t.sort(e)}(s.sortBy,e);throw new Error("options.sortBy is optional but if defined it must be either an array of string (predicates) or a sorting function")}),r,n)}},p.prototype.getFacetStats=function(e){return this._state.isConjunctiveFacet(e)?y(this.facets,e):this._state.isDisjunctiveFacet(e)?y(this.disjunctiveFacets,e):void 0},p.prototype.getRefinements=function(){var e=this._state,t=this,r=[];return Object.keys(e.facetsRefinements).forEach((function(n){e.facetsRefinements[n].forEach((function(i){r.push(R(e,"facet",n,i,t.facets))}))})),Object.keys(e.facetsExcludes).forEach((function(n){e.facetsExcludes[n].forEach((function(i){r.push(R(e,"exclude",n,i,t.facets))}))})),Object.keys(e.disjunctiveFacetsRefinements).forEach((function(n){e.disjunctiveFacetsRefinements[n].forEach((function(i){r.push(R(e,"disjunctive",n,i,t.disjunctiveFacets))}))})),Object.keys(e.hierarchicalFacetsRefinements).forEach((function(n){e.hierarchicalFacetsRefinements[n].forEach((function(i){r.push(function(e,t,r,n){var i=e.getHierarchicalFacetByName(t),a=e._getHierarchicalFacetSeparator(i),s=r.split(a),u=c(n,(function(e){return e.name===t})),o=s.reduce((function(e,t){var r=e&&c(e.data,(function(e){return e.name===t}));return void 0!==r?r:e}),u),f=o&&o.count||0,h=o&&o.exhaustive||!1,l=o&&o.path||"";return{type:"hierarchical",attributeName:t,name:l,count:f,exhaustive:h}}(e,n,i,t.hierarchicalFacets))}))})),Object.keys(e.numericRefinements).forEach((function(t){var n=e.numericRefinements[t];Object.keys(n).forEach((function(e){n[e].forEach((function(n){r.push({type:"numeric",attributeName:t,name:n,numericValue:n,operator:e})}))}))})),e.tagRefinements.forEach((function(e){r.push({type:"tag",attributeName:"_tags",name:e})})),r},e.exports=p},8185:function(e,t,r){"use strict";var n=r(6479),i=r(2956),a=r(2213),s=r(5187),c=r(7331),u=r(3412),o=r(9613),f=r(9906),h=r(7952),l=r(4392),m=r(7050).escapeFacetValue;function d(e,t,r){"function"==typeof e.addAlgoliaAgent&&e.addAlgoliaAgent("JS Helper ("+l+")"),this.setClient(e);var i=r||{};i.index=t,this.state=n.make(i),this.lastResults=null,this._queryId=0,this._lastQueryIdReceived=-1,this.derivedHelpers=[],this._currentNbQueries=0}function v(e){if(e<0)throw new Error("Page requested below 0.");return this._change({state:this.state.setPage(e),isPageReset:!1}),this}function p(){return this.state.page}u(d,c),d.prototype.search=function(){return this._search({onlyWithDerivedHelpers:!1}),this},d.prototype.searchOnlyWithDerivedHelpers=function(){return this._search({onlyWithDerivedHelpers:!0}),this},d.prototype.getQuery=function(){var e=this.state;return s._getHitsSearchParams(e)},d.prototype.searchOnce=function(e,t){var r=e?this.state.setQueryParameters(e):this.state,n=s._getQueries(r.index,r),a=this;if(this._currentNbQueries++,this.emit("searchOnce",{state:r}),!t)return this.client.search(n).then((function(e){return a._currentNbQueries--,0===a._currentNbQueries&&a.emit("searchQueueEmpty"),{content:new i(r,e.results),state:r,_originalResponse:e}}),(function(e){throw a._currentNbQueries--,0===a._currentNbQueries&&a.emit("searchQueueEmpty"),e}));this.client.search(n).then((function(e){a._currentNbQueries--,0===a._currentNbQueries&&a.emit("searchQueueEmpty"),t(null,new i(r,e.results),r)})).catch((function(e){a._currentNbQueries--,0===a._currentNbQueries&&a.emit("searchQueueEmpty"),t(e,null,r)}))},d.prototype.findAnswers=function(e){var t=this.state,r=this.derivedHelpers[0];if(!r)return Promise.resolve([]);var n=r.getModifiedState(t),i=h({attributesForPrediction:e.attributesForPrediction,nbHits:e.nbHits},{params:f(s._getHitsSearchParams(n),["attributesToSnippet","hitsPerPage","restrictSearchableAttributes","snippetEllipsisText"])}),a="search for answers was called, but this client does not have a function client.initIndex(index).findAnswers";if("function"!=typeof this.client.initIndex)throw new Error(a);var c=this.client.initIndex(n.index);if("function"!=typeof c.findAnswers)throw new Error(a);return c.findAnswers(n.query,e.queryLanguages,i)},d.prototype.searchForFacetValues=function(e,t,r,n){var i="function"==typeof this.client.searchForFacetValues,a="function"==typeof this.client.initIndex;if(!i&&!a&&"function"!=typeof this.client.search)throw new Error("search for facet values (searchable) was called, but this client does not have a function client.searchForFacetValues or client.initIndex(index).searchForFacetValues");var c=this.state.setQueryParameters(n||{}),u=c.isDisjunctiveFacet(e),o=s.getSearchForFacetQuery(e,t,r,c);this._currentNbQueries++;var f,h=this;return i?f=this.client.searchForFacetValues([{indexName:c.index,params:o}]):a?f=this.client.initIndex(c.index).searchForFacetValues(o):(delete o.facetName,f=this.client.search([{type:"facet",facet:e,indexName:c.index,params:o}]).then((function(e){return e.results[0]}))),this.emit("searchForFacetValues",{state:c,facet:e,query:t}),f.then((function(t){return h._currentNbQueries--,0===h._currentNbQueries&&h.emit("searchQueueEmpty"),(t=Array.isArray(t)?t[0]:t).facetHits.forEach((function(t){t.escapedValue=m(t.value),t.isRefined=u?c.isDisjunctiveFacetRefined(e,t.escapedValue):c.isFacetRefined(e,t.escapedValue)})),t}),(function(e){throw h._currentNbQueries--,0===h._currentNbQueries&&h.emit("searchQueueEmpty"),e}))},d.prototype.setQuery=function(e){return this._change({state:this.state.resetPage().setQuery(e),isPageReset:!0}),this},d.prototype.clearRefinements=function(e){return this._change({state:this.state.resetPage().clearRefinements(e),isPageReset:!0}),this},d.prototype.clearTags=function(){return this._change({state:this.state.resetPage().clearTags(),isPageReset:!0}),this},d.prototype.addDisjunctiveFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().addDisjunctiveFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.addDisjunctiveRefine=function(){return this.addDisjunctiveFacetRefinement.apply(this,arguments)},d.prototype.addHierarchicalFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().addHierarchicalFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.addNumericRefinement=function(e,t,r){return this._change({state:this.state.resetPage().addNumericRefinement(e,t,r),isPageReset:!0}),this},d.prototype.addFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().addFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.addRefine=function(){return this.addFacetRefinement.apply(this,arguments)},d.prototype.addFacetExclusion=function(e,t){return this._change({state:this.state.resetPage().addExcludeRefinement(e,t),isPageReset:!0}),this},d.prototype.addExclude=function(){return this.addFacetExclusion.apply(this,arguments)},d.prototype.addTag=function(e){return this._change({state:this.state.resetPage().addTagRefinement(e),isPageReset:!0}),this},d.prototype.removeNumericRefinement=function(e,t,r){return this._change({state:this.state.resetPage().removeNumericRefinement(e,t,r),isPageReset:!0}),this},d.prototype.removeDisjunctiveFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().removeDisjunctiveFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.removeDisjunctiveRefine=function(){return this.removeDisjunctiveFacetRefinement.apply(this,arguments)},d.prototype.removeHierarchicalFacetRefinement=function(e){return this._change({state:this.state.resetPage().removeHierarchicalFacetRefinement(e),isPageReset:!0}),this},d.prototype.removeFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().removeFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.removeRefine=function(){return this.removeFacetRefinement.apply(this,arguments)},d.prototype.removeFacetExclusion=function(e,t){return this._change({state:this.state.resetPage().removeExcludeRefinement(e,t),isPageReset:!0}),this},d.prototype.removeExclude=function(){return this.removeFacetExclusion.apply(this,arguments)},d.prototype.removeTag=function(e){return this._change({state:this.state.resetPage().removeTagRefinement(e),isPageReset:!0}),this},d.prototype.toggleFacetExclusion=function(e,t){return this._change({state:this.state.resetPage().toggleExcludeFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.toggleExclude=function(){return this.toggleFacetExclusion.apply(this,arguments)},d.prototype.toggleRefinement=function(e,t){return this.toggleFacetRefinement(e,t)},d.prototype.toggleFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().toggleFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.toggleRefine=function(){return this.toggleFacetRefinement.apply(this,arguments)},d.prototype.toggleTag=function(e){return this._change({state:this.state.resetPage().toggleTagRefinement(e),isPageReset:!0}),this},d.prototype.nextPage=function(){var e=this.state.page||0;return this.setPage(e+1)},d.prototype.previousPage=function(){var e=this.state.page||0;return this.setPage(e-1)},d.prototype.setCurrentPage=v,d.prototype.setPage=v,d.prototype.setIndex=function(e){return this._change({state:this.state.resetPage().setIndex(e),isPageReset:!0}),this},d.prototype.setQueryParameter=function(e,t){return this._change({state:this.state.resetPage().setQueryParameter(e,t),isPageReset:!0}),this},d.prototype.setState=function(e){return this._change({state:n.make(e),isPageReset:!1}),this},d.prototype.overrideStateWithoutTriggeringChangeEvent=function(e){return this.state=new n(e),this},d.prototype.hasRefinements=function(e){return!!o(this.state.getNumericRefinements(e))||(this.state.isConjunctiveFacet(e)?this.state.isFacetRefined(e):this.state.isDisjunctiveFacet(e)?this.state.isDisjunctiveFacetRefined(e):!!this.state.isHierarchicalFacet(e)&&this.state.isHierarchicalFacetRefined(e))},d.prototype.isExcluded=function(e,t){return this.state.isExcludeRefined(e,t)},d.prototype.isDisjunctiveRefined=function(e,t){return this.state.isDisjunctiveFacetRefined(e,t)},d.prototype.hasTag=function(e){return this.state.isTagRefined(e)},d.prototype.isTagRefined=function(){return this.hasTagRefinements.apply(this,arguments)},d.prototype.getIndex=function(){return this.state.index},d.prototype.getCurrentPage=p,d.prototype.getPage=p,d.prototype.getTags=function(){return this.state.tagRefinements},d.prototype.getRefinements=function(e){var t=[];if(this.state.isConjunctiveFacet(e))this.state.getConjunctiveRefinements(e).forEach((function(e){t.push({value:e,type:"conjunctive"})})),this.state.getExcludeRefinements(e).forEach((function(e){t.push({value:e,type:"exclude"})}));else if(this.state.isDisjunctiveFacet(e)){this.state.getDisjunctiveRefinements(e).forEach((function(e){t.push({value:e,type:"disjunctive"})}))}var r=this.state.getNumericRefinements(e);return Object.keys(r).forEach((function(e){var n=r[e];t.push({value:n,operator:e,type:"numeric"})})),t},d.prototype.getNumericRefinement=function(e,t){return this.state.getNumericRefinement(e,t)},d.prototype.getHierarchicalFacetBreadcrumb=function(e){return this.state.getHierarchicalFacetBreadcrumb(e)},d.prototype._search=function(e){var t=this.state,r=[],n=[];e.onlyWithDerivedHelpers||(n=s._getQueries(t.index,t),r.push({state:t,queriesCount:n.length,helper:this}),this.emit("search",{state:t,results:this.lastResults}));var i=this.derivedHelpers.map((function(e){var n=e.getModifiedState(t),i=s._getQueries(n.index,n);return r.push({state:n,queriesCount:i.length,helper:e}),e.emit("search",{state:n,results:e.lastResults}),i})),a=Array.prototype.concat.apply(n,i),c=this._queryId++;this._currentNbQueries++;try{this.client.search(a).then(this._dispatchAlgoliaResponse.bind(this,r,c)).catch(this._dispatchAlgoliaError.bind(this,c))}catch(u){this.emit("error",{error:u})}},d.prototype._dispatchAlgoliaResponse=function(e,t,r){if(!(t0},d.prototype._change=function(e){var t=e.state,r=e.isPageReset;t!==this.state&&(this.state=t,this.emit("change",{state:this.state,results:this.lastResults,isPageReset:r}))},d.prototype.clearCache=function(){return this.client.clearCache&&this.client.clearCache(),this},d.prototype.setClient=function(e){return this.client===e||("function"==typeof e.addAlgoliaAgent&&e.addAlgoliaAgent("JS Helper ("+l+")"),this.client=e),this},d.prototype.getClient=function(){return this.client},d.prototype.derive=function(e){var t=new a(this,e);return this.derivedHelpers.push(t),t},d.prototype.detachDerivedHelper=function(e){var t=this.derivedHelpers.indexOf(e);if(-1===t)throw new Error("Derived helper already detached");this.derivedHelpers.splice(t,1)},d.prototype.hasPendingRequests=function(){return this._currentNbQueries>0},e.exports=d},8959:function(e){"use strict";e.exports=function(e){return Array.isArray(e)?e.filter(Boolean):[]}},8937:function(e){"use strict";e.exports=function(){var e=Array.prototype.slice.call(arguments);return e.reduceRight((function(e,t){return Object.keys(Object(t)).forEach((function(r){void 0!==t[r]&&(void 0!==e[r]&&delete e[r],e[r]=t[r])})),e}),{})}},7050:function(e){"use strict";e.exports={escapeFacetValue:function(e){return"string"!=typeof e?e:String(e).replace(/^-/,"\\-")},unescapeFacetValue:function(e){return"string"!=typeof e?e:e.replace(/^\\-/,"-")}}},4458:function(e){"use strict";e.exports=function(e,t){if(Array.isArray(e))for(var r=0;r1||!a?(e[0].push(i[0]),e[1].push(i[1]),e):(e[0].push(a[0]),e[1].push(a[1]),e)}),[[],[]])}},3412:function(e){"use strict";e.exports=function(e,t){e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}},4720:function(e){"use strict";e.exports=function(e,t){return e.filter((function(r,n){return t.indexOf(r)>-1&&e.indexOf(r)===n}))}},7952:function(e){"use strict";function t(e){return"function"==typeof e||Array.isArray(e)||"[object Object]"===Object.prototype.toString.call(e)}function r(e,n){if(e===n)return e;for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)&&"__proto__"!==i){var a=n[i],s=e[i];void 0!==s&&void 0===a||(t(s)&&t(a)?e[i]=r(s,a):e[i]="object"==typeof(c=a)&&null!==c?r(Array.isArray(c)?[]:{},c):c)}var c;return e}e.exports=function(e){t(e)||(e={});for(var n=1,i=arguments.length;n0}},9906:function(e){"use strict";e.exports=function(e,t){if(null===e)return{};var r,n,i={},a=Object.keys(e);for(n=0;n=0||(i[r]=e[r]);return i}},2262:function(e){"use strict";function t(e,t){if(e!==t){var r=void 0!==e,n=null===e,i=void 0!==t,a=null===t;if(!a&&e>t||n&&i||!r)return 1;if(!n&&e=n.length?a:"desc"===n[i]?-a:a}return e.index-r.index})),i.map((function(e){return e.value}))}},2629:function(e){"use strict";e.exports=function e(t){if("number"==typeof t)return t;if("string"==typeof t)return parseFloat(t);if(Array.isArray(t))return t.map(e);throw new Error("The value should be a number, a parsable string or an array of those.")}},5187:function(e,t,r){"use strict";var n=r(7952);function i(e){return Object.keys(e).sort((function(e,t){return e.localeCompare(t)})).reduce((function(t,r){return t[r]=e[r],t}),{})}var a={_getQueries:function(e,t){var r=[];return r.push({indexName:e,params:a._getHitsSearchParams(t)}),t.getRefinedDisjunctiveFacets().forEach((function(n){r.push({indexName:e,params:a._getDisjunctiveFacetSearchParams(t,n)})})),t.getRefinedHierarchicalFacets().forEach((function(n){var i=t.getHierarchicalFacetByName(n),s=t.getHierarchicalRefinement(n),c=t._getHierarchicalFacetSeparator(i);if(s.length>0&&s[0].split(c).length>1){var u=s[0].split(c).slice(0,-1).reduce((function(e,t,r){return e.concat({attribute:i.attributes[r],value:0===r?t:[e[e.length-1].value,t].join(c)})}),[]);u.forEach((function(n,i){var s=a._getDisjunctiveFacetSearchParams(t,n.attribute,0===i),c=u[i-1];s.facetFilters=i>0?[c.attribute+":"+c.value]:void 0,r.push({indexName:e,params:s})}))}})),r},_getHitsSearchParams:function(e){var t=e.facets.concat(e.disjunctiveFacets).concat(a._getHitsHierarchicalFacetsAttributes(e)),r=a._getFacetFilters(e),s=a._getNumericFilters(e),c=a._getTagFilters(e),u={facets:t.indexOf("*")>-1?["*"]:t,tagFilters:c};return r.length>0&&(u.facetFilters=r),s.length>0&&(u.numericFilters=s),i(n({},e.getQueryParams(),u))},_getDisjunctiveFacetSearchParams:function(e,t,r){var s=a._getFacetFilters(e,t,r),c=a._getNumericFilters(e,t),u=a._getTagFilters(e),o={hitsPerPage:0,page:0,analytics:!1,clickAnalytics:!1};u.length>0&&(o.tagFilters=u);var f=e.getHierarchicalFacetByName(t);return o.facets=f?a._getDisjunctiveHierarchicalFacetAttribute(e,f,r):t,c.length>0&&(o.numericFilters=c),s.length>0&&(o.facetFilters=s),i(n({},e.getQueryParams(),o))},_getNumericFilters:function(e,t){if(e.numericFilters)return e.numericFilters;var r=[];return Object.keys(e.numericRefinements).forEach((function(n){var i=e.numericRefinements[n]||{};Object.keys(i).forEach((function(e){var a=i[e]||[];t!==n&&a.forEach((function(t){if(Array.isArray(t)){var i=t.map((function(t){return n+e+t}));r.push(i)}else r.push(n+e+t)}))}))})),r},_getTagFilters:function(e){return e.tagFilters?e.tagFilters:e.tagRefinements.join(",")},_getFacetFilters:function(e,t,r){var n=[],i=e.facetsRefinements||{};Object.keys(i).forEach((function(e){(i[e]||[]).forEach((function(t){n.push(e+":"+t)}))}));var a=e.facetsExcludes||{};Object.keys(a).forEach((function(e){(a[e]||[]).forEach((function(t){n.push(e+":-"+t)}))}));var s=e.disjunctiveFacetsRefinements||{};Object.keys(s).forEach((function(e){var r=s[e]||[];if(e!==t&&r&&0!==r.length){var i=[];r.forEach((function(t){i.push(e+":"+t)})),n.push(i)}}));var c=e.hierarchicalFacetsRefinements||{};return Object.keys(c).forEach((function(i){var a=(c[i]||[])[0];if(void 0!==a){var s,u,o=e.getHierarchicalFacetByName(i),f=e._getHierarchicalFacetSeparator(o),h=e._getHierarchicalRootPath(o);if(t===i){if(-1===a.indexOf(f)||!h&&!0===r||h&&h.split(f).length===a.split(f).length)return;h?(u=h.split(f).length-1,a=h):(u=a.split(f).length-2,a=a.slice(0,a.lastIndexOf(f))),s=o.attributes[u]}else u=a.split(f).length-1,s=o.attributes[u];s&&n.push([s+":"+a])}})),n},_getHitsHierarchicalFacetsAttributes:function(e){return e.hierarchicalFacets.reduce((function(t,r){var n=e.getHierarchicalRefinement(r.name)[0];if(!n)return t.push(r.attributes[0]),t;var i=e._getHierarchicalFacetSeparator(r),a=n.split(i).length,s=r.attributes.slice(0,a+1);return t.concat(s)}),[])},_getDisjunctiveHierarchicalFacetAttribute:function(e,t,r){var n=e._getHierarchicalFacetSeparator(t);if(!0===r){var i=e._getHierarchicalRootPath(t),a=0;return i&&(a=i.split(n).length),[t.attributes[a]]}var s=(e.getHierarchicalRefinement(t.name)[0]||"").split(n).length-1;return t.attributes.slice(0,s+1)},getSearchForFacetQuery:function(e,t,r,s){var c=s.isDisjunctiveFacet(e)?s.clearRefinements(e):s,u={facetQuery:t,facetName:e};return"number"==typeof r&&(u.maxFacetHits=r),i(n({},a._getHitsSearchParams(c),u))}};e.exports=a},56:function(e){"use strict";e.exports=function(e){return null!==e&&/^[a-zA-Z0-9_-]{1,64}$/.test(e)}},4392:function(e){"use strict";e.exports="3.10.0"},5157:function(e){e.exports=function(){"use strict";function e(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function t(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function r(r){for(var n=1;n=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}function i(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e)){var r=[],n=!0,i=!1,a=void 0;try{for(var s,c=e[Symbol.iterator]();!(n=(s=c.next()).done)&&(r.push(s.value),!t||r.length!==t);n=!0);}catch(e){i=!0,a=e}finally{try{n||null==c.return||c.return()}finally{if(i)throw a}}return r}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function a(e){return function(e){if(Array.isArray(e)){for(var t=0,r=new Array(e.length);t2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return Promise.resolve().then((function(){var r=JSON.stringify(e),n=a()[r];return Promise.all([n||t(),void 0!==n])})).then((function(e){var t=i(e,2),n=t[0],a=t[1];return Promise.all([n,a||r.miss(n)])})).then((function(e){return i(e,1)[0]}))},set:function(e,t){return Promise.resolve().then((function(){var i=a();return i[JSON.stringify(e)]=t,n().setItem(r,JSON.stringify(i)),t}))},delete:function(e){return Promise.resolve().then((function(){var t=a();delete t[JSON.stringify(e)],n().setItem(r,JSON.stringify(t))}))},clear:function(){return Promise.resolve().then((function(){n().removeItem(r)}))}}}function c(e){var t=a(e.caches),r=t.shift();return void 0===r?{get:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return t().then((function(e){return Promise.all([e,r.miss(e)])})).then((function(e){return i(e,1)[0]}))},set:function(e,t){return Promise.resolve(t)},delete:function(e){return Promise.resolve()},clear:function(){return Promise.resolve()}}:{get:function(e,n){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return r.get(e,n,i).catch((function(){return c({caches:t}).get(e,n,i)}))},set:function(e,n){return r.set(e,n).catch((function(){return c({caches:t}).set(e,n)}))},delete:function(e){return r.delete(e).catch((function(){return c({caches:t}).delete(e)}))},clear:function(){return r.clear().catch((function(){return c({caches:t}).clear()}))}}}function u(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{serializable:!0},t={};return{get:function(r,n){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}},a=JSON.stringify(r);if(a in t)return Promise.resolve(e.serializable?JSON.parse(t[a]):t[a]);var s=n(),c=i&&i.miss||function(){return Promise.resolve()};return s.then((function(e){return c(e)})).then((function(){return s}))},set:function(r,n){return t[JSON.stringify(r)]=e.serializable?JSON.stringify(n):n,Promise.resolve(n)},delete:function(e){return delete t[JSON.stringify(e)],Promise.resolve()},clear:function(){return t={},Promise.resolve()}}}function o(e){for(var t=e.length-1;t>0;t--){var r=Math.floor(Math.random()*(t+1)),n=e[t];e[t]=e[r],e[r]=n}return e}function f(e,t){return t?(Object.keys(t).forEach((function(r){e[r]=t[r](e)})),e):e}function h(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),n=1;n0?n:void 0,timeout:r.timeout||t,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}var d={Read:1,Write:2,Any:3},v=1,p=2,g=3;function y(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:v;return r(r({},e),{},{status:t,lastUpdate:Date.now()})}function R(e){return"string"==typeof e?{protocol:"https",url:e,accept:d.Any}:{protocol:e.protocol||"https",url:e.url,accept:e.accept||d.Any}}var F="GET",b="POST";function P(e,t){return Promise.all(t.map((function(t){return e.get(t,(function(){return Promise.resolve(y(t))}))}))).then((function(e){var r=e.filter((function(e){return function(e){return e.status===v||Date.now()-e.lastUpdate>12e4}(e)})),n=e.filter((function(e){return function(e){return e.status===g&&Date.now()-e.lastUpdate<=12e4}(e)})),i=[].concat(a(r),a(n));return{getTimeout:function(e,t){return(0===n.length&&0===e?1:n.length+3+e)*t},statelessHosts:i.length>0?i.map((function(e){return R(e)})):t}}))}function j(e,t,n,i){var s=[],c=function(e,t){if(e.method!==F&&(void 0!==e.data||void 0!==t.data)){var n=Array.isArray(e.data)?e.data:r(r({},e.data),t.data);return JSON.stringify(n)}}(n,i),u=function(e,t){var n=r(r({},e.headers),t.headers),i={};return Object.keys(n).forEach((function(e){var t=n[e];i[e.toLowerCase()]=t})),i}(e,i),o=n.method,f=n.method!==F?{}:r(r({},n.data),i.data),h=r(r(r({"x-algolia-agent":e.userAgent.value},e.queryParameters),f),i.queryParameters),l=0,m=function t(r,a){var f=r.pop();if(void 0===f)throw{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:O(s)};var m={data:c,headers:u,method:o,url:E(f,n.path,h),connectTimeout:a(l,e.timeouts.connect),responseTimeout:a(l,i.timeout)},d=function(e){var t={request:m,response:e,host:f,triesLeft:r.length};return s.push(t),t},v={onSuccess:function(e){return function(e){try{return JSON.parse(e.content)}catch(t){throw function(e,t){return{name:"DeserializationError",message:e,response:t}}(t.message,e)}}(e)},onRetry:function(n){var i=d(n);return n.isTimedOut&&l++,Promise.all([e.logger.info("Retryable failure",w(i)),e.hostsCache.set(f,y(f,n.isTimedOut?g:p))]).then((function(){return t(r,a)}))},onFail:function(e){throw d(e),function(e,t){var r=e.content,n=e.status,i=r;try{i=JSON.parse(r).message}catch(e){}return function(e,t,r){return{name:"ApiError",message:e,status:t,transporterStackTrace:r}}(i,n,t)}(e,O(s))}};return e.requester.send(m).then((function(e){return function(e,t){return function(e){var t=e.status;return e.isTimedOut||function(e){var t=e.isTimedOut,r=e.status;return!t&&0==~~r}(e)||2!=~~(t/100)&&4!=~~(t/100)}(e)?t.onRetry(e):2==~~(e.status/100)?t.onSuccess(e):t.onFail(e)}(e,v)}))};return P(e.hostsCache,t).then((function(e){return m(a(e.statelessHosts).reverse(),e.getTimeout)}))}function _(e){var t={value:"Algolia for JavaScript (".concat(e,")"),add:function(e){var r="; ".concat(e.segment).concat(void 0!==e.version?" (".concat(e.version,")"):"");return-1===t.value.indexOf(r)&&(t.value="".concat(t.value).concat(r)),t}};return t}function E(e,t,r){var n=x(r),i="".concat(e.protocol,"://").concat(e.url,"/").concat("/"===t.charAt(0)?t.substr(1):t);return n.length&&(i+="?".concat(n)),i}function x(e){return Object.keys(e).map((function(t){return h("%s=%s",t,(r=e[t],"[object Object]"===Object.prototype.toString.call(r)||"[object Array]"===Object.prototype.toString.call(r)?JSON.stringify(e[t]):e[t]));var r})).join("&")}function O(e){return e.map((function(e){return w(e)}))}function w(e){var t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return r(r({},e),{},{request:r(r({},e.request),{},{headers:r(r({},e.request.headers),t)})})}var N=function(e){var t=e.appId,n=function(e,t,r){var n={"x-algolia-api-key":r,"x-algolia-application-id":t};return{headers:function(){return e===l.WithinHeaders?n:{}},queryParameters:function(){return e===l.WithinQueryParameters?n:{}}}}(void 0!==e.authMode?e.authMode:l.WithinHeaders,t,e.apiKey),a=function(e){var t=e.hostsCache,r=e.logger,n=e.requester,a=e.requestsCache,s=e.responsesCache,c=e.timeouts,u=e.userAgent,o=e.hosts,f=e.queryParameters,h={hostsCache:t,logger:r,requester:n,requestsCache:a,responsesCache:s,timeouts:c,userAgent:u,headers:e.headers,queryParameters:f,hosts:o.map((function(e){return R(e)})),read:function(e,t){var r=m(t,h.timeouts.read),n=function(){return j(h,h.hosts.filter((function(e){return 0!=(e.accept&d.Read)})),e,r)};if(!0!==(void 0!==r.cacheable?r.cacheable:e.cacheable))return n();var a={request:e,mappedRequestOptions:r,transporter:{queryParameters:h.queryParameters,headers:h.headers}};return h.responsesCache.get(a,(function(){return h.requestsCache.get(a,(function(){return h.requestsCache.set(a,n()).then((function(e){return Promise.all([h.requestsCache.delete(a),e])}),(function(e){return Promise.all([h.requestsCache.delete(a),Promise.reject(e)])})).then((function(e){var t=i(e,2);return t[0],t[1]}))}))}),{miss:function(e){return h.responsesCache.set(a,e)}})},write:function(e,t){return j(h,h.hosts.filter((function(e){return 0!=(e.accept&d.Write)})),e,m(t,h.timeouts.write))}};return h}(r(r({hosts:[{url:"".concat(t,"-dsn.algolia.net"),accept:d.Read},{url:"".concat(t,".algolia.net"),accept:d.Write}].concat(o([{url:"".concat(t,"-1.algolianet.com")},{url:"".concat(t,"-2.algolianet.com")},{url:"".concat(t,"-3.algolianet.com")}]))},e),{},{headers:r(r(r({},n.headers()),{"content-type":"application/x-www-form-urlencoded"}),e.headers),queryParameters:r(r({},n.queryParameters()),e.queryParameters)}));return f({transporter:a,appId:t,addAlgoliaAgent:function(e,t){a.userAgent.add({segment:e,version:t})},clearCache:function(){return Promise.all([a.requestsCache.clear(),a.responsesCache.clear()]).then((function(){}))}},e.methods)},A=function(e){return function(t,r){return t.method===F?e.transporter.read(t,r):e.transporter.write(t,r)}},H=function(e){return function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return f({transporter:e.transporter,appId:e.appId,indexName:t},r.methods)}},S=function(e){return function(t,n){var i=t.map((function(e){return r(r({},e),{},{params:x(e.params||{})})}));return e.transporter.read({method:b,path:"1/indexes/*/queries",data:{requests:i},cacheable:!0},n)}},T=function(e){return function(t,i){return Promise.all(t.map((function(t){var a=t.params,s=a.facetName,c=a.facetQuery,u=n(a,["facetName","facetQuery"]);return H(e)(t.indexName,{methods:{searchForFacetValues:k}}).searchForFacetValues(s,c,r(r({},i),u))})))}},Q=function(e){return function(t,r,n){return e.transporter.read({method:b,path:h("1/answers/%s/prediction",e.indexName),data:{query:t,queryLanguages:r},cacheable:!0},n)}},C=function(e){return function(t,r){return e.transporter.read({method:b,path:h("1/indexes/%s/query",e.indexName),data:{query:t},cacheable:!0},r)}},k=function(e){return function(t,r,n){return e.transporter.read({method:b,path:h("1/indexes/%s/facets/%s/query",e.indexName,t),data:{facetQuery:r},cacheable:!0},n)}},D=1,I=2,q=3;function V(e,t,n){var i,a={appId:e,apiKey:t,timeouts:{connect:1,read:2,write:30},requester:{send:function(e){return new Promise((function(t){var r=new XMLHttpRequest;r.open(e.method,e.url,!0),Object.keys(e.headers).forEach((function(t){return r.setRequestHeader(t,e.headers[t])}));var n,i=function(e,n){return setTimeout((function(){r.abort(),t({status:0,content:n,isTimedOut:!0})}),1e3*e)},a=i(e.connectTimeout,"Connection timeout");r.onreadystatechange=function(){r.readyState>r.OPENED&&void 0===n&&(clearTimeout(a),n=i(e.responseTimeout,"Socket timeout"))},r.onerror=function(){0===r.status&&(clearTimeout(a),clearTimeout(n),t({content:r.responseText||"Network request failed",status:r.status,isTimedOut:!1}))},r.onload=function(){clearTimeout(a),clearTimeout(n),t({content:r.responseText,status:r.status,isTimedOut:!1})},r.send(e.data)}))}},logger:(i=q,{debug:function(e,t){return D>=i&&console.debug(e,t),Promise.resolve()},info:function(e,t){return I>=i&&console.info(e,t),Promise.resolve()},error:function(e,t){return console.error(e,t),Promise.resolve()}}),responsesCache:u(),requestsCache:u({serializable:!1}),hostsCache:c({caches:[s({key:"".concat("4.13.1","-").concat(e)}),u()]}),userAgent:_("4.13.1").add({segment:"Browser",version:"lite"}),authMode:l.WithinQueryParameters};return N(r(r(r({},a),n),{},{methods:{search:S,searchForFacetValues:T,multipleQueries:S,multipleSearchForFacetValues:T,customRequest:A,initIndex:function(e){return function(t){return H(e)(t,{methods:{search:C,searchForFacetValues:k,findAnswers:Q}})}}}}))}return V.version="4.13.1",V}()}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/1a4e3797.f48b4242.js b/handbook/build/assets/js/1a4e3797.f48b4242.js new file mode 100644 index 0000000000..351f128ae9 --- /dev/null +++ b/handbook/build/assets/js/1a4e3797.f48b4242.js @@ -0,0 +1,2 @@ +/*! For license information please see 1a4e3797.f48b4242.js.LICENSE.txt */ +(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[7920],{7331:function(e){function t(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function r(e){return"function"==typeof e}function n(e){return"object"==typeof e&&null!==e}function i(e){return void 0===e}e.exports=t,t.prototype._events=void 0,t.prototype._maxListeners=void 0,t.defaultMaxListeners=10,t.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||isNaN(e))throw TypeError("n must be a positive number");return this._maxListeners=e,this},t.prototype.emit=function(e){var t,a,s,c,u,o;if(this._events||(this._events={}),"error"===e&&(!this._events.error||n(this._events.error)&&!this._events.error.length)){if((t=arguments[1])instanceof Error)throw t;var f=new Error('Uncaught, unspecified "error" event. ('+t+")");throw f.context=t,f}if(i(a=this._events[e]))return!1;if(r(a))switch(arguments.length){case 1:a.call(this);break;case 2:a.call(this,arguments[1]);break;case 3:a.call(this,arguments[1],arguments[2]);break;default:c=Array.prototype.slice.call(arguments,1),a.apply(this,c)}else if(n(a))for(c=Array.prototype.slice.call(arguments,1),s=(o=a.slice()).length,u=0;u0&&this._events[e].length>s&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),"function"==typeof console.trace&&console.trace()),this},t.prototype.on=t.prototype.addListener,t.prototype.once=function(e,t){if(!r(t))throw TypeError("listener must be a function");var n=!1;function i(){this.removeListener(e,i),n||(n=!0,t.apply(this,arguments))}return i.listener=t,this.on(e,i),this},t.prototype.removeListener=function(e,t){var i,a,s,c;if(!r(t))throw TypeError("listener must be a function");if(!this._events||!this._events[e])return this;if(s=(i=this._events[e]).length,a=-1,i===t||r(i.listener)&&i.listener===t)delete this._events[e],this._events.removeListener&&this.emit("removeListener",e,t);else if(n(i)){for(c=s;c-- >0;)if(i[c]===t||i[c].listener&&i[c].listener===t){a=c;break}if(a<0)return this;1===i.length?(i.length=0,delete this._events[e]):i.splice(a,1),this._events.removeListener&&this.emit("removeListener",e,t)}return this},t.prototype.removeAllListeners=function(e){var t,n;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[e]&&delete this._events[e],this;if(0===arguments.length){for(t in this._events)"removeListener"!==t&&this.removeAllListeners(t);return this.removeAllListeners("removeListener"),this._events={},this}if(r(n=this._events[e]))this.removeListener(e,n);else if(n)for(;n.length;)this.removeListener(e,n[n.length-1]);return delete this._events[e],this},t.prototype.listeners=function(e){return this._events&&this._events[e]?r(this._events[e])?[this._events[e]]:this._events[e].slice():[]},t.prototype.listenerCount=function(e){if(this._events){var t=this._events[e];if(r(t))return 1;if(t)return t.length}return 0},t.listenerCount=function(e,t){return e.listenerCount(t)}},1427:function(e,t,r){"use strict";var n=r(8185),i=r(6479),a=r(2956);function s(e,t,r){return new n(e,t,r)}s.version=r(4392),s.AlgoliaSearchHelper=n,s.SearchParameters=i,s.SearchResults=a,e.exports=s},2213:function(e,t,r){"use strict";var n=r(7331);function i(e,t){this.main=e,this.fn=t,this.lastResults=null}r(3412)(i,n),i.prototype.detach=function(){this.removeAllListeners(),this.main.detachDerivedHelper(this)},i.prototype.getModifiedState=function(e){return this.fn(e)},e.exports=i},5396:function(e,t,r){"use strict";var n=r(8937),i=r(9906),a=r(9613),s={addRefinement:function(e,t,r){if(s.isRefined(e,t,r))return e;var i=""+r,a=e[t]?e[t].concat(i):[i],c={};return c[t]=a,n({},c,e)},removeRefinement:function(e,t,r){if(void 0===r)return s.clearRefinement(e,(function(e,r){return t===r}));var n=""+r;return s.clearRefinement(e,(function(e,r){return t===r&&n===e}))},toggleRefinement:function(e,t,r){if(void 0===r)throw new Error("toggleRefinement should be used with a value");return s.isRefined(e,t,r)?s.removeRefinement(e,t,r):s.addRefinement(e,t,r)},clearRefinement:function(e,t,r){if(void 0===t)return a(e)?{}:e;if("string"==typeof t)return i(e,[t]);if("function"==typeof t){var n=!1,s=Object.keys(e).reduce((function(i,a){var s=e[a]||[],c=s.filter((function(e){return!t(e,a,r)}));return c.length!==s.length&&(n=!0),i[a]=c,i}),{});return n?s:e}},isRefined:function(e,t,r){var n=!!e[t]&&e[t].length>0;if(void 0===r||!n)return n;var i=""+r;return-1!==e[t].indexOf(i)}};e.exports=s},6479:function(e,t,r){"use strict";var n=r(7952),i=r(8937),a=r(4720),s=r(4458),c=r(2629),u=r(9906),o=r(9613),f=r(56),h=r(5396);function l(e,t){return Array.isArray(e)&&Array.isArray(t)?e.length===t.length&&e.every((function(e,r){return l(t[r],e)})):e===t}function m(e){var t=e?m._parseNumbers(e):{};void 0===t.userToken||f(t.userToken)||console.warn("[algoliasearch-helper] The `userToken` parameter is invalid. This can lead to wrong analytics.\n - Format: [a-zA-Z0-9_-]{1,64}"),this.facets=t.facets||[],this.disjunctiveFacets=t.disjunctiveFacets||[],this.hierarchicalFacets=t.hierarchicalFacets||[],this.facetsRefinements=t.facetsRefinements||{},this.facetsExcludes=t.facetsExcludes||{},this.disjunctiveFacetsRefinements=t.disjunctiveFacetsRefinements||{},this.numericRefinements=t.numericRefinements||{},this.tagRefinements=t.tagRefinements||[],this.hierarchicalFacetsRefinements=t.hierarchicalFacetsRefinements||{};var r=this;Object.keys(t).forEach((function(e){var n=-1!==m.PARAMETERS.indexOf(e),i=void 0!==t[e];!n&&i&&(r[e]=t[e])}))}m.PARAMETERS=Object.keys(new m),m._parseNumbers=function(e){if(e instanceof m)return e;var t={};if(["aroundPrecision","aroundRadius","getRankingInfo","minWordSizefor2Typos","minWordSizefor1Typo","page","maxValuesPerFacet","distinct","minimumAroundRadius","hitsPerPage","minProximity"].forEach((function(r){var n=e[r];if("string"==typeof n){var i=parseFloat(n);t[r]=isNaN(i)?n:i}})),Array.isArray(e.insideBoundingBox)&&(t.insideBoundingBox=e.insideBoundingBox.map((function(e){return Array.isArray(e)?e.map((function(e){return parseFloat(e)})):e}))),e.numericRefinements){var r={};Object.keys(e.numericRefinements).forEach((function(t){var n=e.numericRefinements[t]||{};r[t]={},Object.keys(n).forEach((function(e){var i=n[e].map((function(e){return Array.isArray(e)?e.map((function(e){return"string"==typeof e?parseFloat(e):e})):"string"==typeof e?parseFloat(e):e}));r[t][e]=i}))})),t.numericRefinements=r}return n({},e,t)},m.make=function(e){var t=new m(e);return(e.hierarchicalFacets||[]).forEach((function(e){if(e.rootPath){var r=t.getHierarchicalRefinement(e.name);r.length>0&&0!==r[0].indexOf(e.rootPath)&&(t=t.clearRefinements(e.name)),0===(r=t.getHierarchicalRefinement(e.name)).length&&(t=t.toggleHierarchicalFacetRefinement(e.name,e.rootPath))}})),t},m.validate=function(e,t){var r=t||{};return e.tagFilters&&r.tagRefinements&&r.tagRefinements.length>0?new Error("[Tags] Cannot switch from the managed tag API to the advanced API. It is probably an error, if it is really what you want, you should first clear the tags with clearTags method."):e.tagRefinements.length>0&&r.tagFilters?new Error("[Tags] Cannot switch from the advanced tag API to the managed API. It is probably an error, if it is not, you should first clear the tags with clearTags method."):e.numericFilters&&r.numericRefinements&&o(r.numericRefinements)?new Error("[Numeric filters] Can't switch from the advanced to the managed API. It is probably an error, if this is really what you want, you have to first clear the numeric filters."):o(e.numericRefinements)&&r.numericFilters?new Error("[Numeric filters] Can't switch from the managed API to the advanced. It is probably an error, if this is really what you want, you have to first clear the numeric filters."):null},m.prototype={constructor:m,clearRefinements:function(e){var t={numericRefinements:this._clearNumericRefinements(e),facetsRefinements:h.clearRefinement(this.facetsRefinements,e,"conjunctiveFacet"),facetsExcludes:h.clearRefinement(this.facetsExcludes,e,"exclude"),disjunctiveFacetsRefinements:h.clearRefinement(this.disjunctiveFacetsRefinements,e,"disjunctiveFacet"),hierarchicalFacetsRefinements:h.clearRefinement(this.hierarchicalFacetsRefinements,e,"hierarchicalFacet")};return t.numericRefinements===this.numericRefinements&&t.facetsRefinements===this.facetsRefinements&&t.facetsExcludes===this.facetsExcludes&&t.disjunctiveFacetsRefinements===this.disjunctiveFacetsRefinements&&t.hierarchicalFacetsRefinements===this.hierarchicalFacetsRefinements?this:this.setQueryParameters(t)},clearTags:function(){return void 0===this.tagFilters&&0===this.tagRefinements.length?this:this.setQueryParameters({tagFilters:void 0,tagRefinements:[]})},setIndex:function(e){return e===this.index?this:this.setQueryParameters({index:e})},setQuery:function(e){return e===this.query?this:this.setQueryParameters({query:e})},setPage:function(e){return e===this.page?this:this.setQueryParameters({page:e})},setFacets:function(e){return this.setQueryParameters({facets:e})},setDisjunctiveFacets:function(e){return this.setQueryParameters({disjunctiveFacets:e})},setHitsPerPage:function(e){return this.hitsPerPage===e?this:this.setQueryParameters({hitsPerPage:e})},setTypoTolerance:function(e){return this.typoTolerance===e?this:this.setQueryParameters({typoTolerance:e})},addNumericRefinement:function(e,t,r){var i=c(r);if(this.isNumericRefined(e,t,i))return this;var a=n({},this.numericRefinements);return a[e]=n({},a[e]),a[e][t]?(a[e][t]=a[e][t].slice(),a[e][t].push(i)):a[e][t]=[i],this.setQueryParameters({numericRefinements:a})},getConjunctiveRefinements:function(e){return this.isConjunctiveFacet(e)&&this.facetsRefinements[e]||[]},getDisjunctiveRefinements:function(e){return this.isDisjunctiveFacet(e)&&this.disjunctiveFacetsRefinements[e]||[]},getHierarchicalRefinement:function(e){return this.hierarchicalFacetsRefinements[e]||[]},getExcludeRefinements:function(e){return this.isConjunctiveFacet(e)&&this.facetsExcludes[e]||[]},removeNumericRefinement:function(e,t,r){return void 0!==r?this.isNumericRefined(e,t,r)?this.setQueryParameters({numericRefinements:this._clearNumericRefinements((function(n,i){return i===e&&n.op===t&&l(n.val,c(r))}))}):this:void 0!==t?this.isNumericRefined(e,t)?this.setQueryParameters({numericRefinements:this._clearNumericRefinements((function(r,n){return n===e&&r.op===t}))}):this:this.isNumericRefined(e)?this.setQueryParameters({numericRefinements:this._clearNumericRefinements((function(t,r){return r===e}))}):this},getNumericRefinements:function(e){return this.numericRefinements[e]||{}},getNumericRefinement:function(e,t){return this.numericRefinements[e]&&this.numericRefinements[e][t]},_clearNumericRefinements:function(e){if(void 0===e)return o(this.numericRefinements)?{}:this.numericRefinements;if("string"==typeof e)return u(this.numericRefinements,[e]);if("function"==typeof e){var t=!1,r=this.numericRefinements,n=Object.keys(r).reduce((function(n,i){var a=r[i],s={};return a=a||{},Object.keys(a).forEach((function(r){var n=a[r]||[],c=[];n.forEach((function(t){e({val:t,op:r},i,"numeric")||c.push(t)})),c.length!==n.length&&(t=!0),s[r]=c})),n[i]=s,n}),{});return t?n:this.numericRefinements}},addFacet:function(e){return this.isConjunctiveFacet(e)?this:this.setQueryParameters({facets:this.facets.concat([e])})},addDisjunctiveFacet:function(e){return this.isDisjunctiveFacet(e)?this:this.setQueryParameters({disjunctiveFacets:this.disjunctiveFacets.concat([e])})},addHierarchicalFacet:function(e){if(this.isHierarchicalFacet(e.name))throw new Error("Cannot declare two hierarchical facets with the same name: `"+e.name+"`");return this.setQueryParameters({hierarchicalFacets:this.hierarchicalFacets.concat([e])})},addFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return h.isRefined(this.facetsRefinements,e,t)?this:this.setQueryParameters({facetsRefinements:h.addRefinement(this.facetsRefinements,e,t)})},addExcludeRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return h.isRefined(this.facetsExcludes,e,t)?this:this.setQueryParameters({facetsExcludes:h.addRefinement(this.facetsExcludes,e,t)})},addDisjunctiveFacetRefinement:function(e,t){if(!this.isDisjunctiveFacet(e))throw new Error(e+" is not defined in the disjunctiveFacets attribute of the helper configuration");return h.isRefined(this.disjunctiveFacetsRefinements,e,t)?this:this.setQueryParameters({disjunctiveFacetsRefinements:h.addRefinement(this.disjunctiveFacetsRefinements,e,t)})},addTagRefinement:function(e){if(this.isTagRefined(e))return this;var t={tagRefinements:this.tagRefinements.concat(e)};return this.setQueryParameters(t)},removeFacet:function(e){return this.isConjunctiveFacet(e)?this.clearRefinements(e).setQueryParameters({facets:this.facets.filter((function(t){return t!==e}))}):this},removeDisjunctiveFacet:function(e){return this.isDisjunctiveFacet(e)?this.clearRefinements(e).setQueryParameters({disjunctiveFacets:this.disjunctiveFacets.filter((function(t){return t!==e}))}):this},removeHierarchicalFacet:function(e){return this.isHierarchicalFacet(e)?this.clearRefinements(e).setQueryParameters({hierarchicalFacets:this.hierarchicalFacets.filter((function(t){return t.name!==e}))}):this},removeFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return h.isRefined(this.facetsRefinements,e,t)?this.setQueryParameters({facetsRefinements:h.removeRefinement(this.facetsRefinements,e,t)}):this},removeExcludeRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return h.isRefined(this.facetsExcludes,e,t)?this.setQueryParameters({facetsExcludes:h.removeRefinement(this.facetsExcludes,e,t)}):this},removeDisjunctiveFacetRefinement:function(e,t){if(!this.isDisjunctiveFacet(e))throw new Error(e+" is not defined in the disjunctiveFacets attribute of the helper configuration");return h.isRefined(this.disjunctiveFacetsRefinements,e,t)?this.setQueryParameters({disjunctiveFacetsRefinements:h.removeRefinement(this.disjunctiveFacetsRefinements,e,t)}):this},removeTagRefinement:function(e){if(!this.isTagRefined(e))return this;var t={tagRefinements:this.tagRefinements.filter((function(t){return t!==e}))};return this.setQueryParameters(t)},toggleRefinement:function(e,t){return this.toggleFacetRefinement(e,t)},toggleFacetRefinement:function(e,t){if(this.isHierarchicalFacet(e))return this.toggleHierarchicalFacetRefinement(e,t);if(this.isConjunctiveFacet(e))return this.toggleConjunctiveFacetRefinement(e,t);if(this.isDisjunctiveFacet(e))return this.toggleDisjunctiveFacetRefinement(e,t);throw new Error("Cannot refine the undeclared facet "+e+"; it should be added to the helper options facets, disjunctiveFacets or hierarchicalFacets")},toggleConjunctiveFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return this.setQueryParameters({facetsRefinements:h.toggleRefinement(this.facetsRefinements,e,t)})},toggleExcludeFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return this.setQueryParameters({facetsExcludes:h.toggleRefinement(this.facetsExcludes,e,t)})},toggleDisjunctiveFacetRefinement:function(e,t){if(!this.isDisjunctiveFacet(e))throw new Error(e+" is not defined in the disjunctiveFacets attribute of the helper configuration");return this.setQueryParameters({disjunctiveFacetsRefinements:h.toggleRefinement(this.disjunctiveFacetsRefinements,e,t)})},toggleHierarchicalFacetRefinement:function(e,t){if(!this.isHierarchicalFacet(e))throw new Error(e+" is not defined in the hierarchicalFacets attribute of the helper configuration");var r=this._getHierarchicalFacetSeparator(this.getHierarchicalFacetByName(e)),n={};return void 0!==this.hierarchicalFacetsRefinements[e]&&this.hierarchicalFacetsRefinements[e].length>0&&(this.hierarchicalFacetsRefinements[e][0]===t||0===this.hierarchicalFacetsRefinements[e][0].indexOf(t+r))?-1===t.indexOf(r)?n[e]=[]:n[e]=[t.slice(0,t.lastIndexOf(r))]:n[e]=[t],this.setQueryParameters({hierarchicalFacetsRefinements:i({},n,this.hierarchicalFacetsRefinements)})},addHierarchicalFacetRefinement:function(e,t){if(this.isHierarchicalFacetRefined(e))throw new Error(e+" is already refined.");if(!this.isHierarchicalFacet(e))throw new Error(e+" is not defined in the hierarchicalFacets attribute of the helper configuration.");var r={};return r[e]=[t],this.setQueryParameters({hierarchicalFacetsRefinements:i({},r,this.hierarchicalFacetsRefinements)})},removeHierarchicalFacetRefinement:function(e){if(!this.isHierarchicalFacetRefined(e))return this;var t={};return t[e]=[],this.setQueryParameters({hierarchicalFacetsRefinements:i({},t,this.hierarchicalFacetsRefinements)})},toggleTagRefinement:function(e){return this.isTagRefined(e)?this.removeTagRefinement(e):this.addTagRefinement(e)},isDisjunctiveFacet:function(e){return this.disjunctiveFacets.indexOf(e)>-1},isHierarchicalFacet:function(e){return void 0!==this.getHierarchicalFacetByName(e)},isConjunctiveFacet:function(e){return this.facets.indexOf(e)>-1},isFacetRefined:function(e,t){return!!this.isConjunctiveFacet(e)&&h.isRefined(this.facetsRefinements,e,t)},isExcludeRefined:function(e,t){return!!this.isConjunctiveFacet(e)&&h.isRefined(this.facetsExcludes,e,t)},isDisjunctiveFacetRefined:function(e,t){return!!this.isDisjunctiveFacet(e)&&h.isRefined(this.disjunctiveFacetsRefinements,e,t)},isHierarchicalFacetRefined:function(e,t){if(!this.isHierarchicalFacet(e))return!1;var r=this.getHierarchicalRefinement(e);return t?-1!==r.indexOf(t):r.length>0},isNumericRefined:function(e,t,r){if(void 0===r&&void 0===t)return!!this.numericRefinements[e];var n=this.numericRefinements[e]&&void 0!==this.numericRefinements[e][t];if(void 0===r||!n)return n;var i,a,u=c(r),o=void 0!==(i=this.numericRefinements[e][t],a=u,s(i,(function(e){return l(e,a)})));return n&&o},isTagRefined:function(e){return-1!==this.tagRefinements.indexOf(e)},getRefinedDisjunctiveFacets:function(){var e=this,t=a(Object.keys(this.numericRefinements).filter((function(t){return Object.keys(e.numericRefinements[t]).length>0})),this.disjunctiveFacets);return Object.keys(this.disjunctiveFacetsRefinements).filter((function(t){return e.disjunctiveFacetsRefinements[t].length>0})).concat(t).concat(this.getRefinedHierarchicalFacets())},getRefinedHierarchicalFacets:function(){var e=this;return a(this.hierarchicalFacets.map((function(e){return e.name})),Object.keys(this.hierarchicalFacetsRefinements).filter((function(t){return e.hierarchicalFacetsRefinements[t].length>0})))},getUnrefinedDisjunctiveFacets:function(){var e=this.getRefinedDisjunctiveFacets();return this.disjunctiveFacets.filter((function(t){return-1===e.indexOf(t)}))},managedParameters:["index","facets","disjunctiveFacets","facetsRefinements","hierarchicalFacets","facetsExcludes","disjunctiveFacetsRefinements","numericRefinements","tagRefinements","hierarchicalFacetsRefinements"],getQueryParams:function(){var e=this.managedParameters,t={},r=this;return Object.keys(this).forEach((function(n){var i=r[n];-1===e.indexOf(n)&&void 0!==i&&(t[n]=i)})),t},setQueryParameter:function(e,t){if(this[e]===t)return this;var r={};return r[e]=t,this.setQueryParameters(r)},setQueryParameters:function(e){if(!e)return this;var t=m.validate(this,e);if(t)throw t;var r=this,n=m._parseNumbers(e),i=Object.keys(this).reduce((function(e,t){return e[t]=r[t],e}),{}),a=Object.keys(n).reduce((function(e,t){var r=void 0!==e[t],i=void 0!==n[t];return r&&!i?u(e,[t]):(i&&(e[t]=n[t]),e)}),i);return new this.constructor(a)},resetPage:function(){return void 0===this.page?this:this.setPage(0)},_getHierarchicalFacetSortBy:function(e){return e.sortBy||["isRefined:desc","name:asc"]},_getHierarchicalFacetSeparator:function(e){return e.separator||" > "},_getHierarchicalRootPath:function(e){return e.rootPath||null},_getHierarchicalShowParentLevel:function(e){return"boolean"!=typeof e.showParentLevel||e.showParentLevel},getHierarchicalFacetByName:function(e){return s(this.hierarchicalFacets,(function(t){return t.name===e}))},getHierarchicalFacetBreadcrumb:function(e){if(!this.isHierarchicalFacet(e))return[];var t=this.getHierarchicalRefinement(e)[0];if(!t)return[];var r=this._getHierarchicalFacetSeparator(this.getHierarchicalFacetByName(e));return t.split(r).map((function(e){return e.trim()}))},toString:function(){return JSON.stringify(this,null,2)}},e.exports=m},9677:function(e,t,r){"use strict";e.exports=function(e){return function(t,r){var s=e.hierarchicalFacets[r],o=e.hierarchicalFacetsRefinements[s.name]&&e.hierarchicalFacetsRefinements[s.name][0]||"",f=e._getHierarchicalFacetSeparator(s),h=e._getHierarchicalRootPath(s),l=e._getHierarchicalShowParentLevel(s),m=a(e._getHierarchicalFacetSortBy(s)),d=t.every((function(e){return e.exhaustive})),v=function(e,t,r,a,s){return function(o,f,h){var l=o;if(h>0){var m=0;for(l=o;m-1})));if(s){var f=s.attributes.indexOf(t),l=u(e.hierarchicalFacets,(function(e){return e.name===s.name}));o.hierarchicalFacets[l][f]={attribute:t,data:i,exhaustive:a.exhaustiveFacetsCount}}else{var m,d=-1!==e.disjunctiveFacets.indexOf(t),g=-1!==e.facets.indexOf(t);d&&(m=p[t],o.disjunctiveFacets[m]={name:t,data:i,exhaustive:a.exhaustiveFacetsCount},v(o.disjunctiveFacets[m],a.facets_stats,t)),g&&(m=h[t],o.facets[m]={name:t,data:i,exhaustive:a.exhaustiveFacetsCount},v(o.facets[m],a.facets_stats,t))}})),this.hierarchicalFacets=s(this.hierarchicalFacets),f.forEach((function(r){var s=t[g],c=s&&s.facets?s.facets:{},f=e.getHierarchicalFacetByName(r);Object.keys(c).forEach((function(t){var r,h=c[t];if(f){r=u(e.hierarchicalFacets,(function(e){return e.name===f.name}));var m=u(o.hierarchicalFacets[r],(function(e){return e.attribute===t}));if(-1===m)return;o.hierarchicalFacets[r][m].data=n({},o.hierarchicalFacets[r][m].data,h)}else{r=p[t];var d=a.facets&&a.facets[t]||{};o.disjunctiveFacets[r]={name:t,data:i({},h,d),exhaustive:s.exhaustiveFacetsCount},v(o.disjunctiveFacets[r],s.facets_stats,t),e.disjunctiveFacetsRefinements[t]&&e.disjunctiveFacetsRefinements[t].forEach((function(n){!o.disjunctiveFacets[r].data[n]&&e.disjunctiveFacetsRefinements[t].indexOf(l(n))>-1&&(o.disjunctiveFacets[r].data[n]=0)}))}})),g++})),e.getRefinedHierarchicalFacets().forEach((function(r){var n=e.getHierarchicalFacetByName(r),a=e._getHierarchicalFacetSeparator(n),s=e.getHierarchicalRefinement(r);0===s.length||s[0].split(a).length<2||t.slice(g).forEach((function(t){var r=t&&t.facets?t.facets:{};Object.keys(r).forEach((function(t){var c=r[t],f=u(e.hierarchicalFacets,(function(e){return e.name===n.name})),h=u(o.hierarchicalFacets[f],(function(e){return e.attribute===t}));if(-1!==h){var l={};if(s.length>0){var m=s[0].split(a)[0];l[m]=o.hierarchicalFacets[f][h].data[m]}o.hierarchicalFacets[f][h].data=i(l,c,o.hierarchicalFacets[f][h].data)}})),g++}))})),Object.keys(e.facetsExcludes).forEach((function(t){var r=e.facetsExcludes[t],n=h[t];o.facets[n]={name:t,data:a.facets[t],exhaustive:a.exhaustiveFacetsCount},r.forEach((function(e){o.facets[n]=o.facets[n]||{name:t},o.facets[n].data=o.facets[n].data||{},o.facets[n].data[e]=0}))})),this.hierarchicalFacets=this.hierarchicalFacets.map(m(e)),this.facets=s(this.facets),this.disjunctiveFacets=s(this.disjunctiveFacets),this._state=e}function g(e,t,r,n){if(n=n||0,Array.isArray(t))return e(t,r[n]);if(!t.data||0===t.data.length)return t;var a=t.data.map((function(t){return g(e,t,r,n+1)})),s=e(a,r[n]);return i({data:s},t)}function y(e,t){var r=c(e,(function(e){return e.name===t}));return r&&r.stats}function R(e,t,r,n,i){var a=c(i,(function(e){return e.name===r})),s=a&&a.data&&a.data[n]?a.data[n]:0,u=a&&a.exhaustive||!1;return{type:t,attributeName:r,name:n,count:s,exhaustive:u}}p.prototype.getFacetByName=function(e){function t(t){return t.name===e}return c(this.facets,t)||c(this.disjunctiveFacets,t)||c(this.hierarchicalFacets,t)},p.DEFAULT_SORT=["isRefined:desc","count:desc","name:asc"],p.prototype.getFacetValues=function(e,t){var r=function(e,t){function r(e){return e.name===t}if(e._state.isConjunctiveFacet(t)){var n=c(e.facets,r);return n?Object.keys(n.data).map((function(r){var i=h(r);return{name:r,escapedValue:i,count:n.data[r],isRefined:e._state.isFacetRefined(t,i),isExcluded:e._state.isExcludeRefined(t,r)}})):[]}if(e._state.isDisjunctiveFacet(t)){var i=c(e.disjunctiveFacets,r);return i?Object.keys(i.data).map((function(r){var n=h(r);return{name:r,escapedValue:n,count:i.data[r],isRefined:e._state.isDisjunctiveFacetRefined(t,n)}})):[]}if(e._state.isHierarchicalFacet(t))return c(e.hierarchicalFacets,r)}(this,e);if(r){var n,s=i({},t,{sortBy:p.DEFAULT_SORT,facetOrdering:!(t&&t.sortBy)}),u=this;if(Array.isArray(r))n=[e];else n=u._state.getHierarchicalFacetByName(r.name).attributes;return g((function(e,t){if(s.facetOrdering){var r=function(e,t){return e.renderingContent&&e.renderingContent.facetOrdering&&e.renderingContent.facetOrdering.values&&e.renderingContent.facetOrdering.values[t]}(u,t);if(Boolean(r))return function(e,t){var r=[],n=[],i=(t.order||[]).reduce((function(e,t,r){return e[t]=r,e}),{});e.forEach((function(e){var t=e.path||e.name;void 0!==i[t]?r[i[t]]=e:n.push(e)})),r=r.filter((function(e){return e}));var s,c=t.sortRemainingBy;return"hidden"===c?r:(s="alpha"===c?[["path","name"],["asc","asc"]]:[["count"],["desc"]],r.concat(a(n,s[0],s[1])))}(e,r)}if(Array.isArray(s.sortBy)){var n=o(s.sortBy,p.DEFAULT_SORT);return a(e,n[0],n[1])}if("function"==typeof s.sortBy)return function(e,t){return t.sort(e)}(s.sortBy,e);throw new Error("options.sortBy is optional but if defined it must be either an array of string (predicates) or a sorting function")}),r,n)}},p.prototype.getFacetStats=function(e){return this._state.isConjunctiveFacet(e)?y(this.facets,e):this._state.isDisjunctiveFacet(e)?y(this.disjunctiveFacets,e):void 0},p.prototype.getRefinements=function(){var e=this._state,t=this,r=[];return Object.keys(e.facetsRefinements).forEach((function(n){e.facetsRefinements[n].forEach((function(i){r.push(R(e,"facet",n,i,t.facets))}))})),Object.keys(e.facetsExcludes).forEach((function(n){e.facetsExcludes[n].forEach((function(i){r.push(R(e,"exclude",n,i,t.facets))}))})),Object.keys(e.disjunctiveFacetsRefinements).forEach((function(n){e.disjunctiveFacetsRefinements[n].forEach((function(i){r.push(R(e,"disjunctive",n,i,t.disjunctiveFacets))}))})),Object.keys(e.hierarchicalFacetsRefinements).forEach((function(n){e.hierarchicalFacetsRefinements[n].forEach((function(i){r.push(function(e,t,r,n){var i=e.getHierarchicalFacetByName(t),a=e._getHierarchicalFacetSeparator(i),s=r.split(a),u=c(n,(function(e){return e.name===t})),o=s.reduce((function(e,t){var r=e&&c(e.data,(function(e){return e.name===t}));return void 0!==r?r:e}),u),f=o&&o.count||0,h=o&&o.exhaustive||!1,l=o&&o.path||"";return{type:"hierarchical",attributeName:t,name:l,count:f,exhaustive:h}}(e,n,i,t.hierarchicalFacets))}))})),Object.keys(e.numericRefinements).forEach((function(t){var n=e.numericRefinements[t];Object.keys(n).forEach((function(e){n[e].forEach((function(n){r.push({type:"numeric",attributeName:t,name:n,numericValue:n,operator:e})}))}))})),e.tagRefinements.forEach((function(e){r.push({type:"tag",attributeName:"_tags",name:e})})),r},e.exports=p},8185:function(e,t,r){"use strict";var n=r(6479),i=r(2956),a=r(2213),s=r(5187),c=r(7331),u=r(3412),o=r(9613),f=r(9906),h=r(7952),l=r(4392),m=r(7050).escapeFacetValue;function d(e,t,r){"function"==typeof e.addAlgoliaAgent&&e.addAlgoliaAgent("JS Helper ("+l+")"),this.setClient(e);var i=r||{};i.index=t,this.state=n.make(i),this.lastResults=null,this._queryId=0,this._lastQueryIdReceived=-1,this.derivedHelpers=[],this._currentNbQueries=0}function v(e){if(e<0)throw new Error("Page requested below 0.");return this._change({state:this.state.setPage(e),isPageReset:!1}),this}function p(){return this.state.page}u(d,c),d.prototype.search=function(){return this._search({onlyWithDerivedHelpers:!1}),this},d.prototype.searchOnlyWithDerivedHelpers=function(){return this._search({onlyWithDerivedHelpers:!0}),this},d.prototype.getQuery=function(){var e=this.state;return s._getHitsSearchParams(e)},d.prototype.searchOnce=function(e,t){var r=e?this.state.setQueryParameters(e):this.state,n=s._getQueries(r.index,r),a=this;if(this._currentNbQueries++,this.emit("searchOnce",{state:r}),!t)return this.client.search(n).then((function(e){return a._currentNbQueries--,0===a._currentNbQueries&&a.emit("searchQueueEmpty"),{content:new i(r,e.results),state:r,_originalResponse:e}}),(function(e){throw a._currentNbQueries--,0===a._currentNbQueries&&a.emit("searchQueueEmpty"),e}));this.client.search(n).then((function(e){a._currentNbQueries--,0===a._currentNbQueries&&a.emit("searchQueueEmpty"),t(null,new i(r,e.results),r)})).catch((function(e){a._currentNbQueries--,0===a._currentNbQueries&&a.emit("searchQueueEmpty"),t(e,null,r)}))},d.prototype.findAnswers=function(e){var t=this.state,r=this.derivedHelpers[0];if(!r)return Promise.resolve([]);var n=r.getModifiedState(t),i=h({attributesForPrediction:e.attributesForPrediction,nbHits:e.nbHits},{params:f(s._getHitsSearchParams(n),["attributesToSnippet","hitsPerPage","restrictSearchableAttributes","snippetEllipsisText"])}),a="search for answers was called, but this client does not have a function client.initIndex(index).findAnswers";if("function"!=typeof this.client.initIndex)throw new Error(a);var c=this.client.initIndex(n.index);if("function"!=typeof c.findAnswers)throw new Error(a);return c.findAnswers(n.query,e.queryLanguages,i)},d.prototype.searchForFacetValues=function(e,t,r,n){var i="function"==typeof this.client.searchForFacetValues,a="function"==typeof this.client.initIndex;if(!i&&!a&&"function"!=typeof this.client.search)throw new Error("search for facet values (searchable) was called, but this client does not have a function client.searchForFacetValues or client.initIndex(index).searchForFacetValues");var c=this.state.setQueryParameters(n||{}),u=c.isDisjunctiveFacet(e),o=s.getSearchForFacetQuery(e,t,r,c);this._currentNbQueries++;var f,h=this;return i?f=this.client.searchForFacetValues([{indexName:c.index,params:o}]):a?f=this.client.initIndex(c.index).searchForFacetValues(o):(delete o.facetName,f=this.client.search([{type:"facet",facet:e,indexName:c.index,params:o}]).then((function(e){return e.results[0]}))),this.emit("searchForFacetValues",{state:c,facet:e,query:t}),f.then((function(t){return h._currentNbQueries--,0===h._currentNbQueries&&h.emit("searchQueueEmpty"),(t=Array.isArray(t)?t[0]:t).facetHits.forEach((function(t){t.escapedValue=m(t.value),t.isRefined=u?c.isDisjunctiveFacetRefined(e,t.escapedValue):c.isFacetRefined(e,t.escapedValue)})),t}),(function(e){throw h._currentNbQueries--,0===h._currentNbQueries&&h.emit("searchQueueEmpty"),e}))},d.prototype.setQuery=function(e){return this._change({state:this.state.resetPage().setQuery(e),isPageReset:!0}),this},d.prototype.clearRefinements=function(e){return this._change({state:this.state.resetPage().clearRefinements(e),isPageReset:!0}),this},d.prototype.clearTags=function(){return this._change({state:this.state.resetPage().clearTags(),isPageReset:!0}),this},d.prototype.addDisjunctiveFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().addDisjunctiveFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.addDisjunctiveRefine=function(){return this.addDisjunctiveFacetRefinement.apply(this,arguments)},d.prototype.addHierarchicalFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().addHierarchicalFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.addNumericRefinement=function(e,t,r){return this._change({state:this.state.resetPage().addNumericRefinement(e,t,r),isPageReset:!0}),this},d.prototype.addFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().addFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.addRefine=function(){return this.addFacetRefinement.apply(this,arguments)},d.prototype.addFacetExclusion=function(e,t){return this._change({state:this.state.resetPage().addExcludeRefinement(e,t),isPageReset:!0}),this},d.prototype.addExclude=function(){return this.addFacetExclusion.apply(this,arguments)},d.prototype.addTag=function(e){return this._change({state:this.state.resetPage().addTagRefinement(e),isPageReset:!0}),this},d.prototype.removeNumericRefinement=function(e,t,r){return this._change({state:this.state.resetPage().removeNumericRefinement(e,t,r),isPageReset:!0}),this},d.prototype.removeDisjunctiveFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().removeDisjunctiveFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.removeDisjunctiveRefine=function(){return this.removeDisjunctiveFacetRefinement.apply(this,arguments)},d.prototype.removeHierarchicalFacetRefinement=function(e){return this._change({state:this.state.resetPage().removeHierarchicalFacetRefinement(e),isPageReset:!0}),this},d.prototype.removeFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().removeFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.removeRefine=function(){return this.removeFacetRefinement.apply(this,arguments)},d.prototype.removeFacetExclusion=function(e,t){return this._change({state:this.state.resetPage().removeExcludeRefinement(e,t),isPageReset:!0}),this},d.prototype.removeExclude=function(){return this.removeFacetExclusion.apply(this,arguments)},d.prototype.removeTag=function(e){return this._change({state:this.state.resetPage().removeTagRefinement(e),isPageReset:!0}),this},d.prototype.toggleFacetExclusion=function(e,t){return this._change({state:this.state.resetPage().toggleExcludeFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.toggleExclude=function(){return this.toggleFacetExclusion.apply(this,arguments)},d.prototype.toggleRefinement=function(e,t){return this.toggleFacetRefinement(e,t)},d.prototype.toggleFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().toggleFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.toggleRefine=function(){return this.toggleFacetRefinement.apply(this,arguments)},d.prototype.toggleTag=function(e){return this._change({state:this.state.resetPage().toggleTagRefinement(e),isPageReset:!0}),this},d.prototype.nextPage=function(){var e=this.state.page||0;return this.setPage(e+1)},d.prototype.previousPage=function(){var e=this.state.page||0;return this.setPage(e-1)},d.prototype.setCurrentPage=v,d.prototype.setPage=v,d.prototype.setIndex=function(e){return this._change({state:this.state.resetPage().setIndex(e),isPageReset:!0}),this},d.prototype.setQueryParameter=function(e,t){return this._change({state:this.state.resetPage().setQueryParameter(e,t),isPageReset:!0}),this},d.prototype.setState=function(e){return this._change({state:n.make(e),isPageReset:!1}),this},d.prototype.overrideStateWithoutTriggeringChangeEvent=function(e){return this.state=new n(e),this},d.prototype.hasRefinements=function(e){return!!o(this.state.getNumericRefinements(e))||(this.state.isConjunctiveFacet(e)?this.state.isFacetRefined(e):this.state.isDisjunctiveFacet(e)?this.state.isDisjunctiveFacetRefined(e):!!this.state.isHierarchicalFacet(e)&&this.state.isHierarchicalFacetRefined(e))},d.prototype.isExcluded=function(e,t){return this.state.isExcludeRefined(e,t)},d.prototype.isDisjunctiveRefined=function(e,t){return this.state.isDisjunctiveFacetRefined(e,t)},d.prototype.hasTag=function(e){return this.state.isTagRefined(e)},d.prototype.isTagRefined=function(){return this.hasTagRefinements.apply(this,arguments)},d.prototype.getIndex=function(){return this.state.index},d.prototype.getCurrentPage=p,d.prototype.getPage=p,d.prototype.getTags=function(){return this.state.tagRefinements},d.prototype.getRefinements=function(e){var t=[];if(this.state.isConjunctiveFacet(e))this.state.getConjunctiveRefinements(e).forEach((function(e){t.push({value:e,type:"conjunctive"})})),this.state.getExcludeRefinements(e).forEach((function(e){t.push({value:e,type:"exclude"})}));else if(this.state.isDisjunctiveFacet(e)){this.state.getDisjunctiveRefinements(e).forEach((function(e){t.push({value:e,type:"disjunctive"})}))}var r=this.state.getNumericRefinements(e);return Object.keys(r).forEach((function(e){var n=r[e];t.push({value:n,operator:e,type:"numeric"})})),t},d.prototype.getNumericRefinement=function(e,t){return this.state.getNumericRefinement(e,t)},d.prototype.getHierarchicalFacetBreadcrumb=function(e){return this.state.getHierarchicalFacetBreadcrumb(e)},d.prototype._search=function(e){var t=this.state,r=[],n=[];e.onlyWithDerivedHelpers||(n=s._getQueries(t.index,t),r.push({state:t,queriesCount:n.length,helper:this}),this.emit("search",{state:t,results:this.lastResults}));var i=this.derivedHelpers.map((function(e){var n=e.getModifiedState(t),i=s._getQueries(n.index,n);return r.push({state:n,queriesCount:i.length,helper:e}),e.emit("search",{state:n,results:e.lastResults}),i})),a=Array.prototype.concat.apply(n,i),c=this._queryId++;this._currentNbQueries++;try{this.client.search(a).then(this._dispatchAlgoliaResponse.bind(this,r,c)).catch(this._dispatchAlgoliaError.bind(this,c))}catch(u){this.emit("error",{error:u})}},d.prototype._dispatchAlgoliaResponse=function(e,t,r){if(!(t0},d.prototype._change=function(e){var t=e.state,r=e.isPageReset;t!==this.state&&(this.state=t,this.emit("change",{state:this.state,results:this.lastResults,isPageReset:r}))},d.prototype.clearCache=function(){return this.client.clearCache&&this.client.clearCache(),this},d.prototype.setClient=function(e){return this.client===e||("function"==typeof e.addAlgoliaAgent&&e.addAlgoliaAgent("JS Helper ("+l+")"),this.client=e),this},d.prototype.getClient=function(){return this.client},d.prototype.derive=function(e){var t=new a(this,e);return this.derivedHelpers.push(t),t},d.prototype.detachDerivedHelper=function(e){var t=this.derivedHelpers.indexOf(e);if(-1===t)throw new Error("Derived helper already detached");this.derivedHelpers.splice(t,1)},d.prototype.hasPendingRequests=function(){return this._currentNbQueries>0},e.exports=d},8959:function(e){"use strict";e.exports=function(e){return Array.isArray(e)?e.filter(Boolean):[]}},8937:function(e){"use strict";e.exports=function(){var e=Array.prototype.slice.call(arguments);return e.reduceRight((function(e,t){return Object.keys(Object(t)).forEach((function(r){void 0!==t[r]&&(void 0!==e[r]&&delete e[r],e[r]=t[r])})),e}),{})}},7050:function(e){"use strict";e.exports={escapeFacetValue:function(e){return"string"!=typeof e?e:String(e).replace(/^-/,"\\-")},unescapeFacetValue:function(e){return"string"!=typeof e?e:e.replace(/^\\-/,"-")}}},4458:function(e){"use strict";e.exports=function(e,t){if(Array.isArray(e))for(var r=0;r1||!a?(e[0].push(i[0]),e[1].push(i[1]),e):(e[0].push(a[0]),e[1].push(a[1]),e)}),[[],[]])}},3412:function(e){"use strict";e.exports=function(e,t){e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}},4720:function(e){"use strict";e.exports=function(e,t){return e.filter((function(r,n){return t.indexOf(r)>-1&&e.indexOf(r)===n}))}},7952:function(e){"use strict";function t(e){return"function"==typeof e||Array.isArray(e)||"[object Object]"===Object.prototype.toString.call(e)}function r(e,n){if(e===n)return e;for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)&&"__proto__"!==i){var a=n[i],s=e[i];void 0!==s&&void 0===a||(t(s)&&t(a)?e[i]=r(s,a):e[i]="object"==typeof(c=a)&&null!==c?r(Array.isArray(c)?[]:{},c):c)}var c;return e}e.exports=function(e){t(e)||(e={});for(var n=1,i=arguments.length;n0}},9906:function(e){"use strict";e.exports=function(e,t){if(null===e)return{};var r,n,i={},a=Object.keys(e);for(n=0;n=0||(i[r]=e[r]);return i}},2262:function(e){"use strict";function t(e,t){if(e!==t){var r=void 0!==e,n=null===e,i=void 0!==t,a=null===t;if(!a&&e>t||n&&i||!r)return 1;if(!n&&e=n.length?a:"desc"===n[i]?-a:a}return e.index-r.index})),i.map((function(e){return e.value}))}},2629:function(e){"use strict";e.exports=function e(t){if("number"==typeof t)return t;if("string"==typeof t)return parseFloat(t);if(Array.isArray(t))return t.map(e);throw new Error("The value should be a number, a parsable string or an array of those.")}},5187:function(e,t,r){"use strict";var n=r(7952);function i(e){return Object.keys(e).sort((function(e,t){return e.localeCompare(t)})).reduce((function(t,r){return t[r]=e[r],t}),{})}var a={_getQueries:function(e,t){var r=[];return r.push({indexName:e,params:a._getHitsSearchParams(t)}),t.getRefinedDisjunctiveFacets().forEach((function(n){r.push({indexName:e,params:a._getDisjunctiveFacetSearchParams(t,n)})})),t.getRefinedHierarchicalFacets().forEach((function(n){var i=t.getHierarchicalFacetByName(n),s=t.getHierarchicalRefinement(n),c=t._getHierarchicalFacetSeparator(i);if(s.length>0&&s[0].split(c).length>1){var u=s[0].split(c).slice(0,-1).reduce((function(e,t,r){return e.concat({attribute:i.attributes[r],value:0===r?t:[e[e.length-1].value,t].join(c)})}),[]);u.forEach((function(n,i){var s=a._getDisjunctiveFacetSearchParams(t,n.attribute,0===i),c=u[i-1];s.facetFilters=i>0?[c.attribute+":"+c.value]:void 0,r.push({indexName:e,params:s})}))}})),r},_getHitsSearchParams:function(e){var t=e.facets.concat(e.disjunctiveFacets).concat(a._getHitsHierarchicalFacetsAttributes(e)),r=a._getFacetFilters(e),s=a._getNumericFilters(e),c=a._getTagFilters(e),u={facets:t.indexOf("*")>-1?["*"]:t,tagFilters:c};return r.length>0&&(u.facetFilters=r),s.length>0&&(u.numericFilters=s),i(n({},e.getQueryParams(),u))},_getDisjunctiveFacetSearchParams:function(e,t,r){var s=a._getFacetFilters(e,t,r),c=a._getNumericFilters(e,t),u=a._getTagFilters(e),o={hitsPerPage:0,page:0,analytics:!1,clickAnalytics:!1};u.length>0&&(o.tagFilters=u);var f=e.getHierarchicalFacetByName(t);return o.facets=f?a._getDisjunctiveHierarchicalFacetAttribute(e,f,r):t,c.length>0&&(o.numericFilters=c),s.length>0&&(o.facetFilters=s),i(n({},e.getQueryParams(),o))},_getNumericFilters:function(e,t){if(e.numericFilters)return e.numericFilters;var r=[];return Object.keys(e.numericRefinements).forEach((function(n){var i=e.numericRefinements[n]||{};Object.keys(i).forEach((function(e){var a=i[e]||[];t!==n&&a.forEach((function(t){if(Array.isArray(t)){var i=t.map((function(t){return n+e+t}));r.push(i)}else r.push(n+e+t)}))}))})),r},_getTagFilters:function(e){return e.tagFilters?e.tagFilters:e.tagRefinements.join(",")},_getFacetFilters:function(e,t,r){var n=[],i=e.facetsRefinements||{};Object.keys(i).forEach((function(e){(i[e]||[]).forEach((function(t){n.push(e+":"+t)}))}));var a=e.facetsExcludes||{};Object.keys(a).forEach((function(e){(a[e]||[]).forEach((function(t){n.push(e+":-"+t)}))}));var s=e.disjunctiveFacetsRefinements||{};Object.keys(s).forEach((function(e){var r=s[e]||[];if(e!==t&&r&&0!==r.length){var i=[];r.forEach((function(t){i.push(e+":"+t)})),n.push(i)}}));var c=e.hierarchicalFacetsRefinements||{};return Object.keys(c).forEach((function(i){var a=(c[i]||[])[0];if(void 0!==a){var s,u,o=e.getHierarchicalFacetByName(i),f=e._getHierarchicalFacetSeparator(o),h=e._getHierarchicalRootPath(o);if(t===i){if(-1===a.indexOf(f)||!h&&!0===r||h&&h.split(f).length===a.split(f).length)return;h?(u=h.split(f).length-1,a=h):(u=a.split(f).length-2,a=a.slice(0,a.lastIndexOf(f))),s=o.attributes[u]}else u=a.split(f).length-1,s=o.attributes[u];s&&n.push([s+":"+a])}})),n},_getHitsHierarchicalFacetsAttributes:function(e){return e.hierarchicalFacets.reduce((function(t,r){var n=e.getHierarchicalRefinement(r.name)[0];if(!n)return t.push(r.attributes[0]),t;var i=e._getHierarchicalFacetSeparator(r),a=n.split(i).length,s=r.attributes.slice(0,a+1);return t.concat(s)}),[])},_getDisjunctiveHierarchicalFacetAttribute:function(e,t,r){var n=e._getHierarchicalFacetSeparator(t);if(!0===r){var i=e._getHierarchicalRootPath(t),a=0;return i&&(a=i.split(n).length),[t.attributes[a]]}var s=(e.getHierarchicalRefinement(t.name)[0]||"").split(n).length-1;return t.attributes.slice(0,s+1)},getSearchForFacetQuery:function(e,t,r,s){var c=s.isDisjunctiveFacet(e)?s.clearRefinements(e):s,u={facetQuery:t,facetName:e};return"number"==typeof r&&(u.maxFacetHits=r),i(n({},a._getHitsSearchParams(c),u))}};e.exports=a},56:function(e){"use strict";e.exports=function(e){return null!==e&&/^[a-zA-Z0-9_-]{1,64}$/.test(e)}},4392:function(e){"use strict";e.exports="3.10.0"},5157:function(e){e.exports=function(){"use strict";function e(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function t(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function r(r){for(var n=1;n=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}function i(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e)){var r=[],n=!0,i=!1,a=void 0;try{for(var s,c=e[Symbol.iterator]();!(n=(s=c.next()).done)&&(r.push(s.value),!t||r.length!==t);n=!0);}catch(e){i=!0,a=e}finally{try{n||null==c.return||c.return()}finally{if(i)throw a}}return r}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function a(e){return function(e){if(Array.isArray(e)){for(var t=0,r=new Array(e.length);t2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return Promise.resolve().then((function(){var r=JSON.stringify(e),n=a()[r];return Promise.all([n||t(),void 0!==n])})).then((function(e){var t=i(e,2),n=t[0],a=t[1];return Promise.all([n,a||r.miss(n)])})).then((function(e){return i(e,1)[0]}))},set:function(e,t){return Promise.resolve().then((function(){var i=a();return i[JSON.stringify(e)]=t,n().setItem(r,JSON.stringify(i)),t}))},delete:function(e){return Promise.resolve().then((function(){var t=a();delete t[JSON.stringify(e)],n().setItem(r,JSON.stringify(t))}))},clear:function(){return Promise.resolve().then((function(){n().removeItem(r)}))}}}function c(e){var t=a(e.caches),r=t.shift();return void 0===r?{get:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return t().then((function(e){return Promise.all([e,r.miss(e)])})).then((function(e){return i(e,1)[0]}))},set:function(e,t){return Promise.resolve(t)},delete:function(e){return Promise.resolve()},clear:function(){return Promise.resolve()}}:{get:function(e,n){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return r.get(e,n,i).catch((function(){return c({caches:t}).get(e,n,i)}))},set:function(e,n){return r.set(e,n).catch((function(){return c({caches:t}).set(e,n)}))},delete:function(e){return r.delete(e).catch((function(){return c({caches:t}).delete(e)}))},clear:function(){return r.clear().catch((function(){return c({caches:t}).clear()}))}}}function u(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{serializable:!0},t={};return{get:function(r,n){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}},a=JSON.stringify(r);if(a in t)return Promise.resolve(e.serializable?JSON.parse(t[a]):t[a]);var s=n(),c=i&&i.miss||function(){return Promise.resolve()};return s.then((function(e){return c(e)})).then((function(){return s}))},set:function(r,n){return t[JSON.stringify(r)]=e.serializable?JSON.stringify(n):n,Promise.resolve(n)},delete:function(e){return delete t[JSON.stringify(e)],Promise.resolve()},clear:function(){return t={},Promise.resolve()}}}function o(e){for(var t=e.length-1;t>0;t--){var r=Math.floor(Math.random()*(t+1)),n=e[t];e[t]=e[r],e[r]=n}return e}function f(e,t){return t?(Object.keys(t).forEach((function(r){e[r]=t[r](e)})),e):e}function h(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),n=1;n0?n:void 0,timeout:r.timeout||t,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}var d={Read:1,Write:2,Any:3},v=1,p=2,g=3;function y(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:v;return r(r({},e),{},{status:t,lastUpdate:Date.now()})}function R(e){return"string"==typeof e?{protocol:"https",url:e,accept:d.Any}:{protocol:e.protocol||"https",url:e.url,accept:e.accept||d.Any}}var F="GET",b="POST";function P(e,t){return Promise.all(t.map((function(t){return e.get(t,(function(){return Promise.resolve(y(t))}))}))).then((function(e){var r=e.filter((function(e){return function(e){return e.status===v||Date.now()-e.lastUpdate>12e4}(e)})),n=e.filter((function(e){return function(e){return e.status===g&&Date.now()-e.lastUpdate<=12e4}(e)})),i=[].concat(a(r),a(n));return{getTimeout:function(e,t){return(0===n.length&&0===e?1:n.length+3+e)*t},statelessHosts:i.length>0?i.map((function(e){return R(e)})):t}}))}function j(e,t,n,i){var s=[],c=function(e,t){if(e.method!==F&&(void 0!==e.data||void 0!==t.data)){var n=Array.isArray(e.data)?e.data:r(r({},e.data),t.data);return JSON.stringify(n)}}(n,i),u=function(e,t){var n=r(r({},e.headers),t.headers),i={};return Object.keys(n).forEach((function(e){var t=n[e];i[e.toLowerCase()]=t})),i}(e,i),o=n.method,f=n.method!==F?{}:r(r({},n.data),i.data),h=r(r(r({"x-algolia-agent":e.userAgent.value},e.queryParameters),f),i.queryParameters),l=0,m=function t(r,a){var f=r.pop();if(void 0===f)throw{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:O(s)};var m={data:c,headers:u,method:o,url:E(f,n.path,h),connectTimeout:a(l,e.timeouts.connect),responseTimeout:a(l,i.timeout)},d=function(e){var t={request:m,response:e,host:f,triesLeft:r.length};return s.push(t),t},v={onSuccess:function(e){return function(e){try{return JSON.parse(e.content)}catch(t){throw function(e,t){return{name:"DeserializationError",message:e,response:t}}(t.message,e)}}(e)},onRetry:function(n){var i=d(n);return n.isTimedOut&&l++,Promise.all([e.logger.info("Retryable failure",w(i)),e.hostsCache.set(f,y(f,n.isTimedOut?g:p))]).then((function(){return t(r,a)}))},onFail:function(e){throw d(e),function(e,t){var r=e.content,n=e.status,i=r;try{i=JSON.parse(r).message}catch(e){}return function(e,t,r){return{name:"ApiError",message:e,status:t,transporterStackTrace:r}}(i,n,t)}(e,O(s))}};return e.requester.send(m).then((function(e){return function(e,t){return function(e){var t=e.status;return e.isTimedOut||function(e){var t=e.isTimedOut,r=e.status;return!t&&0==~~r}(e)||2!=~~(t/100)&&4!=~~(t/100)}(e)?t.onRetry(e):2==~~(e.status/100)?t.onSuccess(e):t.onFail(e)}(e,v)}))};return P(e.hostsCache,t).then((function(e){return m(a(e.statelessHosts).reverse(),e.getTimeout)}))}function _(e){var t={value:"Algolia for JavaScript (".concat(e,")"),add:function(e){var r="; ".concat(e.segment).concat(void 0!==e.version?" (".concat(e.version,")"):"");return-1===t.value.indexOf(r)&&(t.value="".concat(t.value).concat(r)),t}};return t}function E(e,t,r){var n=x(r),i="".concat(e.protocol,"://").concat(e.url,"/").concat("/"===t.charAt(0)?t.substr(1):t);return n.length&&(i+="?".concat(n)),i}function x(e){return Object.keys(e).map((function(t){return h("%s=%s",t,(r=e[t],"[object Object]"===Object.prototype.toString.call(r)||"[object Array]"===Object.prototype.toString.call(r)?JSON.stringify(e[t]):e[t]));var r})).join("&")}function O(e){return e.map((function(e){return w(e)}))}function w(e){var t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return r(r({},e),{},{request:r(r({},e.request),{},{headers:r(r({},e.request.headers),t)})})}var N=function(e){var t=e.appId,n=function(e,t,r){var n={"x-algolia-api-key":r,"x-algolia-application-id":t};return{headers:function(){return e===l.WithinHeaders?n:{}},queryParameters:function(){return e===l.WithinQueryParameters?n:{}}}}(void 0!==e.authMode?e.authMode:l.WithinHeaders,t,e.apiKey),a=function(e){var t=e.hostsCache,r=e.logger,n=e.requester,a=e.requestsCache,s=e.responsesCache,c=e.timeouts,u=e.userAgent,o=e.hosts,f=e.queryParameters,h={hostsCache:t,logger:r,requester:n,requestsCache:a,responsesCache:s,timeouts:c,userAgent:u,headers:e.headers,queryParameters:f,hosts:o.map((function(e){return R(e)})),read:function(e,t){var r=m(t,h.timeouts.read),n=function(){return j(h,h.hosts.filter((function(e){return 0!=(e.accept&d.Read)})),e,r)};if(!0!==(void 0!==r.cacheable?r.cacheable:e.cacheable))return n();var a={request:e,mappedRequestOptions:r,transporter:{queryParameters:h.queryParameters,headers:h.headers}};return h.responsesCache.get(a,(function(){return h.requestsCache.get(a,(function(){return h.requestsCache.set(a,n()).then((function(e){return Promise.all([h.requestsCache.delete(a),e])}),(function(e){return Promise.all([h.requestsCache.delete(a),Promise.reject(e)])})).then((function(e){var t=i(e,2);return t[0],t[1]}))}))}),{miss:function(e){return h.responsesCache.set(a,e)}})},write:function(e,t){return j(h,h.hosts.filter((function(e){return 0!=(e.accept&d.Write)})),e,m(t,h.timeouts.write))}};return h}(r(r({hosts:[{url:"".concat(t,"-dsn.algolia.net"),accept:d.Read},{url:"".concat(t,".algolia.net"),accept:d.Write}].concat(o([{url:"".concat(t,"-1.algolianet.com")},{url:"".concat(t,"-2.algolianet.com")},{url:"".concat(t,"-3.algolianet.com")}]))},e),{},{headers:r(r(r({},n.headers()),{"content-type":"application/x-www-form-urlencoded"}),e.headers),queryParameters:r(r({},n.queryParameters()),e.queryParameters)}));return f({transporter:a,appId:t,addAlgoliaAgent:function(e,t){a.userAgent.add({segment:e,version:t})},clearCache:function(){return Promise.all([a.requestsCache.clear(),a.responsesCache.clear()]).then((function(){}))}},e.methods)},A=function(e){return function(t,r){return t.method===F?e.transporter.read(t,r):e.transporter.write(t,r)}},H=function(e){return function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return f({transporter:e.transporter,appId:e.appId,indexName:t},r.methods)}},S=function(e){return function(t,n){var i=t.map((function(e){return r(r({},e),{},{params:x(e.params||{})})}));return e.transporter.read({method:b,path:"1/indexes/*/queries",data:{requests:i},cacheable:!0},n)}},T=function(e){return function(t,i){return Promise.all(t.map((function(t){var a=t.params,s=a.facetName,c=a.facetQuery,u=n(a,["facetName","facetQuery"]);return H(e)(t.indexName,{methods:{searchForFacetValues:k}}).searchForFacetValues(s,c,r(r({},i),u))})))}},Q=function(e){return function(t,r,n){return e.transporter.read({method:b,path:h("1/answers/%s/prediction",e.indexName),data:{query:t,queryLanguages:r},cacheable:!0},n)}},C=function(e){return function(t,r){return e.transporter.read({method:b,path:h("1/indexes/%s/query",e.indexName),data:{query:t},cacheable:!0},r)}},k=function(e){return function(t,r,n){return e.transporter.read({method:b,path:h("1/indexes/%s/facets/%s/query",e.indexName,t),data:{facetQuery:r},cacheable:!0},n)}},D=1,I=2,q=3;function V(e,t,n){var i,a={appId:e,apiKey:t,timeouts:{connect:1,read:2,write:30},requester:{send:function(e){return new Promise((function(t){var r=new XMLHttpRequest;r.open(e.method,e.url,!0),Object.keys(e.headers).forEach((function(t){return r.setRequestHeader(t,e.headers[t])}));var n,i=function(e,n){return setTimeout((function(){r.abort(),t({status:0,content:n,isTimedOut:!0})}),1e3*e)},a=i(e.connectTimeout,"Connection timeout");r.onreadystatechange=function(){r.readyState>r.OPENED&&void 0===n&&(clearTimeout(a),n=i(e.responseTimeout,"Socket timeout"))},r.onerror=function(){0===r.status&&(clearTimeout(a),clearTimeout(n),t({content:r.responseText||"Network request failed",status:r.status,isTimedOut:!1}))},r.onload=function(){clearTimeout(a),clearTimeout(n),t({content:r.responseText,status:r.status,isTimedOut:!1})},r.send(e.data)}))}},logger:(i=q,{debug:function(e,t){return D>=i&&console.debug(e,t),Promise.resolve()},info:function(e,t){return I>=i&&console.info(e,t),Promise.resolve()},error:function(e,t){return console.error(e,t),Promise.resolve()}}),responsesCache:u(),requestsCache:u({serializable:!1}),hostsCache:c({caches:[s({key:"".concat("4.13.1","-").concat(e)}),u()]}),userAgent:_("4.13.1").add({segment:"Browser",version:"lite"}),authMode:l.WithinQueryParameters};return N(r(r(r({},a),n),{},{methods:{search:S,searchForFacetValues:T,multipleQueries:S,multipleSearchForFacetValues:T,customRequest:A,initIndex:function(e){return function(t){return H(e)(t,{methods:{search:C,searchForFacetValues:k,findAnswers:Q}})}}}}))}return V.version="4.13.1",V}()},8824:function(e,t,r){"use strict";r.d(t,{c:function(){return o}});var n=r(7294),i=r(2263),a=["zero","one","two","few","many","other"];function s(e){return a.filter((function(t){return e.includes(t)}))}var c={locale:"en",pluralForms:s(["one","other"]),select:function(e){return 1===e?"one":"other"}};function u(){var e=(0,i.Z)().i18n.currentLocale;return(0,n.useMemo)((function(){try{return t=e,r=new Intl.PluralRules(t),{locale:t,pluralForms:s(r.resolvedOptions().pluralCategories),select:function(e){return r.select(e)}}}catch(n){return console.error('Failed to use Intl.PluralRules for locale "'+e+'".\nDocusaurus will fallback to the default (English) implementation.\nError: '+n.message+"\n"),c}var t,r}),[e])}function o(){var e=u();return{selectMessage:function(t,r){return function(e,t,r){var n=e.split("|");if(1===n.length)return n[0];n.length>r.pluralForms.length&&console.error("For locale="+r.locale+", a maximum of "+r.pluralForms.length+" plural forms are expected ("+r.pluralForms.join(",")+"), but the message contains "+n.length+": "+e);var i=r.select(t),a=r.pluralForms.indexOf(i);return n[Math.min(a,n.length-1)]}(r,t,e)}}}},2026:function(e,t,r){"use strict";r.r(t),r.d(t,{default:function(){return q}});var n=r(7294);function i(e){var t,r,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t1}));return n.createElement("div",{className:a("col","col--3","padding-left--none",T)},r.map((function(e){var i=e[0],a=e[1],s=r.length>1?i+": ":"";return n.createElement("select",{key:i,onChange:function(e){return t.setSearchVersion(i,e.target.value)},defaultValue:t.searchVersions[i],className:_},a.versions.map((function(e,t){return n.createElement("option",{key:t,label:""+s+e.label,value:e.name})})))})))}function I(){var e,t,r,i,s,u,p=(0,R.Z)(),_=p.siteConfig.themeConfig,T=p.i18n.currentLocale,I=_.algolia,q=I.appId,V=I.apiKey,L=I.indexName,B=I.externalUrlRegex,z=(e=(0,m.c)().selectMessage,function(t){return e(t,(0,b.I)({id:"theme.SearchPage.documentsFound.plurals",description:'Pluralized label for "{count} documents found". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',message:"One document found|{count} documents found"},{count:t}))}),M=(t=(0,F._r)(),r=(0,n.useState)((function(){return Object.entries(t).reduce((function(e,t){var r,n=t[0],i=t[1];return Object.assign({},e,((r={})[n]=i.versions[0].name,r))}),{})})),i=r[0],s=r[1],u=Object.values(t).some((function(e){return e.versions.length>1})),{allDocsData:t,versioningEnabled:u,searchVersions:i,setSearchVersion:function(e,t){return s((function(r){var n;return Object.assign({},r,((n={})[e]=t,n))}))}}),J=(0,g.O)(),U=J.searchQuery,W=J.setSearchQuery,Z={items:[],query:null,totalResults:null,totalPages:null,lastPage:null,hasMore:null,loading:null},X=(0,n.useReducer)((function(e,t){switch(t.type){case"reset":return Z;case"loading":return Object.assign({},e,{loading:!0});case"update":return U!==t.value.query?e:Object.assign({},t.value,{items:0===t.value.lastPage?t.value.items:e.items.concat(t.value.items)});case"advance":var r=e.totalPages>e.lastPage+1;return Object.assign({},e,{lastPage:r?e.lastPage+1:e.lastPage,hasMore:r});default:return e}}),Z),K=X[0],G=X[1],$=c()(q,V),Y=o()($,L,{hitsPerPage:15,advancedSyntax:!0,disjunctiveFacets:["language","docusaurus_tag"]});Y.on("result",(function(e){var t=e.results,r=t.query,n=t.hits,i=t.page,a=t.nbHits,s=t.nbPages;if(""!==r&&Array.isArray(n)){var c=function(e){return e.replace(/algolia-docsearch-suggestion--highlight/g,"search-result-match")},u=n.map((function(e){var t=e.url,r=e._highlightResult.hierarchy,n=e._snippetResult,i=void 0===n?{}:n,a=new URL(t),s=Object.keys(r).map((function(e){return c(r[e].value)}));return{title:s.pop(),url:(0,d.F)(B,a.href)?a.href:a.pathname+a.hash,summary:i.content?c(i.content.value)+"...":"",breadcrumbs:s}}));G({type:"update",value:{items:u,query:r,totalResults:a,totalPages:s,lastPage:i,hasMore:s>i+1,loading:!1}})}else G({type:"reset"})}));var ee=(0,n.useState)(null),te=ee[0],re=ee[1],ne=(0,n.useRef)(0),ie=(0,n.useRef)(l.Z.canUseIntersectionObserver&&new IntersectionObserver((function(e){var t=e[0],r=t.isIntersecting,n=t.boundingClientRect.y;r&&ne.current>n&&G({type:"advance"}),ne.current=n}),{threshold:1})),ae=function(){return U?(0,b.I)({id:"theme.SearchPage.existingResultsTitle",message:'Search results for "{query}"',description:"The search page title for non-empty query"},{query:U}):(0,b.I)({id:"theme.SearchPage.emptyResultsTitle",message:"Search the documentation",description:"The search page title for empty query"})},se=(0,v.zX)((function(e){void 0===e&&(e=0),Y.addDisjunctiveFacetRefinement("docusaurus_tag","default"),Y.addDisjunctiveFacetRefinement("language",T),Object.entries(M.searchVersions).forEach((function(e){var t=e[0],r=e[1];Y.addDisjunctiveFacetRefinement("docusaurus_tag","docs-"+t+"-"+r)})),Y.setQuery(U).setPage(e).search()}));return(0,n.useEffect)((function(){if(te){var e=ie.current;return e?(e.observe(te),function(){return e.unobserve(te)}):function(){return!0}}}),[te]),(0,n.useEffect)((function(){G({type:"reset"}),U&&(G({type:"loading"}),setTimeout((function(){se()}),300))}),[U,M.searchVersions,se]),(0,n.useEffect)((function(){K.lastPage&&0!==K.lastPage&&se(K.lastPage)}),[se,K.lastPage]),n.createElement(P.Z,null,n.createElement(f.Z,null,n.createElement("title",null,(0,y.p)(ae())),n.createElement("meta",{property:"robots",content:"noindex, follow"})),n.createElement("div",{className:"container margin-vert--lg"},n.createElement("h1",null,ae()),n.createElement("form",{className:"row",onSubmit:function(e){return e.preventDefault()}},n.createElement("div",{className:a("col",S,{"col--9":M.versioningEnabled,"col--12":!M.versioningEnabled})},n.createElement("input",{type:"search",name:"q",className:j,placeholder:(0,b.I)({id:"theme.SearchPage.inputPlaceholder",message:"Type your search here",description:"The placeholder for search page input"}),"aria-label":(0,b.I)({id:"theme.SearchPage.inputLabel",message:"Search",description:"The ARIA label for search page input"}),onChange:function(e){return W(e.target.value)},value:U,autoComplete:"off",autoFocus:!0})),M.versioningEnabled&&n.createElement(D,{docsSearchVersionsHelpers:M})),n.createElement("div",{className:"row"},n.createElement("div",{className:a("col","col--8",E)},!!K.totalResults&&z(K.totalResults)),n.createElement("div",{className:a("col","col--4","text--right",Q)},n.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://www.algolia.com/","aria-label":(0,b.I)({id:"theme.SearchPage.algoliaLabel",message:"Search by Algolia",description:"The ARIA label for Algolia mention"})},n.createElement("svg",{viewBox:"0 0 168 24",className:x},n.createElement("g",{fill:"none"},n.createElement("path",{className:O,d:"M120.925 18.804c-4.386.02-4.386-3.54-4.386-4.106l-.007-13.336 2.675-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-10.846-2.18c.821 0 1.43-.047 1.855-.129v-2.719a6.334 6.334 0 0 0-1.574-.199 5.7 5.7 0 0 0-.897.069 2.699 2.699 0 0 0-.814.24c-.24.116-.439.28-.582.491-.15.212-.219.335-.219.656 0 .628.219.991.616 1.23s.938.362 1.615.362zm-.233-9.7c.883 0 1.629.109 2.231.328.602.218 1.088.525 1.444.915.363.396.609.922.76 1.483.157.56.232 1.175.232 1.85v6.874a32.5 32.5 0 0 1-1.868.314c-.834.123-1.772.185-2.813.185-.69 0-1.327-.069-1.895-.198a4.001 4.001 0 0 1-1.471-.636 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.803 0-.656.13-1.073.384-1.525a3.24 3.24 0 0 1 1.047-1.106c.445-.287.95-.492 1.532-.615a8.8 8.8 0 0 1 1.82-.185 8.404 8.404 0 0 1 1.972.24v-.438c0-.307-.035-.6-.11-.874a1.88 1.88 0 0 0-.384-.73 1.784 1.784 0 0 0-.724-.493 3.164 3.164 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.735 7.735 0 0 0-1.26.307l-.321-2.192c.335-.117.834-.233 1.478-.349a10.98 10.98 0 0 1 2.073-.178zm52.842 9.626c.822 0 1.43-.048 1.854-.13V13.7a6.347 6.347 0 0 0-1.574-.199c-.294 0-.595.021-.896.069a2.7 2.7 0 0 0-.814.24 1.46 1.46 0 0 0-.582.491c-.15.212-.218.335-.218.656 0 .628.218.991.615 1.23.404.245.938.362 1.615.362zm-.226-9.694c.883 0 1.629.108 2.231.327.602.219 1.088.526 1.444.915.355.39.609.923.759 1.483a6.8 6.8 0 0 1 .233 1.852v6.873c-.41.088-1.034.19-1.868.314-.834.123-1.772.184-2.813.184-.69 0-1.327-.068-1.895-.198a4.001 4.001 0 0 1-1.471-.635 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.804 0-.656.13-1.073.384-1.524.26-.45.608-.82 1.047-1.107.445-.286.95-.491 1.532-.614a8.803 8.803 0 0 1 2.751-.13c.329.034.671.096 1.04.185v-.437a3.3 3.3 0 0 0-.109-.875 1.873 1.873 0 0 0-.384-.731 1.784 1.784 0 0 0-.724-.492 3.165 3.165 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.75 7.75 0 0 0-1.26.307l-.321-2.193c.335-.116.834-.232 1.478-.348a11.633 11.633 0 0 1 2.073-.177zm-8.034-1.271a1.626 1.626 0 0 1-1.628-1.62c0-.895.725-1.62 1.628-1.62.904 0 1.63.725 1.63 1.62 0 .895-.733 1.62-1.63 1.62zm1.348 13.22h-2.689V7.27l2.69-.423v11.956zm-4.714 0c-4.386.02-4.386-3.54-4.386-4.107l-.008-13.336 2.676-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-8.698-5.903c0-1.156-.253-2.119-.746-2.788-.493-.677-1.183-1.01-2.067-1.01-.882 0-1.574.333-2.065 1.01-.493.676-.733 1.632-.733 2.788 0 1.168.246 1.953.74 2.63.492.683 1.183 1.018 2.066 1.018.882 0 1.574-.342 2.067-1.019.492-.683.738-1.46.738-2.63zm2.737-.007c0 .902-.13 1.584-.397 2.33a5.52 5.52 0 0 1-1.128 1.906 4.986 4.986 0 0 1-1.752 1.223c-.685.286-1.739.45-2.265.45-.528-.006-1.574-.157-2.252-.45a5.096 5.096 0 0 1-1.744-1.223c-.487-.527-.863-1.162-1.137-1.906a6.345 6.345 0 0 1-.41-2.33c0-.902.123-1.77.397-2.508a5.554 5.554 0 0 1 1.15-1.892 5.133 5.133 0 0 1 1.75-1.216c.679-.287 1.425-.423 2.232-.423.808 0 1.553.142 2.237.423a4.88 4.88 0 0 1 1.753 1.216 5.644 5.644 0 0 1 1.135 1.892c.287.738.431 1.606.431 2.508zm-20.138 0c0 1.12.246 2.363.738 2.882.493.52 1.13.78 1.91.78.424 0 .828-.062 1.204-.178.377-.116.677-.253.917-.417V9.33a10.476 10.476 0 0 0-1.766-.226c-.971-.028-1.71.37-2.23 1.004-.513.636-.773 1.75-.773 2.788zm7.438 5.274c0 1.824-.466 3.156-1.404 4.004-.936.846-2.367 1.27-4.296 1.27-.705 0-2.17-.137-3.34-.396l.431-2.118c.98.205 2.272.26 2.95.26 1.074 0 1.84-.219 2.299-.656.459-.437.684-1.086.684-1.948v-.437a8.07 8.07 0 0 1-1.047.397c-.43.13-.93.198-1.492.198-.739 0-1.41-.116-2.018-.349a4.206 4.206 0 0 1-1.567-1.025c-.431-.45-.774-1.017-1.013-1.694-.24-.677-.363-1.885-.363-2.773 0-.834.13-1.88.384-2.577.26-.696.629-1.298 1.129-1.796.493-.498 1.095-.881 1.8-1.162a6.605 6.605 0 0 1 2.428-.457c.87 0 1.67.109 2.45.24.78.129 1.444.265 1.985.415V18.17zM6.972 6.677v1.627c-.712-.446-1.52-.67-2.425-.67-.585 0-1.045.13-1.38.391a1.24 1.24 0 0 0-.502 1.03c0 .425.164.765.494 1.02.33.256.835.532 1.516.83.447.192.795.356 1.045.495.25.138.537.332.862.582.324.25.563.548.718.894.154.345.23.741.23 1.188 0 .947-.334 1.691-1.004 2.234-.67.542-1.537.814-2.601.814-1.18 0-2.16-.229-2.936-.686v-1.708c.84.628 1.814.942 2.92.942.585 0 1.048-.136 1.388-.407.34-.271.51-.646.51-1.125 0-.287-.1-.55-.302-.79-.203-.24-.42-.42-.655-.542-.234-.123-.585-.29-1.053-.503a61.27 61.27 0 0 1-.582-.271 13.67 13.67 0 0 1-.55-.287 4.275 4.275 0 0 1-.567-.351 6.92 6.92 0 0 1-.455-.4c-.18-.17-.31-.34-.39-.51-.08-.17-.155-.37-.224-.598a2.553 2.553 0 0 1-.104-.742c0-.915.333-1.638.998-2.17.664-.532 1.523-.798 2.576-.798.968 0 1.793.17 2.473.51zm7.468 5.696v-.287c-.022-.607-.187-1.088-.495-1.444-.309-.357-.75-.535-1.324-.535-.532 0-.99.194-1.373.583-.382.388-.622.949-.717 1.683h3.909zm1.005 2.792v1.404c-.596.34-1.383.51-2.362.51-1.255 0-2.255-.377-3-1.132-.744-.755-1.116-1.744-1.116-2.968 0-1.297.34-2.316 1.021-3.055.68-.74 1.548-1.11 2.6-1.11 1.033 0 1.852.323 2.458.966.606.644.91 1.572.91 2.784 0 .33-.033.676-.096 1.038h-5.314c.107.702.405 1.239.894 1.611.49.372 1.106.558 1.85.558.862 0 1.58-.202 2.155-.606zm6.605-1.77h-1.212c-.596 0-1.045.116-1.349.35-.303.234-.454.532-.454.894 0 .372.117.664.35.877.235.213.575.32 1.022.32.51 0 .912-.142 1.204-.424.293-.281.44-.651.44-1.108v-.91zm-4.068-2.554V9.325c.627-.361 1.457-.542 2.489-.542 2.116 0 3.175 1.026 3.175 3.08V17h-1.548v-.957c-.415.68-1.143 1.02-2.186 1.02-.766 0-1.38-.22-1.843-.661-.462-.442-.694-1.003-.694-1.684 0-.776.293-1.38.878-1.81.585-.431 1.404-.647 2.457-.647h1.34V11.8c0-.554-.133-.971-.399-1.253-.266-.282-.707-.423-1.324-.423a4.07 4.07 0 0 0-2.345.718zm9.333-1.93v1.42c.394-1 1.101-1.5 2.123-1.5.148 0 .313.016.494.048v1.531a1.885 1.885 0 0 0-.75-.143c-.542 0-.989.24-1.34.718-.351.479-.527 1.048-.527 1.707V17h-1.563V8.91h1.563zm5.01 4.084c.022.82.272 1.492.75 2.019.479.526 1.15.79 2.01.79.639 0 1.235-.176 1.788-.527v1.404c-.521.319-1.186.479-1.995.479-1.265 0-2.276-.4-3.031-1.197-.755-.798-1.133-1.792-1.133-2.984 0-1.16.38-2.151 1.14-2.975.761-.825 1.79-1.237 3.088-1.237.702 0 1.346.149 1.93.447v1.436a3.242 3.242 0 0 0-1.77-.495c-.84 0-1.513.266-2.019.798-.505.532-.758 1.213-.758 2.042zM40.24 5.72v4.579c.458-1 1.293-1.5 2.505-1.5.787 0 1.42.245 1.899.734.479.49.718 1.17.718 2.042V17h-1.564v-5.106c0-.553-.14-.98-.422-1.284-.282-.303-.652-.455-1.11-.455-.531 0-1.002.202-1.411.606-.41.405-.615 1.022-.615 1.851V17h-1.563V5.72h1.563zm14.966 10.02c.596 0 1.096-.253 1.5-.758.404-.506.606-1.157.606-1.955 0-.915-.202-1.62-.606-2.114-.404-.495-.92-.742-1.548-.742-.553 0-1.05.224-1.491.67-.442.447-.662 1.133-.662 2.058 0 .958.212 1.67.638 2.138.425.469.946.703 1.563.703zM53.004 5.72v4.42c.574-.894 1.388-1.341 2.44-1.341 1.022 0 1.857.383 2.506 1.149.649.766.973 1.781.973 3.047 0 1.138-.309 2.109-.925 2.912-.617.803-1.463 1.205-2.537 1.205-1.075 0-1.894-.447-2.457-1.34V17h-1.58V5.72h1.58zm9.908 11.104l-3.223-7.913h1.739l1.005 2.632 1.26 3.415c.096-.32.48-1.458 1.15-3.415l.909-2.632h1.66l-2.92 7.866c-.777 2.074-1.963 3.11-3.559 3.11a2.92 2.92 0 0 1-.734-.079v-1.34c.17.042.351.064.543.064 1.032 0 1.755-.57 2.17-1.708z"}),n.createElement("path",{fill:"#5468FF",d:"M78.988.938h16.594a2.968 2.968 0 0 1 2.966 2.966V20.5a2.967 2.967 0 0 1-2.966 2.964H78.988a2.967 2.967 0 0 1-2.966-2.964V3.897A2.961 2.961 0 0 1 78.988.938z"}),n.createElement("path",{fill:"white",d:"M89.632 5.967v-.772a.978.978 0 0 0-.978-.977h-2.28a.978.978 0 0 0-.978.977v.793c0 .088.082.15.171.13a7.127 7.127 0 0 1 1.984-.28c.65 0 1.295.088 1.917.259.082.02.164-.04.164-.13m-6.248 1.01l-.39-.389a.977.977 0 0 0-1.382 0l-.465.465a.973.973 0 0 0 0 1.38l.383.383c.062.061.15.047.205-.014.226-.307.472-.601.746-.874.281-.28.568-.526.883-.751.068-.042.075-.137.02-.2m4.16 2.453v3.341c0 .096.104.165.192.117l2.97-1.537c.068-.034.089-.117.055-.184a3.695 3.695 0 0 0-3.08-1.866c-.068 0-.136.054-.136.13m0 8.048a4.489 4.489 0 0 1-4.49-4.482 4.488 4.488 0 0 1 4.49-4.482 4.488 4.488 0 0 1 4.489 4.482 4.484 4.484 0 0 1-4.49 4.482m0-10.85a6.363 6.363 0 1 0 0 12.729 6.37 6.37 0 0 0 6.372-6.368 6.358 6.358 0 0 0-6.371-6.36"})))))),K.items.length>0?n.createElement("main",null,K.items.map((function(e,t){var r=e.title,i=e.url,s=e.summary,c=e.breadcrumbs;return n.createElement("article",{key:t,className:w},n.createElement("h2",{className:N},n.createElement(h.Z,{to:i,dangerouslySetInnerHTML:{__html:r}})),c.length>0&&n.createElement("nav",{"aria-label":"breadcrumbs"},n.createElement("ul",{className:a("breadcrumbs",A)},c.map((function(e,t){return n.createElement("li",{key:t,className:"breadcrumbs__item",dangerouslySetInnerHTML:{__html:e}})})))),s&&n.createElement("p",{className:H,dangerouslySetInnerHTML:{__html:s}}))}))):[U&&!K.loading&&n.createElement("p",{key:"no-results"},n.createElement(b.Z,{id:"theme.SearchPage.noResultsText",description:"The paragraph for empty search result"},"No results were found")),!!K.loading&&n.createElement("div",{key:"spinner",className:C})],K.hasMore&&n.createElement("div",{className:k,ref:re},n.createElement(b.Z,{id:"theme.SearchPage.fetchingNewResults",description:"The paragraph for fetching new search results"},"Fetching new results..."))))}function q(){return n.createElement(p.FG,{className:"search-page-wrapper"},n.createElement(I,null))}}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/1a4e3797.b4a26642.js.LICENSE.txt b/handbook/build/assets/js/1a4e3797.f48b4242.js.LICENSE.txt similarity index 100% rename from handbook/build/assets/js/1a4e3797.b4a26642.js.LICENSE.txt rename to handbook/build/assets/js/1a4e3797.f48b4242.js.LICENSE.txt diff --git a/handbook/build/assets/js/1be78505.2600d13c.js b/handbook/build/assets/js/1be78505.2600d13c.js deleted file mode 100644 index c996c70f8c..0000000000 --- a/handbook/build/assets/js/1be78505.2600d13c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[9514,713],{3538:function(e,t,n){n.r(t),n.d(t,{default:function(){return Ae}});var a=n(7294),l=n(4334),r=n(4873),o=n(8015),i=n(4714),c=n(9105),s=n(6141),d=n(3),m=n(4832),u=n(1614),p=n(3735),b=n(8265);var f="backToTopButton_sjWU",v="backToTopButtonShow_xfvO";function h(){var e=function(e){var t=e.threshold,n=(0,a.useState)(!1),l=n[0],r=n[1],o=(0,a.useRef)(!1),i=(0,p.Ct)(),c=i.startScroll,s=i.cancelScroll;return(0,p.RF)((function(e,n){var a=e.scrollY,l=null==n?void 0:n.scrollY;l&&(o.current?o.current=!1:a>=l?(s(),r(!1)):a=l?(s(),r(!1)):a(u => u.Id == 1);\nvar expression2 = LinqExpression.Create((u,i) => u.Id == 1 && i > 0);\n")),(0,i.kt)("h2",{id:"52-\u62fc\u63a5\u4e24\u4e2a\u8868\u8fbe\u5f0f"},"5.2 \u62fc\u63a5\u4e24\u4e2a\u8868\u8fbe\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u521b\u5efa\u4e00\u4e2a\u521d\u59cb\u5316\u7684\u8868\u8fbe\u5f0f\nvar expression = LinqExpression.And();\nvar expression2 = LinqExpression.IndexAnd();\nvar expression3 = LinqExpression.Or();\nvar expression4 = LinqExpression.IndexOr();\n\n// \u62fc\u63a5\u8868\u8fbe\u5f0f\nvar expression5 = expression.And(expression2);\nvar expression6 = expression.AndIf(age > 18, expression2);\nvar expression7 = expression.Or(expression2);\nvar expression8 = expression.OrIf(age > 18, expression2);\n\n// \u83b7\u53d6\u8868\u8fbe\u5f0f\u5c5e\u6027\u540d\nvar properyName = expression.GetExpressionPropertyName(u => u.Name); // Name\n")))}d.isMDXComponent=!0},3905:function(e,n,r){r.d(n,{Zo:function(){return u},kt:function(){return d}});var t=r(7294);function o(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function s(e){for(var n=1;n=0||(o[r]=e[r]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var p=t.createContext({}),l=function(e){var n=t.useContext(p),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},u=function(e){var n=l(e.components);return t.createElement(p.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},f=t.forwardRef((function(e,n){var r=e.components,o=e.mdxType,i=e.originalType,p=e.parentName,u=a(e,["components","mdxType","originalType","parentName"]),f=l(r),d=o,m=f["".concat(p,".").concat(d)]||f[d]||c[d]||i;return r?t.createElement(m,s(s({ref:n},u),{},{components:r})):t.createElement(m,s({ref:n},u))}));function d(e,n){var r=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=r.length,s=new Array(i);s[0]=f;var a={};for(var p in n)hasOwnProperty.call(n,p)&&(a[p]=n[p]);a.originalType=e,a.mdxType="string"==typeof e?e:o,s[1]=a;for(var l=2;l=0||(o[r]=e[r]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var p=t.createContext({}),l=function(e){var n=t.useContext(p),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},u=function(e){var n=l(e.components);return t.createElement(p.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},f=t.forwardRef((function(e,n){var r=e.components,o=e.mdxType,i=e.originalType,p=e.parentName,u=a(e,["components","mdxType","originalType","parentName"]),f=l(r),d=o,m=f["".concat(p,".").concat(d)]||f[d]||c[d]||i;return r?t.createElement(m,s(s({ref:n},u),{},{components:r})):t.createElement(m,s({ref:n},u))}));function d(e,n){var r=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=r.length,s=new Array(i);s[0]=f;var a={};for(var p in n)hasOwnProperty.call(n,p)&&(a[p]=n[p]);a.originalType=e,a.mdxType="string"==typeof e?e:o,s[1]=a;for(var l=2;l(u => u.Id == 1);\nvar expression2 = LinqExpression.Create((u,i) => u.Id == 1 && i > 0);\n")),(0,i.kt)("h2",{id:"52-\u62fc\u63a5\u4e24\u4e2a\u8868\u8fbe\u5f0f"},"5.2 \u62fc\u63a5\u4e24\u4e2a\u8868\u8fbe\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u521b\u5efa\u4e00\u4e2a\u521d\u59cb\u5316\u7684\u8868\u8fbe\u5f0f\nvar expression = LinqExpression.And();\nvar expression2 = LinqExpression.IndexAnd();\nvar expression3 = LinqExpression.Or();\nvar expression4 = LinqExpression.IndexOr();\n\n// \u62fc\u63a5\u8868\u8fbe\u5f0f\nvar expression5 = expression.And(expression2);\nvar expression6 = expression.AndIf(age > 18, expression2);\nvar expression7 = expression.Or(expression2);\nvar expression8 = expression.OrIf(age > 18, expression2);\n\n// \u83b7\u53d6\u8868\u8fbe\u5f0f\u5c5e\u6027\u540d\nvar properyName = expression.GetExpressionPropertyName(u => u.Name); // Name\n")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/22bdbfc1.fc56613a.js b/handbook/build/assets/js/22bdbfc1.363d2198.js similarity index 72% rename from handbook/build/assets/js/22bdbfc1.fc56613a.js rename to handbook/build/assets/js/22bdbfc1.363d2198.js index 8bee70c52e..91003916a0 100644 --- a/handbook/build/assets/js/22bdbfc1.fc56613a.js +++ b/handbook/build/assets/js/22bdbfc1.363d2198.js @@ -1 +1 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[3411],{9689:function(o){o.exports=JSON.parse('{"label":"download","permalink":"/furion/blog/tags/download","allTagsPath":"/furion/blog/tags","count":1}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[3411],{6296:function(o){o.exports=JSON.parse('{"label":"download","permalink":"/furion/blog/tags/download","allTagsPath":"/furion/blog/tags","count":1}')}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/22f09a41.39655112.js b/handbook/build/assets/js/22f09a41.39655112.js new file mode 100644 index 0000000000..043620ee35 --- /dev/null +++ b/handbook/build/assets/js/22f09a41.39655112.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[6494],{3905:function(e,n,t){t.d(n,{Zo:function(){return d},kt:function(){return u}});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function l(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var m=a.createContext({}),p=function(e){var n=a.useContext(m),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},d=function(e){var n=p(e.components);return a.createElement(m.Provider,{value:n},e.children)},k={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},N=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,m=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),N=p(t),u=r,s=N["".concat(m,".").concat(u)]||N[u]||k[u]||i;return t?a.createElement(s,l(l({ref:n},d),{},{components:t})):a.createElement(s,l({ref:n},d))}));function u(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,l=new Array(i);l[0]=N;var o={};for(var m in n)hasOwnProperty.call(n,m)&&(o[m]=n[m]);o.originalType=e,o.mdxType="string"==typeof e?e:r,l[1]=o;for(var p=2;pISpareTimeWorker \u65b9\u5f0f",id:"2635-isparetimeworker-\u65b9\u5f0f",level:3},{value:"26.4 \u95f4\u9694\u65b9\u5f0f\u4f7f\u7528",id:"264-\u95f4\u9694\u65b9\u5f0f\u4f7f\u7528",level:2},{value:"26.4.1 \u6bcf\u9694\u4e00\u6bb5\u65f6\u95f4\u6267\u884c",id:"2641-\u6bcf\u9694\u4e00\u6bb5\u65f6\u95f4\u6267\u884c",level:3},{value:"26.4.2 \u914d\u7f6e\u4efb\u52a1\u4fe1\u606f",id:"2642-\u914d\u7f6e\u4efb\u52a1\u4fe1\u606f",level:3},{value:"26.4.3 \u624b\u52a8\u542f\u52a8\u6267\u884c",id:"2643-\u624b\u52a8\u542f\u52a8\u6267\u884c",level:3},{value:"26.4.4 ISpareTimeWorker \u65b9\u5f0f",id:"2644-isparetimeworker-\u65b9\u5f0f",level:3},{value:"26.5 Cron \u8868\u8fbe\u5f0f\u4f7f\u7528",id:"265-cron-\u8868\u8fbe\u5f0f\u4f7f\u7528",level:2},{value:"26.5.1 \u4ec0\u4e48\u662f Cron \u8868\u8fbe\u5f0f",id:"2651-\u4ec0\u4e48\u662f-cron-\u8868\u8fbe\u5f0f",level:3},{value:"26.5.2 \u5e38\u89c1 Cron \u8868\u8fbe\u5f0f",id:"2652-\u5e38\u89c1-cron-\u8868\u8fbe\u5f0f",level:3},{value:"26.5.3 \u5728\u7ebf\u751f\u6210 Cron \u8868\u8fbe\u5f0f",id:"2653-\u5728\u7ebf\u751f\u6210-cron-\u8868\u8fbe\u5f0f",level:3},{value:"26.5.4 Macro \u6807\u8bc6\u7b26",id:"2654-macro-\u6807\u8bc6\u7b26",level:3},{value:"26.5.5 \u4f7f\u7528 Cron \u8868\u8fbe\u5f0f",id:"2655-\u4f7f\u7528-cron-\u8868\u8fbe\u5f0f",level:3},{value:"26.5.6 \u4f7f\u7528 Macro \u5360\u4f4d\u7b26",id:"2656-\u4f7f\u7528-macro-\u5360\u4f4d\u7b26",level:3},{value:"26.5.7 \u914d\u7f6e\u4efb\u52a1\u4fe1\u606f",id:"2657-\u914d\u7f6e\u4efb\u52a1\u4fe1\u606f",level:3},{value:"26.5.8 \u624b\u52a8\u542f\u52a8\u6267\u884c",id:"2658-\u624b\u52a8\u542f\u52a8\u6267\u884c",level:3},{value:"26.5.9 ISpareTimeWorker \u65b9\u5f0f",id:"2659-isparetimeworker-\u65b9\u5f0f",level:3},{value:"26.6 \u81ea\u5b9a\u4e49\u4e0b\u6b21\u6267\u884c\u65f6\u95f4",id:"266-\u81ea\u5b9a\u4e49\u4e0b\u6b21\u6267\u884c\u65f6\u95f4",level:2},{value:"26.6.1 \u9ad8\u7ea7\u81ea\u5b9a\u4e49\u95f4\u9694\u65b9\u5f0f",id:"2661-\u9ad8\u7ea7\u81ea\u5b9a\u4e49\u95f4\u9694\u65b9\u5f0f",level:3},{value:"26.6.2 \u9ad8\u7ea7\u81ea\u5b9a\u4e49 Cron \u8868\u8fbe\u5f0f",id:"2662-\u9ad8\u7ea7\u81ea\u5b9a\u4e49-cron-\u8868\u8fbe\u5f0f",level:3},{value:"26.7 ISpareTimeWorker \u8bf4\u660e",id:"267-isparetimeworker-\u8bf4\u660e",level:2},{value:"26.7.1 [SpareTime] \u7279\u6027",id:"2671-sparetime-\u7279\u6027",level:3},{value:"26.8 SpareTime \u9759\u6001\u7c7b",id:"268-sparetime-\u9759\u6001\u7c7b",level:2},{value:"26.8.1 \u521d\u59cb\u5316\u4efb\u52a1",id:"2681-\u521d\u59cb\u5316\u4efb\u52a1",level:3},{value:"26.8.2 \u5b9e\u73b0\u540e\u53f0\u6267\u884c",id:"2682-\u5b9e\u73b0\u540e\u53f0\u6267\u884c",level:3},{value:"26.8.3 \u5f00\u59cb\u4e00\u4e2a\u4efb\u52a1",id:"2683-\u5f00\u59cb\u4e00\u4e2a\u4efb\u52a1",level:3},{value:"26.8.4 \u6682\u505c\u4e00\u4e2a\u4efb\u52a1",id:"2684-\u6682\u505c\u4e00\u4e2a\u4efb\u52a1",level:3},{value:"26.8.5 \u53d6\u6d88\u4e00\u4e2a\u4efb\u52a1",id:"2685-\u53d6\u6d88\u4e00\u4e2a\u4efb\u52a1",level:3},{value:"26.8.6 \u9500\u6bc1\u6240\u6709\u4efb\u52a1",id:"2686-\u9500\u6bc1\u6240\u6709\u4efb\u52a1",level:3},{value:"26.8.7 \u83b7\u53d6\u6240\u6709\u4efb\u52a1",id:"2687-\u83b7\u53d6\u6240\u6709\u4efb\u52a1",level:3},{value:"26.8.8 \u83b7\u53d6\u5355\u4e2a\u4efb\u52a1",id:"2688-\u83b7\u53d6\u5355\u4e2a\u4efb\u52a1",level:3},{value:"26.8.9 \u89e3\u6790 Cron \u8868\u8fbe\u5f0f",id:"2689-\u89e3\u6790-cron-\u8868\u8fbe\u5f0f",level:3},{value:"26.9 \u5e76\u884c\u548c\u4e32\u884c\u6267\u884c\u65b9\u5f0f",id:"269-\u5e76\u884c\u548c\u4e32\u884c\u6267\u884c\u65b9\u5f0f",level:2},{value:"26.9.1 SpareTime \u9759\u6001\u65b9\u5f0f\u6307\u5b9a",id:"2691-sparetime-\u9759\u6001\u65b9\u5f0f\u6307\u5b9a",level:3},{value:"26.9.2 ISpareTimeWorker \u65b9\u5f0f",id:"2692-isparetimeworker-\u65b9\u5f0f",level:3},{value:"26.10 \u4efb\u52a1\u5f02\u5e38\u5904\u7406",id:"2610-\u4efb\u52a1\u5f02\u5e38\u5904\u7406",level:2},{value:"26.11 \u5982\u4f55\u5728\u4efb\u52a1\u4e2d\u89e3\u6790\u5bf9\u8c61",id:"2611-\u5982\u4f55\u5728\u4efb\u52a1\u4e2d\u89e3\u6790\u5bf9\u8c61",level:2},{value:"26.11.1 SpareTime \u9759\u6001\u7c7b\u4e2d",id:"26111-sparetime-\u9759\u6001\u7c7b\u4e2d",level:3},{value:"26.11.2 ISpareTimeWorker \u65b9\u5f0f",id:"26112-isparetimeworker-\u65b9\u5f0f",level:3},{value:"26.12 \u5728 BackgroundService \u4e2d\u4f7f\u7528",id:"2612-\u5728-backgroundservice-\u4e2d\u4f7f\u7528",level:2},{value:"26.12.1 \u95f4\u9694\u6267\u884c\u65b9\u5f0f",id:"26121-\u95f4\u9694\u6267\u884c\u65b9\u5f0f",level:3},{value:"26.12.2 Cron \u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f",id:"26122-cron-\u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f",level:3},{value:"26.13 \u5b9a\u65f6\u4efb\u52a1\u76d1\u542c\u5668",id:"2613-\u5b9a\u65f6\u4efb\u52a1\u76d1\u542c\u5668",level:2},{value:"26.13.1 SpareTimerExecuter \u5c5e\u6027\u8bf4\u660e",id:"26131-sparetimerexecuter-\u5c5e\u6027\u8bf4\u660e",level:3},{value:"26.14 IIS \u90e8\u7f72\u56de\u6536\u8bbe\u7f6e",id:"2614-iis-\u90e8\u7f72\u56de\u6536\u8bbe\u7f6e",level:2},{value:"26.15 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"2615-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],u={toc:N};function s(e){var n=e.components,t=(0,r.Z)(e,o);return(0,i.kt)("wrapper",(0,a.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 2.0.0 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,i.kt)("admonition",{title:"IIS \u90e8\u7f72\u8bf4\u660e",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u7531\u4e8e IIS \u6709\u56de\u6536\u7684\u673a\u5236\uff0c\u6240\u4ee5\u5b9a\u65f6\u4efb\u52a1\u5e94\u8be5\u91c7\u7528\u72ec\u7acb\u90e8\u7f72\uff0c\u4e0d\u7136\u7ecf\u5e38\u51fa\u73b0\u4e0d\u80fd\u89e6\u53d1\u7684\u60c5\u51b5\u3002\u67e5\u770b\u3010",(0,i.kt)("a",{parentName:"p",href:"/furion/docs/process-service"},"Worker Service \u7ae0\u8282"),"\u3011")),(0,i.kt)("h2",{id:"261-\u5173\u4e8e\u5b9a\u65f6\u4efb\u52a1"},"26.1 \u5173\u4e8e\u5b9a\u65f6\u4efb\u52a1"),(0,i.kt)("p",null,"\u987e\u540d\u601d\u4e49\uff0c\u5b9a\u65f6\u4efb\u52a1\u5c31\u662f\u5728\u7279\u5b9a\u7684\u65f6\u95f4\u6216\u7b26\u5408\u67d0\u79cd\u65f6\u95f4\u89c4\u5f8b\u6267\u884c\u7684\u4efb\u52a1\u3002\u901a\u5e38\u5b9a\u65f6\u4efb\u52a1\u6709\u56db\u79cd\u65f6\u95f4\u8c03\u5ea6\u65b9\u5f0f\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"\u7f13\u9694\u65f6\u95f4")," \u65b9\u5f0f\uff1a\u5ef6\u8fdf\u591a\u5c11\u65f6\u95f4\u540e\u8c03\u914d\u4efb\u52a1\uff0c\u8fd9\u79cd\u65b9\u5f0f\u4efb\u52a1\u53ea\u4f1a\u88ab\u8c03\u7528\u4e00\u6b21\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"\u95f4\u9694\u65f6\u95f4")," \u65b9\u5f0f\uff1a\u6bcf\u9694\u4e00\u6bb5\u56fa\u5b9a\u65f6\u95f4\u8c03\u914d\u4efb\u52a1\uff0c\u65e0\u95f4\u65ad\u8c03\u7528\u4efb\u52a1\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Cron \u8868\u8fbe\u5f0f")," \u65b9\u6cd5\uff1a\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"li"},"Cron")," \u8868\u8fbe\u5f0f\u8ba1\u7b97\u4e0b\u4e00\u6b21\u6267\u884c\u65f6\u95f4\u8fdb\u884c\u8c03\u914d\u4efb\u52a1\uff0c\u53ef\u4ee5\u914d\u7f6e\u7279\u5b9a\u65f6\u95f4\u8303\u56f4\u5185\u6267\u884c\uff0c\u4e5f\u53ef\u4ee5\u65e0\u95f4\u65ad\u6267\u884c\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"\u81ea\u5b9a\u4e49\u4e0b\u6b21\u6267\u884c\u65f6\u95f4"),"\uff1a\u53ef\u4ee5\u901a\u8fc7\u5404\u79cd\u903b\u8f91\u8fd0\u7b97\u8fd4\u56de\u4e0b\u4e00\u6b21\u6267\u884c\u65f6\u95f4")),(0,i.kt)("h2",{id:"262-\u5982\u4f55\u5b9e\u73b0"},"26.2 \u5982\u4f55\u5b9e\u73b0"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u4e24\u79cd\u65b9\u5f0f\u5b9e\u73b0\u5b9a\u65f6\u4efb\u52a1\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SpareTime")," \u9759\u6001\u7c7b\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"SpareTime")," \u9759\u6001\u7c7b\u63d0\u4f9b ",(0,i.kt)("inlineCode",{parentName:"li"},"SpareTime.Do([options])")," \u65b9\u5f0f\u8c03\u7528\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISpareTimeWorker")," \u4f9d\u8d56\u65b9\u5f0f\uff1a\u901a\u8fc7\u81ea\u5b9a\u4e49\u7c7b\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"li"},"ISpareTimeWorker")," \u63a5\u53e3\u5e76\u7f16\u5199\u4e00\u5b9a\u89c4\u5219\u7684\u65b9\u6cd5\u5373\u53ef\u3002",(0,i.kt)("strong",{parentName:"li"},"\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Startup.cs")," \u4e2d\u6ce8\u518c ",(0,i.kt)("inlineCode",{parentName:"strong"},"services.AddTaskScheduler()")))),(0,i.kt)("h2",{id:"263-\u7f13\u9694\u65b9\u5f0f\u4f7f\u7528"},"26.3 \u7f13\u9694\u65b9\u5f0f\u4f7f\u7528"),(0,i.kt)("h3",{id:"2631-\u7279\u5b9a\u65f6\u95f4\u540e\u6267\u884c"},"26.3.1 \u7279\u5b9a\u65f6\u95f4\u540e\u6267\u884c"),(0,i.kt)("p",null,"\u8fd9\u91cc\u6f14\u793a ",(0,i.kt)("inlineCode",{parentName:"p"},"3s")," \u540e\u6267\u884c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},'Console.WriteLine("\u5f53\u524d\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n\n// timer \u662f\u5b9a\u65f6\u5668\u7684\u5bf9\u8c61\uff0c\u5305\u542b\u5b9a\u65f6\u5668\u76f8\u5173\u4fe1\u606f\n// count \u8868\u793a\u6267\u884c\u6b21\u6570\uff0c\u8fd9\u91cc\u53ea\u6709\u4e00\u6b21\nSpareTime.DoOnce(3000, (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n});\n')),(0,i.kt)("h3",{id:"2632-\u914d\u7f6e\u4efb\u52a1\u4fe1\u606f"},"26.3.2 \u914d\u7f6e\u4efb\u52a1\u4fe1\u606f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},'SpareTime.DoOnce(3000, (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n}, "jobName", "\u63cf\u8ff0\u4e00\u4e0b\u8fd9\u4e2a\u4efb\u52a1\u662f\u5e72\u4ec0\u4e48\u7684");\n')),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"jobName")," \u6807\u8bc6\u4efb\u52a1\u7684\u552f\u4e00\u6807\u8bc6\uff0c\u901a\u8fc7\u8fd9\u4e2a\u6807\u8bc6\u53ef\u4ee5\u542f\u52a8\u3001\u6682\u505c\u3001\u9500\u6bc1\u4efb\u52a1\u3002"),(0,i.kt)("h3",{id:"2633-\u624b\u52a8\u542f\u52a8\u6267\u884c"},"26.3.3 \u624b\u52a8\u542f\u52a8\u6267\u884c"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u4efb\u52a1\u521d\u59cb\u5316\u540e\u5c31\u7acb\u5373\u542f\u52a8\uff0c\u7b49\u5f85\u7b26\u5408\u7684\u65f6\u95f4\u5c31\u6267\u884c\uff0c\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u4ec5\u4ec5\u60f3\u521d\u59cb\u5316\u65f6\u95f4\uff0c\u4e0d\u5e0c\u671b\u7acb\u5373\u6267\u884c\uff0c\u53ea\u9700\u8981\u914d\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"startNow")," \u5373\u53ef\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,6}",showLineNumbers:!0,"":!0,"{3,6}":!0},'SpareTime.DoOnce(3000, (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n},"jobName", startNow: false);\n\n// \u624b\u52a8\u542f\u52a8\u6267\u884c\nSpareTime.Start("jobName");\n')),(0,i.kt)("h3",{id:"2634-\u6a21\u62df\u540e\u53f0\u6267\u884c"},"26.3.4 \u6a21\u62df\u540e\u53f0\u6267\u884c"),(0,i.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u53ea\u9700\u8981\u5f00\u542f\u65b0\u7ebf\u7a0b\u53bb\u6267\u884c\u4e00\u4e2a\u4efb\u52a1\uff0c\u6bd4\u5982\u53d1\u77ed\u4fe1\uff0c\u53d1\u90ae\u4ef6\uff0c\u65e0\u9700\u914d\u7f6e\u3002"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},"// \u6b64\u65b9\u6cd5\u65e0\u9700\u4e3b\u7ebf\u7a0b\u7b49\u5f85\u5373\u53ef\u8fd4\u56de\uff0c\u53ef\u5927\u5927\u63d0\u9ad8\u6027\u80fd\nSpareTime.DoIt(() => {\n // \u8fd9\u91cc\u53d1\u9001\u77ed\u4fe1\uff0c\u53d1\u9001\u90ae\u4ef6\u6216\u8bb0\u5f55\u8bbf\u95ee\u8bb0\u5f55\n});\n")),(0,i.kt)("p",null,"\u8fd8\u53ef\u4ee5\u6307\u5b9a\u591a\u957f\u65f6\u95f4\u540e\u89e6\u53d1\uff0c\u5efa\u8bae ",(0,i.kt)("inlineCode",{parentName:"p"},"10-1000")," \u6beb\u79d2\u4e4b\u95f4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"SpareTime.DoIt(() => {\n // \u53d1\u9001\u77ed\u4fe1\n}, 100);\n")),(0,i.kt)("h3",{id:"2635-isparetimeworker-\u65b9\u5f0f"},"26.3.5 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ISpareTimeWorker")," \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,8}",showLineNumbers:!0,"":!0,"{1,8}":!0},'public class JobWorker : ISpareTimeWorker\n{\n /// \n /// 3s \u540e\u6267\u884c\n /// \n /// \n /// \n [SpareTime(3000, "jobName", DoOnce = true, StartNow = true)]\n public void DoSomething(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n }\n\n /// \n /// 3s \u540e\u6267\u884c\uff08\u652f\u6301\u5f02\u6b65\uff09\n /// \n /// \n /// \n [SpareTime(3000, "jobName", DoOnce = true, StartNow = true)]\n public async Task DoSomethingAsync(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n await Task.CompletedTask;\n }\n}\n')),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Startup.cs")," \u4e2d\u6ce8\u518c ",(0,i.kt)("inlineCode",{parentName:"strong"},"services.AddTaskScheduler()"))),(0,i.kt)("h2",{id:"264-\u95f4\u9694\u65b9\u5f0f\u4f7f\u7528"},"26.4 \u95f4\u9694\u65b9\u5f0f\u4f7f\u7528"),(0,i.kt)("h3",{id:"2641-\u6bcf\u9694\u4e00\u6bb5\u65f6\u95f4\u6267\u884c"},"26.4.1 \u6bcf\u9694\u4e00\u6bb5\u65f6\u95f4\u6267\u884c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},'// \u6bcf\u9694 1s \u6267\u884c\nSpareTime.Do(1000, (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n});\n')),(0,i.kt)("h3",{id:"2642-\u914d\u7f6e\u4efb\u52a1\u4fe1\u606f"},"26.4.2 \u914d\u7f6e\u4efb\u52a1\u4fe1\u606f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4}",showLineNumbers:!0,"":!0,"{1,4}":!0},'SpareTime.Do(1000, (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n}, "jobName", "\u8fd9\u662f\u4e00\u4e2a\u8ba1\u65f6\u5668\u4efb\u52a1");\n')),(0,i.kt)("h3",{id:"2643-\u624b\u52a8\u542f\u52a8\u6267\u884c"},"26.4.3 \u624b\u52a8\u542f\u52a8\u6267\u884c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4,6}",showLineNumbers:!0,"":!0,"{1,4,6}":!0},'SpareTime.Do(1000, (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n}, "jobName", startNow:false);\n\nSpareTime.Start("jobName");\n')),(0,i.kt)("h3",{id:"2644-isparetimeworker-\u65b9\u5f0f"},"26.4.4 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ISpareTimeWorker")," \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,8}",showLineNumbers:!0,"":!0,"{1,8}":!0},'public class JobWorker : ISpareTimeWorker\n{\n /// \n /// \u6bcf\u9694 3s \u6267\u884c\n /// \n /// \n /// \n [SpareTime(3000, "jobName", StartNow = true)]\n public void DoSomething(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n}\n')),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Startup.cs")," \u4e2d\u6ce8\u518c ",(0,i.kt)("inlineCode",{parentName:"strong"},"services.AddTaskScheduler()"))),(0,i.kt)("h2",{id:"265-cron-\u8868\u8fbe\u5f0f\u4f7f\u7528"},"26.5 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Cron")," \u8868\u8fbe\u5f0f\u4f7f\u7528"),(0,i.kt)("h3",{id:"2651-\u4ec0\u4e48\u662f-cron-\u8868\u8fbe\u5f0f"},"26.5.1 \u4ec0\u4e48\u662f ",(0,i.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f"),(0,i.kt)("p",null,"Cron \u8868\u8fbe\u5f0f\u662f\u4e00\u4e2a\u5b57\u7b26\u4e32\uff0c\u5b57\u7b26\u4e32\u4ee5 ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u6216 ",(0,i.kt)("inlineCode",{parentName:"p"},"6")," \u4e2a\u7a7a\u683c\u9694\u5f00\uff0c\u5206\u4e3a 6 \u6216 7 \u4e2a\u57df\uff0c\u6bcf\u4e00\u4e2a\u57df\u4ee3\u8868\u4e00\u4e2a\u542b\u4e49\uff0cCron \u6709\u5982\u4e0b\u4e24\u79cd\u8bed\u6cd5\u683c\u5f0f\uff1a"),(0,i.kt)("p",null,"\uff081\uff09 Seconds Minutes Hours DayofMonth Month DayofWeek Year"),(0,i.kt)("p",null,"\uff082\uff09Seconds Minutes Hours DayofMonth Month DayofWeek"),(0,i.kt)("p",null,"Cron \u4ece\u5de6\u5230\u53f3\uff08\u7528\u7a7a\u683c\u9694\u5f00\uff09\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"\u79d2")," ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5206")," ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5c0f\u65f6")," ",(0,i.kt)("inlineCode",{parentName:"p"},"\u6708\u4efd\u4e2d\u7684\u65e5\u671f")," ",(0,i.kt)("inlineCode",{parentName:"p"},"\u6708\u4efd")," ",(0,i.kt)("inlineCode",{parentName:"p"},"\u661f\u671f\u4e2d\u7684\u65e5\u671f")," ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5e74\u4efd")),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"\u5b57\u6bb5"),(0,i.kt)("th",{parentName:"tr",align:null},"\u5141\u8bb8\u503c"),(0,i.kt)("th",{parentName:"tr",align:null},"\u5141\u8bb8\u7684\u7279\u6b8a\u5b57\u7b26"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"\u79d2\uff08Seconds\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0~59")," \u7684\u6574\u6570"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},", - \\* /")," \u56db\u4e2a\u5b57\u7b26")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"\u5206\uff08Minutes\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0~59")," \u7684\u6574\u6570"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},", - \\* /")," \u56db\u4e2a\u5b57\u7b26")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"\u5c0f\u65f6\uff08Hours\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0~23")," \u7684\u6574\u6570"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},", - \\* /")," \u56db\u4e2a\u5b57\u7b26")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"\u65e5\u671f\uff08DayofMonth\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"1~31")," \u7684\u6574\u6570\uff08\u4f46\u662f\u4f60\u9700\u8981\u8003\u8651\u5e73\u95f0\u6708\u7684\u5929\u6570\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},",- \\* ? / L W C")," \u516b\u4e2a\u5b57\u7b26")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"\u6708\u4efd\uff08Month\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"1~12")," \u7684\u6574\u6570\u6216\u8005 ",(0,i.kt)("inlineCode",{parentName:"td"},"JAN-DEC")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},", - \\* /")," \u56db\u4e2a\u5b57\u7b26")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"\u661f\u671f\uff08DayofWeek\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"1~7")," \u7684\u6574\u6570\u6216\u8005 ",(0,i.kt)("inlineCode",{parentName:"td"},"SUN-SAT \uff081=SUN\uff09")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},", - \\* ? / L C #")," \u516b\u4e2a\u5b57\u7b26")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"\u5e74(\u53ef\u9009\uff0c\u7559\u7a7a)\uff08Year\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"1970~2099")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},", - \\* /")," \u56db\u4e2a\u5b57\u7b26")))),(0,i.kt)("p",null,"\u6bcf\u4e00\u4e2a\u57df\u90fd\u4f7f\u7528\u6570\u5b57\uff0c\u4f46\u8fd8\u53ef\u4ee5\u51fa\u73b0\u5982\u4e0b\u7279\u6b8a\u5b57\u7b26\uff0c\u5b83\u4eec\u7684\u542b\u4e49\u662f\uff1a"),(0,i.kt)("p",null,"\uff081\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"_"),"\uff1a\u8868\u793a\u5339\u914d\u8be5\u57df\u7684\u4efb\u610f\u503c\u3002\u5047\u5982\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Minutes")," \u57df\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"\\_"),", \u5373\u8868\u793a\u6bcf\u5206\u949f\u90fd\u4f1a\u89e6\u53d1\u4e8b\u4ef6\u3002"),(0,i.kt)("p",null,"\uff082\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"?"),"\uff1a\u53ea\u80fd\u7528\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofMonth")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofWeek")," \u4e24\u4e2a\u57df\u3002\u5b83\u4e5f\u5339\u914d\u57df\u7684\u4efb\u610f\u503c\uff0c\u4f46\u5b9e\u9645\u4e0d\u4f1a\u3002\u56e0\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofMonth")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofWeek")," \u4f1a\u76f8\u4e92\u5f71\u54cd\u3002\u4f8b\u5982\u60f3\u5728\u6bcf\u6708\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"20")," \u65e5\u89e6\u53d1\u8c03\u5ea6\uff0c\u4e0d\u7ba1 ",(0,i.kt)("inlineCode",{parentName:"p"},"20")," \u65e5\u5230\u5e95\u662f\u661f\u671f\u51e0\uff0c\u5219\u53ea\u80fd\u4f7f\u7528\u5982\u4e0b\u5199\u6cd5\uff1a ",(0,i.kt)("inlineCode",{parentName:"p"},"13 13 15 20 _ ?"),", \u5176\u4e2d\u6700\u540e\u4e00\u4f4d\u53ea\u80fd\u7528",(0,i.kt)("inlineCode",{parentName:"p"},"\uff1f"),"\uff0c\u800c\u4e0d\u80fd\u4f7f\u7528","_","\uff0c\u5982\u679c\u4f7f\u7528","*","\u8868\u793a\u4e0d\u7ba1\u661f\u671f\u51e0\u90fd\u4f1a\u89e6\u53d1\uff0c\u5b9e\u9645\u4e0a\u5e76\u4e0d\u662f\u8fd9\u6837\u3002"),(0,i.kt)("p",null,"\uff083\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"-"),"\uff1a\u8868\u793a\u8303\u56f4\u3002\u4f8b\u5982\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Minutes")," \u57df\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"5-20"),"\uff0c\u8868\u793a\u4ece ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u5206\u5230 ",(0,i.kt)("inlineCode",{parentName:"p"},"20")," \u5206\u949f\u6bcf\u5206\u949f\u89e6\u53d1\u4e00\u6b21"),(0,i.kt)("p",null,"\uff084\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"/"),"\uff1a\u8868\u793a\u8d77\u59cb\u65f6\u95f4\u5f00\u59cb\u89e6\u53d1\uff0c\u7136\u540e\u6bcf\u9694\u56fa\u5b9a\u65f6\u95f4\u89e6\u53d1\u4e00\u6b21\u3002\u4f8b\u5982\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Minutes")," \u57df\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"5/20"),"\uff0c\u5219\u610f\u5473\u7740 ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u5206\u949f\u89e6\u53d1\u4e00\u6b21\uff0c\u800c ",(0,i.kt)("inlineCode",{parentName:"p"},"25\uff0c45")," \u7b49\u5206\u522b\u89e6\u53d1\u4e00\u6b21."),(0,i.kt)("p",null,"\uff085\uff09",(0,i.kt)("inlineCode",{parentName:"p"},","),"\uff1a\u8868\u793a\u5217\u51fa\u679a\u4e3e\u503c\u3002\u4f8b\u5982\uff1a\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Minutes")," \u57df\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"5,20"),"\uff0c\u5219\u610f\u5473\u7740\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"20")," \u5206\u6bcf\u5206\u949f\u89e6\u53d1\u4e00\u6b21\u3002"),(0,i.kt)("p",null,"\uff086\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"L"),"\uff1a\u8868\u793a\u6700\u540e\uff0c\u53ea\u80fd\u51fa\u73b0\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofWeek")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofMonth")," \u57df\u3002\u5982\u679c\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofWeek")," \u57df\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"5L"),",\u610f\u5473\u7740\u5728\u6700\u540e\u7684\u4e00\u4e2a\u661f\u671f\u56db\u89e6\u53d1\u3002"),(0,i.kt)("p",null,"\uff087\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"W"),"\uff1a\u8868\u793a\u6709\u6548\u5de5\u4f5c\u65e5(\u5468\u4e00\u5230\u5468\u4e94) \u53ea\u80fd\u51fa\u73b0\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofMonth")," \u57df\uff0c\u7cfb\u7edf\u5c06\u5728\u79bb\u6307\u5b9a\u65e5\u671f\u7684\u6700\u8fd1\u7684\u6709\u6548\u5de5\u4f5c\u65e5\u89e6\u53d1\u4e8b\u4ef6\u3002\u4f8b\u5982\uff1a\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofMonth")," \u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"5W"),"\uff0c\u5982\u679c ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u65e5\u662f\u661f\u671f\u516d\uff0c\u5219\u5c06\u5728\u6700\u8fd1\u7684\u5de5\u4f5c\u65e5\uff1a\u661f\u671f\u4e94\uff0c\u5373 ",(0,i.kt)("inlineCode",{parentName:"p"},"4")," \u65e5\u89e6\u53d1\u3002\u5982\u679c ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u65e5\u662f\u661f\u671f\u5929\uff0c\u5219\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"6")," \u65e5(\u5468\u4e00)\u89e6\u53d1\uff1b\u5982\u679c ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u65e5\u5728\u661f\u671f\u4e00\u5230\u661f\u671f\u4e94\u4e2d\u7684\u4e00\u5929\uff0c\u5219\u5c31\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u65e5\u89e6\u53d1\u3002\u53e6\u5916\u4e00\u70b9\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"W")," \u7684\u6700\u8fd1\u5bfb\u627e\u4e0d\u4f1a\u8de8\u8fc7\u6708\u4efd \u3002"),(0,i.kt)("p",null,"\uff088\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"LW"),"\uff1a\u8fd9\u4e24\u4e2a\u5b57\u7b26\u53ef\u4ee5\u8fde\u7528\uff0c\u8868\u793a\u5728\u67d0\u4e2a\u6708\u6700\u540e\u4e00\u4e2a\u5de5\u4f5c\u65e5\uff0c\u5373\u6700\u540e\u4e00\u4e2a\u661f\u671f\u4e94\u3002"),(0,i.kt)("p",null,"\uff089\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"#"),"\uff1a\u7528\u4e8e\u786e\u5b9a\u6bcf\u4e2a\u6708\u7b2c\u51e0\u4e2a\u661f\u671f\u51e0\uff0c\u53ea\u80fd\u51fa\u73b0\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofMonth")," \u57df\u3002\u4f8b\u5982\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"4#2"),"\uff0c\u8868\u793a\u67d0\u6708\u7684\u7b2c\u4e8c\u4e2a\u661f\u671f\u4e09\u3002"),(0,i.kt)("h3",{id:"2652-\u5e38\u89c1-cron-\u8868\u8fbe\u5f0f"},"26.5.2 \u5e38\u89c1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f"),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"\u8868\u8fbe\u5f0f"),(0,i.kt)("th",{parentName:"tr",align:null},"\u8868\u8fbe\u5f0f\u4ee3\u8868\u542b\u4e49"),(0,i.kt)("th",{parentName:"tr",align:null},"\u683c\u5f0f\u5316"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"*/1 * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0/1 * * * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 * * * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5c0f\u65f6"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 0/1 * * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5c0f\u65f6"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 23 ? * MON-FRI")),(0,i.kt)("td",{parentName:"tr",align:null},"\u665a\u4e0a 11:00\uff0c\u5468\u4e00\u81f3\u5468\u4e94"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u79d2"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"*/45 * * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf 45 \u79d2"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"*/5 * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf 5 \u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0/10 * * * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf 10 \u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 */5 * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf 5 \u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"30 11 * * 1-5")),(0,i.kt)("td",{parentName:"tr",align:null},"\u5468\u4e00\u81f3\u5468\u4e94\u4e0a\u5348 11:30"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"30 11 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"11:30"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0-10 11 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0a\u5348 11:00 \u81f3 11:10 \u4e4b\u95f4\u7684\u6bcf\u4e00\u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * 3 *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f\uff0c\u53ea\u5728 3 \u6708\u4efd"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * 3,6 *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f\uff0c\u53ea\u5728 3 \u6708\u548c 6 \u6708"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"30 14,16 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 02:30 \u5206\u548c 04:30 \u5206"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"30 6,14,16 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u65e9\u4e0a 06:30\uff0c\u4e0b\u5348 02:30 \u548c 04:30"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"46 9 * * 1")),(0,i.kt)("td",{parentName:"tr",align:null},"\u65e9\u4e0a 09:46\uff0c\u53ea\u5728\u661f\u671f\u4e00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"23 12 15 * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 12:23\uff0c\u5728\u672c\u6708\u7684\u7b2c 15 \u5929"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"23 12 * JAN *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 12:23\uff0c\u53ea\u5728 1 \u6708\u4efd"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"23 12 ? JAN *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 12:23\uff0c\u53ea\u5728 1 \u6708\u4efd"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"23 12 * JAN-FEB *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 12:23\uff0c1 \u6708\u81f3 2 \u6708"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"23 12 * JAN-MAR *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 12:23\uff0c1 \u6708\u81f3 3 \u6708"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"23 12 * * SUN")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 12:23\uff0c\u4ec5\u5728\u661f\u671f\u5929"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"*/5 15 * * MON-FRI")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf 5 \u5206\u949f\uff0c\u4e0b\u5348 0:00 \u81f3 03:59\uff0c\u5468\u4e00\u81f3\u5468\u4e94"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * * MON#3")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f\uff0c\u5728\u6708\u7684\u7b2c\u4e09\u4e2a\u661f\u671f\u4e00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * * 4L")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u4e00\u5206\u949f\uff0c\u5728\u672c\u6708\u7684\u6700\u540e\u4e00\u5929"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"*/5 * L JAN *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u6708\u4e00\u6b21\u6bcf\u6708 5 \u5206\u949f\uff0c\u53ea\u5728 1 \u6708\u4efd"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"30 02 14 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348\u5728 02:02:30"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"5-10 * * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f\u7684 5-10 \u79d2"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"5-10 30-35 10-12 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"10:00 \u81f3 12:00 \u4e4b\u95f4\u7684\u6bcf\u5206\u949f 5-10 \u79d2\uff0c\u6bcf\u5c0f\u65f6 30-35 \u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"30 */5 * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f\u7684 30 \u79d2\uff0c\u6bcf\u4e94\u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 30 10-13 ? * WED,FRI")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5c0f\u65f6\u7684 30 \u5206\u949f\uff0c\u4e0b\u5348 10:00 \u81f3 01:00 \u4e4b\u95f4\uff0c\u4ec5\u5728\u5468\u4e09\u548c\u5468\u4e94"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"10 0/5 * * * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f\u7684 10 \u79d2\uff0c\u6bcf 05 \u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 6 1/1 * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 06:00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 5 0/1 * * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e00\u4e2a\u5c0f\u65f6\u7684 05 \u5206"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 L * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u6708\u6700\u540e\u4e00\u5929\u4e0a\u5348 00\uff1a00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 L-1 * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u6708\u6700\u540e\u4e00\u5929\u7684\u51cc\u6668 00\uff1a00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 3W * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u6708\u7b2c 3 \u4e2a\u5de5\u4f5c\u65e5\u4e0a\u5348 00\uff1a00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 LW * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u5728\u6bcf\u6708\u7684\u6700\u540e\u4e00\u4e2a\u5de5\u4f5c\u65e5\uff0c\u4e0a\u5348 00\uff1a00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 * * 2L")),(0,i.kt)("td",{parentName:"tr",align:null},"\u672c\u6708\u6700\u540e\u4e00\u4e2a\u661f\u671f\u4e8c\u4e0a\u5348 00\uff1a00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 * * 6#3")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u6708\u7b2c\u4e09\u4e2a\u661f\u671f\u516d\u4e0a\u5348 00\uff1a00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 ? 1 MON#1")),(0,i.kt)("td",{parentName:"tr",align:null},"1 \u6708\u7b2c\u4e00\u4e2a\u661f\u671f\u4e00\u4e0a\u5348 00\uff1a00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 3 * * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5929\u51e0\u70b9\u6267\u884c\u4e00\u6b21"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))))),(0,i.kt)("h3",{id:"2653-\u5728\u7ebf\u751f\u6210-cron-\u8868\u8fbe\u5f0f"},"26.5.3 \u5728\u7ebf\u751f\u6210 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f"),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://cron.qqe2.com/"},"https://cron.qqe2.com/")),(0,i.kt)("h3",{id:"2654-macro-\u6807\u8bc6\u7b26"},"26.5.4 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Macro")," \u6807\u8bc6\u7b26"),(0,i.kt)("p",null,"\u4e3a\u4e86\u65b9\u4fbf\u5b9a\u4e49 ",(0,i.kt)("inlineCode",{parentName:"p"},"Cron")," \u8868\u8fbe\u5f0f\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e5f\u63d0\u4f9b\u4e86\u975e\u5e38\u65b9\u4fbf\u7684\u5360\u4f4d\u7b26\u5b9e\u73b0\u5e38\u7528\u7684\u65f6\u95f4\u683c\u5f0f\uff1a"),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"\u5360\u4f4d\u7b26"),(0,i.kt)("th",{parentName:"tr",align:null},"\u5bf9\u5e94\u8868\u8fbe\u5f0f"),(0,i.kt)("th",{parentName:"tr",align:null},"\u5360\u4f4d\u7b26\u4ee3\u8868\u542b\u4e49"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@every_second")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e00\u79d2\u949f\u8dd1\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@every_minute")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u5728\u5206\u949f\u5f00\u59cb\u65f6\u6bcf\u5206\u949f\u8fd0\u884c\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@hourly")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u5728\u5c0f\u65f6\u5f00\u59cb\u65f6\u6bcf\u5c0f\u65f6\u8fd0\u884c\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@daily")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5929\u5348\u591c\u8fd0\u884c\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@midnight")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5929\u5348\u591c\u8fd0\u884c\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@weekly")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 * * 0")),(0,i.kt)("td",{parentName:"tr",align:null},"\u5468\u65e5\u4e0a\u5348\u5348\u591c\u6bcf\u5468\u8fd0\u884c\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@monthly")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 1 * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u6708\u5728\u6bcf\u6708\u7b2c\u4e00\u5929\u7684\u5348\u591c\u8fd0\u884c\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@yearly")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 1 1 *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5e74 1 \u6708 1 \u65e5\u5348\u591c\u8fd0\u884c\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@annually")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 1 1 *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5e74 1 \u6708 1 \u65e5\u5348\u591c\u8fd0\u884c\u4e00\u6b21")))),(0,i.kt)("h3",{id:"2655-\u4f7f\u7528-cron-\u8868\u8fbe\u5f0f"},"26.5.5 \u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5}",showLineNumbers:!0,"":!0,"{2,5}":!0},'// \u6bcf\u9694 1s \u6267\u884c\nSpareTime.Do("* * * * * *", (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n}, cronFormat: CronFormat.IncludeSeconds);\n')),(0,i.kt)("admonition",{title:"\u5173\u4e8e CronFormat",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u672a\u542f\u7528\u5bf9 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u79d2")," \u7684\u652f\u6301\uff0c\u5982\u9700\u5f00\u542f\uff0c\u5219\u8bbe\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"cronFormat: CronFormat.IncludeSeconds")," \u5373\u53ef\u3002\u9ed8\u8ba4\u503c\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"cronFormat: CronFormat.Standard"))),(0,i.kt)("h3",{id:"2656-\u4f7f\u7528-macro-\u5360\u4f4d\u7b26"},"26.5.6 \u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Macro")," \u5360\u4f4d\u7b26"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},'// \u6bcf\u9694 1s \u6267\u884c\nSpareTime.Do("@every_second", (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n});\n')),(0,i.kt)("h3",{id:"2657-\u914d\u7f6e\u4efb\u52a1\u4fe1\u606f"},"26.5.7 \u914d\u7f6e\u4efb\u52a1\u4fe1\u606f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},'SpareTime.Do("* * * * *", (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n}, "cronName", "\u6bcf\u5206\u949f\u6267\u884c\u4e00\u6b21");\n')),(0,i.kt)("h3",{id:"2658-\u624b\u52a8\u542f\u52a8\u6267\u884c"},"26.5.8 \u624b\u52a8\u542f\u52a8\u6267\u884c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,6}",showLineNumbers:!0,"":!0,"{4,6}":!0},'SpareTime.Do("* * * * *", (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n}, "cronName", "\u6bcf\u5206\u949f\u6267\u884c\u4e00\u6b21", startNow: false);\n\nSpareTime.Start("cronName");\n')),(0,i.kt)("h3",{id:"2659-isparetimeworker-\u65b9\u5f0f"},"26.5.9 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ISpareTimeWorker")," \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,8}",showLineNumbers:!0,"":!0,"{1,8}":!0},'public class JobWorker : ISpareTimeWorker\n{\n /// \n /// \u6bcf\u5206\u949f\u6267\u884c\n /// \n /// \n /// \n [SpareTime("* * * * *", "jobName", StartNow = true)]\n public void DoSomething(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n\n /// \n /// \u6bcf\u5206\u949f\u6267\u884c\uff08\u652f\u6301\u5f02\u6b65\uff09\n /// \n /// \n /// \n [SpareTime("* * * * *", "jobName", StartNow = true)]\n public async Task DoSomethingAsync(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n await Task.Completed;\n }\n}\n')),(0,i.kt)("h2",{id:"266-\u81ea\u5b9a\u4e49\u4e0b\u6b21\u6267\u884c\u65f6\u95f4"},"26.6 \u81ea\u5b9a\u4e49\u4e0b\u6b21\u6267\u884c\u65f6\u95f4"),(0,i.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u9700\u8981\u8fdb\u884c\u4e00\u4e9b\u4e1a\u52a1\u903b\u8f91\uff0c\u6bd4\u5982\u6570\u636e\u5e93\u67e5\u8be2\u7b49\u64cd\u4f5c\u8fd4\u56de\u4e0b\u4e00\u6b21\u6267\u884c\u65f6\u95f4\uff0c\u8fd9\u4e2a\u65f6\u5019\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u9ad8\u7ea7\u81ea\u5b9a\u4e49\u65b9\u5f0f\u3002"),(0,i.kt)("h3",{id:"2661-\u9ad8\u7ea7\u81ea\u5b9a\u4e49\u95f4\u9694\u65b9\u5f0f"},"26.6.1 \u9ad8\u7ea7\u81ea\u5b9a\u4e49\u95f4\u9694\u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,4-5,7}",showLineNumbers:!0,"":!0,"{2,4-5,7}":!0},'SpareTime.Do(()=>{\n // \u8fd9\u91cc\u53ef\u4ee5\u67e5\u8be2\u6570\u636e\u5e93\u6216\u8fdb\u884c\u6216\u8fdb\u884c\u4efb\u4f55\u4e1a\u52a1\u903b\u8f91\n\n if(\u7b26\u5408\u903b\u8f91){\n return 1000; // \u6bcf\u79d2\u6267\u884c\n }\n else return -1; // \u4e0d\u7b26\u5408\u903b\u8f91\u53d6\u6d88\u4efb\u52a1\n},\n(timer,count)=>{\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n});\n')),(0,i.kt)("admonition",{title:"\u914d\u7f6e\u662f\u5426\u6301\u7eed\u68c0\u67e5",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u8be5\u81ea\u5b9a\u4e49\u4f1a\u5728\u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5c0f\u4e8e\u6216\u7b49\u4e8e0")," \u65f6\u7ec8\u6b62\u4efb\u52a1\u7684\u6267\u884c\u3002\u4f46\u662f\u6211\u4eec\u5e0c\u671b\u8be5\u4efb\u52a1\u4e0d\u8981\u7ec8\u6b62\uff0c\u53ea\u8981\u7b26\u5408\u6761\u4ef6\u90fd\u4e00\u76f4\u6267\u884c\uff0c\u53ea\u9700\u8981\u914d\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"cancelInNoneNextTime: false")," \u5373\u53ef")),(0,i.kt)("h3",{id:"2662-\u9ad8\u7ea7\u81ea\u5b9a\u4e49-cron-\u8868\u8fbe\u5f0f"},"26.6.2 \u9ad8\u7ea7\u81ea\u5b9a\u4e49 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,4-5,7}",showLineNumbers:!0,"":!0,"{2,4-5,7}":!0},'SpareTime.Do(()=>{\n // \u8fd9\u91cc\u53ef\u4ee5\u67e5\u8be2\u6570\u636e\u5e93\u6216\u8fdb\u884c\u6216\u8fdb\u884c\u4efb\u4f55\u4e1a\u52a1\u903b\u8f91\n\n if(\u7b26\u5408\u903b\u8f91){\n return DateTimeOffset.Now.AddMinutes(10); // \u5341\u5206\u949f\u540e\u518d\u6267\u884c\n }\n else return null; // \u4e0d\u7b26\u5408\u903b\u8f91\u53d6\u6d88\u4efb\u52a1\n},\n(timer,count) => {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n});\n')),(0,i.kt)("admonition",{title:"\u914d\u7f6e\u662f\u5426\u6301\u7eed\u68c0\u67e5",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u8be5\u81ea\u5b9a\u4e49\u4f1a\u5728\u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"p"},"null")," \u65f6\u7ec8\u6b62\u4efb\u52a1\u7684\u6267\u884c\u3002\u4f46\u662f\u6211\u4eec\u5e0c\u671b\u8be5\u4efb\u52a1\u4e0d\u8981\u7ec8\u6b62\uff0c\u53ea\u8981\u7b26\u5408\u6761\u4ef6\u90fd\u4e00\u76f4\u6267\u884c\uff0c\u53ea\u9700\u8981\u914d\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"cancelInNoneNextTime: false")," \u5373\u53ef\uff0c\u5982\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,4-5,7,12}",showLineNumbers:!0,"":!0,"{2,4-5,7,12}":!0},'SpareTime.Do(()=>{\n // \u8fd9\u91cc\u53ef\u4ee5\u67e5\u8be2\u6570\u636e\u5e93\u6216\u8fdb\u884c\u6216\u8fdb\u884c\u4efb\u4f55\u4e1a\u52a1\u903b\u8f91\n\n if(\u7b26\u5408\u903b\u8f91){\n return SpareTime.GetCronNextOccurrence("cron \u8868\u8fbe\u5f0f");\n }\n else return null; // \u4e0d\u7b26\u5408\u903b\u8f91\u7ee7\u7eed\u68c0\u67e5\n},\n(timer,count) => {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n}, cancelInNoneNextTime: false);\n'))),(0,i.kt)("h2",{id:"267-isparetimeworker-\u8bf4\u660e"},"26.7 ",(0,i.kt)("inlineCode",{parentName:"h2"},"ISpareTimeWorker")," \u8bf4\u660e"),(0,i.kt)("p",null,"\u9664\u4e86\u4e0a\u9762\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"SpareTime")," \u9759\u6001\u7c7b\u65b9\u5f0f\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u8fd8\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"ISpareTimeWorker")," \u65b9\u5f0f\uff0c\u4f7f\u7528\u8be5\u65b9\u5f0f\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700\u8981\u81ea\u5b9a\u4e49\u4e00\u4e2a",(0,i.kt)("strong",{parentName:"p"},"\u516c\u5f00\u4e14\u975e\u62bd\u8c61\u975e\u9759\u6001"),"\u7c7b\u5e76\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"p"},"ISpareTimeWorker")," \u5373\u53ef\u3002"),(0,i.kt)("p",null,"\u5728\u8be5\u7c7b\u4e2d\u5b9a\u4e49\u7684\u4efb\u52a1\u65b9\u6cd5\u9700\u6ee1\u8db3\u4ee5\u4e0b\u89c4\u5219\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u5fc5\u987b\u662f",(0,i.kt)("strong",{parentName:"li"},"\u516c\u5f00\u4e14\u5b9e\u4f8b\u65b9\u6cd5")),(0,i.kt)("li",{parentName:"ul"},"\u8be5\u65b9\u6cd5\u5fc5\u987b\u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"li"},"void")," \u4e14\u63d0\u4f9b ",(0,i.kt)("inlineCode",{parentName:"li"},"SpareTimer")," \u548c ",(0,i.kt)("inlineCode",{parentName:"li"},"long")," \u4e24\u4e2a\u53c2\u6570"),(0,i.kt)("li",{parentName:"ul"},"\u5fc5\u987b\u8d34\u6709 ",(0,i.kt)("inlineCode",{parentName:"li"},"[SpareTime]")," \u7279\u6027")),(0,i.kt)("p",null,"\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4-5,12-13,20-21,28-30,37-38,45}",showLineNumbers:!0,"":!0,"{1,4-5,12-13,20-21,28-30,37-38,45}":!0},'public class JobWorker : ISpareTimeWorker\n{\n // \u6bcf\u9694\u4e00\u79d2\u6267\u884c\uff0c\u4e14\u7acb\u5373\u542f\u52a8\n [SpareTime(1000, "jobName1", StartNow = true)]\n public void DoSomething1(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n\n // \u6bcf\u5206\u949f\u6267\u884c\uff0c\u4e14\u7acb\u5373\u542f\u52a8\n [SpareTime("* * * * *", "jobName2", StartNow = true)]\n public void DoSomething2(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n\n // \u6bcf\u79d2\u6267\u884c\uff0c\u4e14\u7b49\u5f85\u542f\u52a8\n [SpareTime("* * * * * *", "jobName3",CronFormat = CronFormat.IncludeSeconds, StartNow = false)]\n public void DoSomething3(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n\n // \u6bcf\u79d2\u6267\u884c\u4e00\u6b21\uff0c\u6bcf\u5206\u949f\u4e5f\u6267\u884c\u4e00\u6b21\n [SpareTime(1000, "jobName4", StartNow = true)]\n [SpareTime("* * * * *", "jobName5", StartNow = true)]\n public void DoSomething4(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n\n // \u53ea\u6267\u884c\u4e00\u6b21\n [SpareTime(1000, "jobName5", StartNow = true, DoOnce = true)]\n public void DoSomething5(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n\n // \u8bfb\u53d6\u914d\u7f6e\u6587\u4ef6\uff0c\u901a\u8fc7 #(\u914d\u7f6e\u8def\u5f84)\n [SpareTime("#(MyJob:Time)", "jobName6", StartNow = true, DoOnce = true)]\n public void DoSomething5(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n\n // \u652f\u6301\u5f02\u6b65\n [SpareTime(1000, "jobName1", StartNow = true)]\n public async Task DoSomethingAsync(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n await Task.Completed;\n }\n}\n')),(0,i.kt)("admonition",{title:"\u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"ISpareTimeWorker")," \u63a5\u53e3\u4e3b\u8981\u662f\u7528\u6765\u67e5\u627e\u5b9a\u65f6\u5668\u5bf9\u8c61\u7684\uff0c\u4e5f\u5c31\u662f\u5b83\u7684\u5b9e\u73b0\u7c7b\u5e76\u672a\u63d0\u4f9b\u4f9d\u8d56\u6ce8\u5165\u529f\u80fd\uff0c\u6240\u4ee5\u5728\u5b9e\u73b0\u7c7b\u5e76\u4e0d\u652f\u6301\u6784\u9020\u51fd\u6570\u6ce8\u5165\u4f9d\u8d56\u9879\u3002")),(0,i.kt)("h3",{id:"2671-sparetime-\u7279\u6027"},"26.7.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"[SpareTime]")," \u7279\u6027"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"[SpareTime]")," \u652f\u6301\u4ee5\u4e0b\u914d\u7f6e\u5c5e\u6027"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Interval"),"\uff1a\u95f4\u9694\u65f6\u95f4, ",(0,i.kt)("inlineCode",{parentName:"li"},"double")," \u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"CronExpression"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Cron")," \u8868\u8fbe\u5f0f\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"WorkerName"),"\uff1a\u4efb\u52a1\u552f\u4e00\u6807\u8bc6\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"\u5fc5\u586b")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Description"),"\uff1a\u4efb\u52a1\u63cf\u8ff0\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"DoOnce"),"\uff1a\u662f\u5426\u53ea\u6267\u884c\u4e00\u6b21\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,i.kt)("inlineCode",{parentName:"li"},"false")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"StartNow"),"\uff1a\u662f\u5426\u7acb\u5373\u542f\u52a8\uff0c\u9ed8\u8ba4 ",(0,i.kt)("inlineCode",{parentName:"li"},"false")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"CronFormat"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Cron")," \u8868\u8fbe\u5f0f\u683c\u5f0f\u5316\u65b9\u5f0f\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"CronFormat")," \u679a\u4e3e\u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,i.kt)("inlineCode",{parentName:"li"},"CronFormat.Standard")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ExecuteType"),"\uff1a\u914d\u7f6e\u4efb\u52a1\u6267\u884c\u65b9\u5f0f\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"SpareTimeExecuteTypes")," \u679a\u4e3e\u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,i.kt)("inlineCode",{parentName:"li"},"SpareTimeExecuteTypes.Parallel"))),(0,i.kt)("h2",{id:"268-sparetime-\u9759\u6001\u7c7b"},"26.8 ",(0,i.kt)("inlineCode",{parentName:"h2"},"SpareTime")," \u9759\u6001\u7c7b"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"SpareTime")," \u9759\u6001\u7c7b\u63d0\u4f9b\u4e86\u4e00\u4e9b\u65b9\u6cd5\u65b9\u4fbf\u521d\u59cb\u5316\u548c\u7ba1\u7406\u4efb\u52a1"),(0,i.kt)("h3",{id:"2681-\u521d\u59cb\u5316\u4efb\u52a1"},"26.8.1 \u521d\u59cb\u5316\u4efb\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u5f00\u542f\u95f4\u9694\u4efb\u52a1\nSpareTime.Do(interval, [options]);\n\n// \u5f00\u542f Cron \u8868\u8fbe\u5f0f\u4efb\u52a1\nSpareTime.Do(expression, [options]);\n\n// \u53ea\u6267\u884c\u4e00\u6b21\u4efb\u52a1\nSpareTime.DoOnce(interval, [options]);\n\n// \u5b9e\u73b0\u81ea\u5b9a\u4e49\u4efb\u52a1\nSpareTime.Do(()=>{\n return DateTime.Now.AddMinutes(10);\n},[options]);\n")),(0,i.kt)("h3",{id:"2682-\u5b9e\u73b0\u540e\u53f0\u6267\u884c"},"26.8.2 \u5b9e\u73b0\u540e\u53f0\u6267\u884c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u5b9e\u73b0\u540e\u53f0\u6267\u884c\nSpareTime.DoIt(()=>{});\n")),(0,i.kt)("h3",{id:"2683-\u5f00\u59cb\u4e00\u4e2a\u4efb\u52a1"},"26.8.3 \u5f00\u59cb\u4e00\u4e2a\u4efb\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SpareTime.Start("\u4efb\u52a1\u6807\u8bc6");\n')),(0,i.kt)("h3",{id:"2684-\u6682\u505c\u4e00\u4e2a\u4efb\u52a1"},"26.8.4 \u6682\u505c\u4e00\u4e2a\u4efb\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SpareTime.Stop("\u4efb\u52a1\u6807\u8bc6");\n// \u8fd8\u53ef\u4ee5\u6807\u8bb0\u4e00\u4e2a\u4efb\u52a1\u6267\u884c\u5931\u8d25\nSpareTime.Stop("\u4efb\u52a1\u6807\u8bc6", true);\n')),(0,i.kt)("h3",{id:"2685-\u53d6\u6d88\u4e00\u4e2a\u4efb\u52a1"},"26.8.5 \u53d6\u6d88\u4e00\u4e2a\u4efb\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SpareTime.Cancel("\u4efb\u52a1\u540d\u79f0");\n')),(0,i.kt)("h3",{id:"2686-\u9500\u6bc1\u6240\u6709\u4efb\u52a1"},"26.8.6 \u9500\u6bc1\u6240\u6709\u4efb\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"SpareTime.Dispose();\n")),(0,i.kt)("h3",{id:"2687-\u83b7\u53d6\u6240\u6709\u4efb\u52a1"},"26.8.7 \u83b7\u53d6\u6240\u6709\u4efb\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var workers = SpareTime.GetWorkers();\n")),(0,i.kt)("h3",{id:"2688-\u83b7\u53d6\u5355\u4e2a\u4efb\u52a1"},"26.8.8 \u83b7\u53d6\u5355\u4e2a\u4efb\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var worker = SpareTime.GetWorker("workerName");\n')),(0,i.kt)("h3",{id:"2689-\u89e3\u6790-cron-\u8868\u8fbe\u5f0f"},"26.8.9 \u89e3\u6790 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var nextTime = SpareTime.GetCronNextOccurrence("* * * * *");\n')),(0,i.kt)("h2",{id:"269-\u5e76\u884c\u548c\u4e32\u884c\u6267\u884c\u65b9\u5f0f"},"26.9 ",(0,i.kt)("inlineCode",{parentName:"h2"},"\u5e76\u884c"),"\u548c",(0,i.kt)("inlineCode",{parentName:"h2"},"\u4e32\u884c"),"\u6267\u884c\u65b9\u5f0f"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u4efb\u52a1\u4e24\u79cd\u6267\u884c\u65b9\u5f0f ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5e76\u884c")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"\u4e32\u884c"),"\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"\u5e76\u884c"),"\uff1a\u65e0\u9700\u7b49\u5f85\u4e0a\u4e00\u6b21\u4efb\u52a1\u5b8c\u6210\uff0c",(0,i.kt)("strong",{parentName:"li"},"\u9ed8\u8ba4\u503c")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"\u4e32\u884c"),"\uff1a\u9700\u7b49\u5f85\u4e0a\u4e00\u6b21\u4efb\u52a1\u5b8c\u6210")),(0,i.kt)("h3",{id:"2691-sparetime-\u9759\u6001\u65b9\u5f0f\u6307\u5b9a"},"26.9.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"SpareTime")," \u9759\u6001\u65b9\u5f0f\u6307\u5b9a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5}",showLineNumbers:!0,"":!0,"{3,5}":!0},'SpareTime.Do(1000, (t, i) =>\n{\n Thread.Sleep(5000); // \u6a21\u62df\u6267\u884c\u8017\u65f6\u4efb\u52a1\n Console.WriteLine($"{t.WorkerName} -{t.Description} - {DateTime.Now:yyyy-MM-dd HH:mm:ss} - {i}");\n}, "serialName", "\u6a21\u62df\u4e32\u884c\u4efb\u52a1", executeType: SpareTimeExecuteTypes.Serial);\n')),(0,i.kt)("h3",{id:"2692-isparetimeworker-\u65b9\u5f0f"},"26.9.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ISpareTimeWorker")," \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'[SpareTime(1000, "jobName1", StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]\npublic void DoSomething1(SpareTimer timer, long count)\n{\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n}\n')),(0,i.kt)("h2",{id:"2610-\u4efb\u52a1\u5f02\u5e38\u5904\u7406"},"26.10 \u4efb\u52a1\u5f02\u5e38\u5904\u7406"),(0,i.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u53ef\u80fd\u5728\u6267\u884c\u4efb\u52a1\u8fc7\u7a0b\u4e2d\u51fa\u73b0\u5f02\u5e38\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e5f\u63d0\u4f9b\u4e86\u5c5e\u6027\u5224\u65ad\u662f\u5426\u6709\u5f02\u5e38\u548c\u5f02\u5e38\u4fe1\u606f\uff0c\u65b9\u4fbf\u8bb0\u5f55\u5230\u65e5\u5fd7\u4e2d\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4-7,11}",showLineNumbers:!0,"":!0,"{4-7,11}":!0},'SpareTime.Do(1000, (t, c) =>\n{\n // \u5224\u65ad\u662f\u5426\u6709\u5f02\u5e38\n if (t.Exception.Any())\n {\n Console.WriteLine(t.Exception.Values.LastOrDefault()?.Message);\n }\n // \u6267\u884c\u7b2c\u4e09\u6b21\u629b\u5f02\u5e38\n if (c > 2)\n {\n throw Oops.Oh("\u629b\u5f02\u5e38" + c);\n }\n else\n {\n Console.WriteLine($"{t.WorkerName} -{t.Description} - {DateTime.Now:yyyy-MM-dd HH:mm:ss} - {c}");\n }\n}, "exceptionJob");\n')),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4e00\u4e2a\u4efb\u52a1\u8fde\u7eed\u9519\u8bef\u6b21\u6570\u8fbe ",(0,i.kt)("inlineCode",{parentName:"p"},"10\u6b21")," \u5219\u4efb\u52a1\u5c06\u81ea\u52a8\u505c\u6b62\uff0c\u5e76\u6807\u8bb0\u4efb\u52a1\u72b6\u6001\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"Failed"),"\u3002")),(0,i.kt)("h2",{id:"2611-\u5982\u4f55\u5728\u4efb\u52a1\u4e2d\u89e3\u6790\u5bf9\u8c61"},"26.11 \u5982\u4f55\u5728\u4efb\u52a1\u4e2d\u89e3\u6790\u5bf9\u8c61"),(0,i.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u9700\u8981\u5728\u4efb\u52a1\u4e2d\u8fdb\u884c\u6570\u636e\u5e93\u64cd\u4f5c\u6216\u89e3\u6790\u670d\u52a1\uff0c\u8fd9\u65f6\u5019\u6211\u4eec\u53ea\u9700\u8981\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u4f5c\u7528\u57df\u5373\u53ef"),(0,i.kt)("h3",{id:"26111-sparetime-\u9759\u6001\u7c7b\u4e2d"},"26.11.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"SpareTime")," \u9759\u6001\u7c7b\u4e2d"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},'SpareTime.Do(1000, (timer,count) => {\n Scoped.Create((_, scope) =>\n {\n var services = scope.ServiceProvider;\n\n // \u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n var dbContext = Db.GetDbContext(services);\n\n // \u83b7\u53d6\u4ed3\u50a8\n var respository = Db.GetRepository(services);\n\n // \u89e3\u6790\u5176\u4ed6\u670d\u52a1\n var otherService = services.GetService();\n var otherService2 = App.GetService(services);\n });\n}, "\u4efb\u52a1\u6807\u8bc6");\n')),(0,i.kt)("h3",{id:"26112-isparetimeworker-\u65b9\u5f0f"},"26.11.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ISpareTimeWorker")," \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},'[SpareTime(1000, "jobName1", StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]\npublic void DoSomething1(SpareTimer timer, long count)\n{\n Scoped.Create((_, scope) =>\n {\n var services = scope.ServiceProvider;\n\n // \u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n var dbContext = Db.GetDbContext(services);\n\n // \u83b7\u53d6\u4ed3\u50a8\n var respository = Db.GetRepository(services);\n\n // \u89e3\u6790\u5176\u4ed6\u670d\u52a1\n var otherService = services.GetService();\n var otherService2 = App.GetService(services);\n });\n}\n')),(0,i.kt)("admonition",{title:"\u6570\u636e\u5e93\u64cd\u4f5c\u6ce8\u610f",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f5c\u7528\u57df\u4e2d\u5bf9",(0,i.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u6709\u4efb\u4f55\u53d8\u66f4\u64cd\u4f5c"),"\uff0c\u9700\u624b\u52a8\u8c03\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216\u5e26 ",(0,i.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u65b9\u6cd5\u3002\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Scoped.CreateUow(handler)")," \u4ee3\u66ff\u3002")),(0,i.kt)("h2",{id:"2612-\u5728-backgroundservice-\u4e2d\u4f7f\u7528"},"26.12 \u5728 ",(0,i.kt)("inlineCode",{parentName:"h2"},"BackgroundService")," \u4e2d\u4f7f\u7528"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"BackgroundService")," \u662f ",(0,i.kt)("inlineCode",{parentName:"p"},".NET Core 3")," \u4e4b\u540e\u63d0\u4f9b\u7684\u8f7b\u91cf\u7ea7\u540e\u53f0\u4efb\u52a1\uff0c\u540c\u65f6\u53ef\u4ee5\u53d1\u5e03\u5230 ",(0,i.kt)("inlineCode",{parentName:"p"},"Windows")," \u670d\u52a1\u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"Linux")," \u5b88\u62a4\u8fdb\u7a0b\u4e2d\u3002"),(0,i.kt)("h3",{id:"26121-\u95f4\u9694\u6267\u884c\u65b9\u5f0f"},"26.12.1 \u95f4\u9694\u6267\u884c\u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,18,20,30}",showLineNumbers:!0,"":!0,"{7,18,20,30}":!0},'namespace WorkerService;\n\npublic class Worker : BackgroundService\n{\n private readonly ILogger _logger;\n\n private const int delay = 1000;\n\n public Worker(ILogger logger)\n {\n _logger = logger;\n }\n\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);\n\n await taskFactory.StartNew(async () =>\n {\n // \u4f60\u7684\u4e1a\u52a1\u4ee3\u7801\u5199\u5230\u8fd9\u91cc\u9762\n\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n\n await Task.CompletedTask;\n\n }, stoppingToken);\n\n await Task.Delay(delay, stoppingToken);\n }\n }\n}\n')),(0,i.kt)("h3",{id:"26122-cron-\u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f"},"26.12.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,14,21,23,32}",showLineNumbers:!0,"":!0,"{9,14,21,23,32}":!0},'using Furion.TimeCrontab;\n\nnamespace WorkerService;\n\npublic class Worker : BackgroundService\n{\n private readonly ILogger _logger;\n\n private readonly Crontab _crontab;\n\n public Worker(ILogger logger)\n {\n _logger = logger;\n _crontab = Crontab.Parse("* * * * * *", CronStringFormat.WithSeconds);\n }\n\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);\n\n await taskFactory.StartNew(async () =>\n {\n // \u4f60\u7684\u4e1a\u52a1\u4ee3\u7801\u5199\u5230\u8fd9\u91cc\u9762\n\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n\n await Task.CompletedTask;\n }, stoppingToken);\n\n await Task.Delay(_crontab.GetSleepMilliseconds(DateTime.UtcNow), stoppingToken);\n }\n }\n}\n')),(0,i.kt)("h2",{id:"2613-\u5b9a\u65f6\u4efb\u52a1\u76d1\u542c\u5668"},"26.13 \u5b9a\u65f6\u4efb\u52a1\u76d1\u542c\u5668"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion v2.18+")," \u7248\u672c\u4e4b\u540e\u65b0\u589e\u4e86\u5b9a\u65f6\u4efb\u52a1\u76d1\u542c\u5668 ",(0,i.kt)("inlineCode",{parentName:"p"},"ISpareTimeListener"),"\uff0c\u901a\u8fc7\u76d1\u542c\u5668\u53ef\u4ee5\u5b9e\u73b0\u6240\u6709\u5b9a\u65f6\u4efb\u52a1\u7684\u72b6\u6001\u3002\u5982\uff0c\u521b\u5efa\u4e00\u4e2a ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5355\u4f8b")," \u7684\u76d1\u542c\u5668 ",(0,i.kt)("inlineCode",{parentName:"p"},"SpareTimeListener"),"\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8,15}",showLineNumbers:!0,"":!0,"{8,15}":!0},'using Furion.DependencyInjection;\nusing Furion.TaskScheduler;\nusing System;\nusing System.Threading.Tasks;\n\nnamespace Furion.Core\n{\n public class SpareTimeListener : ISpareTimeListener, ISingleton\n {\n /// \n /// \u76d1\u542c\u6240\u6709\u4efb\u52a1\n /// \n /// \n /// \n public Task OnListener(SpareTimerExecuter executer)\n {\n switch (executer.Status)\n {\n // \u6267\u884c\u5f00\u59cb\u901a\u77e5\n case 0:\n Console.WriteLine($"{executer.Timer.WorkerName} \u4efb\u52a1\u5f00\u59cb\u901a\u77e5");\n break;\n // \u4efb\u52a1\u6267\u884c\u4e4b\u524d\u901a\u77e5\n case 1:\n Console.WriteLine($"{executer.Timer.WorkerName} \u6267\u884c\u4e4b\u524d\u901a\u77e5");\n break;\n // \u6267\u884c\u6210\u529f\u901a\u77e5\n case 2:\n Console.WriteLine($"{executer.Timer.WorkerName} \u6267\u884c\u6210\u529f\u901a\u77e5");\n break;\n // \u4efb\u52a1\u6267\u884c\u5931\u8d25\u901a\u77e5\n case 3:\n Console.WriteLine($"{executer.Timer.WorkerName} \u6267\u884c\u5931\u8d25\u901a\u77e5");\n break;\n // \u4efb\u52a1\u6267\u884c\u505c\u6b62\u901a\u77e5\n case -1:\n Console.WriteLine($"{executer.Timer.WorkerName} \u6267\u884c\u505c\u6b62\u901a\u77e5");\n break;\n // \u4efb\u52a1\u6267\u884c\u53d6\u6d88\u901a\u77e5\n case -2:\n Console.WriteLine($"{executer.Timer.WorkerName} \u6267\u884c\u53d6\u6d88\u901a\u77e5");\n break;\n default:\n break;\n }\n\n return Task.CompletedTask;\n }\n }\n}\n')),(0,i.kt)("h3",{id:"26131-sparetimerexecuter-\u5c5e\u6027\u8bf4\u660e"},"26.13.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"SpareTimerExecuter")," \u5c5e\u6027\u8bf4\u660e"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Timer"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"SpareTimer")," \u5b9a\u65f6\u5668\u5bf9\u8c61"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Status"),"\uff1a\u76d1\u542c\u72b6\u6001",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"0"),"\uff1a\u4efb\u52a1\u5f00\u59cb"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"1"),"\uff1a\u6267\u884c\u4e4b\u524d"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"2"),"\uff1a\u6267\u884c\u6210\u529f"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"3"),"\uff1a\u6267\u884c\u5931\u8d25"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"-1"),"\uff1a\u4efb\u52a1\u505c\u6b62"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"-2"),"\uff1a\u4efb\u52a1\u53d6\u6d88")))),(0,i.kt)("h2",{id:"2614-iis-\u90e8\u7f72\u56de\u6536\u8bbe\u7f6e"},"26.14 IIS \u90e8\u7f72\u56de\u6536\u8bbe\u7f6e"),(0,i.kt)("p",null,"\u5982\u679c\u5728\u9879\u76ee\u4e2d\u4f7f\u7528\u4e86\u5b9a\u65f6\u4efb\u52a1\u4e14\u90e8\u7f72\u5230 ",(0,i.kt)("inlineCode",{parentName:"p"},"IIS")," \u4e2d\uff0c\u90a3\u4e48\u9700\u8981\u8bbe\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"IIS")," \u7981\u6b62\u56de\u6536\uff0c\u5982\uff1a"),(0,i.kt)("img",{src:(0,l.Z)("img/iishuishou.jpg")}),(0,i.kt)("admonition",{title:"\u90e8\u7f72\u5efa\u8bae",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"\u5efa\u8bae\u5b9a\u65f6\u4efb\u52a1\u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u72ec\u7acb\u90e8\u7f72\u65b9\u5f0f\uff0c\u4e0d\u5e94\u4f9d\u6258 ",(0,i.kt)("inlineCode",{parentName:"p"},"Web")," \u9879\u76ee\u8fdb\u7a0b\u4e2d\u3002",(0,i.kt)("a",{parentName:"p",href:"/furion/docs/process-service"},"\u67e5\u770b\u3010 Worker Service\u3011\u7ae0\u8282"))),(0,i.kt)("h2",{id:"2615-\u53cd\u9988\u4e0e\u5efa\u8bae"},"26.15 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/22f09a41.a8df2925.js b/handbook/build/assets/js/22f09a41.a8df2925.js deleted file mode 100644 index 17f35adbe3..0000000000 --- a/handbook/build/assets/js/22f09a41.a8df2925.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[6494],{3666:function(e,n,t){t.r(n),t.d(n,{assets:function(){return k},contentTitle:function(){return p},default:function(){return s},frontMatter:function(){return m},metadata:function(){return d},toc:function(){return N}});var a=t(3117),r=t(102),i=(t(7294),t(3905)),l=t(1402),o=["components"],m={id:"job",title:"26. \u5b9a\u65f6\u4efb\u52a1/\u540e\u53f0\u4efb\u52a1",sidebar_label:"26. \u5b9a\u65f6\u4efb\u52a1/\u540e\u53f0\u4efb\u52a1"},p=void 0,d={unversionedId:"job",id:"job",title:"26. \u5b9a\u65f6\u4efb\u52a1/\u540e\u53f0\u4efb\u52a1",description:"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 Furion 2.0.0 + \u7248\u672c\u4f7f\u7528\u3002",source:"@site/docs/job.mdx",sourceDirName:".",slug:"/job",permalink:"/furion/docs/job",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/job.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1661853545,formattedLastUpdatedAt:"Aug 30, 2022",frontMatter:{id:"job",title:"26. \u5b9a\u65f6\u4efb\u52a1/\u540e\u53f0\u4efb\u52a1",sidebar_label:"26. \u5b9a\u65f6\u4efb\u52a1/\u540e\u53f0\u4efb\u52a1"},sidebar:"docs",previous:{title:"25. \u8f85\u52a9\u89d2\u8272\u670d\u52a1 (Worker Service)",permalink:"/furion/docs/process-service"},next:{title:"27. \u5206\u5e03\u5f0f ID \u751f\u6210",permalink:"/furion/docs/idgenerator"}},k={},N=[{value:"26.1 \u5173\u4e8e\u5b9a\u65f6\u4efb\u52a1",id:"261-\u5173\u4e8e\u5b9a\u65f6\u4efb\u52a1",level:2},{value:"26.2 \u5982\u4f55\u5b9e\u73b0",id:"262-\u5982\u4f55\u5b9e\u73b0",level:2},{value:"26.3 \u7f13\u9694\u65b9\u5f0f\u4f7f\u7528",id:"263-\u7f13\u9694\u65b9\u5f0f\u4f7f\u7528",level:2},{value:"26.3.1 \u7279\u5b9a\u65f6\u95f4\u540e\u6267\u884c",id:"2631-\u7279\u5b9a\u65f6\u95f4\u540e\u6267\u884c",level:3},{value:"26.3.2 \u914d\u7f6e\u4efb\u52a1\u4fe1\u606f",id:"2632-\u914d\u7f6e\u4efb\u52a1\u4fe1\u606f",level:3},{value:"26.3.3 \u624b\u52a8\u542f\u52a8\u6267\u884c",id:"2633-\u624b\u52a8\u542f\u52a8\u6267\u884c",level:3},{value:"26.3.4 \u6a21\u62df\u540e\u53f0\u6267\u884c",id:"2634-\u6a21\u62df\u540e\u53f0\u6267\u884c",level:3},{value:"26.3.5 ISpareTimeWorker \u65b9\u5f0f",id:"2635-isparetimeworker-\u65b9\u5f0f",level:3},{value:"26.4 \u95f4\u9694\u65b9\u5f0f\u4f7f\u7528",id:"264-\u95f4\u9694\u65b9\u5f0f\u4f7f\u7528",level:2},{value:"26.4.1 \u6bcf\u9694\u4e00\u6bb5\u65f6\u95f4\u6267\u884c",id:"2641-\u6bcf\u9694\u4e00\u6bb5\u65f6\u95f4\u6267\u884c",level:3},{value:"26.4.2 \u914d\u7f6e\u4efb\u52a1\u4fe1\u606f",id:"2642-\u914d\u7f6e\u4efb\u52a1\u4fe1\u606f",level:3},{value:"26.4.3 \u624b\u52a8\u542f\u52a8\u6267\u884c",id:"2643-\u624b\u52a8\u542f\u52a8\u6267\u884c",level:3},{value:"26.4.4 ISpareTimeWorker \u65b9\u5f0f",id:"2644-isparetimeworker-\u65b9\u5f0f",level:3},{value:"26.5 Cron \u8868\u8fbe\u5f0f\u4f7f\u7528",id:"265-cron-\u8868\u8fbe\u5f0f\u4f7f\u7528",level:2},{value:"26.5.1 \u4ec0\u4e48\u662f Cron \u8868\u8fbe\u5f0f",id:"2651-\u4ec0\u4e48\u662f-cron-\u8868\u8fbe\u5f0f",level:3},{value:"26.5.2 \u5e38\u89c1 Cron \u8868\u8fbe\u5f0f",id:"2652-\u5e38\u89c1-cron-\u8868\u8fbe\u5f0f",level:3},{value:"26.5.3 \u5728\u7ebf\u751f\u6210 Cron \u8868\u8fbe\u5f0f",id:"2653-\u5728\u7ebf\u751f\u6210-cron-\u8868\u8fbe\u5f0f",level:3},{value:"26.5.4 Macro \u6807\u8bc6\u7b26",id:"2654-macro-\u6807\u8bc6\u7b26",level:3},{value:"26.5.5 \u4f7f\u7528 Cron \u8868\u8fbe\u5f0f",id:"2655-\u4f7f\u7528-cron-\u8868\u8fbe\u5f0f",level:3},{value:"26.5.6 \u4f7f\u7528 Macro \u5360\u4f4d\u7b26",id:"2656-\u4f7f\u7528-macro-\u5360\u4f4d\u7b26",level:3},{value:"26.5.7 \u914d\u7f6e\u4efb\u52a1\u4fe1\u606f",id:"2657-\u914d\u7f6e\u4efb\u52a1\u4fe1\u606f",level:3},{value:"26.5.8 \u624b\u52a8\u542f\u52a8\u6267\u884c",id:"2658-\u624b\u52a8\u542f\u52a8\u6267\u884c",level:3},{value:"26.5.9 ISpareTimeWorker \u65b9\u5f0f",id:"2659-isparetimeworker-\u65b9\u5f0f",level:3},{value:"26.6 \u81ea\u5b9a\u4e49\u4e0b\u6b21\u6267\u884c\u65f6\u95f4",id:"266-\u81ea\u5b9a\u4e49\u4e0b\u6b21\u6267\u884c\u65f6\u95f4",level:2},{value:"26.6.1 \u9ad8\u7ea7\u81ea\u5b9a\u4e49\u95f4\u9694\u65b9\u5f0f",id:"2661-\u9ad8\u7ea7\u81ea\u5b9a\u4e49\u95f4\u9694\u65b9\u5f0f",level:3},{value:"26.6.2 \u9ad8\u7ea7\u81ea\u5b9a\u4e49 Cron \u8868\u8fbe\u5f0f",id:"2662-\u9ad8\u7ea7\u81ea\u5b9a\u4e49-cron-\u8868\u8fbe\u5f0f",level:3},{value:"26.7 ISpareTimeWorker \u8bf4\u660e",id:"267-isparetimeworker-\u8bf4\u660e",level:2},{value:"26.7.1 [SpareTime] \u7279\u6027",id:"2671-sparetime-\u7279\u6027",level:3},{value:"26.8 SpareTime \u9759\u6001\u7c7b",id:"268-sparetime-\u9759\u6001\u7c7b",level:2},{value:"26.8.1 \u521d\u59cb\u5316\u4efb\u52a1",id:"2681-\u521d\u59cb\u5316\u4efb\u52a1",level:3},{value:"26.8.2 \u5b9e\u73b0\u540e\u53f0\u6267\u884c",id:"2682-\u5b9e\u73b0\u540e\u53f0\u6267\u884c",level:3},{value:"26.8.3 \u5f00\u59cb\u4e00\u4e2a\u4efb\u52a1",id:"2683-\u5f00\u59cb\u4e00\u4e2a\u4efb\u52a1",level:3},{value:"26.8.4 \u6682\u505c\u4e00\u4e2a\u4efb\u52a1",id:"2684-\u6682\u505c\u4e00\u4e2a\u4efb\u52a1",level:3},{value:"26.8.5 \u53d6\u6d88\u4e00\u4e2a\u4efb\u52a1",id:"2685-\u53d6\u6d88\u4e00\u4e2a\u4efb\u52a1",level:3},{value:"26.8.6 \u9500\u6bc1\u6240\u6709\u4efb\u52a1",id:"2686-\u9500\u6bc1\u6240\u6709\u4efb\u52a1",level:3},{value:"26.8.7 \u83b7\u53d6\u6240\u6709\u4efb\u52a1",id:"2687-\u83b7\u53d6\u6240\u6709\u4efb\u52a1",level:3},{value:"26.8.8 \u83b7\u53d6\u5355\u4e2a\u4efb\u52a1",id:"2688-\u83b7\u53d6\u5355\u4e2a\u4efb\u52a1",level:3},{value:"26.8.9 \u89e3\u6790 Cron \u8868\u8fbe\u5f0f",id:"2689-\u89e3\u6790-cron-\u8868\u8fbe\u5f0f",level:3},{value:"26.9 \u5e76\u884c\u548c\u4e32\u884c\u6267\u884c\u65b9\u5f0f",id:"269-\u5e76\u884c\u548c\u4e32\u884c\u6267\u884c\u65b9\u5f0f",level:2},{value:"26.9.1 SpareTime \u9759\u6001\u65b9\u5f0f\u6307\u5b9a",id:"2691-sparetime-\u9759\u6001\u65b9\u5f0f\u6307\u5b9a",level:3},{value:"26.9.2 ISpareTimeWorker \u65b9\u5f0f",id:"2692-isparetimeworker-\u65b9\u5f0f",level:3},{value:"26.10 \u4efb\u52a1\u5f02\u5e38\u5904\u7406",id:"2610-\u4efb\u52a1\u5f02\u5e38\u5904\u7406",level:2},{value:"26.11 \u5982\u4f55\u5728\u4efb\u52a1\u4e2d\u89e3\u6790\u5bf9\u8c61",id:"2611-\u5982\u4f55\u5728\u4efb\u52a1\u4e2d\u89e3\u6790\u5bf9\u8c61",level:2},{value:"26.11.1 SpareTime \u9759\u6001\u7c7b\u4e2d",id:"26111-sparetime-\u9759\u6001\u7c7b\u4e2d",level:3},{value:"26.11.2 ISpareTimeWorker \u65b9\u5f0f",id:"26112-isparetimeworker-\u65b9\u5f0f",level:3},{value:"26.12 \u5728 BackgroundService \u4e2d\u4f7f\u7528",id:"2612-\u5728-backgroundservice-\u4e2d\u4f7f\u7528",level:2},{value:"26.12.1 \u95f4\u9694\u6267\u884c\u65b9\u5f0f",id:"26121-\u95f4\u9694\u6267\u884c\u65b9\u5f0f",level:3},{value:"26.12.2 Cron \u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f",id:"26122-cron-\u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f",level:3},{value:"26.13 \u5b9a\u65f6\u4efb\u52a1\u76d1\u542c\u5668",id:"2613-\u5b9a\u65f6\u4efb\u52a1\u76d1\u542c\u5668",level:2},{value:"26.13.1 SpareTimerExecuter \u5c5e\u6027\u8bf4\u660e",id:"26131-sparetimerexecuter-\u5c5e\u6027\u8bf4\u660e",level:3},{value:"26.14 IIS \u90e8\u7f72\u56de\u6536\u8bbe\u7f6e",id:"2614-iis-\u90e8\u7f72\u56de\u6536\u8bbe\u7f6e",level:2},{value:"26.15 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"2615-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],u={toc:N};function s(e){var n=e.components,t=(0,r.Z)(e,o);return(0,i.kt)("wrapper",(0,a.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 2.0.0 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,i.kt)("admonition",{title:"IIS \u90e8\u7f72\u8bf4\u660e",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u7531\u4e8e IIS \u6709\u56de\u6536\u7684\u673a\u5236\uff0c\u6240\u4ee5\u5b9a\u65f6\u4efb\u52a1\u5e94\u8be5\u91c7\u7528\u72ec\u7acb\u90e8\u7f72\uff0c\u4e0d\u7136\u7ecf\u5e38\u51fa\u73b0\u4e0d\u80fd\u89e6\u53d1\u7684\u60c5\u51b5\u3002\u67e5\u770b\u3010",(0,i.kt)("a",{parentName:"p",href:"/furion/docs/process-service"},"Worker Service \u7ae0\u8282"),"\u3011")),(0,i.kt)("h2",{id:"261-\u5173\u4e8e\u5b9a\u65f6\u4efb\u52a1"},"26.1 \u5173\u4e8e\u5b9a\u65f6\u4efb\u52a1"),(0,i.kt)("p",null,"\u987e\u540d\u601d\u4e49\uff0c\u5b9a\u65f6\u4efb\u52a1\u5c31\u662f\u5728\u7279\u5b9a\u7684\u65f6\u95f4\u6216\u7b26\u5408\u67d0\u79cd\u65f6\u95f4\u89c4\u5f8b\u6267\u884c\u7684\u4efb\u52a1\u3002\u901a\u5e38\u5b9a\u65f6\u4efb\u52a1\u6709\u56db\u79cd\u65f6\u95f4\u8c03\u5ea6\u65b9\u5f0f\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"\u7f13\u9694\u65f6\u95f4")," \u65b9\u5f0f\uff1a\u5ef6\u8fdf\u591a\u5c11\u65f6\u95f4\u540e\u8c03\u914d\u4efb\u52a1\uff0c\u8fd9\u79cd\u65b9\u5f0f\u4efb\u52a1\u53ea\u4f1a\u88ab\u8c03\u7528\u4e00\u6b21\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"\u95f4\u9694\u65f6\u95f4")," \u65b9\u5f0f\uff1a\u6bcf\u9694\u4e00\u6bb5\u56fa\u5b9a\u65f6\u95f4\u8c03\u914d\u4efb\u52a1\uff0c\u65e0\u95f4\u65ad\u8c03\u7528\u4efb\u52a1\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Cron \u8868\u8fbe\u5f0f")," \u65b9\u6cd5\uff1a\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"li"},"Cron")," \u8868\u8fbe\u5f0f\u8ba1\u7b97\u4e0b\u4e00\u6b21\u6267\u884c\u65f6\u95f4\u8fdb\u884c\u8c03\u914d\u4efb\u52a1\uff0c\u53ef\u4ee5\u914d\u7f6e\u7279\u5b9a\u65f6\u95f4\u8303\u56f4\u5185\u6267\u884c\uff0c\u4e5f\u53ef\u4ee5\u65e0\u95f4\u65ad\u6267\u884c\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"\u81ea\u5b9a\u4e49\u4e0b\u6b21\u6267\u884c\u65f6\u95f4"),"\uff1a\u53ef\u4ee5\u901a\u8fc7\u5404\u79cd\u903b\u8f91\u8fd0\u7b97\u8fd4\u56de\u4e0b\u4e00\u6b21\u6267\u884c\u65f6\u95f4")),(0,i.kt)("h2",{id:"262-\u5982\u4f55\u5b9e\u73b0"},"26.2 \u5982\u4f55\u5b9e\u73b0"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u4e24\u79cd\u65b9\u5f0f\u5b9e\u73b0\u5b9a\u65f6\u4efb\u52a1\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SpareTime")," \u9759\u6001\u7c7b\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"SpareTime")," \u9759\u6001\u7c7b\u63d0\u4f9b ",(0,i.kt)("inlineCode",{parentName:"li"},"SpareTime.Do([options])")," \u65b9\u5f0f\u8c03\u7528\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISpareTimeWorker")," \u4f9d\u8d56\u65b9\u5f0f\uff1a\u901a\u8fc7\u81ea\u5b9a\u4e49\u7c7b\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"li"},"ISpareTimeWorker")," \u63a5\u53e3\u5e76\u7f16\u5199\u4e00\u5b9a\u89c4\u5219\u7684\u65b9\u6cd5\u5373\u53ef\u3002",(0,i.kt)("strong",{parentName:"li"},"\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Startup.cs")," \u4e2d\u6ce8\u518c ",(0,i.kt)("inlineCode",{parentName:"strong"},"services.AddTaskScheduler()")))),(0,i.kt)("h2",{id:"263-\u7f13\u9694\u65b9\u5f0f\u4f7f\u7528"},"26.3 \u7f13\u9694\u65b9\u5f0f\u4f7f\u7528"),(0,i.kt)("h3",{id:"2631-\u7279\u5b9a\u65f6\u95f4\u540e\u6267\u884c"},"26.3.1 \u7279\u5b9a\u65f6\u95f4\u540e\u6267\u884c"),(0,i.kt)("p",null,"\u8fd9\u91cc\u6f14\u793a ",(0,i.kt)("inlineCode",{parentName:"p"},"3s")," \u540e\u6267\u884c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},'Console.WriteLine("\u5f53\u524d\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n\n// timer \u662f\u5b9a\u65f6\u5668\u7684\u5bf9\u8c61\uff0c\u5305\u542b\u5b9a\u65f6\u5668\u76f8\u5173\u4fe1\u606f\n// count \u8868\u793a\u6267\u884c\u6b21\u6570\uff0c\u8fd9\u91cc\u53ea\u6709\u4e00\u6b21\nSpareTime.DoOnce(3000, (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n});\n')),(0,i.kt)("h3",{id:"2632-\u914d\u7f6e\u4efb\u52a1\u4fe1\u606f"},"26.3.2 \u914d\u7f6e\u4efb\u52a1\u4fe1\u606f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},'SpareTime.DoOnce(3000, (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n}, "jobName", "\u63cf\u8ff0\u4e00\u4e0b\u8fd9\u4e2a\u4efb\u52a1\u662f\u5e72\u4ec0\u4e48\u7684");\n')),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"jobName")," \u6807\u8bc6\u4efb\u52a1\u7684\u552f\u4e00\u6807\u8bc6\uff0c\u901a\u8fc7\u8fd9\u4e2a\u6807\u8bc6\u53ef\u4ee5\u542f\u52a8\u3001\u6682\u505c\u3001\u9500\u6bc1\u4efb\u52a1\u3002"),(0,i.kt)("h3",{id:"2633-\u624b\u52a8\u542f\u52a8\u6267\u884c"},"26.3.3 \u624b\u52a8\u542f\u52a8\u6267\u884c"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u4efb\u52a1\u521d\u59cb\u5316\u540e\u5c31\u7acb\u5373\u542f\u52a8\uff0c\u7b49\u5f85\u7b26\u5408\u7684\u65f6\u95f4\u5c31\u6267\u884c\uff0c\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u4ec5\u4ec5\u60f3\u521d\u59cb\u5316\u65f6\u95f4\uff0c\u4e0d\u5e0c\u671b\u7acb\u5373\u6267\u884c\uff0c\u53ea\u9700\u8981\u914d\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"startNow")," \u5373\u53ef\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,6}",showLineNumbers:!0,"":!0,"{3,6}":!0},'SpareTime.DoOnce(3000, (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n},"jobName", startNow: false);\n\n// \u624b\u52a8\u542f\u52a8\u6267\u884c\nSpareTime.Start("jobName");\n')),(0,i.kt)("h3",{id:"2634-\u6a21\u62df\u540e\u53f0\u6267\u884c"},"26.3.4 \u6a21\u62df\u540e\u53f0\u6267\u884c"),(0,i.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u53ea\u9700\u8981\u5f00\u542f\u65b0\u7ebf\u7a0b\u53bb\u6267\u884c\u4e00\u4e2a\u4efb\u52a1\uff0c\u6bd4\u5982\u53d1\u77ed\u4fe1\uff0c\u53d1\u90ae\u4ef6\uff0c\u65e0\u9700\u914d\u7f6e\u3002"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},"// \u6b64\u65b9\u6cd5\u65e0\u9700\u4e3b\u7ebf\u7a0b\u7b49\u5f85\u5373\u53ef\u8fd4\u56de\uff0c\u53ef\u5927\u5927\u63d0\u9ad8\u6027\u80fd\nSpareTime.DoIt(() => {\n // \u8fd9\u91cc\u53d1\u9001\u77ed\u4fe1\uff0c\u53d1\u9001\u90ae\u4ef6\u6216\u8bb0\u5f55\u8bbf\u95ee\u8bb0\u5f55\n});\n")),(0,i.kt)("p",null,"\u8fd8\u53ef\u4ee5\u6307\u5b9a\u591a\u957f\u65f6\u95f4\u540e\u89e6\u53d1\uff0c\u5efa\u8bae ",(0,i.kt)("inlineCode",{parentName:"p"},"10-1000")," \u6beb\u79d2\u4e4b\u95f4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"SpareTime.DoIt(() => {\n // \u53d1\u9001\u77ed\u4fe1\n}, 100);\n")),(0,i.kt)("h3",{id:"2635-isparetimeworker-\u65b9\u5f0f"},"26.3.5 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ISpareTimeWorker")," \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,8}",showLineNumbers:!0,"":!0,"{1,8}":!0},'public class JobWorker : ISpareTimeWorker\n{\n /// \n /// 3s \u540e\u6267\u884c\n /// \n /// \n /// \n [SpareTime(3000, "jobName", DoOnce = true, StartNow = true)]\n public void DoSomething(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n }\n\n /// \n /// 3s \u540e\u6267\u884c\uff08\u652f\u6301\u5f02\u6b65\uff09\n /// \n /// \n /// \n [SpareTime(3000, "jobName", DoOnce = true, StartNow = true)]\n public async Task DoSomethingAsync(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n await Task.CompletedTask;\n }\n}\n')),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Startup.cs")," \u4e2d\u6ce8\u518c ",(0,i.kt)("inlineCode",{parentName:"strong"},"services.AddTaskScheduler()"))),(0,i.kt)("h2",{id:"264-\u95f4\u9694\u65b9\u5f0f\u4f7f\u7528"},"26.4 \u95f4\u9694\u65b9\u5f0f\u4f7f\u7528"),(0,i.kt)("h3",{id:"2641-\u6bcf\u9694\u4e00\u6bb5\u65f6\u95f4\u6267\u884c"},"26.4.1 \u6bcf\u9694\u4e00\u6bb5\u65f6\u95f4\u6267\u884c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},'// \u6bcf\u9694 1s \u6267\u884c\nSpareTime.Do(1000, (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n});\n')),(0,i.kt)("h3",{id:"2642-\u914d\u7f6e\u4efb\u52a1\u4fe1\u606f"},"26.4.2 \u914d\u7f6e\u4efb\u52a1\u4fe1\u606f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4}",showLineNumbers:!0,"":!0,"{1,4}":!0},'SpareTime.Do(1000, (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n}, "jobName", "\u8fd9\u662f\u4e00\u4e2a\u8ba1\u65f6\u5668\u4efb\u52a1");\n')),(0,i.kt)("h3",{id:"2643-\u624b\u52a8\u542f\u52a8\u6267\u884c"},"26.4.3 \u624b\u52a8\u542f\u52a8\u6267\u884c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4,6}",showLineNumbers:!0,"":!0,"{1,4,6}":!0},'SpareTime.Do(1000, (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n}, "jobName", startNow:false);\n\nSpareTime.Start("jobName");\n')),(0,i.kt)("h3",{id:"2644-isparetimeworker-\u65b9\u5f0f"},"26.4.4 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ISpareTimeWorker")," \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,8}",showLineNumbers:!0,"":!0,"{1,8}":!0},'public class JobWorker : ISpareTimeWorker\n{\n /// \n /// \u6bcf\u9694 3s \u6267\u884c\n /// \n /// \n /// \n [SpareTime(3000, "jobName", StartNow = true)]\n public void DoSomething(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n}\n')),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Startup.cs")," \u4e2d\u6ce8\u518c ",(0,i.kt)("inlineCode",{parentName:"strong"},"services.AddTaskScheduler()"))),(0,i.kt)("h2",{id:"265-cron-\u8868\u8fbe\u5f0f\u4f7f\u7528"},"26.5 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Cron")," \u8868\u8fbe\u5f0f\u4f7f\u7528"),(0,i.kt)("h3",{id:"2651-\u4ec0\u4e48\u662f-cron-\u8868\u8fbe\u5f0f"},"26.5.1 \u4ec0\u4e48\u662f ",(0,i.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f"),(0,i.kt)("p",null,"Cron \u8868\u8fbe\u5f0f\u662f\u4e00\u4e2a\u5b57\u7b26\u4e32\uff0c\u5b57\u7b26\u4e32\u4ee5 ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u6216 ",(0,i.kt)("inlineCode",{parentName:"p"},"6")," \u4e2a\u7a7a\u683c\u9694\u5f00\uff0c\u5206\u4e3a 6 \u6216 7 \u4e2a\u57df\uff0c\u6bcf\u4e00\u4e2a\u57df\u4ee3\u8868\u4e00\u4e2a\u542b\u4e49\uff0cCron \u6709\u5982\u4e0b\u4e24\u79cd\u8bed\u6cd5\u683c\u5f0f\uff1a"),(0,i.kt)("p",null,"\uff081\uff09 Seconds Minutes Hours DayofMonth Month DayofWeek Year"),(0,i.kt)("p",null,"\uff082\uff09Seconds Minutes Hours DayofMonth Month DayofWeek"),(0,i.kt)("p",null,"Cron \u4ece\u5de6\u5230\u53f3\uff08\u7528\u7a7a\u683c\u9694\u5f00\uff09\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"\u79d2")," ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5206")," ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5c0f\u65f6")," ",(0,i.kt)("inlineCode",{parentName:"p"},"\u6708\u4efd\u4e2d\u7684\u65e5\u671f")," ",(0,i.kt)("inlineCode",{parentName:"p"},"\u6708\u4efd")," ",(0,i.kt)("inlineCode",{parentName:"p"},"\u661f\u671f\u4e2d\u7684\u65e5\u671f")," ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5e74\u4efd")),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"\u5b57\u6bb5"),(0,i.kt)("th",{parentName:"tr",align:null},"\u5141\u8bb8\u503c"),(0,i.kt)("th",{parentName:"tr",align:null},"\u5141\u8bb8\u7684\u7279\u6b8a\u5b57\u7b26"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"\u79d2\uff08Seconds\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0~59")," \u7684\u6574\u6570"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},", - \\* /")," \u56db\u4e2a\u5b57\u7b26")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"\u5206\uff08Minutes\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0~59")," \u7684\u6574\u6570"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},", - \\* /")," \u56db\u4e2a\u5b57\u7b26")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"\u5c0f\u65f6\uff08Hours\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0~23")," \u7684\u6574\u6570"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},", - \\* /")," \u56db\u4e2a\u5b57\u7b26")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"\u65e5\u671f\uff08DayofMonth\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"1~31")," \u7684\u6574\u6570\uff08\u4f46\u662f\u4f60\u9700\u8981\u8003\u8651\u5e73\u95f0\u6708\u7684\u5929\u6570\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},",- \\* ? / L W C")," \u516b\u4e2a\u5b57\u7b26")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"\u6708\u4efd\uff08Month\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"1~12")," \u7684\u6574\u6570\u6216\u8005 ",(0,i.kt)("inlineCode",{parentName:"td"},"JAN-DEC")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},", - \\* /")," \u56db\u4e2a\u5b57\u7b26")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"\u661f\u671f\uff08DayofWeek\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"1~7")," \u7684\u6574\u6570\u6216\u8005 ",(0,i.kt)("inlineCode",{parentName:"td"},"SUN-SAT \uff081=SUN\uff09")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},", - \\* ? / L C #")," \u516b\u4e2a\u5b57\u7b26")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"\u5e74(\u53ef\u9009\uff0c\u7559\u7a7a)\uff08Year\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"1970~2099")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},", - \\* /")," \u56db\u4e2a\u5b57\u7b26")))),(0,i.kt)("p",null,"\u6bcf\u4e00\u4e2a\u57df\u90fd\u4f7f\u7528\u6570\u5b57\uff0c\u4f46\u8fd8\u53ef\u4ee5\u51fa\u73b0\u5982\u4e0b\u7279\u6b8a\u5b57\u7b26\uff0c\u5b83\u4eec\u7684\u542b\u4e49\u662f\uff1a"),(0,i.kt)("p",null,"\uff081\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"_"),"\uff1a\u8868\u793a\u5339\u914d\u8be5\u57df\u7684\u4efb\u610f\u503c\u3002\u5047\u5982\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Minutes")," \u57df\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"\\_"),", \u5373\u8868\u793a\u6bcf\u5206\u949f\u90fd\u4f1a\u89e6\u53d1\u4e8b\u4ef6\u3002"),(0,i.kt)("p",null,"\uff082\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"?"),"\uff1a\u53ea\u80fd\u7528\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofMonth")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofWeek")," \u4e24\u4e2a\u57df\u3002\u5b83\u4e5f\u5339\u914d\u57df\u7684\u4efb\u610f\u503c\uff0c\u4f46\u5b9e\u9645\u4e0d\u4f1a\u3002\u56e0\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofMonth")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofWeek")," \u4f1a\u76f8\u4e92\u5f71\u54cd\u3002\u4f8b\u5982\u60f3\u5728\u6bcf\u6708\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"20")," \u65e5\u89e6\u53d1\u8c03\u5ea6\uff0c\u4e0d\u7ba1 ",(0,i.kt)("inlineCode",{parentName:"p"},"20")," \u65e5\u5230\u5e95\u662f\u661f\u671f\u51e0\uff0c\u5219\u53ea\u80fd\u4f7f\u7528\u5982\u4e0b\u5199\u6cd5\uff1a ",(0,i.kt)("inlineCode",{parentName:"p"},"13 13 15 20 _ ?"),", \u5176\u4e2d\u6700\u540e\u4e00\u4f4d\u53ea\u80fd\u7528",(0,i.kt)("inlineCode",{parentName:"p"},"\uff1f"),"\uff0c\u800c\u4e0d\u80fd\u4f7f\u7528","_","\uff0c\u5982\u679c\u4f7f\u7528","*","\u8868\u793a\u4e0d\u7ba1\u661f\u671f\u51e0\u90fd\u4f1a\u89e6\u53d1\uff0c\u5b9e\u9645\u4e0a\u5e76\u4e0d\u662f\u8fd9\u6837\u3002"),(0,i.kt)("p",null,"\uff083\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"-"),"\uff1a\u8868\u793a\u8303\u56f4\u3002\u4f8b\u5982\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Minutes")," \u57df\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"5-20"),"\uff0c\u8868\u793a\u4ece ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u5206\u5230 ",(0,i.kt)("inlineCode",{parentName:"p"},"20")," \u5206\u949f\u6bcf\u5206\u949f\u89e6\u53d1\u4e00\u6b21"),(0,i.kt)("p",null,"\uff084\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"/"),"\uff1a\u8868\u793a\u8d77\u59cb\u65f6\u95f4\u5f00\u59cb\u89e6\u53d1\uff0c\u7136\u540e\u6bcf\u9694\u56fa\u5b9a\u65f6\u95f4\u89e6\u53d1\u4e00\u6b21\u3002\u4f8b\u5982\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Minutes")," \u57df\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"5/20"),"\uff0c\u5219\u610f\u5473\u7740 ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u5206\u949f\u89e6\u53d1\u4e00\u6b21\uff0c\u800c ",(0,i.kt)("inlineCode",{parentName:"p"},"25\uff0c45")," \u7b49\u5206\u522b\u89e6\u53d1\u4e00\u6b21."),(0,i.kt)("p",null,"\uff085\uff09",(0,i.kt)("inlineCode",{parentName:"p"},","),"\uff1a\u8868\u793a\u5217\u51fa\u679a\u4e3e\u503c\u3002\u4f8b\u5982\uff1a\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Minutes")," \u57df\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"5,20"),"\uff0c\u5219\u610f\u5473\u7740\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"20")," \u5206\u6bcf\u5206\u949f\u89e6\u53d1\u4e00\u6b21\u3002"),(0,i.kt)("p",null,"\uff086\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"L"),"\uff1a\u8868\u793a\u6700\u540e\uff0c\u53ea\u80fd\u51fa\u73b0\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofWeek")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofMonth")," \u57df\u3002\u5982\u679c\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofWeek")," \u57df\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"5L"),",\u610f\u5473\u7740\u5728\u6700\u540e\u7684\u4e00\u4e2a\u661f\u671f\u56db\u89e6\u53d1\u3002"),(0,i.kt)("p",null,"\uff087\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"W"),"\uff1a\u8868\u793a\u6709\u6548\u5de5\u4f5c\u65e5(\u5468\u4e00\u5230\u5468\u4e94) \u53ea\u80fd\u51fa\u73b0\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofMonth")," \u57df\uff0c\u7cfb\u7edf\u5c06\u5728\u79bb\u6307\u5b9a\u65e5\u671f\u7684\u6700\u8fd1\u7684\u6709\u6548\u5de5\u4f5c\u65e5\u89e6\u53d1\u4e8b\u4ef6\u3002\u4f8b\u5982\uff1a\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofMonth")," \u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"5W"),"\uff0c\u5982\u679c ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u65e5\u662f\u661f\u671f\u516d\uff0c\u5219\u5c06\u5728\u6700\u8fd1\u7684\u5de5\u4f5c\u65e5\uff1a\u661f\u671f\u4e94\uff0c\u5373 ",(0,i.kt)("inlineCode",{parentName:"p"},"4")," \u65e5\u89e6\u53d1\u3002\u5982\u679c ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u65e5\u662f\u661f\u671f\u5929\uff0c\u5219\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"6")," \u65e5(\u5468\u4e00)\u89e6\u53d1\uff1b\u5982\u679c ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u65e5\u5728\u661f\u671f\u4e00\u5230\u661f\u671f\u4e94\u4e2d\u7684\u4e00\u5929\uff0c\u5219\u5c31\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"5")," \u65e5\u89e6\u53d1\u3002\u53e6\u5916\u4e00\u70b9\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"W")," \u7684\u6700\u8fd1\u5bfb\u627e\u4e0d\u4f1a\u8de8\u8fc7\u6708\u4efd \u3002"),(0,i.kt)("p",null,"\uff088\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"LW"),"\uff1a\u8fd9\u4e24\u4e2a\u5b57\u7b26\u53ef\u4ee5\u8fde\u7528\uff0c\u8868\u793a\u5728\u67d0\u4e2a\u6708\u6700\u540e\u4e00\u4e2a\u5de5\u4f5c\u65e5\uff0c\u5373\u6700\u540e\u4e00\u4e2a\u661f\u671f\u4e94\u3002"),(0,i.kt)("p",null,"\uff089\uff09",(0,i.kt)("inlineCode",{parentName:"p"},"#"),"\uff1a\u7528\u4e8e\u786e\u5b9a\u6bcf\u4e2a\u6708\u7b2c\u51e0\u4e2a\u661f\u671f\u51e0\uff0c\u53ea\u80fd\u51fa\u73b0\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"DayofMonth")," \u57df\u3002\u4f8b\u5982\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"4#2"),"\uff0c\u8868\u793a\u67d0\u6708\u7684\u7b2c\u4e8c\u4e2a\u661f\u671f\u4e09\u3002"),(0,i.kt)("h3",{id:"2652-\u5e38\u89c1-cron-\u8868\u8fbe\u5f0f"},"26.5.2 \u5e38\u89c1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f"),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"\u8868\u8fbe\u5f0f"),(0,i.kt)("th",{parentName:"tr",align:null},"\u8868\u8fbe\u5f0f\u4ee3\u8868\u542b\u4e49"),(0,i.kt)("th",{parentName:"tr",align:null},"\u683c\u5f0f\u5316"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"*/1 * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0/1 * * * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 * * * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5c0f\u65f6"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 0/1 * * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5c0f\u65f6"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 23 ? * MON-FRI")),(0,i.kt)("td",{parentName:"tr",align:null},"\u665a\u4e0a 11:00\uff0c\u5468\u4e00\u81f3\u5468\u4e94"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u79d2"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"*/45 * * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf 45 \u79d2"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"*/5 * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf 5 \u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0/10 * * * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf 10 \u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 */5 * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf 5 \u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"30 11 * * 1-5")),(0,i.kt)("td",{parentName:"tr",align:null},"\u5468\u4e00\u81f3\u5468\u4e94\u4e0a\u5348 11:30"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"30 11 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"11:30"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0-10 11 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0a\u5348 11:00 \u81f3 11:10 \u4e4b\u95f4\u7684\u6bcf\u4e00\u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * 3 *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f\uff0c\u53ea\u5728 3 \u6708\u4efd"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * 3,6 *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f\uff0c\u53ea\u5728 3 \u6708\u548c 6 \u6708"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"30 14,16 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 02:30 \u5206\u548c 04:30 \u5206"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"30 6,14,16 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u65e9\u4e0a 06:30\uff0c\u4e0b\u5348 02:30 \u548c 04:30"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"46 9 * * 1")),(0,i.kt)("td",{parentName:"tr",align:null},"\u65e9\u4e0a 09:46\uff0c\u53ea\u5728\u661f\u671f\u4e00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"23 12 15 * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 12:23\uff0c\u5728\u672c\u6708\u7684\u7b2c 15 \u5929"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"23 12 * JAN *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 12:23\uff0c\u53ea\u5728 1 \u6708\u4efd"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"23 12 ? JAN *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 12:23\uff0c\u53ea\u5728 1 \u6708\u4efd"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"23 12 * JAN-FEB *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 12:23\uff0c1 \u6708\u81f3 2 \u6708"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"23 12 * JAN-MAR *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 12:23\uff0c1 \u6708\u81f3 3 \u6708"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"23 12 * * SUN")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 12:23\uff0c\u4ec5\u5728\u661f\u671f\u5929"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"*/5 15 * * MON-FRI")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf 5 \u5206\u949f\uff0c\u4e0b\u5348 0:00 \u81f3 03:59\uff0c\u5468\u4e00\u81f3\u5468\u4e94"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * * MON#3")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f\uff0c\u5728\u6708\u7684\u7b2c\u4e09\u4e2a\u661f\u671f\u4e00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * * 4L")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u4e00\u5206\u949f\uff0c\u5728\u672c\u6708\u7684\u6700\u540e\u4e00\u5929"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"*/5 * L JAN *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u6708\u4e00\u6b21\u6bcf\u6708 5 \u5206\u949f\uff0c\u53ea\u5728 1 \u6708\u4efd"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"30 02 14 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348\u5728 02:02:30"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"5-10 * * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f\u7684 5-10 \u79d2"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"5-10 30-35 10-12 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"10:00 \u81f3 12:00 \u4e4b\u95f4\u7684\u6bcf\u5206\u949f 5-10 \u79d2\uff0c\u6bcf\u5c0f\u65f6 30-35 \u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"30 */5 * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f\u7684 30 \u79d2\uff0c\u6bcf\u4e94\u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 30 10-13 ? * WED,FRI")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5c0f\u65f6\u7684 30 \u5206\u949f\uff0c\u4e0b\u5348 10:00 \u81f3 01:00 \u4e4b\u95f4\uff0c\u4ec5\u5728\u5468\u4e09\u548c\u5468\u4e94"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"10 0/5 * * * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5206\u949f\u7684 10 \u79d2\uff0c\u6bcf 05 \u5206\u949f"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 6 1/1 * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e0b\u5348 06:00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 5 0/1 * * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e00\u4e2a\u5c0f\u65f6\u7684 05 \u5206"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 L * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u6708\u6700\u540e\u4e00\u5929\u4e0a\u5348 00\uff1a00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 L-1 * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u6708\u6700\u540e\u4e00\u5929\u7684\u51cc\u6668 00\uff1a00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 3W * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u6708\u7b2c 3 \u4e2a\u5de5\u4f5c\u65e5\u4e0a\u5348 00\uff1a00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 LW * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u5728\u6bcf\u6708\u7684\u6700\u540e\u4e00\u4e2a\u5de5\u4f5c\u65e5\uff0c\u4e0a\u5348 00\uff1a00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 * * 2L")),(0,i.kt)("td",{parentName:"tr",align:null},"\u672c\u6708\u6700\u540e\u4e00\u4e2a\u661f\u671f\u4e8c\u4e0a\u5348 00\uff1a00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 * * 6#3")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u6708\u7b2c\u4e09\u4e2a\u661f\u671f\u516d\u4e0a\u5348 00\uff1a00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 ? 1 MON#1")),(0,i.kt)("td",{parentName:"tr",align:null},"1 \u6708\u7b2c\u4e00\u4e2a\u661f\u671f\u4e00\u4e0a\u5348 00\uff1a00"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.Standard"))),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 3 * * ?")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5929\u51e0\u70b9\u6267\u884c\u4e00\u6b21"),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"CronFormat.IncludeSeconds"))))),(0,i.kt)("h3",{id:"2653-\u5728\u7ebf\u751f\u6210-cron-\u8868\u8fbe\u5f0f"},"26.5.3 \u5728\u7ebf\u751f\u6210 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f"),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://cron.qqe2.com/"},"https://cron.qqe2.com/")),(0,i.kt)("h3",{id:"2654-macro-\u6807\u8bc6\u7b26"},"26.5.4 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Macro")," \u6807\u8bc6\u7b26"),(0,i.kt)("p",null,"\u4e3a\u4e86\u65b9\u4fbf\u5b9a\u4e49 ",(0,i.kt)("inlineCode",{parentName:"p"},"Cron")," \u8868\u8fbe\u5f0f\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e5f\u63d0\u4f9b\u4e86\u975e\u5e38\u65b9\u4fbf\u7684\u5360\u4f4d\u7b26\u5b9e\u73b0\u5e38\u7528\u7684\u65f6\u95f4\u683c\u5f0f\uff1a"),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"\u5360\u4f4d\u7b26"),(0,i.kt)("th",{parentName:"tr",align:null},"\u5bf9\u5e94\u8868\u8fbe\u5f0f"),(0,i.kt)("th",{parentName:"tr",align:null},"\u5360\u4f4d\u7b26\u4ee3\u8868\u542b\u4e49"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@every_second")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u4e00\u79d2\u949f\u8dd1\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@every_minute")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"* * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u5728\u5206\u949f\u5f00\u59cb\u65f6\u6bcf\u5206\u949f\u8fd0\u884c\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@hourly")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 * * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u5728\u5c0f\u65f6\u5f00\u59cb\u65f6\u6bcf\u5c0f\u65f6\u8fd0\u884c\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@daily")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5929\u5348\u591c\u8fd0\u884c\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@midnight")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 * * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5929\u5348\u591c\u8fd0\u884c\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@weekly")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 * * 0")),(0,i.kt)("td",{parentName:"tr",align:null},"\u5468\u65e5\u4e0a\u5348\u5348\u591c\u6bcf\u5468\u8fd0\u884c\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@monthly")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 1 * *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u6708\u5728\u6bcf\u6708\u7b2c\u4e00\u5929\u7684\u5348\u591c\u8fd0\u884c\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@yearly")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 1 1 *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5e74 1 \u6708 1 \u65e5\u5348\u591c\u8fd0\u884c\u4e00\u6b21")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"@annually")),(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"0 0 1 1 *")),(0,i.kt)("td",{parentName:"tr",align:null},"\u6bcf\u5e74 1 \u6708 1 \u65e5\u5348\u591c\u8fd0\u884c\u4e00\u6b21")))),(0,i.kt)("h3",{id:"2655-\u4f7f\u7528-cron-\u8868\u8fbe\u5f0f"},"26.5.5 \u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5}",showLineNumbers:!0,"":!0,"{2,5}":!0},'// \u6bcf\u9694 1s \u6267\u884c\nSpareTime.Do("* * * * * *", (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n}, cronFormat: CronFormat.IncludeSeconds);\n')),(0,i.kt)("admonition",{title:"\u5173\u4e8e CronFormat",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u672a\u542f\u7528\u5bf9 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u79d2")," \u7684\u652f\u6301\uff0c\u5982\u9700\u5f00\u542f\uff0c\u5219\u8bbe\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"cronFormat: CronFormat.IncludeSeconds")," \u5373\u53ef\u3002\u9ed8\u8ba4\u503c\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"cronFormat: CronFormat.Standard"))),(0,i.kt)("h3",{id:"2656-\u4f7f\u7528-macro-\u5360\u4f4d\u7b26"},"26.5.6 \u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Macro")," \u5360\u4f4d\u7b26"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},'// \u6bcf\u9694 1s \u6267\u884c\nSpareTime.Do("@every_second", (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n});\n')),(0,i.kt)("h3",{id:"2657-\u914d\u7f6e\u4efb\u52a1\u4fe1\u606f"},"26.5.7 \u914d\u7f6e\u4efb\u52a1\u4fe1\u606f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},'SpareTime.Do("* * * * *", (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n}, "cronName", "\u6bcf\u5206\u949f\u6267\u884c\u4e00\u6b21");\n')),(0,i.kt)("h3",{id:"2658-\u624b\u52a8\u542f\u52a8\u6267\u884c"},"26.5.8 \u624b\u52a8\u542f\u52a8\u6267\u884c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,6}",showLineNumbers:!0,"":!0,"{4,6}":!0},'SpareTime.Do("* * * * *", (timer, count) => {\n Console.WriteLine("\u73b0\u5728\u65f6\u95f4\uff1a" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n}, "cronName", "\u6bcf\u5206\u949f\u6267\u884c\u4e00\u6b21", startNow: false);\n\nSpareTime.Start("cronName");\n')),(0,i.kt)("h3",{id:"2659-isparetimeworker-\u65b9\u5f0f"},"26.5.9 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ISpareTimeWorker")," \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,8}",showLineNumbers:!0,"":!0,"{1,8}":!0},'public class JobWorker : ISpareTimeWorker\n{\n /// \n /// \u6bcf\u5206\u949f\u6267\u884c\n /// \n /// \n /// \n [SpareTime("* * * * *", "jobName", StartNow = true)]\n public void DoSomething(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n\n /// \n /// \u6bcf\u5206\u949f\u6267\u884c\uff08\u652f\u6301\u5f02\u6b65\uff09\n /// \n /// \n /// \n [SpareTime("* * * * *", "jobName", StartNow = true)]\n public async Task DoSomethingAsync(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n await Task.Completed;\n }\n}\n')),(0,i.kt)("h2",{id:"266-\u81ea\u5b9a\u4e49\u4e0b\u6b21\u6267\u884c\u65f6\u95f4"},"26.6 \u81ea\u5b9a\u4e49\u4e0b\u6b21\u6267\u884c\u65f6\u95f4"),(0,i.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u9700\u8981\u8fdb\u884c\u4e00\u4e9b\u4e1a\u52a1\u903b\u8f91\uff0c\u6bd4\u5982\u6570\u636e\u5e93\u67e5\u8be2\u7b49\u64cd\u4f5c\u8fd4\u56de\u4e0b\u4e00\u6b21\u6267\u884c\u65f6\u95f4\uff0c\u8fd9\u4e2a\u65f6\u5019\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u9ad8\u7ea7\u81ea\u5b9a\u4e49\u65b9\u5f0f\u3002"),(0,i.kt)("h3",{id:"2661-\u9ad8\u7ea7\u81ea\u5b9a\u4e49\u95f4\u9694\u65b9\u5f0f"},"26.6.1 \u9ad8\u7ea7\u81ea\u5b9a\u4e49\u95f4\u9694\u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,4-5,7}",showLineNumbers:!0,"":!0,"{2,4-5,7}":!0},'SpareTime.Do(()=>{\n // \u8fd9\u91cc\u53ef\u4ee5\u67e5\u8be2\u6570\u636e\u5e93\u6216\u8fdb\u884c\u6216\u8fdb\u884c\u4efb\u4f55\u4e1a\u52a1\u903b\u8f91\n\n if(\u7b26\u5408\u903b\u8f91){\n return 1000; // \u6bcf\u79d2\u6267\u884c\n }\n else return -1; // \u4e0d\u7b26\u5408\u903b\u8f91\u53d6\u6d88\u4efb\u52a1\n},\n(timer,count)=>{\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n});\n')),(0,i.kt)("admonition",{title:"\u914d\u7f6e\u662f\u5426\u6301\u7eed\u68c0\u67e5",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u8be5\u81ea\u5b9a\u4e49\u4f1a\u5728\u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5c0f\u4e8e\u6216\u7b49\u4e8e0")," \u65f6\u7ec8\u6b62\u4efb\u52a1\u7684\u6267\u884c\u3002\u4f46\u662f\u6211\u4eec\u5e0c\u671b\u8be5\u4efb\u52a1\u4e0d\u8981\u7ec8\u6b62\uff0c\u53ea\u8981\u7b26\u5408\u6761\u4ef6\u90fd\u4e00\u76f4\u6267\u884c\uff0c\u53ea\u9700\u8981\u914d\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"cancelInNoneNextTime: false")," \u5373\u53ef")),(0,i.kt)("h3",{id:"2662-\u9ad8\u7ea7\u81ea\u5b9a\u4e49-cron-\u8868\u8fbe\u5f0f"},"26.6.2 \u9ad8\u7ea7\u81ea\u5b9a\u4e49 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,4-5,7}",showLineNumbers:!0,"":!0,"{2,4-5,7}":!0},'SpareTime.Do(()=>{\n // \u8fd9\u91cc\u53ef\u4ee5\u67e5\u8be2\u6570\u636e\u5e93\u6216\u8fdb\u884c\u6216\u8fdb\u884c\u4efb\u4f55\u4e1a\u52a1\u903b\u8f91\n\n if(\u7b26\u5408\u903b\u8f91){\n return DateTimeOffset.Now.AddMinutes(10); // \u5341\u5206\u949f\u540e\u518d\u6267\u884c\n }\n else return null; // \u4e0d\u7b26\u5408\u903b\u8f91\u53d6\u6d88\u4efb\u52a1\n},\n(timer,count) => {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n});\n')),(0,i.kt)("admonition",{title:"\u914d\u7f6e\u662f\u5426\u6301\u7eed\u68c0\u67e5",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u8be5\u81ea\u5b9a\u4e49\u4f1a\u5728\u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"p"},"null")," \u65f6\u7ec8\u6b62\u4efb\u52a1\u7684\u6267\u884c\u3002\u4f46\u662f\u6211\u4eec\u5e0c\u671b\u8be5\u4efb\u52a1\u4e0d\u8981\u7ec8\u6b62\uff0c\u53ea\u8981\u7b26\u5408\u6761\u4ef6\u90fd\u4e00\u76f4\u6267\u884c\uff0c\u53ea\u9700\u8981\u914d\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"cancelInNoneNextTime: false")," \u5373\u53ef\uff0c\u5982\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,4-5,7,12}",showLineNumbers:!0,"":!0,"{2,4-5,7,12}":!0},'SpareTime.Do(()=>{\n // \u8fd9\u91cc\u53ef\u4ee5\u67e5\u8be2\u6570\u636e\u5e93\u6216\u8fdb\u884c\u6216\u8fdb\u884c\u4efb\u4f55\u4e1a\u52a1\u903b\u8f91\n\n if(\u7b26\u5408\u903b\u8f91){\n return SpareTime.GetCronNextOccurrence("cron \u8868\u8fbe\u5f0f");\n }\n else return null; // \u4e0d\u7b26\u5408\u903b\u8f91\u7ee7\u7eed\u68c0\u67e5\n},\n(timer,count) => {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n}, cancelInNoneNextTime: false);\n'))),(0,i.kt)("h2",{id:"267-isparetimeworker-\u8bf4\u660e"},"26.7 ",(0,i.kt)("inlineCode",{parentName:"h2"},"ISpareTimeWorker")," \u8bf4\u660e"),(0,i.kt)("p",null,"\u9664\u4e86\u4e0a\u9762\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"SpareTime")," \u9759\u6001\u7c7b\u65b9\u5f0f\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u8fd8\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"ISpareTimeWorker")," \u65b9\u5f0f\uff0c\u4f7f\u7528\u8be5\u65b9\u5f0f\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700\u8981\u81ea\u5b9a\u4e49\u4e00\u4e2a",(0,i.kt)("strong",{parentName:"p"},"\u516c\u5f00\u4e14\u975e\u62bd\u8c61\u975e\u9759\u6001"),"\u7c7b\u5e76\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"p"},"ISpareTimeWorker")," \u5373\u53ef\u3002"),(0,i.kt)("p",null,"\u5728\u8be5\u7c7b\u4e2d\u5b9a\u4e49\u7684\u4efb\u52a1\u65b9\u6cd5\u9700\u6ee1\u8db3\u4ee5\u4e0b\u89c4\u5219\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u5fc5\u987b\u662f",(0,i.kt)("strong",{parentName:"li"},"\u516c\u5f00\u4e14\u5b9e\u4f8b\u65b9\u6cd5")),(0,i.kt)("li",{parentName:"ul"},"\u8be5\u65b9\u6cd5\u5fc5\u987b\u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"li"},"void")," \u4e14\u63d0\u4f9b ",(0,i.kt)("inlineCode",{parentName:"li"},"SpareTimer")," \u548c ",(0,i.kt)("inlineCode",{parentName:"li"},"long")," \u4e24\u4e2a\u53c2\u6570"),(0,i.kt)("li",{parentName:"ul"},"\u5fc5\u987b\u8d34\u6709 ",(0,i.kt)("inlineCode",{parentName:"li"},"[SpareTime]")," \u7279\u6027")),(0,i.kt)("p",null,"\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4-5,12-13,20-21,28-30,37-38,45}",showLineNumbers:!0,"":!0,"{1,4-5,12-13,20-21,28-30,37-38,45}":!0},'public class JobWorker : ISpareTimeWorker\n{\n // \u6bcf\u9694\u4e00\u79d2\u6267\u884c\uff0c\u4e14\u7acb\u5373\u542f\u52a8\n [SpareTime(1000, "jobName1", StartNow = true)]\n public void DoSomething1(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n\n // \u6bcf\u5206\u949f\u6267\u884c\uff0c\u4e14\u7acb\u5373\u542f\u52a8\n [SpareTime("* * * * *", "jobName2", StartNow = true)]\n public void DoSomething2(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n\n // \u6bcf\u79d2\u6267\u884c\uff0c\u4e14\u7b49\u5f85\u542f\u52a8\n [SpareTime("* * * * * *", "jobName3",CronFormat = CronFormat.IncludeSeconds, StartNow = false)]\n public void DoSomething3(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n\n // \u6bcf\u79d2\u6267\u884c\u4e00\u6b21\uff0c\u6bcf\u5206\u949f\u4e5f\u6267\u884c\u4e00\u6b21\n [SpareTime(1000, "jobName4", StartNow = true)]\n [SpareTime("* * * * *", "jobName5", StartNow = true)]\n public void DoSomething4(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n\n // \u53ea\u6267\u884c\u4e00\u6b21\n [SpareTime(1000, "jobName5", StartNow = true, DoOnce = true)]\n public void DoSomething5(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n\n // \u8bfb\u53d6\u914d\u7f6e\u6587\u4ef6\uff0c\u901a\u8fc7 #(\u914d\u7f6e\u8def\u5f84)\n [SpareTime("#(MyJob:Time)", "jobName6", StartNow = true, DoOnce = true)]\n public void DoSomething5(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n }\n\n // \u652f\u6301\u5f02\u6b65\n [SpareTime(1000, "jobName1", StartNow = true)]\n public async Task DoSomethingAsync(SpareTimer timer, long count)\n {\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n await Task.Completed;\n }\n}\n')),(0,i.kt)("admonition",{title:"\u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"ISpareTimeWorker")," \u63a5\u53e3\u4e3b\u8981\u662f\u7528\u6765\u67e5\u627e\u5b9a\u65f6\u5668\u5bf9\u8c61\u7684\uff0c\u4e5f\u5c31\u662f\u5b83\u7684\u5b9e\u73b0\u7c7b\u5e76\u672a\u63d0\u4f9b\u4f9d\u8d56\u6ce8\u5165\u529f\u80fd\uff0c\u6240\u4ee5\u5728\u5b9e\u73b0\u7c7b\u5e76\u4e0d\u652f\u6301\u6784\u9020\u51fd\u6570\u6ce8\u5165\u4f9d\u8d56\u9879\u3002")),(0,i.kt)("h3",{id:"2671-sparetime-\u7279\u6027"},"26.7.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"[SpareTime]")," \u7279\u6027"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"[SpareTime]")," \u652f\u6301\u4ee5\u4e0b\u914d\u7f6e\u5c5e\u6027"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Interval"),"\uff1a\u95f4\u9694\u65f6\u95f4, ",(0,i.kt)("inlineCode",{parentName:"li"},"double")," \u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"CronExpression"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Cron")," \u8868\u8fbe\u5f0f\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"WorkerName"),"\uff1a\u4efb\u52a1\u552f\u4e00\u6807\u8bc6\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"\u5fc5\u586b")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Description"),"\uff1a\u4efb\u52a1\u63cf\u8ff0\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"DoOnce"),"\uff1a\u662f\u5426\u53ea\u6267\u884c\u4e00\u6b21\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,i.kt)("inlineCode",{parentName:"li"},"false")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"StartNow"),"\uff1a\u662f\u5426\u7acb\u5373\u542f\u52a8\uff0c\u9ed8\u8ba4 ",(0,i.kt)("inlineCode",{parentName:"li"},"false")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"CronFormat"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Cron")," \u8868\u8fbe\u5f0f\u683c\u5f0f\u5316\u65b9\u5f0f\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"CronFormat")," \u679a\u4e3e\u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,i.kt)("inlineCode",{parentName:"li"},"CronFormat.Standard")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ExecuteType"),"\uff1a\u914d\u7f6e\u4efb\u52a1\u6267\u884c\u65b9\u5f0f\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"SpareTimeExecuteTypes")," \u679a\u4e3e\u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,i.kt)("inlineCode",{parentName:"li"},"SpareTimeExecuteTypes.Parallel"))),(0,i.kt)("h2",{id:"268-sparetime-\u9759\u6001\u7c7b"},"26.8 ",(0,i.kt)("inlineCode",{parentName:"h2"},"SpareTime")," \u9759\u6001\u7c7b"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"SpareTime")," \u9759\u6001\u7c7b\u63d0\u4f9b\u4e86\u4e00\u4e9b\u65b9\u6cd5\u65b9\u4fbf\u521d\u59cb\u5316\u548c\u7ba1\u7406\u4efb\u52a1"),(0,i.kt)("h3",{id:"2681-\u521d\u59cb\u5316\u4efb\u52a1"},"26.8.1 \u521d\u59cb\u5316\u4efb\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u5f00\u542f\u95f4\u9694\u4efb\u52a1\nSpareTime.Do(interval, [options]);\n\n// \u5f00\u542f Cron \u8868\u8fbe\u5f0f\u4efb\u52a1\nSpareTime.Do(expression, [options]);\n\n// \u53ea\u6267\u884c\u4e00\u6b21\u4efb\u52a1\nSpareTime.DoOnce(interval, [options]);\n\n// \u5b9e\u73b0\u81ea\u5b9a\u4e49\u4efb\u52a1\nSpareTime.Do(()=>{\n return DateTime.Now.AddMinutes(10);\n},[options]);\n")),(0,i.kt)("h3",{id:"2682-\u5b9e\u73b0\u540e\u53f0\u6267\u884c"},"26.8.2 \u5b9e\u73b0\u540e\u53f0\u6267\u884c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u5b9e\u73b0\u540e\u53f0\u6267\u884c\nSpareTime.DoIt(()=>{});\n")),(0,i.kt)("h3",{id:"2683-\u5f00\u59cb\u4e00\u4e2a\u4efb\u52a1"},"26.8.3 \u5f00\u59cb\u4e00\u4e2a\u4efb\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SpareTime.Start("\u4efb\u52a1\u6807\u8bc6");\n')),(0,i.kt)("h3",{id:"2684-\u6682\u505c\u4e00\u4e2a\u4efb\u52a1"},"26.8.4 \u6682\u505c\u4e00\u4e2a\u4efb\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SpareTime.Stop("\u4efb\u52a1\u6807\u8bc6");\n// \u8fd8\u53ef\u4ee5\u6807\u8bb0\u4e00\u4e2a\u4efb\u52a1\u6267\u884c\u5931\u8d25\nSpareTime.Stop("\u4efb\u52a1\u6807\u8bc6", true);\n')),(0,i.kt)("h3",{id:"2685-\u53d6\u6d88\u4e00\u4e2a\u4efb\u52a1"},"26.8.5 \u53d6\u6d88\u4e00\u4e2a\u4efb\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SpareTime.Cancel("\u4efb\u52a1\u540d\u79f0");\n')),(0,i.kt)("h3",{id:"2686-\u9500\u6bc1\u6240\u6709\u4efb\u52a1"},"26.8.6 \u9500\u6bc1\u6240\u6709\u4efb\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"SpareTime.Dispose();\n")),(0,i.kt)("h3",{id:"2687-\u83b7\u53d6\u6240\u6709\u4efb\u52a1"},"26.8.7 \u83b7\u53d6\u6240\u6709\u4efb\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var workers = SpareTime.GetWorkers();\n")),(0,i.kt)("h3",{id:"2688-\u83b7\u53d6\u5355\u4e2a\u4efb\u52a1"},"26.8.8 \u83b7\u53d6\u5355\u4e2a\u4efb\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var worker = SpareTime.GetWorker("workerName");\n')),(0,i.kt)("h3",{id:"2689-\u89e3\u6790-cron-\u8868\u8fbe\u5f0f"},"26.8.9 \u89e3\u6790 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var nextTime = SpareTime.GetCronNextOccurrence("* * * * *");\n')),(0,i.kt)("h2",{id:"269-\u5e76\u884c\u548c\u4e32\u884c\u6267\u884c\u65b9\u5f0f"},"26.9 ",(0,i.kt)("inlineCode",{parentName:"h2"},"\u5e76\u884c"),"\u548c",(0,i.kt)("inlineCode",{parentName:"h2"},"\u4e32\u884c"),"\u6267\u884c\u65b9\u5f0f"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u4efb\u52a1\u4e24\u79cd\u6267\u884c\u65b9\u5f0f ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5e76\u884c")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"\u4e32\u884c"),"\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"\u5e76\u884c"),"\uff1a\u65e0\u9700\u7b49\u5f85\u4e0a\u4e00\u6b21\u4efb\u52a1\u5b8c\u6210\uff0c",(0,i.kt)("strong",{parentName:"li"},"\u9ed8\u8ba4\u503c")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"\u4e32\u884c"),"\uff1a\u9700\u7b49\u5f85\u4e0a\u4e00\u6b21\u4efb\u52a1\u5b8c\u6210")),(0,i.kt)("h3",{id:"2691-sparetime-\u9759\u6001\u65b9\u5f0f\u6307\u5b9a"},"26.9.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"SpareTime")," \u9759\u6001\u65b9\u5f0f\u6307\u5b9a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5}",showLineNumbers:!0,"":!0,"{3,5}":!0},'SpareTime.Do(1000, (t, i) =>\n{\n Thread.Sleep(5000); // \u6a21\u62df\u6267\u884c\u8017\u65f6\u4efb\u52a1\n Console.WriteLine($"{t.WorkerName} -{t.Description} - {DateTime.Now:yyyy-MM-dd HH:mm:ss} - {i}");\n}, "serialName", "\u6a21\u62df\u4e32\u884c\u4efb\u52a1", executeType: SpareTimeExecuteTypes.Serial);\n')),(0,i.kt)("h3",{id:"2692-isparetimeworker-\u65b9\u5f0f"},"26.9.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ISpareTimeWorker")," \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'[SpareTime(1000, "jobName1", StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]\npublic void DoSomething1(SpareTimer timer, long count)\n{\n Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));\n Console.WriteLine($"\u4e00\u5171\u6267\u884c\u4e86\uff1a{count} \u6b21");\n}\n')),(0,i.kt)("h2",{id:"2610-\u4efb\u52a1\u5f02\u5e38\u5904\u7406"},"26.10 \u4efb\u52a1\u5f02\u5e38\u5904\u7406"),(0,i.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u53ef\u80fd\u5728\u6267\u884c\u4efb\u52a1\u8fc7\u7a0b\u4e2d\u51fa\u73b0\u5f02\u5e38\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e5f\u63d0\u4f9b\u4e86\u5c5e\u6027\u5224\u65ad\u662f\u5426\u6709\u5f02\u5e38\u548c\u5f02\u5e38\u4fe1\u606f\uff0c\u65b9\u4fbf\u8bb0\u5f55\u5230\u65e5\u5fd7\u4e2d\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4-7,11}",showLineNumbers:!0,"":!0,"{4-7,11}":!0},'SpareTime.Do(1000, (t, c) =>\n{\n // \u5224\u65ad\u662f\u5426\u6709\u5f02\u5e38\n if (t.Exception.Any())\n {\n Console.WriteLine(t.Exception.Values.LastOrDefault()?.Message);\n }\n // \u6267\u884c\u7b2c\u4e09\u6b21\u629b\u5f02\u5e38\n if (c > 2)\n {\n throw Oops.Oh("\u629b\u5f02\u5e38" + c);\n }\n else\n {\n Console.WriteLine($"{t.WorkerName} -{t.Description} - {DateTime.Now:yyyy-MM-dd HH:mm:ss} - {c}");\n }\n}, "exceptionJob");\n')),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4e00\u4e2a\u4efb\u52a1\u8fde\u7eed\u9519\u8bef\u6b21\u6570\u8fbe ",(0,i.kt)("inlineCode",{parentName:"p"},"10\u6b21")," \u5219\u4efb\u52a1\u5c06\u81ea\u52a8\u505c\u6b62\uff0c\u5e76\u6807\u8bb0\u4efb\u52a1\u72b6\u6001\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"Failed"),"\u3002")),(0,i.kt)("h2",{id:"2611-\u5982\u4f55\u5728\u4efb\u52a1\u4e2d\u89e3\u6790\u5bf9\u8c61"},"26.11 \u5982\u4f55\u5728\u4efb\u52a1\u4e2d\u89e3\u6790\u5bf9\u8c61"),(0,i.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u9700\u8981\u5728\u4efb\u52a1\u4e2d\u8fdb\u884c\u6570\u636e\u5e93\u64cd\u4f5c\u6216\u89e3\u6790\u670d\u52a1\uff0c\u8fd9\u65f6\u5019\u6211\u4eec\u53ea\u9700\u8981\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u4f5c\u7528\u57df\u5373\u53ef"),(0,i.kt)("h3",{id:"26111-sparetime-\u9759\u6001\u7c7b\u4e2d"},"26.11.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"SpareTime")," \u9759\u6001\u7c7b\u4e2d"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},'SpareTime.Do(1000, (timer,count) => {\n Scoped.Create((_, scope) =>\n {\n var services = scope.ServiceProvider;\n\n // \u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n var dbContext = Db.GetDbContext(services);\n\n // \u83b7\u53d6\u4ed3\u50a8\n var respository = Db.GetRepository(services);\n\n // \u89e3\u6790\u5176\u4ed6\u670d\u52a1\n var otherService = services.GetService();\n var otherService2 = App.GetService(services);\n });\n}, "\u4efb\u52a1\u6807\u8bc6");\n')),(0,i.kt)("h3",{id:"26112-isparetimeworker-\u65b9\u5f0f"},"26.11.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ISpareTimeWorker")," \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},'[SpareTime(1000, "jobName1", StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]\npublic void DoSomething1(SpareTimer timer, long count)\n{\n Scoped.Create((_, scope) =>\n {\n var services = scope.ServiceProvider;\n\n // \u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n var dbContext = Db.GetDbContext(services);\n\n // \u83b7\u53d6\u4ed3\u50a8\n var respository = Db.GetRepository(services);\n\n // \u89e3\u6790\u5176\u4ed6\u670d\u52a1\n var otherService = services.GetService();\n var otherService2 = App.GetService(services);\n });\n}\n')),(0,i.kt)("admonition",{title:"\u6570\u636e\u5e93\u64cd\u4f5c\u6ce8\u610f",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f5c\u7528\u57df\u4e2d\u5bf9",(0,i.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u6709\u4efb\u4f55\u53d8\u66f4\u64cd\u4f5c"),"\uff0c\u9700\u624b\u52a8\u8c03\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216\u5e26 ",(0,i.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u65b9\u6cd5\u3002\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Scoped.CreateUow(handler)")," \u4ee3\u66ff\u3002")),(0,i.kt)("h2",{id:"2612-\u5728-backgroundservice-\u4e2d\u4f7f\u7528"},"26.12 \u5728 ",(0,i.kt)("inlineCode",{parentName:"h2"},"BackgroundService")," \u4e2d\u4f7f\u7528"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"BackgroundService")," \u662f ",(0,i.kt)("inlineCode",{parentName:"p"},".NET Core 3")," \u4e4b\u540e\u63d0\u4f9b\u7684\u8f7b\u91cf\u7ea7\u540e\u53f0\u4efb\u52a1\uff0c\u540c\u65f6\u53ef\u4ee5\u53d1\u5e03\u5230 ",(0,i.kt)("inlineCode",{parentName:"p"},"Windows")," \u670d\u52a1\u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"Linux")," \u5b88\u62a4\u8fdb\u7a0b\u4e2d\u3002"),(0,i.kt)("h3",{id:"26121-\u95f4\u9694\u6267\u884c\u65b9\u5f0f"},"26.12.1 \u95f4\u9694\u6267\u884c\u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,18,20,30}",showLineNumbers:!0,"":!0,"{7,18,20,30}":!0},'namespace WorkerService;\n\npublic class Worker : BackgroundService\n{\n private readonly ILogger _logger;\n\n private const int delay = 1000;\n\n public Worker(ILogger logger)\n {\n _logger = logger;\n }\n\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);\n\n await taskFactory.StartNew(async () =>\n {\n // \u4f60\u7684\u4e1a\u52a1\u4ee3\u7801\u5199\u5230\u8fd9\u91cc\u9762\n\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n\n await Task.CompletedTask;\n\n }, stoppingToken);\n\n await Task.Delay(delay, stoppingToken);\n }\n }\n}\n')),(0,i.kt)("h3",{id:"26122-cron-\u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f"},"26.12.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,14,21,23,32}",showLineNumbers:!0,"":!0,"{9,14,21,23,32}":!0},'using Furion.TimeCrontab;\n\nnamespace WorkerService;\n\npublic class Worker : BackgroundService\n{\n private readonly ILogger _logger;\n\n private readonly Crontab _crontab;\n\n public Worker(ILogger logger)\n {\n _logger = logger;\n _crontab = Crontab.Parse("* * * * * *", CronStringFormat.WithSeconds);\n }\n\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);\n\n await taskFactory.StartNew(async () =>\n {\n // \u4f60\u7684\u4e1a\u52a1\u4ee3\u7801\u5199\u5230\u8fd9\u91cc\u9762\n\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n\n await Task.CompletedTask;\n }, stoppingToken);\n\n await Task.Delay(_crontab.GetSleepMilliseconds(DateTime.UtcNow), stoppingToken);\n }\n }\n}\n')),(0,i.kt)("h2",{id:"2613-\u5b9a\u65f6\u4efb\u52a1\u76d1\u542c\u5668"},"26.13 \u5b9a\u65f6\u4efb\u52a1\u76d1\u542c\u5668"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion v2.18+")," \u7248\u672c\u4e4b\u540e\u65b0\u589e\u4e86\u5b9a\u65f6\u4efb\u52a1\u76d1\u542c\u5668 ",(0,i.kt)("inlineCode",{parentName:"p"},"ISpareTimeListener"),"\uff0c\u901a\u8fc7\u76d1\u542c\u5668\u53ef\u4ee5\u5b9e\u73b0\u6240\u6709\u5b9a\u65f6\u4efb\u52a1\u7684\u72b6\u6001\u3002\u5982\uff0c\u521b\u5efa\u4e00\u4e2a ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5355\u4f8b")," \u7684\u76d1\u542c\u5668 ",(0,i.kt)("inlineCode",{parentName:"p"},"SpareTimeListener"),"\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8,15}",showLineNumbers:!0,"":!0,"{8,15}":!0},'using Furion.DependencyInjection;\nusing Furion.TaskScheduler;\nusing System;\nusing System.Threading.Tasks;\n\nnamespace Furion.Core\n{\n public class SpareTimeListener : ISpareTimeListener, ISingleton\n {\n /// \n /// \u76d1\u542c\u6240\u6709\u4efb\u52a1\n /// \n /// \n /// \n public Task OnListener(SpareTimerExecuter executer)\n {\n switch (executer.Status)\n {\n // \u6267\u884c\u5f00\u59cb\u901a\u77e5\n case 0:\n Console.WriteLine($"{executer.Timer.WorkerName} \u4efb\u52a1\u5f00\u59cb\u901a\u77e5");\n break;\n // \u4efb\u52a1\u6267\u884c\u4e4b\u524d\u901a\u77e5\n case 1:\n Console.WriteLine($"{executer.Timer.WorkerName} \u6267\u884c\u4e4b\u524d\u901a\u77e5");\n break;\n // \u6267\u884c\u6210\u529f\u901a\u77e5\n case 2:\n Console.WriteLine($"{executer.Timer.WorkerName} \u6267\u884c\u6210\u529f\u901a\u77e5");\n break;\n // \u4efb\u52a1\u6267\u884c\u5931\u8d25\u901a\u77e5\n case 3:\n Console.WriteLine($"{executer.Timer.WorkerName} \u6267\u884c\u5931\u8d25\u901a\u77e5");\n break;\n // \u4efb\u52a1\u6267\u884c\u505c\u6b62\u901a\u77e5\n case -1:\n Console.WriteLine($"{executer.Timer.WorkerName} \u6267\u884c\u505c\u6b62\u901a\u77e5");\n break;\n // \u4efb\u52a1\u6267\u884c\u53d6\u6d88\u901a\u77e5\n case -2:\n Console.WriteLine($"{executer.Timer.WorkerName} \u6267\u884c\u53d6\u6d88\u901a\u77e5");\n break;\n default:\n break;\n }\n\n return Task.CompletedTask;\n }\n }\n}\n')),(0,i.kt)("h3",{id:"26131-sparetimerexecuter-\u5c5e\u6027\u8bf4\u660e"},"26.13.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"SpareTimerExecuter")," \u5c5e\u6027\u8bf4\u660e"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Timer"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"SpareTimer")," \u5b9a\u65f6\u5668\u5bf9\u8c61"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Status"),"\uff1a\u76d1\u542c\u72b6\u6001",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"0"),"\uff1a\u4efb\u52a1\u5f00\u59cb"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"1"),"\uff1a\u6267\u884c\u4e4b\u524d"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"2"),"\uff1a\u6267\u884c\u6210\u529f"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"3"),"\uff1a\u6267\u884c\u5931\u8d25"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"-1"),"\uff1a\u4efb\u52a1\u505c\u6b62"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"-2"),"\uff1a\u4efb\u52a1\u53d6\u6d88")))),(0,i.kt)("h2",{id:"2614-iis-\u90e8\u7f72\u56de\u6536\u8bbe\u7f6e"},"26.14 IIS \u90e8\u7f72\u56de\u6536\u8bbe\u7f6e"),(0,i.kt)("p",null,"\u5982\u679c\u5728\u9879\u76ee\u4e2d\u4f7f\u7528\u4e86\u5b9a\u65f6\u4efb\u52a1\u4e14\u90e8\u7f72\u5230 ",(0,i.kt)("inlineCode",{parentName:"p"},"IIS")," \u4e2d\uff0c\u90a3\u4e48\u9700\u8981\u8bbe\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"IIS")," \u7981\u6b62\u56de\u6536\uff0c\u5982\uff1a"),(0,i.kt)("img",{src:(0,l.Z)("img/iishuishou.jpg")}),(0,i.kt)("admonition",{title:"\u90e8\u7f72\u5efa\u8bae",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"\u5efa\u8bae\u5b9a\u65f6\u4efb\u52a1\u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u72ec\u7acb\u90e8\u7f72\u65b9\u5f0f\uff0c\u4e0d\u5e94\u4f9d\u6258 ",(0,i.kt)("inlineCode",{parentName:"p"},"Web")," \u9879\u76ee\u8fdb\u7a0b\u4e2d\u3002",(0,i.kt)("a",{parentName:"p",href:"/furion/docs/process-service"},"\u67e5\u770b\u3010 Worker Service\u3011\u7ae0\u8282"))),(0,i.kt)("h2",{id:"2615-\u53cd\u9988\u4e0e\u5efa\u8bae"},"26.15 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}s.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return d},kt:function(){return u}});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function l(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var m=a.createContext({}),p=function(e){var n=a.useContext(m),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},d=function(e){var n=p(e.components);return a.createElement(m.Provider,{value:n},e.children)},k={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},N=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,m=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),N=p(t),u=r,s=N["".concat(m,".").concat(u)]||N[u]||k[u]||i;return t?a.createElement(s,l(l({ref:n},d),{},{components:t})):a.createElement(s,l({ref:n},d))}));function u(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,l=new Array(i);l[0]=N;var o={};for(var m in n)hasOwnProperty.call(n,m)&&(o[m]=n[m]);o.originalType=e,o.mdxType="string"==typeof e?e:r,l[1]=o;for(var p=2;pusing",id:"\u9ed8\u8ba4\u5168\u5c40-using",level:3}],m={toc:c};function d(e){var n=e.components,t=(0,r.Z)(e,l);return(0,a.kt)("wrapper",(0,o.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\u7b80\u4ecb"},"\u7b80\u4ecb"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET6/C#10")," \u4e4b\u540e\uff0c\u5fae\u8f6f\u65b0\u589e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings")," \u673a\u5236\uff0c\u53ef\u4ee5\u5728\u9879\u76ee\u7684\u6839\u76ee\u5f55\u4e0b\u521b\u5efa\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u6587\u4ef6\uff0c\u628a\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u653e\u7f6e\u5176\u4e2d\u3002"),(0,a.kt)("p",null,"\u8fd9\u6837 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u6240\u5728\u7684\u9879\u76ee ",(0,a.kt)("inlineCode",{parentName:"p"},".cs")," \u6587\u4ef6\u5c31\u65e0\u9700\u91cd\u590d ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u4e86\uff0c\u5927\u5927\u7684\u63d0\u9ad8\u5f00\u53d1\u6548\u7387\uff0c\u4e5f\u8ba9\u4ee3\u7801\u53d8\u7684\u66f4\u52a0\u7b80\u6d01\u3002"),(0,a.kt)("h3",{id:"\u5fc5\u8981\u914d\u7f6e"},"\u5fc5\u8981\u914d\u7f6e"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u542f\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"GlobalUsings")," \u673a\u5236\u9700\u8981\u4ee5\u4e0b\u4e24\u4e2a\u6b65\u9aa4\uff1a")),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"\u5728\u4f60\u9700\u8981\u5168\u5c40 ",(0,a.kt)("inlineCode",{parentName:"li"},"using")," \u7684\u9879\u76ee\u5c42\u6839\u76ee\u5f55\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"li"},"GlobalUsings.cs")," \u6587\u4ef6\uff0c\u5982\u679c\u591a\u4e2a\u9879\u76ee\u5c42\u9700\u8981\uff0c\u5219\u6bcf\u4e2a\u5c42\u90fd\u5e94\u8be5\u6709\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"li"},"GlobalUsings.cs")),(0,a.kt)("li",{parentName:"ol"},"\u7f16\u8f91\u9879\u76ee\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},".csproj")," \u6587\u4ef6\uff0c\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"li"},"enable"),"\uff0c\u6ce8\u610f\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"")," \u4e2d\u6dfb\u52a0\uff0c\u901a\u5e38\u548c ",(0,a.kt)("inlineCode",{parentName:"li"},"")," \u540c\u7236\u540c\u7ea7")),(0,a.kt)("h3",{id:"\u57fa\u672c\u4f7f\u7528"},"\u57fa\u672c\u4f7f\u7528"),(0,a.kt)("p",null,"\u914d\u7f6e\u4e4b\u540e\uff0c\u73b0\u5728\u5c31\u53ef\u4ee5\u628a\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u653e\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u4e2d\u4e86\uff0c\u5199\u6cd5\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="Furion \u63a8\u8350\u7684\u5168\u5c40\u547d\u540d\u7a7a\u95f4"',showLineNumbers:!0,title:'"Furion','\u63a8\u8350\u7684\u5168\u5c40\u547d\u540d\u7a7a\u95f4"':!0},"global using Furion;\nglobal using Furion.DatabaseAccessor;\nglobal using Furion.DataEncryption;\nglobal using Furion.DataValidation;\nglobal using Furion.DependencyInjection;\nglobal using Furion.DynamicApiController;\nglobal using Furion.Extensions;\nglobal using Furion.FriendlyException;\nglobal using Mapster;\nglobal using Microsoft.AspNetCore.Authorization;\nglobal using Microsoft.AspNetCore.Http;\nglobal using Microsoft.AspNetCore.Mvc;\nglobal using Microsoft.CodeAnalysis;\nglobal using Microsoft.EntityFrameworkCore;\nglobal using System.ComponentModel.DataAnnotations;\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u5fc5\u987b\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"strong"},"global")," \u5f00\u5934\uff01")),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u4e00\u822c\u63a8\u8350\u628a\u5b9e\u4f53\u7c7b\u7684\u547d\u540d\u7a7a\u95f4\u4e5f\u653e\u8fdb\u53bb\uff0c\u56e0\u4e3a\u4ed3\u50a8 ",(0,a.kt)("inlineCode",{parentName:"p"},"IRepository")," \u4f7f\u7528\u7684\u9891\u7387\u975e\u5e38\u9ad8\u3002"),(0,a.kt)("p",{parentName:"admonition"},"\u53e6\u5916\u63a8\u8350\u5927\u5bb6\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u4e2d\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"CodeMaid")," \u63d2\u4ef6\u54e6\uff0c\u81ea\u52a8\u6e05\u7406\u89e3\u51b3\u65b9\u6848\u6240\u6709\u65e0\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using"),"\uff0c\u7ed3\u5408 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u975e\u5e38\u68d2\uff01")),(0,a.kt)("admonition",{title:"\u4e2a\u522b\u60c5\u51b5",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u53ef\u80fd\u7531\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u7248\u672c\u7684\u95ee\u9898\uff0c\u5bfc\u81f4 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u5b9a\u4e49\u51fa\u9519\uff0c\u8fd9\u65f6\u5019\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u540e\u9762\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"global::"),"\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"global using global::Furion;\n"))),(0,a.kt)("p",null,"\u63a5\u4e0b\u6765\u5728\u4ee3\u7801\u4e2d\u4f7f\u7528\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},"// \u65e0\u9700 using Furion \u7684\u547d\u540d\u7a7a\u95f4\u4e86\u54e6\uff0c\u6e05\u723d\u4e86\u4e0d\u5c11\n\nnamespace Your.Application;\n\npublic class DefaultAppService : IDynamicApiController\n{\n private readonly IRepository _boardCardRepository;\n private readonly IRepository _boardGroupRepository;\n private readonly IRepository _boardCardAttachmentRepository;\n private readonly IRepository _boardCardUserRepository;\n}\n\n// ....\n")),(0,a.kt)("img",{src:(0,i.Z)("img/cd2223.png")}),(0,a.kt)("h3",{id:"\u9ed8\u8ba4\u5168\u5c40-using"},"\u9ed8\u8ba4\u5168\u5c40 ",(0,a.kt)("inlineCode",{parentName:"h3"},"using")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u5b9e\u9645\u4e0a\u5fae\u8f6f\u5df2\u7ecf\u81ea\u52a8\u628a\u4e00\u4e9b\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"using")," \u5728\u7f16\u8bd1\u540e\u7684\u4ee3\u7801\u4e2d\u81ea\u52a8\u8865\u4e0a\u4e86"),"\uff0c\u8def\u5f84\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u9879\u76ee/obj/Debug/net6.0/\u9879\u76ee.GlobalUsings.cs")," \u6587\u4ef6\u4e2d\uff0c\u6587\u4ef6\u5185\u5bb9\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \nglobal using global::System;\nglobal using global::System.Collections.Generic;\nglobal using global::System.IO;\nglobal using global::System.Linq;\nglobal using global::System.Net.Http;\nglobal using global::System.Threading;\nglobal using global::System.Threading.Tasks;\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u4e5f\u5c31\u662f\u4ee5\u4e0a\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"using")," \u65e0\u9700\u5199\u5728\u4f60\u521b\u5efa\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"GlobalUsings.cs")," \u4e2d\u4e86\uff0c\u5fae\u8f6f\u4f1a\u5728\u7f16\u8bd1\u65f6\u81ea\u52a8\u5408\u5e76\u3002")))}d.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return u},kt:function(){return m}});var o=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function i(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=o.createContext({}),p=function(e){var n=o.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u=function(e){var n=p(e.components);return o.createElement(s.Provider,{value:n},e.children)},g={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},c=o.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),c=p(t),m=r,d=c["".concat(s,".").concat(m)]||c[m]||g[m]||a;return t?o.createElement(d,i(i({ref:n},u),{},{components:t})):o.createElement(d,i({ref:n},u))}));function m(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,i=new Array(a);i[0]=c;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:r,i[1]=l;for(var p=2;p=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=o.createContext({}),p=function(e){var n=o.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u=function(e){var n=p(e.components);return o.createElement(s.Provider,{value:n},e.children)},g={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},c=o.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),c=p(t),m=r,d=c["".concat(s,".").concat(m)]||c[m]||g[m]||a;return t?o.createElement(d,i(i({ref:n},u),{},{components:t})):o.createElement(d,i({ref:n},u))}));function m(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,i=new Array(a);i[0]=c;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:r,i[1]=l;for(var p=2;pusing",id:"\u9ed8\u8ba4\u5168\u5c40-using",level:3}],m={toc:c};function d(e){var n=e.components,t=(0,r.Z)(e,l);return(0,a.kt)("wrapper",(0,o.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\u7b80\u4ecb"},"\u7b80\u4ecb"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET6/C#10")," \u4e4b\u540e\uff0c\u5fae\u8f6f\u65b0\u589e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings")," \u673a\u5236\uff0c\u53ef\u4ee5\u5728\u9879\u76ee\u7684\u6839\u76ee\u5f55\u4e0b\u521b\u5efa\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u6587\u4ef6\uff0c\u628a\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u653e\u7f6e\u5176\u4e2d\u3002"),(0,a.kt)("p",null,"\u8fd9\u6837 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u6240\u5728\u7684\u9879\u76ee ",(0,a.kt)("inlineCode",{parentName:"p"},".cs")," \u6587\u4ef6\u5c31\u65e0\u9700\u91cd\u590d ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u4e86\uff0c\u5927\u5927\u7684\u63d0\u9ad8\u5f00\u53d1\u6548\u7387\uff0c\u4e5f\u8ba9\u4ee3\u7801\u53d8\u7684\u66f4\u52a0\u7b80\u6d01\u3002"),(0,a.kt)("h3",{id:"\u5fc5\u8981\u914d\u7f6e"},"\u5fc5\u8981\u914d\u7f6e"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u542f\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"GlobalUsings")," \u673a\u5236\u9700\u8981\u4ee5\u4e0b\u4e24\u4e2a\u6b65\u9aa4\uff1a")),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"\u5728\u4f60\u9700\u8981\u5168\u5c40 ",(0,a.kt)("inlineCode",{parentName:"li"},"using")," \u7684\u9879\u76ee\u5c42\u6839\u76ee\u5f55\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"li"},"GlobalUsings.cs")," \u6587\u4ef6\uff0c\u5982\u679c\u591a\u4e2a\u9879\u76ee\u5c42\u9700\u8981\uff0c\u5219\u6bcf\u4e2a\u5c42\u90fd\u5e94\u8be5\u6709\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"li"},"GlobalUsings.cs")),(0,a.kt)("li",{parentName:"ol"},"\u7f16\u8f91\u9879\u76ee\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},".csproj")," \u6587\u4ef6\uff0c\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"li"},"enable"),"\uff0c\u6ce8\u610f\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"")," \u4e2d\u6dfb\u52a0\uff0c\u901a\u5e38\u548c ",(0,a.kt)("inlineCode",{parentName:"li"},"")," \u540c\u7236\u540c\u7ea7")),(0,a.kt)("h3",{id:"\u57fa\u672c\u4f7f\u7528"},"\u57fa\u672c\u4f7f\u7528"),(0,a.kt)("p",null,"\u914d\u7f6e\u4e4b\u540e\uff0c\u73b0\u5728\u5c31\u53ef\u4ee5\u628a\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u653e\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u4e2d\u4e86\uff0c\u5199\u6cd5\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="Furion \u63a8\u8350\u7684\u5168\u5c40\u547d\u540d\u7a7a\u95f4"',showLineNumbers:!0,title:'"Furion','\u63a8\u8350\u7684\u5168\u5c40\u547d\u540d\u7a7a\u95f4"':!0},"global using Furion;\nglobal using Furion.DatabaseAccessor;\nglobal using Furion.DataEncryption;\nglobal using Furion.DataValidation;\nglobal using Furion.DependencyInjection;\nglobal using Furion.DynamicApiController;\nglobal using Furion.Extensions;\nglobal using Furion.FriendlyException;\nglobal using Mapster;\nglobal using Microsoft.AspNetCore.Authorization;\nglobal using Microsoft.AspNetCore.Http;\nglobal using Microsoft.AspNetCore.Mvc;\nglobal using Microsoft.CodeAnalysis;\nglobal using Microsoft.EntityFrameworkCore;\nglobal using System.ComponentModel.DataAnnotations;\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u5fc5\u987b\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"strong"},"global")," \u5f00\u5934\uff01")),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u4e00\u822c\u63a8\u8350\u628a\u5b9e\u4f53\u7c7b\u7684\u547d\u540d\u7a7a\u95f4\u4e5f\u653e\u8fdb\u53bb\uff0c\u56e0\u4e3a\u4ed3\u50a8 ",(0,a.kt)("inlineCode",{parentName:"p"},"IRepository")," \u4f7f\u7528\u7684\u9891\u7387\u975e\u5e38\u9ad8\u3002"),(0,a.kt)("p",{parentName:"admonition"},"\u53e6\u5916\u63a8\u8350\u5927\u5bb6\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u4e2d\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"CodeMaid")," \u63d2\u4ef6\u54e6\uff0c\u81ea\u52a8\u6e05\u7406\u89e3\u51b3\u65b9\u6848\u6240\u6709\u65e0\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using"),"\uff0c\u7ed3\u5408 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u975e\u5e38\u68d2\uff01")),(0,a.kt)("admonition",{title:"\u4e2a\u522b\u60c5\u51b5",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u53ef\u80fd\u7531\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u7248\u672c\u7684\u95ee\u9898\uff0c\u5bfc\u81f4 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u5b9a\u4e49\u51fa\u9519\uff0c\u8fd9\u65f6\u5019\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u540e\u9762\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"global::"),"\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"global using global::Furion;\n"))),(0,a.kt)("p",null,"\u63a5\u4e0b\u6765\u5728\u4ee3\u7801\u4e2d\u4f7f\u7528\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},"// \u65e0\u9700 using Furion \u7684\u547d\u540d\u7a7a\u95f4\u4e86\u54e6\uff0c\u6e05\u723d\u4e86\u4e0d\u5c11\n\nnamespace Your.Application;\n\npublic class DefaultAppService : IDynamicApiController\n{\n private readonly IRepository _boardCardRepository;\n private readonly IRepository _boardGroupRepository;\n private readonly IRepository _boardCardAttachmentRepository;\n private readonly IRepository _boardCardUserRepository;\n}\n\n// ....\n")),(0,a.kt)("img",{src:(0,i.Z)("img/cd2223.png")}),(0,a.kt)("h3",{id:"\u9ed8\u8ba4\u5168\u5c40-using"},"\u9ed8\u8ba4\u5168\u5c40 ",(0,a.kt)("inlineCode",{parentName:"h3"},"using")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u5b9e\u9645\u4e0a\u5fae\u8f6f\u5df2\u7ecf\u81ea\u52a8\u628a\u4e00\u4e9b\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"using")," \u5728\u7f16\u8bd1\u540e\u7684\u4ee3\u7801\u4e2d\u81ea\u52a8\u8865\u4e0a\u4e86"),"\uff0c\u8def\u5f84\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u9879\u76ee/obj/Debug/net6.0/\u9879\u76ee.GlobalUsings.cs")," \u6587\u4ef6\u4e2d\uff0c\u6587\u4ef6\u5185\u5bb9\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \nglobal using global::System;\nglobal using global::System.Collections.Generic;\nglobal using global::System.IO;\nglobal using global::System.Linq;\nglobal using global::System.Net.Http;\nglobal using global::System.Threading;\nglobal using global::System.Threading.Tasks;\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u4e5f\u5c31\u662f\u4ee5\u4e0a\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"using")," \u65e0\u9700\u5199\u5728\u4f60\u521b\u5efa\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"GlobalUsings.cs")," \u4e2d\u4e86\uff0c\u5fae\u8f6f\u4f1a\u5728\u7f16\u8bd1\u65f6\u81ea\u52a8\u5408\u5e76\u3002")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/2529.ad701460.js b/handbook/build/assets/js/2529.ad701460.js new file mode 100644 index 0000000000..9cfd44a09f --- /dev/null +++ b/handbook/build/assets/js/2529.ad701460.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[2529],{3905:function(e,t,r){r.d(t,{Zo:function(){return s},kt:function(){return f}});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),m=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},s=function(e){var t=m(e.components);return n.createElement(c.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,l=e.originalType,c=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=m(r),f=a,g=d["".concat(c,".").concat(f)]||d[f]||u[f]||l;return r?n.createElement(g,i(i({ref:t},s),{},{components:r})):n.createElement(g,i({ref:t},s))}));function f(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=r.length,i=new Array(l);i[0]=d;var o={};for(var c in t)hasOwnProperty.call(t,c)&&(o[c]=t[c]);o.originalType=e,o.mdxType="string"==typeof e?e:a,i[1]=o;for(var m=2;m0;return a.createElement(i.Z,c,a.createElement("div",{className:"container margin-vert--lg"},a.createElement("div",{className:"row"},a.createElement(P,{sidebar:t}),a.createElement("main",{className:(0,l.Z)("col",{"col--7":m,"col--9 col--offset-1":!m}),itemScope:!0,itemType:"http://schema.org/Blog"},o),r&&a.createElement("div",{className:"col col--2"},r))))}},390:function(e,t,r){r.d(t,{Z:function(){return R}});var n=r(7294),a=r(4334),l=r(9460),i=r(4996);function o(e){var t,r=e.children,a=e.className,o=(0,l.C)(),c=o.frontMatter,m=o.assets,s=(0,i.C)().withBaseUrl,u=null!=(t=m.image)?t:c.image;return n.createElement("article",{className:a,itemProp:"blogPost",itemScope:!0,itemType:"http://schema.org/BlogPosting"},u&&n.createElement("meta",{itemProp:"image",content:s(u,{absolute:!0})}),r)}var c=r(9960),m="title_f1Hy";function s(e){var t=e.className,r=(0,l.C)(),i=r.metadata,o=r.isBlogPostPage,s=i.permalink,u=i.title,d=o?"h1":"h2";return n.createElement(d,{className:(0,a.Z)(m,t),itemProp:"headline"},o?u:n.createElement(c.Z,{itemProp:"url",to:s},u))}var u=r(5999),d=r(8824),f="container_mt6G";function g(e){var t,r=e.readingTime,a=(t=(0,d.c)().selectMessage,function(e){var r=Math.ceil(e);return t(r,(0,u.I)({id:"theme.blog.post.readingTime.plurals",description:'Pluralized label for "{readingTime} min read". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',message:"One min read|{readingTime} min read"},{readingTime:r}))});return n.createElement(n.Fragment,null,a(r))}function p(e){var t=e.date,r=e.formattedDate;return n.createElement("time",{dateTime:t,itemProp:"datePublished"},r)}function v(){return n.createElement(n.Fragment,null," \xb7 ")}function h(e){var t=e.className,r=(0,l.C)().metadata,i=r.date,o=r.formattedDate,c=r.readingTime;return n.createElement("div",{className:(0,a.Z)(f,"margin-vert--md",t)},n.createElement(p,{date:i,formattedDate:o}),void 0!==c&&n.createElement(n.Fragment,null,n.createElement(v,null),n.createElement(g,{readingTime:c})))}function E(e){return e.href?n.createElement(c.Z,e):n.createElement(n.Fragment,null,e.children)}function b(e){var t=e.author,r=e.className,l=t.name,i=t.title,o=t.url,c=t.imageURL,m=t.email,s=o||m&&"mailto:"+m||void 0;return n.createElement("div",{className:(0,a.Z)("avatar margin-bottom--sm",r)},c&&n.createElement(E,{href:s,className:"avatar__photo-link"},n.createElement("img",{className:"avatar__photo",src:c,alt:l})),l&&n.createElement("div",{className:"avatar__intro",itemProp:"author",itemScope:!0,itemType:"https://schema.org/Person"},n.createElement("div",{className:"avatar__name"},n.createElement(E,{href:s,itemProp:"url"},n.createElement("span",{itemProp:"name"},l))),i&&n.createElement("small",{className:"avatar__subtitle",itemProp:"description"},i)))}var P="authorCol_Hf19",N="imageOnlyAuthorRow_pa_O",Z="imageOnlyAuthorCol_G86a";function _(e){var t=e.className,r=(0,l.C)(),i=r.metadata.authors,o=r.assets;if(0===i.length)return null;var c=i.every((function(e){return!e.name}));return n.createElement("div",{className:(0,a.Z)("margin-top--md margin-bottom--sm",c?N:"row",t)},i.map((function(e,t){var r;return n.createElement("div",{className:(0,a.Z)(!c&&"col col--6",c?Z:P),key:t},n.createElement(b,{author:Object.assign({},e,{imageURL:null!=(r=o.authorsImageUrls[t])?r:e.imageURL})}))})))}function y(){return n.createElement("header",null,n.createElement(s,null),n.createElement(h,null),n.createElement(_,null))}var k=r(8780),O=r(5042);function w(e){var t=e.children,r=e.className,i=(0,l.C)().isBlogPostPage;return n.createElement("div",{id:i?k.blogPostContainerID:void 0,className:(0,a.Z)("markdown",r),itemProp:"articleBody"},n.createElement(O.Z,null,t))}var T=r(4881),C=r(1526),x=r(3117),j=r(102),F=["blogPostTitle"];function B(){return n.createElement("b",null,n.createElement(u.Z,{id:"theme.blog.post.readMore",description:"The label used in blog post item excerpts to link to full blog posts"},"Read More"))}function I(e){var t=e.blogPostTitle,r=(0,j.Z)(e,F);return n.createElement(c.Z,(0,x.Z)({"aria-label":(0,u.I)({message:"Read more about {title}",id:"theme.blog.post.readMoreLabel",description:"The ARIA label for the link to full blog posts from excerpts"},{title:t})},r),n.createElement(B,null))}var L="blogPostFooterDetailsFull_mRVl";function M(){var e=(0,l.C)(),t=e.metadata,r=e.isBlogPostPage,i=t.tags,o=t.title,c=t.editUrl,m=t.hasTruncateMarker,s=!r&&m,u=i.length>0;return u||s||c?n.createElement("footer",{className:(0,a.Z)("row docusaurus-mt-lg",r&&L)},u&&n.createElement("div",{className:(0,a.Z)("col",{"col--9":s})},n.createElement(C.Z,{tags:i})),r&&c&&n.createElement("div",{className:"col margin-top--sm"},n.createElement(T.Z,{editUrl:c})),s&&n.createElement("div",{className:(0,a.Z)("col text--right",{"col--3":u})},n.createElement(I,{blogPostTitle:o,to:t.permalink}))):null}function R(e){var t=e.children,r=e.className,i=(0,l.C)().isBlogPostPage?void 0:"margin-bottom--xl";return n.createElement(o,{className:(0,a.Z)(i,r)},n.createElement(y,null),n.createElement(w,null,t),n.createElement(M,null))}},4881:function(e,t,r){r.d(t,{Z:function(){return d}});var n=r(7294),a=r(5999),l=r(5281),i=r(3117),o=r(102),c=r(4334),m="iconEdit_Z9Sw",s=["className"];function u(e){var t=e.className,r=(0,o.Z)(e,s);return n.createElement("svg",(0,i.Z)({fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,c.Z)(m,t),"aria-hidden":"true"},r),n.createElement("g",null,n.createElement("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})))}function d(e){var t=e.editUrl;return n.createElement("a",{href:t,target:"_blank",rel:"noreferrer noopener",className:l.k.common.editThisPage},n.createElement(u,null),n.createElement(a.Z,{id:"theme.common.editThisPage",description:"The link label to edit the current page"},"Edit this page"))}},5042:function(e,t,r){r.d(t,{Z:function(){return i}});var n=r(7294),a=r(3905),l=r(1414);function i(e){var t=e.children;return n.createElement(a.Zo,{components:l.Z},t)}},2244:function(e,t,r){r.d(t,{Z:function(){return i}});var n=r(7294),a=r(4334),l=r(9960);function i(e){var t=e.permalink,r=e.title,i=e.subLabel,o=e.isNext;return n.createElement(l.Z,{className:(0,a.Z)("pagination-nav__link",o?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t},i&&n.createElement("div",{className:"pagination-nav__sublabel"},i),n.createElement("div",{className:"pagination-nav__label"},r))}},3008:function(e,t,r){r.d(t,{Z:function(){return m}});var n=r(7294),a=r(4334),l=r(9960),i="tag_zVej",o="tagRegular_sFm0",c="tagWithCount_h2kH";function m(e){var t=e.permalink,r=e.label,m=e.count;return n.createElement(l.Z,{href:t,className:(0,a.Z)(i,m?c:o)},r,m&&n.createElement("span",null,m))}},1526:function(e,t,r){r.d(t,{Z:function(){return m}});var n=r(7294),a=r(4334),l=r(5999),i=r(3008),o="tags_jXut",c="tag_QGVx";function m(e){var t=e.tags;return n.createElement(n.Fragment,null,n.createElement("b",null,n.createElement(l.Z,{id:"theme.tags.tagsListLabel",description:"The label alongside a tag list"},"Tags:")),n.createElement("ul",{className:(0,a.Z)(o,"padding--none","margin-left--sm")},t.map((function(e){var t=e.label,r=e.permalink;return n.createElement("li",{key:r,className:c},n.createElement(i.Z,{label:t,permalink:r}))}))))}},9460:function(e,t,r){r.d(t,{C:function(){return o},n:function(){return i}});var n=r(7294),a=r(4700),l=n.createContext(null);function i(e){var t=e.children,r=e.content,a=e.isBlogPostPage,i=function(e){var t=e.content,r=e.isBlogPostPage;return(0,n.useMemo)((function(){return{metadata:t.metadata,frontMatter:t.frontMatter,assets:t.assets,toc:t.toc,isBlogPostPage:r}}),[t,r])}({content:r,isBlogPostPage:void 0!==a&&a});return n.createElement(l.Provider,{value:i},t)}function o(){var e=(0,n.useContext)(l);if(null===e)throw new a.i6("BlogPostProvider");return e}},8824:function(e,t,r){r.d(t,{c:function(){return m}});var n=r(7294),a=r(2263),l=["zero","one","two","few","many","other"];function i(e){return l.filter((function(t){return e.includes(t)}))}var o={locale:"en",pluralForms:i(["one","other"]),select:function(e){return 1===e?"one":"other"}};function c(){var e=(0,a.Z)().i18n.currentLocale;return(0,n.useMemo)((function(){try{return t=e,r=new Intl.PluralRules(t),{locale:t,pluralForms:i(r.resolvedOptions().pluralCategories),select:function(e){return r.select(e)}}}catch(n){return console.error('Failed to use Intl.PluralRules for locale "'+e+'".\nDocusaurus will fallback to the default (English) implementation.\nError: '+n.message+"\n"),o}var t,r}),[e])}function m(){var e=c();return{selectMessage:function(t,r){return function(e,t,r){var n=e.split("|");if(1===n.length)return n[0];n.length>r.pluralForms.length&&console.error("For locale="+r.locale+", a maximum of "+r.pluralForms.length+" plural forms are expected ("+r.pluralForms.join(",")+"), but the message contains "+n.length+": "+e);var a=r.select(t),l=r.pluralForms.indexOf(a);return n[Math.min(l,n.length-1)]}(r,t,e)}}}}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/26682ccc.1fee17ed.js b/handbook/build/assets/js/26682ccc.1fee17ed.js new file mode 100644 index 0000000000..99b8c08c55 --- /dev/null +++ b/handbook/build/assets/js/26682ccc.1fee17ed.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4821],{3905:function(e,n,r){r.d(n,{Zo:function(){return l},kt:function(){return m}});var t=r(7294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function s(e){for(var n=1;n=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var u=t.createContext({}),p=function(e){var n=t.useContext(u),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},l=function(e){var n=p(e.components);return t.createElement(u.Provider,{value:n},e.children)},y={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},c=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,i=e.originalType,u=e.parentName,l=o(e,["components","mdxType","originalType","parentName"]),c=p(r),m=a,d=c["".concat(u,".").concat(m)]||c[m]||y[m]||i;return r?t.createElement(d,s(s({ref:n},l),{},{components:r})):t.createElement(d,s({ref:n},l))}));function m(e,n){var r=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=r.length,s=new Array(i);s[0]=c;var o={};for(var u in n)hasOwnProperty.call(n,u)&&(o[u]=n[u]);o.originalType=e,o.mdxType="string"==typeof e?e:a,s[1]=o;for(var p=2;pCase When",id:"91069-case-when",level:3},{value:"9.10.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9107-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:y};function m(e){var n=e.components,r=(0,a.Z)(e,s);return(0,i.kt)("wrapper",(0,t.Z)({},c,r,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"9101-\u6839\u636e\u4e3b\u952e\u67e5\u8be2\u4e00\u6761"},"9.10.1 \u6839\u636e\u4e3b\u952e\u67e5\u8be2\u4e00\u6761"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar person = repository.Find(1);\n\n// \u793a\u4f8b\u4e8c\nvar person = repository.FindOrDefault(1);\n\n// \u793a\u4f8b\u4e09\nvar person = repository.Entities.Find(1);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar person = await repository.FindAsync(1);\n\n// \u793a\u4f8b\u4e8c\nvar person = await repository.FindOrDefaultAsync(1);\n\n// \u793a\u4f8b\u4e09\nvar person = await repository.Entities.FindAsync(1);\n\n")),(0,i.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u53ef\u4ee5\u652f\u6301\u591a\u4e2a\u952e\u67e5\u8be2\uff0c\u5982\u4e3b\u952e\u3001\u8054\u5408\u952e\u3002",(0,i.kt)("inlineCode",{parentName:"p"},'repository.Find(1, "\u767e\u5c0f\u50e7")'),";")),(0,i.kt)("h2",{id:"9102-\u6839\u636e\u6761\u4ef6\u67e5\u8be2\u4e00\u6761"},"9.10.2 \u6839\u636e\u6761\u4ef6\u67e5\u8be2\u4e00\u6761"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar person = repository.Single(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e8c\nvar person = repository.SingleOrDefault(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e09\nvar person = repository.First(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u56db\nvar person = repository.FirstOrDefault(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e94\nvar person = repository.Last(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u516d\nvar person = repository.LastOrDefault(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e03\nvar person = repository.Entities.Single(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u516b\nvar person = repository.Entities.First(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e5d\nvar person = repository.Entities.FirstOrDefault(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u5341\nvar person = repository.Entities.Last(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u5341\u4e00\nvar person = repository.Entities.LastOrDefault(u => u.Name == "Furion");\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar person = await repository.SingleAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e8c\nvar person = await repository.SingleOrDefaultAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e09\nvar person = await repository.FirstAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u56db\nvar person = await repository.FirstOrDefaultAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e94\nvar person = await repository.LastAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u516d\nvar person = await repository.LastOrDefaultAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e03\nvar person = await repository.Entities.SingleAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u516b\nvar person = await repository.Entities.FirstAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e5d\nvar person = await repository.Entities.FirstOrDefaultAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u5341\nvar person = await repository.Entities.LastAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u5341\u4e00\nvar person = await repository.Entities.LastOrDefaultAsync(u => u.Name == "Furion");\n')),(0,i.kt)("h2",{id:"9103-\u67e5\u8be2\u6240\u6709\u6570\u636e"},"9.10.3 \u67e5\u8be2\u6240\u6709\u6570\u636e"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = repository.Entities;\n\n// \u793a\u4f8b\u4e8c\nvar persons = repository.DetachedEntities;\n\n// \u793a\u4f8b\u4e09\nvar persons = repository.AsQueryable();\n\n// \u793a\u4f8b\u56db\nvar persons = repository.AsEnumerable();\n\n// \u793a\u4f8b\u4e94\nvar persons = await repository.AsQueryable().ToListAsync();\n")),(0,i.kt)("h2",{id:"9104-\u6839\u636e\u6761\u4ef6\u67e5\u8be2\u6240\u6709\u6570\u636e"},"9.10.4 \u6839\u636e\u6761\u4ef6\u67e5\u8be2\u6240\u6709\u6570\u636e"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u793a\u4f8b\u4e00\nvar persons = repository.Where(u => u.Id > 10);\n\n// \u793a\u4f8b\u4e8c\nvar persons = repository.Where(u => u.Id > 10 && u.Name.Equals("Furion"));\n\n// \u793a\u4f8b\u4e09 (\u591a\u4e2a where \u91cc\u662f "\u5e76\u4e14"\uff0cId>10 and Name == "Furion")\nvar persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"));\n\n// \u793a\u4f8b\u56db (\u5224\u65ad name \u662f\u5426\u6709\u503c\uff0c\u5982\u679c name \u662f\u7a7a\u7684\u5219\u4e0d\u4f1a\u6267\u884c u => u.Id > 10 && u.Name.Equals("Furion")\uff0c\u5982\u679c name \u6709\u503c\u5c31\u4f1a\u6267\u884c u => u.Id > 10 && u.Name.Equals("Furion"))\nvar persons = repository.Where(!string.IsNullOrEmpty(name), u => u.Id > 10 && u.Name.Equals("Furion"));\n\n// \u793a\u4f8b\u4e94\nvar persons = repository.Where(!string.IsNullOrEmpty(name), u => u.Id > 10)\n .Where(age > 18, u => u.Name.Contains("\u767e\u5c0f\u50e7"))\n .Where(u => u.Age > 18);\n\n// \u793a\u4f8b\u516d (\u5728\u4e00\u4e2a where \u91cc\u7528\u9017\u53f7\u5206\u9694\u662f "\u6216\u8005"\uff0cName=="Furion" or Name == "\u767e\u5c0f\u50e7" or Name == "MonkSoul")\nvar persons = repository.Where(u => u.Name == "Furion",\n u => u.Name == "\u767e\u5c0f\u50e7",\n u => u.Name == "MonkSoul");\n\n// \u793a\u4f8b\u4e03\nvar persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"))\n .Where(age > 18, u => u.Name.Contains("\u767e\u5c0f\u50e7"))\n .Where(u => u.Name == "Furion",\n u => u.Name == "\u767e\u5c0f\u50e7",\n u => u.Name == "MonkSoul");\n\n// \u793a\u4f8b\u516b\nvar persons = repository.Where((age > 18, u => u.Name == "Furion"),\n (!string.IsNullOrEmpty(name), u => u.Id > 10));\n\n// \u793a\u4f8b\u4e5d\nvar persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"))\n .Where(age > 18, u => u.Name.Contains("\u767e\u5c0f\u50e7"))\n .Where(u => u.Name == "Furion",\n u => u.Name == "\u767e\u5c0f\u50e7",\n u => u.Name == "MonkSoul")\n .Where((age > 18, u => u.Name == "Furion"),\n (!string.IsNullOrEmpty(name), u => u.Id > 10));\n\n// \u793a\u4f8b\u5341\nvar persons = repository.Entities.Where(u => u.Id > 10)\n .Where(age > 18, u => u.Name.Contains("\u767e\u5c0f\u50e7"));\n\n// \u793a\u4f8b\u5341\u4e00\nvar persons = repository.DetachedEntities.Where(u => u.Id > 20);\n\n// \u793a\u4f8b\u5341\u4e8c\nvar persons = repository.AsQueryable(u => u.Id > 20).Where(u => u.Name == "Furion");\n')),(0,i.kt)("h2",{id:"9105-\u5206\u9875\u67e5\u8be2"},"9.10.5 \u5206\u9875\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = repository.Where(u => u.Id > 10).ToPagedList();\n\n// \u793a\u4f8b\u4e8c\nvar persons = repository.Where(u => u.Id > 10).ToPagedList(1, 10);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = await repository.Where(u => u.Id > 10).ToPagedListAsync();\n\n// \u793a\u4f8b\u4e8c\nvar persons = await repository.Where(u => u.Id > 10).ToPagedListAsync(1, 10);\n")),(0,i.kt)("h2",{id:"9106-\u5176\u4ed6\u67e5\u8be2"},"9.10.6 \u5176\u4ed6\u67e5\u8be2"),(0,i.kt)("h3",{id:"91061-\u67e5\u770b\u8bb0\u5f55\u662f\u5426\u5b58\u5728"},"9.10.6.1 \u67e5\u770b\u8bb0\u5f55\u662f\u5426\u5b58\u5728"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar isExists = repository.Any();\n\n// \u793a\u4f8b\u4e8c\nvar isExists = repository.Any(u => u.Id > 10);\n\n// \u793a\u4f8b\u4e09\nvar isExists = repository.Entities.Any();\n\n// \u793a\u4f8b\u56db\nvar isExists = repository.DetachedEntities.Any(u => u.Id > 10);\n\n// \u793a\u4f8b\u4e94\nvar isExists = repository.Where(u => u.Id > 10).Any();\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar isExists = await repository.AnyAsync();\n\n// \u793a\u4f8b\u4e8c\nvar isExists = await repository.AnyAsync(u => u.Id > 10);\n\n// \u793a\u4f8b\u4e09\nvar isExists = await repository.Entities.AnyAsync();\n\n// \u793a\u4f8b\u56db\nvar isExists = await repository.DetachedEntities.AnyAsync(u => u.Id > 10);\n\n// \u793a\u4f8b\u4e94\nvar isExists = await repository.Where(u => u.Id > 10).AnyAsync();\n")),(0,i.kt)("h3",{id:"91062-\u67e5\u8be2\u8bb0\u5f55\u6570"},"9.10.6.2 \u67e5\u8be2\u8bb0\u5f55\u6570"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar count = repository.Count();\n\n// \u793a\u4f8b\u4e8c\nvar count = repository.Count(u => u.Id > 10);\n\n// \u793a\u4f8b\u4e09\nvar count = repository.Entities.Count(u => u.Id > 10);\n\n// \u793a\u4f8b\u56db\nvar count = repository.Entities.DetachedEntities.Count();\n\n// \u793a\u4f8b\u4e94\nvar count = repository.Where(u => u.Id > 10).Count();\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar count = await repository.CountAsync();\n\n// \u793a\u4f8b\u4e8c\nvar count = await repository.CountAsync(u => u.Id > 10);\n\n// \u793a\u4f8b\u4e09\nvar count = await repository.Entities.CountAsync(u => u.Id > 10);\n\n// \u793a\u4f8b\u56db\nvar count = await repository.Entities.DetachedEntities.CountAsync();\n\n// \u793a\u4f8b\u4e94\nvar count = await repository.Where(u => u.Id > 10).CountAsync();\n")),(0,i.kt)("h3",{id:"91063-\u67e5\u8be2\u6700\u5927\u503c"},"9.10.6.3 \u67e5\u8be2\u6700\u5927\u503c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar entity = repository.Max();\n\n// \u793a\u4f8b\u4e8c\nvar value = repository.Max(u => u.Id);\n\n// \u793a\u4f8b\u4e09\nvar entity = repository.Entities.Max();\n\n// \u793a\u4f8b\u56db\nvar value = repository.Entities.DetachedEntities.Max(u => u.Age);\n\n// \u793a\u4f8b\u4e94\nvar value = repository.Where(u => u.Id > 10).Max(u => u.Age);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar entity = await repository.MaxAsync();\n\n// \u793a\u4f8b\u4e8c\nvar value = await repository.MaxAsync(u => u.Id);\n\n// \u793a\u4f8b\u4e09\nvar entity = await repository.Entities.MaxAsync();\n\n// \u793a\u4f8b\u56db\nvar value = await repository.Entities.DetachedEntities.MaxAsync(u => u.Age);\n\n// \u793a\u4f8b\u4e94\nvar value = await repository.Where(u => u.Id > 10).MaxAsync(u => u.Age);\n")),(0,i.kt)("h3",{id:"91064-\u67e5\u8be2\u6700\u5c0f\u503c"},"9.10.6.4 \u67e5\u8be2\u6700\u5c0f\u503c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar entity = repository.Min();\n\n// \u793a\u4f8b\u4e8c\nvar value = repository.Min(u => u.Id);\n\n// \u793a\u4f8b\u4e09\nvar entity = repository.Entities.Min();\n\n// \u793a\u4f8b\u56db\nvar value = repository.Entities.DetachedEntities.Min(u => u.Age);\n\n// \u793a\u4f8b\u4e94\nvar value = repository.Where(u => u.Id > 10).Min(u => u.Age);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar entity = await repository.MinAsync();\n\n// \u793a\u4f8b\u4e8c\nvar value = await repository.MinAsync(u => u.Id);\n\n// \u793a\u4f8b\u4e09\nvar entity = await repository.Entities.MinAsync();\n\n// \u793a\u4f8b\u56db\nvar value = await repository.Entities.DetachedEntities.MinAsync(u => u.Age);\n\n// \u793a\u4f8b\u4e94\nvar value = await repository.Where(u => u.Id > 10).MinAsync(u => u.Age);\n")),(0,i.kt)("h3",{id:"91065-\u6c42\u548c\u67e5\u8be2"},"9.10.6.5 \u6c42\u548c\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar sum = repository.Entities.Sum(u => u.Cost);\n\n// \u793a\u4f8b\u4e8c\nvar sum = repository.AsQueryable().Sum(u => u.Cost);\n\n// \u793a\u4f8b\u4e09\nvar sum = repository.DetachedEntities.Sum(u => u.Cost);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar sum = await repository.Entities.SumAsync(u => u.Cost);\n\n// \u793a\u4f8b\u4e8c\nvar sum = await repository.AsQueryable().SumAsync(u => u.Cost);\n\n// \u793a\u4f8b\u4e09\nvar sum = await repository.DetachedEntities.SumAsync(u => u.Cost);\n")),(0,i.kt)("h3",{id:"91066-\u6c42\u5e73\u5747\u503c\u67e5\u8be2"},"9.10.6.6 \u6c42\u5e73\u5747\u503c\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar sum = repository.Entities.Average(u => u.Cost);\n\n// \u793a\u4f8b\u4e8c\nvar sum = repository.AsQueryable().Average(u => u.Cost);\n\n// \u793a\u4f8b\u4e09\nvar sum = repository.DetachedEntities.Average(u => u.Cost);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar sum = await repository.Entities.AverageAsync(u => u.Cost);\n\n// \u793a\u4f8b\u4e8c\nvar sum = await repository.AsQueryable().AverageAsync(u => u.Cost);\n\n// \u793a\u4f8b\u4e09\nvar sum = await repository.DetachedEntities.AverageAsync(u => u.Cost);\n")),(0,i.kt)("h3",{id:"91067-\u65f6\u95f4\u67e5\u8be2"},"9.10.6.7 \u65f6\u95f4\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var starDate = DateTime.Parse("2020-09-10");\nvar endDate = DateTime.Parse("2020-09-10");\nvar query = repository.Where(u => u.CreatedDt >= starDate && u.CreatedDt <= endDate);\n')),(0,i.kt)("h3",{id:"91068-\u6a21\u7cca\u67e5\u8be2"},"9.10.6.8 \u6a21\u7cca\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u793a\u4f8b\u4e00\nrepository.Where(u => u.Name.StartsWith("Furion"));\n\n// \u793a\u4f8b\u4e8c\n_testRepository.Where(u => u.Name.EndsWith("Furion"));\n\n// \u793a\u4f8b\u4e09\n_testRepository.Where(u => u.Name.Contains("Furion"));\n')),(0,i.kt)("h3",{id:"91069-case-when"},"9.10.6.9 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Case When")),(0,i.kt)("p",null,"\u6570\u636e\u5e93\u4e2d\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Case When")," \u5b9e\u9645\u4e0a\u5bf9\u5e94\u7684\u662f\u6211\u4eec\u7a0b\u5e8f\u4e2d\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u4e09\u5143\u8868\u8fbe\u5f0f")," \uff0c\u4e5f\u5c31\u662f\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u4e09\u5143\u8868\u8fbe\u5f0f")," \u5373\u53ef\u81ea\u52a8\u751f\u6210 ",(0,i.kt)("inlineCode",{parentName:"p"},"Case When")," \u8bed\u53e5\u3002"),(0,i.kt)("h2",{id:"9107-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.10.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/26682ccc.23223d4d.js b/handbook/build/assets/js/26682ccc.23223d4d.js deleted file mode 100644 index 7736d85950..0000000000 --- a/handbook/build/assets/js/26682ccc.23223d4d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4821],{4855:function(e,n,r){r.r(n),r.d(n,{assets:function(){return l},contentTitle:function(){return u},default:function(){return m},frontMatter:function(){return o},metadata:function(){return p},toc:function(){return y}});var t=r(3117),a=r(102),i=(r(7294),r(3905)),s=["components"],o={id:"dbcontext-query",title:"9.10 \u67e5\u8be2\u64cd\u4f5c",sidebar_label:"9.10 \u67e5\u8be2\u64cd\u4f5c"},u=void 0,p={unversionedId:"dbcontext-query",id:"dbcontext-query",title:"9.10 \u67e5\u8be2\u64cd\u4f5c",description:"9.10.1 \u6839\u636e\u4e3b\u952e\u67e5\u8be2\u4e00\u6761",source:"@site/docs/dbcontext-query.mdx",sourceDirName:".",slug:"/dbcontext-query",permalink:"/furion/docs/dbcontext-query",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-query.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"dbcontext-query",title:"9.10 \u67e5\u8be2\u64cd\u4f5c",sidebar_label:"9.10 \u67e5\u8be2\u64cd\u4f5c"},sidebar:"docs",previous:{title:"9.9 \u6279\u91cf\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-batch"},next:{title:"9.11 \u9ad8\u7ea7\u67e5\u8be2\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-hight-query"}},l={},y=[{value:"9.10.1 \u6839\u636e\u4e3b\u952e\u67e5\u8be2\u4e00\u6761",id:"9101-\u6839\u636e\u4e3b\u952e\u67e5\u8be2\u4e00\u6761",level:2},{value:"9.10.2 \u6839\u636e\u6761\u4ef6\u67e5\u8be2\u4e00\u6761",id:"9102-\u6839\u636e\u6761\u4ef6\u67e5\u8be2\u4e00\u6761",level:2},{value:"9.10.3 \u67e5\u8be2\u6240\u6709\u6570\u636e",id:"9103-\u67e5\u8be2\u6240\u6709\u6570\u636e",level:2},{value:"9.10.4 \u6839\u636e\u6761\u4ef6\u67e5\u8be2\u6240\u6709\u6570\u636e",id:"9104-\u6839\u636e\u6761\u4ef6\u67e5\u8be2\u6240\u6709\u6570\u636e",level:2},{value:"9.10.5 \u5206\u9875\u67e5\u8be2",id:"9105-\u5206\u9875\u67e5\u8be2",level:2},{value:"9.10.6 \u5176\u4ed6\u67e5\u8be2",id:"9106-\u5176\u4ed6\u67e5\u8be2",level:2},{value:"9.10.6.1 \u67e5\u770b\u8bb0\u5f55\u662f\u5426\u5b58\u5728",id:"91061-\u67e5\u770b\u8bb0\u5f55\u662f\u5426\u5b58\u5728",level:3},{value:"9.10.6.2 \u67e5\u8be2\u8bb0\u5f55\u6570",id:"91062-\u67e5\u8be2\u8bb0\u5f55\u6570",level:3},{value:"9.10.6.3 \u67e5\u8be2\u6700\u5927\u503c",id:"91063-\u67e5\u8be2\u6700\u5927\u503c",level:3},{value:"9.10.6.4 \u67e5\u8be2\u6700\u5c0f\u503c",id:"91064-\u67e5\u8be2\u6700\u5c0f\u503c",level:3},{value:"9.10.6.5 \u6c42\u548c\u67e5\u8be2",id:"91065-\u6c42\u548c\u67e5\u8be2",level:3},{value:"9.10.6.6 \u6c42\u5e73\u5747\u503c\u67e5\u8be2",id:"91066-\u6c42\u5e73\u5747\u503c\u67e5\u8be2",level:3},{value:"9.10.6.7 \u65f6\u95f4\u67e5\u8be2",id:"91067-\u65f6\u95f4\u67e5\u8be2",level:3},{value:"9.10.6.8 \u6a21\u7cca\u67e5\u8be2",id:"91068-\u6a21\u7cca\u67e5\u8be2",level:3},{value:"9.10.6.9 Case When",id:"91069-case-when",level:3},{value:"9.10.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9107-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:y};function m(e){var n=e.components,r=(0,a.Z)(e,s);return(0,i.kt)("wrapper",(0,t.Z)({},c,r,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"9101-\u6839\u636e\u4e3b\u952e\u67e5\u8be2\u4e00\u6761"},"9.10.1 \u6839\u636e\u4e3b\u952e\u67e5\u8be2\u4e00\u6761"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar person = repository.Find(1);\n\n// \u793a\u4f8b\u4e8c\nvar person = repository.FindOrDefault(1);\n\n// \u793a\u4f8b\u4e09\nvar person = repository.Entities.Find(1);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar person = await repository.FindAsync(1);\n\n// \u793a\u4f8b\u4e8c\nvar person = await repository.FindOrDefaultAsync(1);\n\n// \u793a\u4f8b\u4e09\nvar person = await repository.Entities.FindAsync(1);\n\n")),(0,i.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u53ef\u4ee5\u652f\u6301\u591a\u4e2a\u952e\u67e5\u8be2\uff0c\u5982\u4e3b\u952e\u3001\u8054\u5408\u952e\u3002",(0,i.kt)("inlineCode",{parentName:"p"},'repository.Find(1, "\u767e\u5c0f\u50e7")'),";")),(0,i.kt)("h2",{id:"9102-\u6839\u636e\u6761\u4ef6\u67e5\u8be2\u4e00\u6761"},"9.10.2 \u6839\u636e\u6761\u4ef6\u67e5\u8be2\u4e00\u6761"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar person = repository.Single(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e8c\nvar person = repository.SingleOrDefault(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e09\nvar person = repository.First(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u56db\nvar person = repository.FirstOrDefault(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e94\nvar person = repository.Last(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u516d\nvar person = repository.LastOrDefault(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e03\nvar person = repository.Entities.Single(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u516b\nvar person = repository.Entities.First(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e5d\nvar person = repository.Entities.FirstOrDefault(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u5341\nvar person = repository.Entities.Last(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u5341\u4e00\nvar person = repository.Entities.LastOrDefault(u => u.Name == "Furion");\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar person = await repository.SingleAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e8c\nvar person = await repository.SingleOrDefaultAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e09\nvar person = await repository.FirstAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u56db\nvar person = await repository.FirstOrDefaultAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e94\nvar person = await repository.LastAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u516d\nvar person = await repository.LastOrDefaultAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e03\nvar person = await repository.Entities.SingleAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u516b\nvar person = await repository.Entities.FirstAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u4e5d\nvar person = await repository.Entities.FirstOrDefaultAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u5341\nvar person = await repository.Entities.LastAsync(u => u.Name == "Furion");\n\n// \u793a\u4f8b\u5341\u4e00\nvar person = await repository.Entities.LastOrDefaultAsync(u => u.Name == "Furion");\n')),(0,i.kt)("h2",{id:"9103-\u67e5\u8be2\u6240\u6709\u6570\u636e"},"9.10.3 \u67e5\u8be2\u6240\u6709\u6570\u636e"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = repository.Entities;\n\n// \u793a\u4f8b\u4e8c\nvar persons = repository.DetachedEntities;\n\n// \u793a\u4f8b\u4e09\nvar persons = repository.AsQueryable();\n\n// \u793a\u4f8b\u56db\nvar persons = repository.AsEnumerable();\n\n// \u793a\u4f8b\u4e94\nvar persons = await repository.AsQueryable().ToListAsync();\n")),(0,i.kt)("h2",{id:"9104-\u6839\u636e\u6761\u4ef6\u67e5\u8be2\u6240\u6709\u6570\u636e"},"9.10.4 \u6839\u636e\u6761\u4ef6\u67e5\u8be2\u6240\u6709\u6570\u636e"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u793a\u4f8b\u4e00\nvar persons = repository.Where(u => u.Id > 10);\n\n// \u793a\u4f8b\u4e8c\nvar persons = repository.Where(u => u.Id > 10 && u.Name.Equals("Furion"));\n\n// \u793a\u4f8b\u4e09 (\u591a\u4e2a where \u91cc\u662f "\u5e76\u4e14"\uff0cId>10 and Name == "Furion")\nvar persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"));\n\n// \u793a\u4f8b\u56db (\u5224\u65ad name \u662f\u5426\u6709\u503c\uff0c\u5982\u679c name \u662f\u7a7a\u7684\u5219\u4e0d\u4f1a\u6267\u884c u => u.Id > 10 && u.Name.Equals("Furion")\uff0c\u5982\u679c name \u6709\u503c\u5c31\u4f1a\u6267\u884c u => u.Id > 10 && u.Name.Equals("Furion"))\nvar persons = repository.Where(!string.IsNullOrEmpty(name), u => u.Id > 10 && u.Name.Equals("Furion"));\n\n// \u793a\u4f8b\u4e94\nvar persons = repository.Where(!string.IsNullOrEmpty(name), u => u.Id > 10)\n .Where(age > 18, u => u.Name.Contains("\u767e\u5c0f\u50e7"))\n .Where(u => u.Age > 18);\n\n// \u793a\u4f8b\u516d (\u5728\u4e00\u4e2a where \u91cc\u7528\u9017\u53f7\u5206\u9694\u662f "\u6216\u8005"\uff0cName=="Furion" or Name == "\u767e\u5c0f\u50e7" or Name == "MonkSoul")\nvar persons = repository.Where(u => u.Name == "Furion",\n u => u.Name == "\u767e\u5c0f\u50e7",\n u => u.Name == "MonkSoul");\n\n// \u793a\u4f8b\u4e03\nvar persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"))\n .Where(age > 18, u => u.Name.Contains("\u767e\u5c0f\u50e7"))\n .Where(u => u.Name == "Furion",\n u => u.Name == "\u767e\u5c0f\u50e7",\n u => u.Name == "MonkSoul");\n\n// \u793a\u4f8b\u516b\nvar persons = repository.Where((age > 18, u => u.Name == "Furion"),\n (!string.IsNullOrEmpty(name), u => u.Id > 10));\n\n// \u793a\u4f8b\u4e5d\nvar persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"))\n .Where(age > 18, u => u.Name.Contains("\u767e\u5c0f\u50e7"))\n .Where(u => u.Name == "Furion",\n u => u.Name == "\u767e\u5c0f\u50e7",\n u => u.Name == "MonkSoul")\n .Where((age > 18, u => u.Name == "Furion"),\n (!string.IsNullOrEmpty(name), u => u.Id > 10));\n\n// \u793a\u4f8b\u5341\nvar persons = repository.Entities.Where(u => u.Id > 10)\n .Where(age > 18, u => u.Name.Contains("\u767e\u5c0f\u50e7"));\n\n// \u793a\u4f8b\u5341\u4e00\nvar persons = repository.DetachedEntities.Where(u => u.Id > 20);\n\n// \u793a\u4f8b\u5341\u4e8c\nvar persons = repository.AsQueryable(u => u.Id > 20).Where(u => u.Name == "Furion");\n')),(0,i.kt)("h2",{id:"9105-\u5206\u9875\u67e5\u8be2"},"9.10.5 \u5206\u9875\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = repository.Where(u => u.Id > 10).ToPagedList();\n\n// \u793a\u4f8b\u4e8c\nvar persons = repository.Where(u => u.Id > 10).ToPagedList(1, 10);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = await repository.Where(u => u.Id > 10).ToPagedListAsync();\n\n// \u793a\u4f8b\u4e8c\nvar persons = await repository.Where(u => u.Id > 10).ToPagedListAsync(1, 10);\n")),(0,i.kt)("h2",{id:"9106-\u5176\u4ed6\u67e5\u8be2"},"9.10.6 \u5176\u4ed6\u67e5\u8be2"),(0,i.kt)("h3",{id:"91061-\u67e5\u770b\u8bb0\u5f55\u662f\u5426\u5b58\u5728"},"9.10.6.1 \u67e5\u770b\u8bb0\u5f55\u662f\u5426\u5b58\u5728"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar isExists = repository.Any();\n\n// \u793a\u4f8b\u4e8c\nvar isExists = repository.Any(u => u.Id > 10);\n\n// \u793a\u4f8b\u4e09\nvar isExists = repository.Entities.Any();\n\n// \u793a\u4f8b\u56db\nvar isExists = repository.DetachedEntities.Any(u => u.Id > 10);\n\n// \u793a\u4f8b\u4e94\nvar isExists = repository.Where(u => u.Id > 10).Any();\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar isExists = await repository.AnyAsync();\n\n// \u793a\u4f8b\u4e8c\nvar isExists = await repository.AnyAsync(u => u.Id > 10);\n\n// \u793a\u4f8b\u4e09\nvar isExists = await repository.Entities.AnyAsync();\n\n// \u793a\u4f8b\u56db\nvar isExists = await repository.DetachedEntities.AnyAsync(u => u.Id > 10);\n\n// \u793a\u4f8b\u4e94\nvar isExists = await repository.Where(u => u.Id > 10).AnyAsync();\n")),(0,i.kt)("h3",{id:"91062-\u67e5\u8be2\u8bb0\u5f55\u6570"},"9.10.6.2 \u67e5\u8be2\u8bb0\u5f55\u6570"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar count = repository.Count();\n\n// \u793a\u4f8b\u4e8c\nvar count = repository.Count(u => u.Id > 10);\n\n// \u793a\u4f8b\u4e09\nvar count = repository.Entities.Count(u => u.Id > 10);\n\n// \u793a\u4f8b\u56db\nvar count = repository.Entities.DetachedEntities.Count();\n\n// \u793a\u4f8b\u4e94\nvar count = repository.Where(u => u.Id > 10).Count();\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar count = await repository.CountAsync();\n\n// \u793a\u4f8b\u4e8c\nvar count = await repository.CountAsync(u => u.Id > 10);\n\n// \u793a\u4f8b\u4e09\nvar count = await repository.Entities.CountAsync(u => u.Id > 10);\n\n// \u793a\u4f8b\u56db\nvar count = await repository.Entities.DetachedEntities.CountAsync();\n\n// \u793a\u4f8b\u4e94\nvar count = await repository.Where(u => u.Id > 10).CountAsync();\n")),(0,i.kt)("h3",{id:"91063-\u67e5\u8be2\u6700\u5927\u503c"},"9.10.6.3 \u67e5\u8be2\u6700\u5927\u503c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar entity = repository.Max();\n\n// \u793a\u4f8b\u4e8c\nvar value = repository.Max(u => u.Id);\n\n// \u793a\u4f8b\u4e09\nvar entity = repository.Entities.Max();\n\n// \u793a\u4f8b\u56db\nvar value = repository.Entities.DetachedEntities.Max(u => u.Age);\n\n// \u793a\u4f8b\u4e94\nvar value = repository.Where(u => u.Id > 10).Max(u => u.Age);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar entity = await repository.MaxAsync();\n\n// \u793a\u4f8b\u4e8c\nvar value = await repository.MaxAsync(u => u.Id);\n\n// \u793a\u4f8b\u4e09\nvar entity = await repository.Entities.MaxAsync();\n\n// \u793a\u4f8b\u56db\nvar value = await repository.Entities.DetachedEntities.MaxAsync(u => u.Age);\n\n// \u793a\u4f8b\u4e94\nvar value = await repository.Where(u => u.Id > 10).MaxAsync(u => u.Age);\n")),(0,i.kt)("h3",{id:"91064-\u67e5\u8be2\u6700\u5c0f\u503c"},"9.10.6.4 \u67e5\u8be2\u6700\u5c0f\u503c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar entity = repository.Min();\n\n// \u793a\u4f8b\u4e8c\nvar value = repository.Min(u => u.Id);\n\n// \u793a\u4f8b\u4e09\nvar entity = repository.Entities.Min();\n\n// \u793a\u4f8b\u56db\nvar value = repository.Entities.DetachedEntities.Min(u => u.Age);\n\n// \u793a\u4f8b\u4e94\nvar value = repository.Where(u => u.Id > 10).Min(u => u.Age);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar entity = await repository.MinAsync();\n\n// \u793a\u4f8b\u4e8c\nvar value = await repository.MinAsync(u => u.Id);\n\n// \u793a\u4f8b\u4e09\nvar entity = await repository.Entities.MinAsync();\n\n// \u793a\u4f8b\u56db\nvar value = await repository.Entities.DetachedEntities.MinAsync(u => u.Age);\n\n// \u793a\u4f8b\u4e94\nvar value = await repository.Where(u => u.Id > 10).MinAsync(u => u.Age);\n")),(0,i.kt)("h3",{id:"91065-\u6c42\u548c\u67e5\u8be2"},"9.10.6.5 \u6c42\u548c\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar sum = repository.Entities.Sum(u => u.Cost);\n\n// \u793a\u4f8b\u4e8c\nvar sum = repository.AsQueryable().Sum(u => u.Cost);\n\n// \u793a\u4f8b\u4e09\nvar sum = repository.DetachedEntities.Sum(u => u.Cost);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar sum = await repository.Entities.SumAsync(u => u.Cost);\n\n// \u793a\u4f8b\u4e8c\nvar sum = await repository.AsQueryable().SumAsync(u => u.Cost);\n\n// \u793a\u4f8b\u4e09\nvar sum = await repository.DetachedEntities.SumAsync(u => u.Cost);\n")),(0,i.kt)("h3",{id:"91066-\u6c42\u5e73\u5747\u503c\u67e5\u8be2"},"9.10.6.6 \u6c42\u5e73\u5747\u503c\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar sum = repository.Entities.Average(u => u.Cost);\n\n// \u793a\u4f8b\u4e8c\nvar sum = repository.AsQueryable().Average(u => u.Cost);\n\n// \u793a\u4f8b\u4e09\nvar sum = repository.DetachedEntities.Average(u => u.Cost);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar sum = await repository.Entities.AverageAsync(u => u.Cost);\n\n// \u793a\u4f8b\u4e8c\nvar sum = await repository.AsQueryable().AverageAsync(u => u.Cost);\n\n// \u793a\u4f8b\u4e09\nvar sum = await repository.DetachedEntities.AverageAsync(u => u.Cost);\n")),(0,i.kt)("h3",{id:"91067-\u65f6\u95f4\u67e5\u8be2"},"9.10.6.7 \u65f6\u95f4\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var starDate = DateTime.Parse("2020-09-10");\nvar endDate = DateTime.Parse("2020-09-10");\nvar query = repository.Where(u => u.CreatedDt >= starDate && u.CreatedDt <= endDate);\n')),(0,i.kt)("h3",{id:"91068-\u6a21\u7cca\u67e5\u8be2"},"9.10.6.8 \u6a21\u7cca\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u793a\u4f8b\u4e00\nrepository.Where(u => u.Name.StartsWith("Furion"));\n\n// \u793a\u4f8b\u4e8c\n_testRepository.Where(u => u.Name.EndsWith("Furion"));\n\n// \u793a\u4f8b\u4e09\n_testRepository.Where(u => u.Name.Contains("Furion"));\n')),(0,i.kt)("h3",{id:"91069-case-when"},"9.10.6.9 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Case When")),(0,i.kt)("p",null,"\u6570\u636e\u5e93\u4e2d\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Case When")," \u5b9e\u9645\u4e0a\u5bf9\u5e94\u7684\u662f\u6211\u4eec\u7a0b\u5e8f\u4e2d\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u4e09\u5143\u8868\u8fbe\u5f0f")," \uff0c\u4e5f\u5c31\u662f\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u4e09\u5143\u8868\u8fbe\u5f0f")," \u5373\u53ef\u81ea\u52a8\u751f\u6210 ",(0,i.kt)("inlineCode",{parentName:"p"},"Case When")," \u8bed\u53e5\u3002"),(0,i.kt)("h2",{id:"9107-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.10.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0},3905:function(e,n,r){r.d(n,{Zo:function(){return l},kt:function(){return m}});var t=r(7294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function i(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function s(e){for(var n=1;n=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var u=t.createContext({}),p=function(e){var n=t.useContext(u),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},l=function(e){var n=p(e.components);return t.createElement(u.Provider,{value:n},e.children)},y={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},c=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,i=e.originalType,u=e.parentName,l=o(e,["components","mdxType","originalType","parentName"]),c=p(r),m=a,d=c["".concat(u,".").concat(m)]||c[m]||y[m]||i;return r?t.createElement(d,s(s({ref:n},l),{},{components:r})):t.createElement(d,s({ref:n},l))}));function m(e,n){var r=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=r.length,s=new Array(i);s[0]=c;var o={};for(var u in n)hasOwnProperty.call(n,u)&&(o[u]=n[u]);o.originalType=e,o.mdxType="string"==typeof e?e:a,s[1]=o;for(var p=2;p();\n Console.WriteLine(helloService.SayHello());\n\n Console.WriteLine("=============");\n\n var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();\n Console.WriteLine(baidu);\n }\n }\n\n public interface IHelloService\n {\n string SayHello();\n }\n public class HelloService : IHelloService, ITransient\n {\n public string SayHello()\n {\n return "Hello Furion.";\n }\n }\n}\n')),(0,i.kt)("p",null,"\u4ee5\u4e0a\u4ee3\u7801\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"var services = Inject.Create();")," \u521b\u5efa\u4e00\u4e2a\u670d\u52a1\u96c6\u5408\uff0c\u6700\u540e\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"services.Build()")," \u5373\u53ef\u5b8c\u6210\u521d\u59cb\u5316\u3002"))}m.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return s},kt:function(){return m}});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function a(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var u=r.createContext({}),c=function(e){var n=r.useContext(u),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},s=function(e){var n=c(e.components);return r.createElement(u.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},f=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),f=c(t),m=o,g=f["".concat(u,".").concat(m)]||f[m]||p[m]||i;return t?r.createElement(g,a(a({ref:n},s),{},{components:t})):r.createElement(g,a({ref:n},s))}));function m(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=f;var l={};for(var u in n)hasOwnProperty.call(n,u)&&(l[u]=n[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var c=2;c=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var u=r.createContext({}),c=function(e){var n=r.useContext(u),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},s=function(e){var n=c(e.components);return r.createElement(u.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},f=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),f=c(t),m=o,g=f["".concat(u,".").concat(m)]||f[m]||p[m]||i;return t?r.createElement(g,a(a({ref:n},s),{},{components:t})):r.createElement(g,a({ref:n},s))}));function m(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=f;var l={};for(var u in n)hasOwnProperty.call(n,u)&&(l[u]=n[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var c=2;c();\n Console.WriteLine(helloService.SayHello());\n\n Console.WriteLine("=============");\n\n var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();\n Console.WriteLine(baidu);\n }\n }\n\n public interface IHelloService\n {\n string SayHello();\n }\n public class HelloService : IHelloService, ITransient\n {\n public string SayHello()\n {\n return "Hello Furion.";\n }\n }\n}\n')),(0,i.kt)("p",null,"\u4ee5\u4e0a\u4ee3\u7801\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"var services = Inject.Create();")," \u521b\u5efa\u4e00\u4e2a\u670d\u52a1\u96c6\u5408\uff0c\u6700\u540e\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"services.Build()")," \u5373\u53ef\u5b8c\u6210\u521d\u59cb\u5316\u3002"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/2b75607b.4ea221d8.js b/handbook/build/assets/js/2b75607b.4ea221d8.js new file mode 100644 index 0000000000..43ea94eaef --- /dev/null +++ b/handbook/build/assets/js/2b75607b.4ea221d8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[9931],{3905:function(e,n,t){t.d(n,{Zo:function(){return p},kt:function(){return m}});var r=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function o(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var u=r.createContext({}),d=function(e){var n=r.useContext(u),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},p=function(e){var n=d(e.components);return r.createElement(u.Provider,{value:n},e.children)},s={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},c=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,u=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),c=d(t),m=a,k=c["".concat(u,".").concat(m)]||c[m]||s[m]||i;return t?r.createElement(k,o(o({ref:n},p),{},{components:t})):r.createElement(k,o({ref:n},p))}));function m(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,o=new Array(i);o[0]=c;var l={};for(var u in n)hasOwnProperty.call(n,u)&&(l[u]=n[u]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var d=2;d\u8fde\u7eed GUID \u65b9\u5f0f",id:"2731-\u8fde\u7eed-guid-\u65b9\u5f0f",level:3},{value:"27.3.2 \u77ed ID",id:"2732-\u77ed-id",level:3},{value:"27.3.3 \u96ea\u82b1\u7b97\u6cd5 ID",id:"2733-\u96ea\u82b1\u7b97\u6cd5-id",level:3},{value:"27.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"274-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:s};function m(e){var n=e.components,t=(0,a.Z)(e,o);return(0,i.kt)("wrapper",(0,r.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"271-\u4e3a\u4ec0\u4e48\u9700\u8981\u5206\u5e03\u5f0f-id"},"27.1 \u4e3a\u4ec0\u4e48\u9700\u8981\u5206\u5e03\u5f0f ID"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"\u5168\u5c40\u552f\u4e00\u6027"),": \u4e0d\u80fd\u51fa\u73b0\u91cd\u590d\u7684 ID \u53f7, \u65e2\u7136\u662f\u552f\u4e00\u6807\u8bc6, \u8fd9\u662f\u6700\u57fa\u672c\u7684\u8981\u6c42\u3002")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"\u8d8b\u52bf\u9012\u589e"),": \u5728 MySQL InnoDB \u5f15\u64ce\u4e2d\u4f7f\u7528\u7684\u662f\u805a\u96c6\u7d22\u5f15, \u7531\u4e8e\u591a\u6570 RDBMS \u4f7f\u7528 B-tree \u7684\u6570\u636e\u7ed3\u6784\u6765\u5b58\u50a8\u7d22\u5f15\u6570\u636e, \u5728\u4e3b\u952e\u7684\u9009\u62e9\u4e0a\u9762\u6211\u4eec\u5e94\u8be5\u5c3d\u91cf\u4f7f\u7528\u6709\u5e8f\u7684\u4e3b\u952e\u4fdd\u8bc1\u5199\u5165\u6027\u80fd\u3002")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"\u5355\u8c03\u9012\u589e"),": \u4fdd\u8bc1\u4e0b\u4e00\u4e2a ID \u4e00\u5b9a\u5927\u4e8e\u4e0a\u4e00\u4e2a ID, \u4f8b\u5982\u4e8b\u52a1\u7248\u672c\u53f7, IM \u589e\u91cf\u6d88\u606f, \u6392\u5e8f\u7b49\u7279\u6b8a\u9700\u6c42\u3002")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"\u4fe1\u606f\u5b89\u5168"),": \u5982\u679c ID \u662f\u8fde\u7eed\u7684, \u6076\u610f\u7528\u6237\u7684\u6252\u53d6\u5de5\u4f5c\u5c31\u975e\u5e38\u5bb9\u6613\u505a\u4e86, \u76f4\u63a5\u6309\u7167\u987a\u5e8f\u4e0b\u8f7d\u6307\u5b9a URL \u5373\u53ef; \u5982\u679c\u662f\u8ba2\u5355\u53f7\u5c31\u66f4\u5371\u9669\u4e86, \u7ade\u5bf9\u53ef\u4ee5\u76f4\u63a5\u77e5\u9053\u6211\u4eec\u4e00\u5929\u7684\u5355\u91cf\u3002 \u6240\u4ee5\u5728\u4e00\u4e9b\u5e94\u7528\u573a\u666f\u4e0b, \u4f1a\u9700\u8981 ID \u65e0\u89c4\u5219, \u4e0d\u89c4\u5219\u3002"))),(0,i.kt)("h2",{id:"272-\u5206\u5e03\u5f0f-id-\u6709\u54ea\u4e9b"},"27.2 \u5206\u5e03\u5f0f ID \u6709\u54ea\u4e9b"),(0,i.kt)("p",null,"\u5e38\u89c1\u7684\u5206\u5e03\u5f0f ID \u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u8fde\u7eed GUID"),"\u3001",(0,i.kt)("inlineCode",{parentName:"p"},"\u77ed ID"),"\u3001",(0,i.kt)("inlineCode",{parentName:"p"},"\u96ea\u82b1\u7b97\u6cd5 ID"),"\u3002"),(0,i.kt)("h2",{id:"273-\u5982\u4f55\u4f7f\u7528"},"27.3 \u5982\u4f55\u4f7f\u7528"),(0,i.kt)("h3",{id:"2731-\u8fde\u7eed-guid-\u65b9\u5f0f"},"27.3.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"\u8fde\u7eed GUID")," \u65b9\u5f0f"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u9759\u6001 ",(0,i.kt)("inlineCode",{parentName:"li"},"IDGen")," \u65b9\u5f0f")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var guid = IDGen.NextID();\n\n// \u8fd8\u53ef\u4ee5\u914d\u7f6e\u66f4\u591a\u53c2\u6570\nvar guid2 = IDGen.NextID(new SequentialGuidSettings { LittleEndianBinary16Format = true })); // SequentialGuidSettings \u53c2\u6570\u53d6\u51b3\u4e8e\u4f60\u7684\u5206\u5e03\u5f0fID\u7684\u5b9e\u73b0\n")),(0,i.kt)("admonition",{title:"\u7279\u522b\u63d0\u9192",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u5728\u5faa\u73af\u4e2d\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"IDGen")," \u9759\u6001\u7c7b\u65b9\u5f0f\uff0c\u6027\u80fd\u6700\u5dee\uff0c\u539f\u56e0\u662f\u5e95\u5c42\u4e0d\u65ad\u89e3\u6790\u670d\u52a1\u3002\u5982\u679c\u975e\u5faa\u73af\u4e2d\uff0c\u6027\u80fd\u7b49\u4e8e\u4e0b\u9762\u4e24\u79cd\u7528\u6cd5\u3002")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IDistributedIDGenerator")," \u6ce8\u5165\u65b9\u5f0f ",(0,i.kt)("strong",{parentName:"li"},"\u63a8\u8350"))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6}",showLineNumbers:!0,"":!0,"{2,6}":!0},"private readonly IDistributedIDGenerator _idGenerator;\npublic AppServices(IDistributedIDGenerator idGenerator)\n{\n _idGenerator = idGenerator;\n\n var guidObject = _idGenerator.Create();\n}\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SequentialGuidIDGenerator")," \u65b9\u5f0f")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var idGen = new SequentialGuidIDGenerator();\nvar guid = idGen.Create();\n\n// \u66f4\u591a\u53c2\u6570\nvar idGen2 = new SequentialGuidIDGenerator();\nvar guid2 = idGen2.Create(new SequentialGuidSettings { LittleEndianBinary16Format = true });\n")),(0,i.kt)("h3",{id:"2732-\u77ed-id"},"27.3.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"\u77ed ID")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"\u77ed ID")," \u6309\u9053\u7406\u4e0d\u5e94\u8be5\u653e\u5728\u5206\u5e03\u5f0f ID \u751f\u6210\u8fd9\u4e2a\u7ae0\u8282\uff0c\u5b83\u7684\u4f5c\u7528\u7528\u9014\u5e38\u7528\u4e8e\u5e76\u53d1\u4e0d\u5f3a\u7684\u5185\u90e8\u7cfb\u7edf\u4e2d\uff0c\u6bd4\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u4efb\u52a1ID"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Issue \u7f16\u53f7")," \u7b49\u7b49\u3002"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var shortid = ShortIDGen.NextID(); // \u751f\u6210\u4e00\u4e2a\u5305\u542b\u6570\u5b57\uff0c\u5b57\u6bcd\uff0c\u4e0d\u5305\u542b\u7279\u6b8a\u7b26\u53f7\u7684 8 \u4f4d\u77edid\n\n// \u6dfb\u52a0\u66f4\u591a\u914d\u7f6e\nvar shortid = ShortIDGen.NextID(new GenerationOptions {\n UseNumbers = false, // \u4e0d\u5305\u542b\u6570\u5b57\n UseSpecialCharacters = true, // \u5305\u542b\u7279\u6b8a\u7b26\u53f7\n Length = 8// \u8bbe\u7f6e\u957f\u5ea6\uff0c\u6ce8\u610f\uff1a\u4e0d\u8bbe\u7f6e\u6b21\u957f\u5ea6\u662f\u968f\u673a\u957f\u5ea6\uff01\uff01\uff01\uff01\uff01\uff01\uff01\n});\n\n// \u81ea\u5b9a\u4e49\u751f\u6210\u77ed ID \u53c2\u4e0e\u8fd0\u7b97\u5b57\u7b26\nstring characters = "\u24b6\u24b7\u24b8\u24b9\u24ba\u24bb\u24bc\u24bd\u24be\u24bf\u24c0\u24c1\u24c2\u24c3\u24c4\u24c5\u24c6\u24c7\u24c8\u24c9\u24ca\u24cb\u24cc\u24cd\u24ce\u24cf\u24d0\u24d1\u24d2\u24d3\u24d4\u24d5\u24d6\u24d7\u24d8\u24d9\u24da\u24db\u24dc\u24dd\u24de\u24df\u24e0\u24e1\u24e2\u24e3\u24e4\u24e5\u24e6\u24e7\u24e8\u24e9\u2460\u2461\u2462\u2463\u2464\u2465\u2466\u2467\u2468\u2469\u246a\u246b"; //whatever you want;\nShortIDGen.SetCharacters(characters);\n\n// \u81ea\u5b9a\u4e49\u968f\u673a\u6570\uff08for\uff09\u6b65\u957f\nint seed = 1939048828;\nShortIDGen.SetSeed(seed);\n\n// \u91cd\u8f7d\u6240\u6709\u81ea\u5b9a\u4e49\u914d\u7f6e\nShortIDGen.Reset();\n')),(0,i.kt)("h3",{id:"2733-\u96ea\u82b1\u7b97\u6cd5-id"},"27.3.3 ",(0,i.kt)("inlineCode",{parentName:"h3"},"\u96ea\u82b1\u7b97\u6cd5 ID")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u5728\u6700\u65b0\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"2.1 +")," \u7248\u672c\u79fb\u9664\u4e86",(0,i.kt)("inlineCode",{parentName:"p"},"\u96ea\u82b1\u7b97\u6cd5 ID")," \u529f\u80fd\uff0c\u539f\u56e0\u662f\uff1a"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u76ee\u524d\uff0c",(0,i.kt)("inlineCode",{parentName:"strong"},"\u96ea\u82b1\u7b97\u6cd5 ID")," \u4f7f\u7528\u9891\u7387\u4e0d\u9ad8\uff0c\u800c\u4e14\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"strong"},"\u96ea\u82b1\u7b97\u6cd5 ID")," \u7684\u65b9\u5f0f\u4e5f\u662f\u5343\u5dee\u4e07\u522b\uff0c\u6240\u4ee5\u6846\u67b6\u79fb\u9664\u8be5\u529f\u80fd\uff0c\u91c7\u7528\u62d3\u5c55\u6216\u81ea\u96c6\u6210\u65b9\u5f0f\u3002")),(0,i.kt)("h2",{id:"274-\u53cd\u9988\u4e0e\u5efa\u8bae"},"27.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,i.kt)("hr",null))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/2b75607b.87fde087.js b/handbook/build/assets/js/2b75607b.87fde087.js deleted file mode 100644 index 2e0905d647..0000000000 --- a/handbook/build/assets/js/2b75607b.87fde087.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[9931],{652:function(e,n,t){t.r(n),t.d(n,{assets:function(){return p},contentTitle:function(){return u},default:function(){return m},frontMatter:function(){return l},metadata:function(){return d},toc:function(){return s}});var r=t(3117),a=t(102),i=(t(7294),t(3905)),o=["components"],l={id:"idgenerator",title:"27. \u5206\u5e03\u5f0f ID \u751f\u6210",sidebar_label:"27. \u5206\u5e03\u5f0f ID \u751f\u6210"},u=void 0,d={unversionedId:"idgenerator",id:"idgenerator",title:"27. \u5206\u5e03\u5f0f ID \u751f\u6210",description:"27.1 \u4e3a\u4ec0\u4e48\u9700\u8981\u5206\u5e03\u5f0f ID",source:"@site/docs/idgenerator.mdx",sourceDirName:".",slug:"/idgenerator",permalink:"/furion/docs/idgenerator",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/idgenerator.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"idgenerator",title:"27. \u5206\u5e03\u5f0f ID \u751f\u6210",sidebar_label:"27. \u5206\u5e03\u5f0f ID \u751f\u6210"},sidebar:"docs",previous:{title:"26. \u5b9a\u65f6\u4efb\u52a1/\u540e\u53f0\u4efb\u52a1",permalink:"/furion/docs/job"},next:{title:"28. \u6a21\u5757\u5316\u5f00\u53d1",permalink:"/furion/docs/module-dev"}},p={},s=[{value:"27.1 \u4e3a\u4ec0\u4e48\u9700\u8981\u5206\u5e03\u5f0f ID",id:"271-\u4e3a\u4ec0\u4e48\u9700\u8981\u5206\u5e03\u5f0f-id",level:2},{value:"27.2 \u5206\u5e03\u5f0f ID \u6709\u54ea\u4e9b",id:"272-\u5206\u5e03\u5f0f-id-\u6709\u54ea\u4e9b",level:2},{value:"27.3 \u5982\u4f55\u4f7f\u7528",id:"273-\u5982\u4f55\u4f7f\u7528",level:2},{value:"27.3.1 \u8fde\u7eed GUID \u65b9\u5f0f",id:"2731-\u8fde\u7eed-guid-\u65b9\u5f0f",level:3},{value:"27.3.2 \u77ed ID",id:"2732-\u77ed-id",level:3},{value:"27.3.3 \u96ea\u82b1\u7b97\u6cd5 ID",id:"2733-\u96ea\u82b1\u7b97\u6cd5-id",level:3},{value:"27.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"274-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:s};function m(e){var n=e.components,t=(0,a.Z)(e,o);return(0,i.kt)("wrapper",(0,r.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"271-\u4e3a\u4ec0\u4e48\u9700\u8981\u5206\u5e03\u5f0f-id"},"27.1 \u4e3a\u4ec0\u4e48\u9700\u8981\u5206\u5e03\u5f0f ID"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"\u5168\u5c40\u552f\u4e00\u6027"),": \u4e0d\u80fd\u51fa\u73b0\u91cd\u590d\u7684 ID \u53f7, \u65e2\u7136\u662f\u552f\u4e00\u6807\u8bc6, \u8fd9\u662f\u6700\u57fa\u672c\u7684\u8981\u6c42\u3002")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"\u8d8b\u52bf\u9012\u589e"),": \u5728 MySQL InnoDB \u5f15\u64ce\u4e2d\u4f7f\u7528\u7684\u662f\u805a\u96c6\u7d22\u5f15, \u7531\u4e8e\u591a\u6570 RDBMS \u4f7f\u7528 B-tree \u7684\u6570\u636e\u7ed3\u6784\u6765\u5b58\u50a8\u7d22\u5f15\u6570\u636e, \u5728\u4e3b\u952e\u7684\u9009\u62e9\u4e0a\u9762\u6211\u4eec\u5e94\u8be5\u5c3d\u91cf\u4f7f\u7528\u6709\u5e8f\u7684\u4e3b\u952e\u4fdd\u8bc1\u5199\u5165\u6027\u80fd\u3002")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"\u5355\u8c03\u9012\u589e"),": \u4fdd\u8bc1\u4e0b\u4e00\u4e2a ID \u4e00\u5b9a\u5927\u4e8e\u4e0a\u4e00\u4e2a ID, \u4f8b\u5982\u4e8b\u52a1\u7248\u672c\u53f7, IM \u589e\u91cf\u6d88\u606f, \u6392\u5e8f\u7b49\u7279\u6b8a\u9700\u6c42\u3002")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"\u4fe1\u606f\u5b89\u5168"),": \u5982\u679c ID \u662f\u8fde\u7eed\u7684, \u6076\u610f\u7528\u6237\u7684\u6252\u53d6\u5de5\u4f5c\u5c31\u975e\u5e38\u5bb9\u6613\u505a\u4e86, \u76f4\u63a5\u6309\u7167\u987a\u5e8f\u4e0b\u8f7d\u6307\u5b9a URL \u5373\u53ef; \u5982\u679c\u662f\u8ba2\u5355\u53f7\u5c31\u66f4\u5371\u9669\u4e86, \u7ade\u5bf9\u53ef\u4ee5\u76f4\u63a5\u77e5\u9053\u6211\u4eec\u4e00\u5929\u7684\u5355\u91cf\u3002 \u6240\u4ee5\u5728\u4e00\u4e9b\u5e94\u7528\u573a\u666f\u4e0b, \u4f1a\u9700\u8981 ID \u65e0\u89c4\u5219, \u4e0d\u89c4\u5219\u3002"))),(0,i.kt)("h2",{id:"272-\u5206\u5e03\u5f0f-id-\u6709\u54ea\u4e9b"},"27.2 \u5206\u5e03\u5f0f ID \u6709\u54ea\u4e9b"),(0,i.kt)("p",null,"\u5e38\u89c1\u7684\u5206\u5e03\u5f0f ID \u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u8fde\u7eed GUID"),"\u3001",(0,i.kt)("inlineCode",{parentName:"p"},"\u77ed ID"),"\u3001",(0,i.kt)("inlineCode",{parentName:"p"},"\u96ea\u82b1\u7b97\u6cd5 ID"),"\u3002"),(0,i.kt)("h2",{id:"273-\u5982\u4f55\u4f7f\u7528"},"27.3 \u5982\u4f55\u4f7f\u7528"),(0,i.kt)("h3",{id:"2731-\u8fde\u7eed-guid-\u65b9\u5f0f"},"27.3.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"\u8fde\u7eed GUID")," \u65b9\u5f0f"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u9759\u6001 ",(0,i.kt)("inlineCode",{parentName:"li"},"IDGen")," \u65b9\u5f0f")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var guid = IDGen.NextID();\n\n// \u8fd8\u53ef\u4ee5\u914d\u7f6e\u66f4\u591a\u53c2\u6570\nvar guid2 = IDGen.NextID(new SequentialGuidSettings { LittleEndianBinary16Format = true })); // SequentialGuidSettings \u53c2\u6570\u53d6\u51b3\u4e8e\u4f60\u7684\u5206\u5e03\u5f0fID\u7684\u5b9e\u73b0\n")),(0,i.kt)("admonition",{title:"\u7279\u522b\u63d0\u9192",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u5728\u5faa\u73af\u4e2d\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"IDGen")," \u9759\u6001\u7c7b\u65b9\u5f0f\uff0c\u6027\u80fd\u6700\u5dee\uff0c\u539f\u56e0\u662f\u5e95\u5c42\u4e0d\u65ad\u89e3\u6790\u670d\u52a1\u3002\u5982\u679c\u975e\u5faa\u73af\u4e2d\uff0c\u6027\u80fd\u7b49\u4e8e\u4e0b\u9762\u4e24\u79cd\u7528\u6cd5\u3002")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IDistributedIDGenerator")," \u6ce8\u5165\u65b9\u5f0f ",(0,i.kt)("strong",{parentName:"li"},"\u63a8\u8350"))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6}",showLineNumbers:!0,"":!0,"{2,6}":!0},"private readonly IDistributedIDGenerator _idGenerator;\npublic AppServices(IDistributedIDGenerator idGenerator)\n{\n _idGenerator = idGenerator;\n\n var guidObject = _idGenerator.Create();\n}\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SequentialGuidIDGenerator")," \u65b9\u5f0f")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var idGen = new SequentialGuidIDGenerator();\nvar guid = idGen.Create();\n\n// \u66f4\u591a\u53c2\u6570\nvar idGen2 = new SequentialGuidIDGenerator();\nvar guid2 = idGen2.Create(new SequentialGuidSettings { LittleEndianBinary16Format = true });\n")),(0,i.kt)("h3",{id:"2732-\u77ed-id"},"27.3.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"\u77ed ID")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"\u77ed ID")," \u6309\u9053\u7406\u4e0d\u5e94\u8be5\u653e\u5728\u5206\u5e03\u5f0f ID \u751f\u6210\u8fd9\u4e2a\u7ae0\u8282\uff0c\u5b83\u7684\u4f5c\u7528\u7528\u9014\u5e38\u7528\u4e8e\u5e76\u53d1\u4e0d\u5f3a\u7684\u5185\u90e8\u7cfb\u7edf\u4e2d\uff0c\u6bd4\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u4efb\u52a1ID"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Issue \u7f16\u53f7")," \u7b49\u7b49\u3002"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var shortid = ShortIDGen.NextID(); // \u751f\u6210\u4e00\u4e2a\u5305\u542b\u6570\u5b57\uff0c\u5b57\u6bcd\uff0c\u4e0d\u5305\u542b\u7279\u6b8a\u7b26\u53f7\u7684 8 \u4f4d\u77edid\n\n// \u6dfb\u52a0\u66f4\u591a\u914d\u7f6e\nvar shortid = ShortIDGen.NextID(new GenerationOptions {\n UseNumbers = false, // \u4e0d\u5305\u542b\u6570\u5b57\n UseSpecialCharacters = true, // \u5305\u542b\u7279\u6b8a\u7b26\u53f7\n Length = 8// \u8bbe\u7f6e\u957f\u5ea6\uff0c\u6ce8\u610f\uff1a\u4e0d\u8bbe\u7f6e\u6b21\u957f\u5ea6\u662f\u968f\u673a\u957f\u5ea6\uff01\uff01\uff01\uff01\uff01\uff01\uff01\n});\n\n// \u81ea\u5b9a\u4e49\u751f\u6210\u77ed ID \u53c2\u4e0e\u8fd0\u7b97\u5b57\u7b26\nstring characters = "\u24b6\u24b7\u24b8\u24b9\u24ba\u24bb\u24bc\u24bd\u24be\u24bf\u24c0\u24c1\u24c2\u24c3\u24c4\u24c5\u24c6\u24c7\u24c8\u24c9\u24ca\u24cb\u24cc\u24cd\u24ce\u24cf\u24d0\u24d1\u24d2\u24d3\u24d4\u24d5\u24d6\u24d7\u24d8\u24d9\u24da\u24db\u24dc\u24dd\u24de\u24df\u24e0\u24e1\u24e2\u24e3\u24e4\u24e5\u24e6\u24e7\u24e8\u24e9\u2460\u2461\u2462\u2463\u2464\u2465\u2466\u2467\u2468\u2469\u246a\u246b"; //whatever you want;\nShortIDGen.SetCharacters(characters);\n\n// \u81ea\u5b9a\u4e49\u968f\u673a\u6570\uff08for\uff09\u6b65\u957f\nint seed = 1939048828;\nShortIDGen.SetSeed(seed);\n\n// \u91cd\u8f7d\u6240\u6709\u81ea\u5b9a\u4e49\u914d\u7f6e\nShortIDGen.Reset();\n')),(0,i.kt)("h3",{id:"2733-\u96ea\u82b1\u7b97\u6cd5-id"},"27.3.3 ",(0,i.kt)("inlineCode",{parentName:"h3"},"\u96ea\u82b1\u7b97\u6cd5 ID")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u5728\u6700\u65b0\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"2.1 +")," \u7248\u672c\u79fb\u9664\u4e86",(0,i.kt)("inlineCode",{parentName:"p"},"\u96ea\u82b1\u7b97\u6cd5 ID")," \u529f\u80fd\uff0c\u539f\u56e0\u662f\uff1a"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u76ee\u524d\uff0c",(0,i.kt)("inlineCode",{parentName:"strong"},"\u96ea\u82b1\u7b97\u6cd5 ID")," \u4f7f\u7528\u9891\u7387\u4e0d\u9ad8\uff0c\u800c\u4e14\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"strong"},"\u96ea\u82b1\u7b97\u6cd5 ID")," \u7684\u65b9\u5f0f\u4e5f\u662f\u5343\u5dee\u4e07\u522b\uff0c\u6240\u4ee5\u6846\u67b6\u79fb\u9664\u8be5\u529f\u80fd\uff0c\u91c7\u7528\u62d3\u5c55\u6216\u81ea\u96c6\u6210\u65b9\u5f0f\u3002")),(0,i.kt)("h2",{id:"274-\u53cd\u9988\u4e0e\u5efa\u8bae"},"27.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,i.kt)("hr",null))}m.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return p},kt:function(){return m}});var r=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function o(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var u=r.createContext({}),d=function(e){var n=r.useContext(u),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},p=function(e){var n=d(e.components);return r.createElement(u.Provider,{value:n},e.children)},s={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},c=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,u=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),c=d(t),m=a,k=c["".concat(u,".").concat(m)]||c[m]||s[m]||i;return t?r.createElement(k,o(o({ref:n},p),{},{components:t})):r.createElement(k,o({ref:n},p))}));function m(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,o=new Array(i);o[0]=c;var l={};for(var u in n)hasOwnProperty.call(n,u)&&(l[u]=n[u]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var d=2;d child <"+("string"==typeof e.type?e.type:e.type.name)+'>: all children of the component should be , and every should have a unique "value" prop.')})),v=null!=k?k:b.map((function(e){var n=e.props;return{value:n.value,label:n.label,attributes:n.attributes}})),g=(0,l.l)(v,(function(e,n){return e.value===n.value}));if(g.length>0)throw new Error('Docusaurus error: Duplicate values "'+g.map((function(e){return e.value})).join(", ")+'" found in . Every value needs to be unique.');var C=null===d?d:null!=(n=null!=d?d:null==(t=b.find((function(e){return e.props.default})))?void 0:t.props.value)?n:b[0].props.value;if(null!==C&&!v.some((function(e){return e.value===C})))throw new Error('Docusaurus error: The has a defaultValue "'+C+'" but none of its children has the corresponding value. Available values are: '+v.map((function(e){return e.value})).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");var y=(0,s.U)(),h=y.tabGroupChoices,O=y.setTabGroupChoices,w=(0,r.useState)(C),x=w[0],T=w[1],S=[],U=(0,u.o5)().blockElementScrollPositionUntilNextRender;if(null!=f){var E=h[f];null!=E&&E!==x&&v.some((function(e){return e.value===E}))&&T(E)}var A=function(e){var n=e.currentTarget,t=S.indexOf(n),a=v[t].value;a!==x&&(U(n),T(a),null!=f&&O(f,String(a)))},D=function(e){var n,t=null;switch(e.key){case"ArrowRight":var a,r=S.indexOf(e.currentTarget)+1;t=null!=(a=S[r])?a:S[0];break;case"ArrowLeft":var o,i=S.indexOf(e.currentTarget)-1;t=null!=(o=S[i])?o:S[S.length-1]}null==(n=t)||n.focus()};return r.createElement("div",{className:(0,o.Z)("tabs-container",p)},r.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":c},N)},v.map((function(e){var n=e.value,t=e.label,i=e.attributes;return r.createElement("li",(0,a.Z)({role:"tab",tabIndex:x===n?0:-1,"aria-selected":x===n,key:n,ref:function(e){return S.push(e)},onKeyDown:D,onFocus:A,onClick:A},i,{className:(0,o.Z)("tabs__item",m,null==i?void 0:i.className,{"tabs__item--active":x===n})}),null!=t?t:n)}))),i?(0,r.cloneElement)(b.filter((function(e){return e.props.value===x}))[0],{className:"margin-top--md"}):r.createElement("div",{className:"margin-top--md"},b.map((function(e,n){return(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==x})}))))}function d(e){var n=(0,i.Z)();return r.createElement(c,(0,a.Z)({key:String(n)},e))}},5748:function(e,n,t){t.r(n),t.d(n,{assets:function(){return c},contentTitle:function(){return p},default:function(){return f},frontMatter:function(){return u},metadata:function(){return m},toc:function(){return d}});var a=t(3117),r=t(102),o=(t(7294),t(3905)),i=(t(1402),t(5559)),l=t(433),s=["components"],u={id:"tran",title:"9.26 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143",sidebar_label:"9.26 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143 (UnitOfWork)"},p=void 0,m={unversionedId:"tran",id:"tran",title:"9.26 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143",description:"",source:"@site/docs/tran.mdx",sourceDirName:".",slug:"/tran",permalink:"/furion/docs/tran",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/tran.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1660797425,formattedLastUpdatedAt:"Aug 18, 2022",frontMatter:{id:"tran",title:"9.26 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143",sidebar_label:"9.26 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143 (UnitOfWork)"},sidebar:"docs",previous:{title:"9.25. \u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668",permalink:"/furion/docs/dbcontext-entitytrigger"},next:{title:"9.27 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",permalink:"/furion/docs/dbcontext-read-write"}},c={},d=[{value:"9.26.1 \u4e8b\u52a1",id:"9261-\u4e8b\u52a1",level:2},{value:"9.26.2 \u5de5\u4f5c\u5355\u5143",id:"9262-\u5de5\u4f5c\u5355\u5143",level:2},{value:"9.26.3 \u5982\u4f55\u4f7f\u7528",id:"9263-\u5982\u4f55\u4f7f\u7528",level:2},{value:"9.26.3.1 [UnitOfWork] \u81ea\u52a8\u7ba1\u7406",id:"92631-unitofwork-\u81ea\u52a8\u7ba1\u7406",level:3},{value:"9.26.3.2 EnsureTransaction() \u65b9\u6cd5 \u2728",id:"92632-ensuretransaction-\u65b9\u6cd5-",level:3},{value:"9.26.3.2 \u624b\u52a8\u7ba1\u7406",id:"92632-\u624b\u52a8\u7ba1\u7406",level:3},{value:"9.26.4 \u5de5\u4f5c\u5355\u5143\u7279\u6027\u8bf4\u660e",id:"9264-\u5de5\u4f5c\u5355\u5143\u7279\u6027\u8bf4\u660e",level:2},{value:"9.26.4.1 [UnitOfWork] \u7279\u6027",id:"92641-unitofwork-\u7279\u6027",level:3},{value:"9.26.4.2 [ManualCommit] \u7279\u6027",id:"92642-manualcommit-\u7279\u6027",level:3},{value:"9.26.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9265-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],k={toc:d};function f(e){var n=e.components,t=(0,r.Z)(e,s);return(0,o.kt)("wrapper",(0,a.Z)({},k,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"9261-\u4e8b\u52a1"},"9.26.1 \u4e8b\u52a1"),(0,o.kt)("p",null,"\u4e8b\u52a1\u6307\u4f5c\u4e3a\u5355\u4e2a\u903b\u8f91\u5de5\u4f5c\u5355\u5143\u6267\u884c\u7684\u4e00\u7cfb\u5217\u64cd\u4f5c\uff0c\u8981\u4e48",(0,o.kt)("strong",{parentName:"p"},"\u5b8c\u5168\u5730\u6267\u884c\uff0c\u8981\u4e48\u5b8c\u5168\u5730\u4e0d\u6267\u884c"),"\u3002"),(0,o.kt)("p",null,"\u7b80\u5355\u7684\u8bf4\uff0c\u4e8b\u52a1\u5c31\u662f\u5e76\u53d1\u63a7\u5236\u7684\u5355\u4f4d\uff0c\u662f\u7528\u6237\u5b9a\u4e49\u7684\u4e00\u4e2a\u64cd\u4f5c\u5e8f\u5217\u3002 \u800c\u4e00\u4e2a\u903b\u8f91\u5de5\u4f5c\u5355\u5143\u8981\u6210\u4e3a\u4e8b\u52a1\uff0c\u5c31\u5fc5\u987b\u6ee1\u8db3 ",(0,o.kt)("inlineCode",{parentName:"p"},"ACID")," \u5c5e\u6027\u3002"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"A"),"\uff1a\u539f\u5b50\u6027\uff08Atomicity\uff09\uff1a\u4e8b\u52a1\u4e2d\u7684\u64cd\u4f5c\u8981\u4e48\u90fd\u4e0d\u505a\uff0c\u8981\u4e48\u5c31\u5168\u505a"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"C"),"\uff1a\u4e00\u81f4\u6027\uff08Consistency\uff09\uff1a\u4e8b\u52a1\u6267\u884c\u7684\u7ed3\u679c\u5fc5\u987b\u662f\u4ece\u6570\u636e\u5e93\u4ece\u4e00\u4e2a\u4e00\u81f4\u6027\u72b6\u6001\u8f6c\u6362\u5230\u53e6\u4e00\u4e2a\u4e00\u81f4\u6027\u72b6\u6001"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"I"),"\uff1a\u9694\u79bb\u6027\uff08Isolation\uff09\uff1a\u4e00\u4e2a\u4e8b\u52a1\u7684\u6267\u884c\u4e0d\u80fd\u88ab\u5176\u4ed6\u4e8b\u52a1\u5e72\u6270"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"D"),"\uff1a\u6301\u4e45\u6027\uff08Durability\uff09\uff1a\u4e00\u4e2a\u4e8b\u52a1\u4e00\u65e6\u63d0\u4ea4\uff0c\u5b83\u5bf9\u6570\u636e\u5e93\u4e2d\u6570\u636e\u7684\u6539\u53d8\u5c31\u5e94\u8be5\u662f\u6c38\u4e45\u6027\u7684")),(0,o.kt)("h2",{id:"9262-\u5de5\u4f5c\u5355\u5143"},"9.26.2 \u5de5\u4f5c\u5355\u5143"),(0,o.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u5c31\u662f\u4e3a\u4e86\u4fdd\u8bc1\u4e00\u6b21\u5b8c\u6574\u7684\u529f\u80fd\u64cd\u4f5c\u6240\u4ea7\u751f\u7684\u4e00\u4e9b\u5217\u63d0\u4ea4\u6570\u636e\u7684\u5b8c\u6574\u6027\uff0c\u8d77\u7740\u4e8b\u52a1\u7684\u4f5c\u7528\u3002\u5728\u8ba1\u7b97\u673a\u9886\u57df\u4e2d\uff0c\u5de5\u4f5c\u5355\u5143\u901a\u5e38\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"UnitOfWork")," \u540d\u79f0\u8868\u793a\u3002"),(0,o.kt)("p",null,"\u901a\u5e38\u6211\u4eec\u4fdd\u8bc1\u7528\u6237\u7684\u6bcf\u4e00\u6b21\u8bf7\u6c42\u90fd\u662f\u5904\u4e8e\u5728\u4e00\u4e2a\u529f\u80fd\u5355\u5143\u4e2d\uff0c\u4e5f\u5c31\u662f\u5de5\u4f5c\u5355\u5143\u3002"),(0,o.kt)("h2",{id:"9263-\u5982\u4f55\u4f7f\u7528"},"9.26.3 \u5982\u4f55\u4f7f\u7528"),(0,o.kt)("h3",{id:"92631-unitofwork-\u81ea\u52a8\u7ba1\u7406"},"9.26.3.1 ",(0,o.kt)("inlineCode",{parentName:"h3"},"[UnitOfWork]")," \u81ea\u52a8\u7ba1\u7406"),(0,o.kt)("p",null,"\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u6211\u4eec\u53ea\u9700\u8981\u5728\u63a7\u5236\u5668 Action \u4e2d\u8d34 ",(0,o.kt)("inlineCode",{parentName:"p"},"[UnitOfWork]")," \u7279\u6027\u5373\u53ef\u5f00\u542f\u5de5\u4f5c\u5355\u5143\u6a21\u5f0f\uff0c\u4fdd\u8bc1\u4e86\u6bcf\u4e00\u6b21\u8bf7\u6c42\u90fd\u662f\u4e00\u4e2a ",(0,o.kt)("inlineCode",{parentName:"p"},"\u5de5\u4f5c\u5355\u5143"),"\uff0c\u8981\u4e48\u540c\u65f6\u6210\u529f\uff0c\u8981\u4e48\u540c\u65f6\u5931\u8d25\u3002"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u5355\u5e93\u64cd\u4f5c"))),(0,o.kt)("p",null,"\u4e0b\u9762\u65b9\u5f0f\u652f\u6301\u6240\u6709\u5173\u7cfb\u578b\u6570\u636e\u5e93\u7c7b\u578b"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},'[UnitOfWork] // \u7531\u4e8e\u51fa\u73b0\u9519\u8bef\uff0c\u6240\u4ee5\u6240\u6709\u6570\u636e\u5e93\u53d8\u66f4\u90fd\u4f1a\u81ea\u52a8\u56de\u6eda\npublic async Task \u6d4b\u8bd5\u73af\u5883\u4e8b\u52a1(int id)\n{\n // \u5404\u79cd\u5947\u8469\u6570\u636e\u5e93\u64cd\u4f5c\n await _personRepository.DeleteNowAsync(id);\n\n // \u5176\u4ed6\u6570\u636e\u5e93\u64cd\u4f5c\u3002\u3002\n\n // \u6545\u610f\u51fa\u9519\n var d = await _personRepository.SqlQueriesAsync("select * from persion2 d");\n}\n')),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u591a\u5e93\u64cd\u4f5c"))),(0,o.kt)("p",null,"\u652f\u6301\u5404\u79cd\u5947\u8469\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"ORM"),"\uff0c\u5305\u62ec ",(0,o.kt)("inlineCode",{parentName:"p"},"ADO.NET"),"\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"EFCore")," \u7b49\u7b2c\u4e09\u65b9\uff0c",(0,o.kt)("strong",{parentName:"p"},"\u652f\u6301\u6240\u6709\u5173\u7cfb\u578b\u6570\u636e\u5e93\u7c7b\u578b\u4f46\u4e0d\u652f\u6301 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Sqlite"))),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[UnitOfWork(UseAmbientTransaction = true)] // \u7531\u4e8e\u51fa\u73b0\u9519\u8bef\uff0c\u6240\u4ee5\u6240\u6709\u6570\u636e\u5e93\u53d8\u66f4\u90fd\u4f1a\u81ea\u52a8\u56de\u6eda\npublic async Task \u6d4b\u8bd5\u73af\u5883\u4e8b\u52a1(int id)\n{\n // \u5404\u79cd\u5947\u8469\u6570\u636e\u5e93\u64cd\u4f5c\n await _personRepository.DeleteNowAsync(id);\n\n // \u5176\u4ed6\u6570\u636e\u5e93\u64cd\u4f5c\u3002\u3002\n\n // \u6545\u610f\u51fa\u9519\n var d = await _personRepository.SqlQueriesAsync("select * from persion2 d");\n}\n')),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"UnitOfWork")," \u5185\u7f6e\u914d\u7f6e\uff1a",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"UseAmbientTransaction"),"\uff1a\u662f\u5426\u5f00\u542f\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"false"),"\uff0c",(0,o.kt)("strong",{parentName:"li"},"\u4e0d\u652f\u6301 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Sqlite"))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"TransactionScope"),"\uff1a\u914d\u7f6e\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1\u8303\u56f4\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"TransactionScopeOption")," \u7c7b\u578b\uff0c\u5f53 ",(0,o.kt)("inlineCode",{parentName:"li"},"UseAmbientTransaction")," \u4e3a ",(0,o.kt)("inlineCode",{parentName:"li"},"true")," \u6709\u6548"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"TransactionIsolationLevel"),"\uff1a\u914d\u7f6e\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1\u9694\u79bb\u7ea7\u522b\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"IsolationLevel")," \u7c7b\u578b\uff0c\u5f53 ",(0,o.kt)("inlineCode",{parentName:"li"},"UseAmbientTransaction")," \u4e3a ",(0,o.kt)("inlineCode",{parentName:"li"},"true")," \u6709\u6548"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"TransactionTimeout"),"\uff1a\u914d\u7f6e\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1\u6267\u884c\u8d85\u65f6\u65f6\u95f4\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"int")," \u7c7b\u578b\uff0c\u5f53 ",(0,o.kt)("inlineCode",{parentName:"li"},"UseAmbientTransaction")," \u4e3a ",(0,o.kt)("inlineCode",{parentName:"li"},"true")," \u6709\u6548"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"TransactionScopeAsyncFlow"),"\uff1a\u914d\u7f6e\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1\u5f02\u6b65\u6d41\u652f\u6301\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"TransactionScopeAsyncFlowOption")," \u7c7b\u578b\uff0c\u5f53 ",(0,o.kt)("inlineCode",{parentName:"li"},"UseAmbientTransaction")," \u4e3a ",(0,o.kt)("inlineCode",{parentName:"li"},"true")," \u6709\u6548"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"EnsureTransaction"),"\uff1a\u5f3a\u5236\u4f7f\u5b57\u7b26\u4e32 ",(0,o.kt)("inlineCode",{parentName:"li"},"sql")," \u62d3\u5c55\u4e8b\u52a1\u6709\u6548\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"false"))))),(0,o.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 3.7.3 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,o.kt)("p",null,"\u5982\u4f7f\u7528\u975e ",(0,o.kt)("inlineCode",{parentName:"p"},"EFCore")," ORM \u6846\u67b6\uff0c\u53ef\u5b9e\u73b0 ",(0,o.kt)("inlineCode",{parentName:"p"},"IUnitOfWork")," \u63a5\u53e3\u4e4b\u540e\u8c03\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"services.AddUnitOfWork()")," \u6ce8\u518c\u5373\u53ef\uff0c\u5982\u793a\u4f8b\u4ee3\u7801\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8,30,41,52,63}",showLineNumbers:!0,"{8,30,41,52,63}":!0},'using Microsoft.AspNetCore.Mvc.Filters;\n\nnamespace Furion.DatabaseAccessor;\n\n/// \n/// SqlSugar \u5de5\u4f5c\u5355\u5143\u5b9e\u73b0\n/// \npublic sealed class SqlSugarUnitOfWork : IUnitOfWork\n{\n /// \n /// SqlSugar \u5bf9\u8c61\n /// \n private readonly ISqlSugarClient _sqlSugarClient;\n\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n /// \n public SqlSugarUnitOfWork(ISqlSugarClient sqlSugarClient)\n {\n _sqlSugarClient = sqlSugarClient;\n }\n\n /// \n /// \u5f00\u542f\u5de5\u4f5c\u5355\u5143\u5904\u7406\n /// \n /// \n /// \n /// \n public void BeginTransaction(FilterContext context, UnitOfWorkAttribute unitOfWork)\n {\n _sqlSugarClient.AsTenant().BeginTran();\n }\n\n /// \n /// \u63d0\u4ea4\u5de5\u4f5c\u5355\u5143\u5904\u7406\n /// \n /// \n /// \n /// \n public void CommitTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork)\n {\n _sqlSugarClient.AsTenant().CommitTran();\n }\n\n /// \n /// \u56de\u6eda\u5de5\u4f5c\u5355\u5143\u5904\u7406\n /// \n /// \n /// \n /// \n public void RollbackTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork)\n {\n _sqlSugarClient.AsTenant().RollbackTran();\n }\n\n /// \n /// \u6267\u884c\u5b8c\u6bd5\uff08\u65e0\u8bba\u6210\u529f\u5931\u8d25\uff09\n /// \n /// \n /// \n /// \n public void OnCompleted(FilterContext context, FilterContext resultContext)\n {\n _sqlSugarClient.Dispose();\n }\n}\n')),(0,o.kt)("p",null,"\u4e4b\u540e\u6ce8\u518c\u5373\u53ef\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddUnitOfWork();\n")),(0,o.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6-\u5982\u4f55\u5224\u65ad\u662f\u5426\u5f00\u542f\u4e86\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u6709\u65f6\u5019\u6211\u4eec\u81ea\u5b9a\u4e49\u4e86\u5de5\u4f5c\u5355\u5143\u4e4b\u540e\uff0c\u4e2a\u522b ",(0,o.kt)("inlineCode",{parentName:"p"},"ORM")," \u4e0d\u652f\u6301\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1\uff0c\u90a3\u4e48\u5c31\u4f1a\u51fa\u73b0\u6267\u884c\u9519\u8bef\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"System.Transactions.Transaction.Current != null")," \u6765\u5224\u65ad\u662f\u5426\u542f\u7528\u4e86\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1\uff0c\u4e0d\u7b49\u4e8e ",(0,o.kt)("inlineCode",{parentName:"p"},"null")," \u5219\u4e3a\u542f\u7528\uff0c\u5426\u5219\u672a\u542f\u7528\u3002")),(0,o.kt)("h3",{id:"92632-ensuretransaction-\u65b9\u6cd5-"},"9.26.3.2 ",(0,o.kt)("inlineCode",{parentName:"h3"},"EnsureTransaction()")," \u65b9\u6cd5 \u2728"),(0,o.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u901a\u8fc7\u9759\u6001\u7c7b\u6216\u8005\u5176\u4ed6\u65b9\u5f0f\u4e0d\u5c0f\u5fc3\u521b\u5efa\u4e86\u65b0\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"DbContext")," \u5b9e\u4f8b\uff0c\u8fd9\u65f6\u5019\u8d34\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"[UnitOfWork]")," \u4e5f\u4e0d\u89c1\u8d77\u6548\uff0c\u8fd9\u65f6\u5019\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u65b9\u6cd5\u6765\u786e\u8ba4\u4e8b\u52a1\u662f\u5426\u6709\u6548\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"repository.EnsureTransaction();\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u5982\u679c\u4e0d\u559c\u6b22\u624b\u52a8\u65b9\u5f0f\u4e5f\u53ef\u4ee5\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"strong"},"[UnitOfWork(true)]")," \u5f00\u542f\u6b64\u529f\u80fd\u3002")),(0,o.kt)("p",null,"\u8be5\u65b9\u6cd5\u4f1a\u5c06\u5f53\u524d\u4ed3\u50a8\u6dfb\u52a0\u5230\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6c60\u4e2d\uff0c\u5e76\u786e\u4fdd\u4e8b\u52a1\u53ef\u7528\u3002"),(0,o.kt)("h3",{id:"92632-\u624b\u52a8\u7ba1\u7406"},"9.26.3.2 \u624b\u52a8\u7ba1\u7406"),(0,o.kt)(i.Z,{defaultValue:"one",values:[{label:"\u793a\u4f8b\u4e00",value:"one"},{label:"\u793a\u4f8b\u4e8c",value:"two"},{label:"\u793a\u4f8b\u4e09\uff08\u5206\u5e03\u5f0f\uff09",value:"three"}],mdxType:"Tabs"},(0,o.kt)(l.Z,{value:"one",mdxType:"TabItem"},(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u5f00\u542f\u4e8b\u52a1\nusing (var transaction = _testRepository.Database.BeginTransaction())\n{\n try\n {\n _testRepository.Insert(new Blog { Url = "http://blogs.msdn.com/dotnet" });\n _testRepository.SaveNow();\n\n _testRepository.Insert(new Blog { Url = "http://blogs.msdn.com/visualstudio" });\n _testRepository.SaveNow();\n\n var blogs = _testRepository.Entity\n .OrderBy(b => b.Url)\n .ToList();\n\n // \u63d0\u4ea4\u4e8b\u52a1\n transaction.Commit();\n }\n catch (Exception)\n {\n // \u56de\u6eda\u4e8b\u52a1\n // transaction.RollBack(); // \u65b0\u7248\u672c\u81ea\u52a8\u56de\u6eda\u4e86\n }\n}\n'))),(0,o.kt)(l.Z,{value:"two",mdxType:"TabItem"},(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var options = new DbContextOptionsBuilder()\n .UseSqlServer(new SqlConnection(connectionString))\n .Options;\n\n// \u521b\u5efa\u8fde\u63a5\u5b57\u7b26\u4e32\nusing (var context1 = new DefaultDbContext(options))\n{\n // \u5f00\u542f\u4e8b\u52a1\n using (var transaction = context1.Database.BeginTransaction())\n {\n try\n {\n _testRepository.Insert(new Blog { Url = "http://blogs.msdn.com/dotnet" });\n _testRepository.SaveNow();\n\n context1.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });\n context1.SaveChanges();\n\n // \u521b\u5efa\u65b0\u7684\u8fde\u63a5\u5bf9\u8c61\n using (var context2 = new DefaultDbContext(options))\n {\n // \u5171\u4eab\u8fde\u63a5\u4e8b\u52a1\n context2.Database.UseTransaction(transaction.GetDbTransaction());\n\n var blogs = context2.Blogs\n .OrderBy(b => b.Url)\n .ToList();\n }\n\n // \u63d0\u4ea4\u4e8b\u52a1\n transaction.Commit();\n }\n catch (Exception)\n {\n // \u56de\u6eda\u4e8b\u52a1\n // transaction.RollBack(); // \u65b0\u7248\u672c\u81ea\u52a8\u56de\u6eda\u4e86\n }\n }\n}\n'))),(0,o.kt)(l.Z,{value:"three",mdxType:"TabItem"},(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-3}",showLineNumbers:!0,"":!0,"{1-3}":!0},'// \u5f00\u542f\u5206\u5e03\u5f0f\u4e8b\u52a1\n// \u5982\u679c\u4e8b\u52a1\u5305\u88f9\u7684\u4ee3\u7801\u4e2d\u5305\u542b\u5f02\u6b65 async/await\uff0c\u90a3\u4e48\u9700\u8981\u8bbe\u7f6e TransactionScopeAsyncFlowOption.Enabled = true\nusing (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }))\n{\n using (var connection = new SqlConnection(connectionString))\n {\n connection.Open();\n\n try\n {\n // \u8fd9\u91cc\u662f Ado.NET \u64cd\u4f5c\n var command = connection.CreateCommand();\n command.CommandText = "DELETE FROM dbo.Blogs";\n command.ExecuteNonQuery();\n\n // \u521b\u5efaEF Core \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n var options = new DbContextOptionsBuilder()\n .UseSqlServer(connection)\n .Options;\n using (var context = new BloggingContext(options))\n {\n context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });\n context.SaveChanges();\n }\n\n // \u6846\u67b6\u5c01\u88c5\u7684\u4ed3\u50a8\n _testRepository.Insert(new Blog { Url = "http://blogs.msdn.com/dotnet" });\n _testRepository.SaveChanges();\n\n // \u63d0\u4ea4\u4e8b\u52a1\n scope.Complete();\n }\n catch (System.Exception)\n {\n // \u81ea\u52a8\u56de\u6eda\n }\n }\n}\n')))),(0,o.kt)("h2",{id:"9264-\u5de5\u4f5c\u5355\u5143\u7279\u6027\u8bf4\u660e"},"9.26.4 \u5de5\u4f5c\u5355\u5143\u7279\u6027\u8bf4\u660e"),(0,o.kt)("h3",{id:"92641-unitofwork-\u7279\u6027"},"9.26.4.1 ",(0,o.kt)("inlineCode",{parentName:"h3"},"[UnitOfWork]")," \u7279\u6027"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"[UnitOfWork]")," \u7279\u6027\u53ea\u80fd\u7528\u4e8e\u63a7\u5236\u5668\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Action")," \u4e2d\uff0c\u4e00\u65e6\u8d34\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"[UnitOfWork]")," \u7279\u6027\u540e\uff0c\u90a3\u4e48\u8be5\u8bf7\u6c42\u81ea\u52a8\u542f\u7528\u5de5\u4f5c\u5355\u5143\u6a21\u5f0f\uff0c\u8981\u4e48\u6210\u529f\uff0c\u8981\u4e48\u5931\u8d25\u3002"),(0,o.kt)("h3",{id:"92642-manualcommit-\u7279\u6027"},"9.26.4.2 ",(0,o.kt)("inlineCode",{parentName:"h3"},"[ManualCommit]")," \u7279\u6027"),(0,o.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4f1a\u5728\u4e00\u6b21\u6210\u529f\u8bf7\u6c42\u4e4b\u540e\u81ea\u52a8\u8c03\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"SaveChanges()")," \u65b9\u6cd5\uff0c\u5982\u679c\u9009\u62e9\u624b\u52a8\u8c03\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"SaveChanges()")," \u65b9\u6cd5\uff0c\u53ef\u4ee5\u5728\u63a7\u5236\u5668 ",(0,o.kt)("inlineCode",{parentName:"p"},"Action")," \u4e2d\u8d34 ",(0,o.kt)("inlineCode",{parentName:"p"},"[ManualCommit]")," \u7279\u6027\u5373\u53ef\u3002"),(0,o.kt)("h2",{id:"9265-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.26.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,o.kt)("hr",null),(0,o.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,o.kt)("inlineCode",{parentName:"p"},"\u4e8b\u52a1")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,o.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/ef/core/saving/transactions"},"EF Core - \u4f7f\u7528\u4e8b\u52a1")," \u7ae0\u8282\u3002")))}f.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return p},kt:function(){return d}});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function i(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),u=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},p=function(e){var n=u(e.components);return a.createElement(s.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},c=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),c=u(t),d=r,k=c["".concat(s,".").concat(d)]||c[d]||m[d]||o;return t?a.createElement(k,i(i({ref:n},p),{},{components:t})):a.createElement(k,i({ref:n},p))}));function d(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var o=t.length,i=new Array(o);i[0]=c;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:r,i[1]=l;for(var u=2;u=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),u=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},p=function(e){var n=u(e.components);return a.createElement(s.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},c=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),c=u(t),d=r,k=c["".concat(s,".").concat(d)]||c[d]||m[d]||o;return t?a.createElement(k,i(i({ref:n},p),{},{components:t})):a.createElement(k,i({ref:n},p))}));function d(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var o=t.length,i=new Array(o);i[0]=c;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:r,i[1]=l;for(var u=2;u child <"+("string"==typeof e.type?e.type:e.type.name)+'>: all children of the component should be , and every should have a unique "value" prop.')})),v=null!=k?k:b.map((function(e){var n=e.props;return{value:n.value,label:n.label,attributes:n.attributes}})),g=(0,l.l)(v,(function(e,n){return e.value===n.value}));if(g.length>0)throw new Error('Docusaurus error: Duplicate values "'+g.map((function(e){return e.value})).join(", ")+'" found in . Every value needs to be unique.');var C=null===d?d:null!=(n=null!=d?d:null==(t=b.find((function(e){return e.props.default})))?void 0:t.props.value)?n:b[0].props.value;if(null!==C&&!v.some((function(e){return e.value===C})))throw new Error('Docusaurus error: The has a defaultValue "'+C+'" but none of its children has the corresponding value. Available values are: '+v.map((function(e){return e.value})).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");var y=(0,s.U)(),h=y.tabGroupChoices,O=y.setTabGroupChoices,w=(0,r.useState)(C),x=w[0],T=w[1],S=[],U=(0,u.o5)().blockElementScrollPositionUntilNextRender;if(null!=f){var E=h[f];null!=E&&E!==x&&v.some((function(e){return e.value===E}))&&T(E)}var A=function(e){var n=e.currentTarget,t=S.indexOf(n),a=v[t].value;a!==x&&(U(n),T(a),null!=f&&O(f,String(a)))},D=function(e){var n,t=null;switch(e.key){case"ArrowRight":var a,r=S.indexOf(e.currentTarget)+1;t=null!=(a=S[r])?a:S[0];break;case"ArrowLeft":var o,i=S.indexOf(e.currentTarget)-1;t=null!=(o=S[i])?o:S[S.length-1]}null==(n=t)||n.focus()};return r.createElement("div",{className:(0,o.Z)("tabs-container",p)},r.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":c},N)},v.map((function(e){var n=e.value,t=e.label,i=e.attributes;return r.createElement("li",(0,a.Z)({role:"tab",tabIndex:x===n?0:-1,"aria-selected":x===n,key:n,ref:function(e){return S.push(e)},onKeyDown:D,onFocus:A,onClick:A},i,{className:(0,o.Z)("tabs__item",m,null==i?void 0:i.className,{"tabs__item--active":x===n})}),null!=t?t:n)}))),i?(0,r.cloneElement)(b.filter((function(e){return e.props.value===x}))[0],{className:"margin-top--md"}):r.createElement("div",{className:"margin-top--md"},b.map((function(e,n){return(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==x})}))))}function d(e){var n=(0,i.Z)();return r.createElement(c,(0,a.Z)({key:String(n)},e))}},4390:function(e,n,t){t.r(n),t.d(n,{assets:function(){return c},contentTitle:function(){return p},default:function(){return f},frontMatter:function(){return u},metadata:function(){return m},toc:function(){return d}});var a=t(3117),r=t(102),o=(t(7294),t(3905)),i=(t(4996),t(5488)),l=t(5162),s=["components"],u={id:"tran",title:"9.26 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143",sidebar_label:"9.26 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143 (UnitOfWork)"},p=void 0,m={unversionedId:"tran",id:"tran",title:"9.26 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143",description:"",source:"@site/docs/tran.mdx",sourceDirName:".",slug:"/tran",permalink:"/furion/docs/tran",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/tran.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1660797425,formattedLastUpdatedAt:"Aug 18, 2022",frontMatter:{id:"tran",title:"9.26 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143",sidebar_label:"9.26 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143 (UnitOfWork)"},sidebar:"docs",previous:{title:"9.25. \u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668",permalink:"/furion/docs/dbcontext-entitytrigger"},next:{title:"9.27 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",permalink:"/furion/docs/dbcontext-read-write"}},c={},d=[{value:"9.26.1 \u4e8b\u52a1",id:"9261-\u4e8b\u52a1",level:2},{value:"9.26.2 \u5de5\u4f5c\u5355\u5143",id:"9262-\u5de5\u4f5c\u5355\u5143",level:2},{value:"9.26.3 \u5982\u4f55\u4f7f\u7528",id:"9263-\u5982\u4f55\u4f7f\u7528",level:2},{value:"9.26.3.1 [UnitOfWork] \u81ea\u52a8\u7ba1\u7406",id:"92631-unitofwork-\u81ea\u52a8\u7ba1\u7406",level:3},{value:"9.26.3.2 EnsureTransaction() \u65b9\u6cd5 \u2728",id:"92632-ensuretransaction-\u65b9\u6cd5-",level:3},{value:"9.26.3.2 \u624b\u52a8\u7ba1\u7406",id:"92632-\u624b\u52a8\u7ba1\u7406",level:3},{value:"9.26.4 \u5de5\u4f5c\u5355\u5143\u7279\u6027\u8bf4\u660e",id:"9264-\u5de5\u4f5c\u5355\u5143\u7279\u6027\u8bf4\u660e",level:2},{value:"9.26.4.1 [UnitOfWork] \u7279\u6027",id:"92641-unitofwork-\u7279\u6027",level:3},{value:"9.26.4.2 [ManualCommit] \u7279\u6027",id:"92642-manualcommit-\u7279\u6027",level:3},{value:"9.26.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9265-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],k={toc:d};function f(e){var n=e.components,t=(0,r.Z)(e,s);return(0,o.kt)("wrapper",(0,a.Z)({},k,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"9261-\u4e8b\u52a1"},"9.26.1 \u4e8b\u52a1"),(0,o.kt)("p",null,"\u4e8b\u52a1\u6307\u4f5c\u4e3a\u5355\u4e2a\u903b\u8f91\u5de5\u4f5c\u5355\u5143\u6267\u884c\u7684\u4e00\u7cfb\u5217\u64cd\u4f5c\uff0c\u8981\u4e48",(0,o.kt)("strong",{parentName:"p"},"\u5b8c\u5168\u5730\u6267\u884c\uff0c\u8981\u4e48\u5b8c\u5168\u5730\u4e0d\u6267\u884c"),"\u3002"),(0,o.kt)("p",null,"\u7b80\u5355\u7684\u8bf4\uff0c\u4e8b\u52a1\u5c31\u662f\u5e76\u53d1\u63a7\u5236\u7684\u5355\u4f4d\uff0c\u662f\u7528\u6237\u5b9a\u4e49\u7684\u4e00\u4e2a\u64cd\u4f5c\u5e8f\u5217\u3002 \u800c\u4e00\u4e2a\u903b\u8f91\u5de5\u4f5c\u5355\u5143\u8981\u6210\u4e3a\u4e8b\u52a1\uff0c\u5c31\u5fc5\u987b\u6ee1\u8db3 ",(0,o.kt)("inlineCode",{parentName:"p"},"ACID")," \u5c5e\u6027\u3002"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"A"),"\uff1a\u539f\u5b50\u6027\uff08Atomicity\uff09\uff1a\u4e8b\u52a1\u4e2d\u7684\u64cd\u4f5c\u8981\u4e48\u90fd\u4e0d\u505a\uff0c\u8981\u4e48\u5c31\u5168\u505a"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"C"),"\uff1a\u4e00\u81f4\u6027\uff08Consistency\uff09\uff1a\u4e8b\u52a1\u6267\u884c\u7684\u7ed3\u679c\u5fc5\u987b\u662f\u4ece\u6570\u636e\u5e93\u4ece\u4e00\u4e2a\u4e00\u81f4\u6027\u72b6\u6001\u8f6c\u6362\u5230\u53e6\u4e00\u4e2a\u4e00\u81f4\u6027\u72b6\u6001"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"I"),"\uff1a\u9694\u79bb\u6027\uff08Isolation\uff09\uff1a\u4e00\u4e2a\u4e8b\u52a1\u7684\u6267\u884c\u4e0d\u80fd\u88ab\u5176\u4ed6\u4e8b\u52a1\u5e72\u6270"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"D"),"\uff1a\u6301\u4e45\u6027\uff08Durability\uff09\uff1a\u4e00\u4e2a\u4e8b\u52a1\u4e00\u65e6\u63d0\u4ea4\uff0c\u5b83\u5bf9\u6570\u636e\u5e93\u4e2d\u6570\u636e\u7684\u6539\u53d8\u5c31\u5e94\u8be5\u662f\u6c38\u4e45\u6027\u7684")),(0,o.kt)("h2",{id:"9262-\u5de5\u4f5c\u5355\u5143"},"9.26.2 \u5de5\u4f5c\u5355\u5143"),(0,o.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u5c31\u662f\u4e3a\u4e86\u4fdd\u8bc1\u4e00\u6b21\u5b8c\u6574\u7684\u529f\u80fd\u64cd\u4f5c\u6240\u4ea7\u751f\u7684\u4e00\u4e9b\u5217\u63d0\u4ea4\u6570\u636e\u7684\u5b8c\u6574\u6027\uff0c\u8d77\u7740\u4e8b\u52a1\u7684\u4f5c\u7528\u3002\u5728\u8ba1\u7b97\u673a\u9886\u57df\u4e2d\uff0c\u5de5\u4f5c\u5355\u5143\u901a\u5e38\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"UnitOfWork")," \u540d\u79f0\u8868\u793a\u3002"),(0,o.kt)("p",null,"\u901a\u5e38\u6211\u4eec\u4fdd\u8bc1\u7528\u6237\u7684\u6bcf\u4e00\u6b21\u8bf7\u6c42\u90fd\u662f\u5904\u4e8e\u5728\u4e00\u4e2a\u529f\u80fd\u5355\u5143\u4e2d\uff0c\u4e5f\u5c31\u662f\u5de5\u4f5c\u5355\u5143\u3002"),(0,o.kt)("h2",{id:"9263-\u5982\u4f55\u4f7f\u7528"},"9.26.3 \u5982\u4f55\u4f7f\u7528"),(0,o.kt)("h3",{id:"92631-unitofwork-\u81ea\u52a8\u7ba1\u7406"},"9.26.3.1 ",(0,o.kt)("inlineCode",{parentName:"h3"},"[UnitOfWork]")," \u81ea\u52a8\u7ba1\u7406"),(0,o.kt)("p",null,"\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u6211\u4eec\u53ea\u9700\u8981\u5728\u63a7\u5236\u5668 Action \u4e2d\u8d34 ",(0,o.kt)("inlineCode",{parentName:"p"},"[UnitOfWork]")," \u7279\u6027\u5373\u53ef\u5f00\u542f\u5de5\u4f5c\u5355\u5143\u6a21\u5f0f\uff0c\u4fdd\u8bc1\u4e86\u6bcf\u4e00\u6b21\u8bf7\u6c42\u90fd\u662f\u4e00\u4e2a ",(0,o.kt)("inlineCode",{parentName:"p"},"\u5de5\u4f5c\u5355\u5143"),"\uff0c\u8981\u4e48\u540c\u65f6\u6210\u529f\uff0c\u8981\u4e48\u540c\u65f6\u5931\u8d25\u3002"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u5355\u5e93\u64cd\u4f5c"))),(0,o.kt)("p",null,"\u4e0b\u9762\u65b9\u5f0f\u652f\u6301\u6240\u6709\u5173\u7cfb\u578b\u6570\u636e\u5e93\u7c7b\u578b"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},'[UnitOfWork] // \u7531\u4e8e\u51fa\u73b0\u9519\u8bef\uff0c\u6240\u4ee5\u6240\u6709\u6570\u636e\u5e93\u53d8\u66f4\u90fd\u4f1a\u81ea\u52a8\u56de\u6eda\npublic async Task \u6d4b\u8bd5\u73af\u5883\u4e8b\u52a1(int id)\n{\n // \u5404\u79cd\u5947\u8469\u6570\u636e\u5e93\u64cd\u4f5c\n await _personRepository.DeleteNowAsync(id);\n\n // \u5176\u4ed6\u6570\u636e\u5e93\u64cd\u4f5c\u3002\u3002\n\n // \u6545\u610f\u51fa\u9519\n var d = await _personRepository.SqlQueriesAsync("select * from persion2 d");\n}\n')),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u591a\u5e93\u64cd\u4f5c"))),(0,o.kt)("p",null,"\u652f\u6301\u5404\u79cd\u5947\u8469\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"ORM"),"\uff0c\u5305\u62ec ",(0,o.kt)("inlineCode",{parentName:"p"},"ADO.NET"),"\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"EFCore")," \u7b49\u7b2c\u4e09\u65b9\uff0c",(0,o.kt)("strong",{parentName:"p"},"\u652f\u6301\u6240\u6709\u5173\u7cfb\u578b\u6570\u636e\u5e93\u7c7b\u578b\u4f46\u4e0d\u652f\u6301 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Sqlite"))),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[UnitOfWork(UseAmbientTransaction = true)] // \u7531\u4e8e\u51fa\u73b0\u9519\u8bef\uff0c\u6240\u4ee5\u6240\u6709\u6570\u636e\u5e93\u53d8\u66f4\u90fd\u4f1a\u81ea\u52a8\u56de\u6eda\npublic async Task \u6d4b\u8bd5\u73af\u5883\u4e8b\u52a1(int id)\n{\n // \u5404\u79cd\u5947\u8469\u6570\u636e\u5e93\u64cd\u4f5c\n await _personRepository.DeleteNowAsync(id);\n\n // \u5176\u4ed6\u6570\u636e\u5e93\u64cd\u4f5c\u3002\u3002\n\n // \u6545\u610f\u51fa\u9519\n var d = await _personRepository.SqlQueriesAsync("select * from persion2 d");\n}\n')),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"UnitOfWork")," \u5185\u7f6e\u914d\u7f6e\uff1a",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"UseAmbientTransaction"),"\uff1a\u662f\u5426\u5f00\u542f\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"false"),"\uff0c",(0,o.kt)("strong",{parentName:"li"},"\u4e0d\u652f\u6301 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Sqlite"))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"TransactionScope"),"\uff1a\u914d\u7f6e\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1\u8303\u56f4\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"TransactionScopeOption")," \u7c7b\u578b\uff0c\u5f53 ",(0,o.kt)("inlineCode",{parentName:"li"},"UseAmbientTransaction")," \u4e3a ",(0,o.kt)("inlineCode",{parentName:"li"},"true")," \u6709\u6548"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"TransactionIsolationLevel"),"\uff1a\u914d\u7f6e\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1\u9694\u79bb\u7ea7\u522b\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"IsolationLevel")," \u7c7b\u578b\uff0c\u5f53 ",(0,o.kt)("inlineCode",{parentName:"li"},"UseAmbientTransaction")," \u4e3a ",(0,o.kt)("inlineCode",{parentName:"li"},"true")," \u6709\u6548"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"TransactionTimeout"),"\uff1a\u914d\u7f6e\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1\u6267\u884c\u8d85\u65f6\u65f6\u95f4\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"int")," \u7c7b\u578b\uff0c\u5f53 ",(0,o.kt)("inlineCode",{parentName:"li"},"UseAmbientTransaction")," \u4e3a ",(0,o.kt)("inlineCode",{parentName:"li"},"true")," \u6709\u6548"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"TransactionScopeAsyncFlow"),"\uff1a\u914d\u7f6e\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1\u5f02\u6b65\u6d41\u652f\u6301\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"TransactionScopeAsyncFlowOption")," \u7c7b\u578b\uff0c\u5f53 ",(0,o.kt)("inlineCode",{parentName:"li"},"UseAmbientTransaction")," \u4e3a ",(0,o.kt)("inlineCode",{parentName:"li"},"true")," \u6709\u6548"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"EnsureTransaction"),"\uff1a\u5f3a\u5236\u4f7f\u5b57\u7b26\u4e32 ",(0,o.kt)("inlineCode",{parentName:"li"},"sql")," \u62d3\u5c55\u4e8b\u52a1\u6709\u6548\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"false"))))),(0,o.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 3.7.3 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,o.kt)("p",null,"\u5982\u4f7f\u7528\u975e ",(0,o.kt)("inlineCode",{parentName:"p"},"EFCore")," ORM \u6846\u67b6\uff0c\u53ef\u5b9e\u73b0 ",(0,o.kt)("inlineCode",{parentName:"p"},"IUnitOfWork")," \u63a5\u53e3\u4e4b\u540e\u8c03\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"services.AddUnitOfWork()")," \u6ce8\u518c\u5373\u53ef\uff0c\u5982\u793a\u4f8b\u4ee3\u7801\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8,30,41,52,63}",showLineNumbers:!0,"{8,30,41,52,63}":!0},'using Microsoft.AspNetCore.Mvc.Filters;\n\nnamespace Furion.DatabaseAccessor;\n\n/// \n/// SqlSugar \u5de5\u4f5c\u5355\u5143\u5b9e\u73b0\n/// \npublic sealed class SqlSugarUnitOfWork : IUnitOfWork\n{\n /// \n /// SqlSugar \u5bf9\u8c61\n /// \n private readonly ISqlSugarClient _sqlSugarClient;\n\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n /// \n public SqlSugarUnitOfWork(ISqlSugarClient sqlSugarClient)\n {\n _sqlSugarClient = sqlSugarClient;\n }\n\n /// \n /// \u5f00\u542f\u5de5\u4f5c\u5355\u5143\u5904\u7406\n /// \n /// \n /// \n /// \n public void BeginTransaction(FilterContext context, UnitOfWorkAttribute unitOfWork)\n {\n _sqlSugarClient.AsTenant().BeginTran();\n }\n\n /// \n /// \u63d0\u4ea4\u5de5\u4f5c\u5355\u5143\u5904\u7406\n /// \n /// \n /// \n /// \n public void CommitTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork)\n {\n _sqlSugarClient.AsTenant().CommitTran();\n }\n\n /// \n /// \u56de\u6eda\u5de5\u4f5c\u5355\u5143\u5904\u7406\n /// \n /// \n /// \n /// \n public void RollbackTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork)\n {\n _sqlSugarClient.AsTenant().RollbackTran();\n }\n\n /// \n /// \u6267\u884c\u5b8c\u6bd5\uff08\u65e0\u8bba\u6210\u529f\u5931\u8d25\uff09\n /// \n /// \n /// \n /// \n public void OnCompleted(FilterContext context, FilterContext resultContext)\n {\n _sqlSugarClient.Dispose();\n }\n}\n')),(0,o.kt)("p",null,"\u4e4b\u540e\u6ce8\u518c\u5373\u53ef\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddUnitOfWork();\n")),(0,o.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6-\u5982\u4f55\u5224\u65ad\u662f\u5426\u5f00\u542f\u4e86\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u6709\u65f6\u5019\u6211\u4eec\u81ea\u5b9a\u4e49\u4e86\u5de5\u4f5c\u5355\u5143\u4e4b\u540e\uff0c\u4e2a\u522b ",(0,o.kt)("inlineCode",{parentName:"p"},"ORM")," \u4e0d\u652f\u6301\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1\uff0c\u90a3\u4e48\u5c31\u4f1a\u51fa\u73b0\u6267\u884c\u9519\u8bef\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"System.Transactions.Transaction.Current != null")," \u6765\u5224\u65ad\u662f\u5426\u542f\u7528\u4e86\u5206\u5e03\u5f0f\u73af\u5883\u4e8b\u52a1\uff0c\u4e0d\u7b49\u4e8e ",(0,o.kt)("inlineCode",{parentName:"p"},"null")," \u5219\u4e3a\u542f\u7528\uff0c\u5426\u5219\u672a\u542f\u7528\u3002")),(0,o.kt)("h3",{id:"92632-ensuretransaction-\u65b9\u6cd5-"},"9.26.3.2 ",(0,o.kt)("inlineCode",{parentName:"h3"},"EnsureTransaction()")," \u65b9\u6cd5 \u2728"),(0,o.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u901a\u8fc7\u9759\u6001\u7c7b\u6216\u8005\u5176\u4ed6\u65b9\u5f0f\u4e0d\u5c0f\u5fc3\u521b\u5efa\u4e86\u65b0\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"DbContext")," \u5b9e\u4f8b\uff0c\u8fd9\u65f6\u5019\u8d34\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"[UnitOfWork]")," \u4e5f\u4e0d\u89c1\u8d77\u6548\uff0c\u8fd9\u65f6\u5019\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u65b9\u6cd5\u6765\u786e\u8ba4\u4e8b\u52a1\u662f\u5426\u6709\u6548\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"repository.EnsureTransaction();\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u5982\u679c\u4e0d\u559c\u6b22\u624b\u52a8\u65b9\u5f0f\u4e5f\u53ef\u4ee5\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"strong"},"[UnitOfWork(true)]")," \u5f00\u542f\u6b64\u529f\u80fd\u3002")),(0,o.kt)("p",null,"\u8be5\u65b9\u6cd5\u4f1a\u5c06\u5f53\u524d\u4ed3\u50a8\u6dfb\u52a0\u5230\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6c60\u4e2d\uff0c\u5e76\u786e\u4fdd\u4e8b\u52a1\u53ef\u7528\u3002"),(0,o.kt)("h3",{id:"92632-\u624b\u52a8\u7ba1\u7406"},"9.26.3.2 \u624b\u52a8\u7ba1\u7406"),(0,o.kt)(i.Z,{defaultValue:"one",values:[{label:"\u793a\u4f8b\u4e00",value:"one"},{label:"\u793a\u4f8b\u4e8c",value:"two"},{label:"\u793a\u4f8b\u4e09\uff08\u5206\u5e03\u5f0f\uff09",value:"three"}],mdxType:"Tabs"},(0,o.kt)(l.Z,{value:"one",mdxType:"TabItem"},(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u5f00\u542f\u4e8b\u52a1\nusing (var transaction = _testRepository.Database.BeginTransaction())\n{\n try\n {\n _testRepository.Insert(new Blog { Url = "http://blogs.msdn.com/dotnet" });\n _testRepository.SaveNow();\n\n _testRepository.Insert(new Blog { Url = "http://blogs.msdn.com/visualstudio" });\n _testRepository.SaveNow();\n\n var blogs = _testRepository.Entity\n .OrderBy(b => b.Url)\n .ToList();\n\n // \u63d0\u4ea4\u4e8b\u52a1\n transaction.Commit();\n }\n catch (Exception)\n {\n // \u56de\u6eda\u4e8b\u52a1\n // transaction.RollBack(); // \u65b0\u7248\u672c\u81ea\u52a8\u56de\u6eda\u4e86\n }\n}\n'))),(0,o.kt)(l.Z,{value:"two",mdxType:"TabItem"},(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var options = new DbContextOptionsBuilder()\n .UseSqlServer(new SqlConnection(connectionString))\n .Options;\n\n// \u521b\u5efa\u8fde\u63a5\u5b57\u7b26\u4e32\nusing (var context1 = new DefaultDbContext(options))\n{\n // \u5f00\u542f\u4e8b\u52a1\n using (var transaction = context1.Database.BeginTransaction())\n {\n try\n {\n _testRepository.Insert(new Blog { Url = "http://blogs.msdn.com/dotnet" });\n _testRepository.SaveNow();\n\n context1.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });\n context1.SaveChanges();\n\n // \u521b\u5efa\u65b0\u7684\u8fde\u63a5\u5bf9\u8c61\n using (var context2 = new DefaultDbContext(options))\n {\n // \u5171\u4eab\u8fde\u63a5\u4e8b\u52a1\n context2.Database.UseTransaction(transaction.GetDbTransaction());\n\n var blogs = context2.Blogs\n .OrderBy(b => b.Url)\n .ToList();\n }\n\n // \u63d0\u4ea4\u4e8b\u52a1\n transaction.Commit();\n }\n catch (Exception)\n {\n // \u56de\u6eda\u4e8b\u52a1\n // transaction.RollBack(); // \u65b0\u7248\u672c\u81ea\u52a8\u56de\u6eda\u4e86\n }\n }\n}\n'))),(0,o.kt)(l.Z,{value:"three",mdxType:"TabItem"},(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-3}",showLineNumbers:!0,"":!0,"{1-3}":!0},'// \u5f00\u542f\u5206\u5e03\u5f0f\u4e8b\u52a1\n// \u5982\u679c\u4e8b\u52a1\u5305\u88f9\u7684\u4ee3\u7801\u4e2d\u5305\u542b\u5f02\u6b65 async/await\uff0c\u90a3\u4e48\u9700\u8981\u8bbe\u7f6e TransactionScopeAsyncFlowOption.Enabled = true\nusing (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }))\n{\n using (var connection = new SqlConnection(connectionString))\n {\n connection.Open();\n\n try\n {\n // \u8fd9\u91cc\u662f Ado.NET \u64cd\u4f5c\n var command = connection.CreateCommand();\n command.CommandText = "DELETE FROM dbo.Blogs";\n command.ExecuteNonQuery();\n\n // \u521b\u5efaEF Core \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n var options = new DbContextOptionsBuilder()\n .UseSqlServer(connection)\n .Options;\n using (var context = new BloggingContext(options))\n {\n context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });\n context.SaveChanges();\n }\n\n // \u6846\u67b6\u5c01\u88c5\u7684\u4ed3\u50a8\n _testRepository.Insert(new Blog { Url = "http://blogs.msdn.com/dotnet" });\n _testRepository.SaveChanges();\n\n // \u63d0\u4ea4\u4e8b\u52a1\n scope.Complete();\n }\n catch (System.Exception)\n {\n // \u81ea\u52a8\u56de\u6eda\n }\n }\n}\n')))),(0,o.kt)("h2",{id:"9264-\u5de5\u4f5c\u5355\u5143\u7279\u6027\u8bf4\u660e"},"9.26.4 \u5de5\u4f5c\u5355\u5143\u7279\u6027\u8bf4\u660e"),(0,o.kt)("h3",{id:"92641-unitofwork-\u7279\u6027"},"9.26.4.1 ",(0,o.kt)("inlineCode",{parentName:"h3"},"[UnitOfWork]")," \u7279\u6027"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"[UnitOfWork]")," \u7279\u6027\u53ea\u80fd\u7528\u4e8e\u63a7\u5236\u5668\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Action")," \u4e2d\uff0c\u4e00\u65e6\u8d34\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"[UnitOfWork]")," \u7279\u6027\u540e\uff0c\u90a3\u4e48\u8be5\u8bf7\u6c42\u81ea\u52a8\u542f\u7528\u5de5\u4f5c\u5355\u5143\u6a21\u5f0f\uff0c\u8981\u4e48\u6210\u529f\uff0c\u8981\u4e48\u5931\u8d25\u3002"),(0,o.kt)("h3",{id:"92642-manualcommit-\u7279\u6027"},"9.26.4.2 ",(0,o.kt)("inlineCode",{parentName:"h3"},"[ManualCommit]")," \u7279\u6027"),(0,o.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4f1a\u5728\u4e00\u6b21\u6210\u529f\u8bf7\u6c42\u4e4b\u540e\u81ea\u52a8\u8c03\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"SaveChanges()")," \u65b9\u6cd5\uff0c\u5982\u679c\u9009\u62e9\u624b\u52a8\u8c03\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"SaveChanges()")," \u65b9\u6cd5\uff0c\u53ef\u4ee5\u5728\u63a7\u5236\u5668 ",(0,o.kt)("inlineCode",{parentName:"p"},"Action")," \u4e2d\u8d34 ",(0,o.kt)("inlineCode",{parentName:"p"},"[ManualCommit]")," \u7279\u6027\u5373\u53ef\u3002"),(0,o.kt)("h2",{id:"9265-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.26.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,o.kt)("hr",null),(0,o.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,o.kt)("inlineCode",{parentName:"p"},"\u4e8b\u52a1")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,o.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/ef/core/saving/transactions"},"EF Core - \u4f7f\u7528\u4e8b\u52a1")," \u7ae0\u8282\u3002")))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/3427cf63.5efd64d8.js b/handbook/build/assets/js/3427cf63.5efd64d8.js deleted file mode 100644 index 9356b7c2e7..0000000000 --- a/handbook/build/assets/js/3427cf63.5efd64d8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[841],{8600:function(e,t,n){n.r(t),n.d(t,{assets:function(){return d},contentTitle:function(){return p},default:function(){return m},frontMatter:function(){return u},metadata:function(){return c},toc:function(){return s}});var r=n(3117),o=n(102),i=(n(7294),n(3905)),l=n(1402),a=["components"],u={id:"author",title:"1.2 \u5173\u4e8e\u4f5c\u8005",sidebar_label:"1.2 \u5173\u4e8e\u4f5c\u8005"},p=void 0,c={unversionedId:"author",id:"author",title:"1.2 \u5173\u4e8e\u4f5c\u8005",description:"",source:"@site/docs/author.mdx",sourceDirName:".",slug:"/author",permalink:"/furion/docs/author",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/author.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1661139023,formattedLastUpdatedAt:"Aug 22, 2022",frontMatter:{id:"author",title:"1.2 \u5173\u4e8e\u4f5c\u8005",sidebar_label:"1.2 \u5173\u4e8e\u4f5c\u8005"},sidebar:"docs",previous:{title:"1.1 \u4ecb\u7ecd",permalink:"/furion/docs/"},next:{title:"1.3 \u793a\u4f8b\u67b6\u6784\u8bf4\u660e",permalink:"/furion/docs/source"}},d={},s=[{value:"\u7f51\u540d",id:"\u7f51\u540d",level:2},{value:"\u4e13\u5c5e\u5934\u50cf",id:"\u4e13\u5c5e\u5934\u50cf",level:2},{value:"\u4e2a\u6027\u7b7e\u540d",id:"\u4e2a\u6027\u7b7e\u540d",level:2},{value:"\u5949\u732e\u5ba3\u8a00",id:"\u5949\u732e\u5ba3\u8a00",level:2},{value:"\u5f00\u6e90\u521d\u8877",id:"\u5f00\u6e90\u521d\u8877",level:2},{value:"\u5174\u8da3\u7231\u597d",id:"\u5174\u8da3\u7231\u597d",level:2},{value:"\u4e2a\u4eba\u4e3b\u9875",id:"\u4e2a\u4eba\u4e3b\u9875",level:2},{value:"\u6280\u672f\u80fd\u529b",id:"\u6280\u672f\u80fd\u529b",level:2},{value:"\u5e38\u7528\u5de5\u5177",id:"\u5e38\u7528\u5de5\u5177",level:2},{value:"\u9886\u57df\u5174\u8da3",id:"\u9886\u57df\u5174\u8da3",level:2}],f={toc:s};function m(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},f,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{title:"~",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u7eb5\u4f60\u9605\u4eba\u4f55\u5176\u591a\uff0c\u518d\u65e0\u4e00\u4eba\u6070\u4f3c\u6211\u3002")),(0,i.kt)("h2",{id:"\u7f51\u540d"},"\u7f51\u540d"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u767e\u5c0f\u50e7"),(0,i.kt)("li",{parentName:"ul"},"MonkSoul"),(0,i.kt)("li",{parentName:"ul"},"Rustln")),(0,i.kt)("h2",{id:"\u4e13\u5c5e\u5934\u50cf"},"\u4e13\u5c5e\u5934\u50cf"),(0,i.kt)("img",{src:(0,l.Z)("img/furionlogo.png")}),(0,i.kt)("p",null,"\u4e8e 2016 \u5e74 07 \u6708 14 \u65e5\uff0c\u4eb2\u81ea\u8bbe\u8ba1\u4e86\u8be5\u5934\u50cf\u3002"),(0,i.kt)("h2",{id:"\u4e2a\u6027\u7b7e\u540d"},"\u4e2a\u6027\u7b7e\u540d"),(0,i.kt)("p",null,"\u6210\u5728\u7ecf\u8425\uff0c\u8d25\u5728\u7ba1\u7406\uff0c\u9519\u5728\u4e0d\u5b66\u4e60\u3002"),(0,i.kt)("h2",{id:"\u5949\u732e\u5ba3\u8a00"},"\u5949\u732e\u5ba3\u8a00"),(0,i.kt)("p",null,"\u65e0\u79c1\u5949\u732e\u4e0d\u662f\u5929\u65b9\u591c\u8c2d\uff0c\u6709\u65f6\u5019\uff0c\u6211\u4eec\u4e5f\u53ef\u4ee5\u505a\u5230\u3002"),(0,i.kt)("h2",{id:"\u5f00\u6e90\u521d\u8877"},"\u5f00\u6e90\u521d\u8877"),(0,i.kt)("p",null,"\u5f00\u6e90\u5982\u540c\u4eba\u7684\u8138\uff0c\u597d\u574f\u4e00\u9762\u4fbf\u77e5\uff0c\u7f3a\u70b9\u53ef\u80fd\u4f1a\u53d7\u5230\u5632\u8bbd\u6279\u8bc4\uff0c\u4f18\u70b9\u4e5f\u4f1a\u6536\u83b7\u8d5e\u626c\u5c0a\u91cd\u3002\u522b\u62c5\u5fc3\uff0c\u4ed6\u4eec\u6b63\u5728\u5851\u9020\u66f4\u597d\u7684\u4f60\u3002"),(0,i.kt)("h2",{id:"\u5174\u8da3\u7231\u597d"},"\u5174\u8da3\u7231\u597d"),(0,i.kt)("p",null,"\u5bf9\u65b0\u6280\u672f\u9887\u611f\u5174\u8da3\uff0c\u559c\u6b22\u5f00\u6e90\u4e8b\u4e1a\uff0c\u559c\u6b22\u5206\u4eab\u6280\u672f\uff0c\u559c\u6b22\u8d5b\u8f66\uff0c\u559c\u6b22\u7eb9\u8eab\u6587\u5316\uff0c\u559c\u6b22\u79d1\u6280\u4ea7\u54c1\uff0c\u559c\u6b22\u7a7f\u8d8a\u706b\u7ebf\u548c\u6211\u7684\u4e16\u754c\u6e38\u620f\u3002"),(0,i.kt)("p",null,"\u559c\u6b22\u901b\u5f00\u6e90\u4e2d\u56fd\u3001IT \u4e4b\u5bb6\u3001Gitee/Github\u3001\u5237\u6296\u97f3\u3001\u770b\u52a8\u6f2b\u3001\u770b\u7f8e\u5267\u3002"),(0,i.kt)("h2",{id:"\u4e2a\u4eba\u4e3b\u9875"},"\u4e2a\u4eba\u4e3b\u9875"),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/monksoul"},"https://gitee.com/monksoul")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://github.com/monksoul"},"https://github.com/monksoul")),(0,i.kt)("h2",{id:"\u6280\u672f\u80fd\u529b"},"\u6280\u672f\u80fd\u529b"),(0,i.kt)("p",null,"\u5c0f\u50e7\u4e0d\u624d\uff0c\u81ea 2008 \u5e74 \u63a5\u89e6 IT \u884c\u4e1a\u6709\u5341\u4f59\u8f7d\uff0c\u5bf9\u4e92\u8054\u7f51\u4e3b\u6d41\u6280\u672f\u7565\u61c2\u76ae\u6bdb\uff0c\u6700\u559c\u6b22\u7684\u7f16\u7a0b\u6280\u672f\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"Rust")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"React"),"\u3002"),(0,i.kt)("h2",{id:"\u5e38\u7528\u5de5\u5177"},"\u5e38\u7528\u5de5\u5177"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Vim/NeoVim"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio Code"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"PostgreSQL"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2022"),"\u3002"),(0,i.kt)("h2",{id:"\u9886\u57df\u5174\u8da3"},"\u9886\u57df\u5174\u8da3"),(0,i.kt)("p",null,"\u5bf9\u8f6f\u4ef6\u5de5\u7a0b\u3001\u67b6\u6784\u3001\u5e95\u5c42\u3001\u7b97\u6cd5\u3001\u5d4c\u5165\u5f0f/\u5355\u7247\u673a\u3001\u7f51\u7edc\u7f16\u7a0b\u7b49\u9887\u611f\u5174\u8da3\u3002"))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return c},kt:function(){return f}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},s=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,c=a(e,["components","mdxType","originalType","parentName"]),s=p(n),f=o,m=s["".concat(u,".").concat(f)]||s[f]||d[f]||i;return n?r.createElement(m,l(l({ref:t},c),{},{components:n})):r.createElement(m,l({ref:t},c))}));function f(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,l=new Array(i);l[0]=s;var a={};for(var u in t)hasOwnProperty.call(t,u)&&(a[u]=t[u]);a.originalType=e,a.mdxType="string"==typeof e?e:o,l[1]=a;for(var p=2;p=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},s=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,c=a(e,["components","mdxType","originalType","parentName"]),s=p(n),f=o,m=s["".concat(u,".").concat(f)]||s[f]||d[f]||i;return n?r.createElement(m,l(l({ref:t},c),{},{components:n})):r.createElement(m,l({ref:t},c))}));function f(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,l=new Array(i);l[0]=s;var a={};for(var u in t)hasOwnProperty.call(t,u)&&(a[u]=t[u]);a.originalType=e,a.mdxType="string"==typeof e?e:o,l[1]=a;for(var p=2;p();\n")))}d.isMDXComponent=!0},3905:function(e,t,r){r.d(t,{Zo:function(){return u},kt:function(){return d}});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),f=p(r),d=o,b=f["".concat(c,".").concat(d)]||f[d]||s[d]||a;return r?n.createElement(b,i(i({ref:t},u),{},{components:r})):n.createElement(b,i({ref:t},u))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=f;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var p=2;p=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),f=p(r),d=o,b=f["".concat(c,".").concat(d)]||f[d]||s[d]||a;return r?n.createElement(b,i(i({ref:t},u),{},{components:r})):n.createElement(b,i({ref:t},u))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=f;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var p=2;p();\n")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/3653278d.7b1f8f0c.js b/handbook/build/assets/js/3653278d.7b1f8f0c.js new file mode 100644 index 0000000000..4de9000470 --- /dev/null +++ b/handbook/build/assets/js/3653278d.7b1f8f0c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[7132],{3905:function(e,n,t){t.d(n,{Zo:function(){return c},kt:function(){return d}});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function a(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var u=r.createContext({}),l=function(e){var n=r.useContext(u),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},c=function(e){var n=l(e.components);return r.createElement(u.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},m=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),m=l(t),d=o,y=m["".concat(u,".").concat(d)]||m[d]||p[d]||i;return t?r.createElement(y,a(a({ref:n},c),{},{components:t})):r.createElement(y,a({ref:n},c))}));function d(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=m;var s={};for(var u in n)hasOwnProperty.call(n,u)&&(s[u]=n[u]);s.originalType=e,s.mdxType="string"==typeof e?e:o,a[1]=s;for(var l=2;lSQL",id:"91221-\u521b\u5efa\u89c6\u56fe-sql",level:3},{value:"9.12.2.2 \u89c6\u56fe\u6a21\u578b",id:"91222-\u89c6\u56fe\u6a21\u578b",level:3},{value:"9.12.3 \u89c6\u56fe\u4f7f\u7528",id:"9123-\u89c6\u56fe\u4f7f\u7528",level:2},{value:"9.12.4 \u89c6\u56fe\u6700\u4f73\u8bfb\u53d6\u65b9\u5f0f \u2714",id:"9124-\u89c6\u56fe\u6700\u4f73\u8bfb\u53d6\u65b9\u5f0f-",level:2},{value:"9.12.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9125-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:p};function d(e){var n=e.components,t=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"9121-\u5173\u4e8e\u89c6\u56fe"},"9.12.1 \u5173\u4e8e\u89c6\u56fe"),(0,i.kt)("p",null,"\u89c6\u56fe\u662f\u6570\u636e\u5e93\u4e2d\u975e\u5e38\u91cd\u8981\u7684\u5bf9\u8c61\uff0c\u662f\u4e00\u5f20\u865a\u62df\u8868\uff0c\u901a\u8fc7\u89c6\u56fe\u6211\u4eec\u53ef\u4ee5\u5bf9\u7ed3\u679c\u8fdb\u884c\u7b5b\u9009\u7f13\u5b58\uff0c\u540c\u65f6\u8fd8\u80fd\u5b9e\u73b0\u9897\u7c92\u5316\u6743\u9650\u63a7\u5236\uff0c\u5982\u63a7\u5236\u6307\u5b9a\u884c\uff0c\u6307\u5b9a\u5217\u3002"),(0,i.kt)("h2",{id:"9122-\u89c6\u56fe\u7684\u4f7f\u7528"},"9.12.2 \u89c6\u56fe\u7684\u4f7f\u7528"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e2d\u5b9e\u73b0\u89c6\u56fe\u7684\u64cd\u4f5c\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700\u8981\u521b\u5efa\u89c6\u56fe\u6a21\u578b\uff0c\u5e76\u7ee7\u627f ",(0,i.kt)("inlineCode",{parentName:"p"},"EntityNotKey")," \u57fa\u7c7b\u5373\u53ef\u3002\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,i.kt)("h3",{id:"91221-\u521b\u5efa\u89c6\u56fe-sql"},"9.12.2.1 \u521b\u5efa\u89c6\u56fe ",(0,i.kt)("inlineCode",{parentName:"h3"},"SQL")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sql",metastring:"showLineNumbers",showLineNumbers:!0},"CREATE VIEW V_Person AS\nSELECT Id,Name,Age,Address FROM person\n")),(0,i.kt)("h3",{id:"91222-\u89c6\u56fe\u6a21\u578b"},"9.12.2.2 \u89c6\u56fe\u6a21\u578b"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,10}",showLineNumbers:!0,"":!0,"{5,10}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Core\n{\n public class V_Person : EntityNotKey\n {\n /// \n /// \u914d\u7f6e\u89c6\u56fe\u540d\n /// \n public V_Person() : base("V_Person")\n {\n }\n\n /// \n /// \u4e3b\u952eId\n /// \n public int Id { get; set; }\n\n /// \n /// \u59d3\u540d\n /// \n public string Name { get; set; }\n\n /// \n /// \u5e74\u9f84\n /// \n public int Age { get; set; }\n\n /// \n /// \u4f4f\u5740\n /// \n public string Address { get; set; }\n }\n}\n')),(0,i.kt)("admonition",{title:"\u89c6\u56fe\u540d\u79f0",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u89c6\u56fe\u5b9e\u4f53\u53ea\u9700\u8981\u7ee7\u627f ",(0,i.kt)("inlineCode",{parentName:"p"},"EntityNotKey")," \u57fa\u7c7b\u5e76\u7f16\u5199\u65e0\u53c2\u6784\u9020\u51fd\u6570\u7ee7\u627f ",(0,i.kt)("inlineCode",{parentName:"p"},'base("\u89c6\u56fe\u540d\u79f0")')," \u5373\u53ef\u3002")),(0,i.kt)("h2",{id:"9123-\u89c6\u56fe\u4f7f\u7528"},"9.12.3 \u89c6\u56fe\u4f7f\u7528"),(0,i.kt)("p",null,"\u89c6\u56fe\u9664\u4e86\u4e0d\u80fd\u64cd\u4f5c\uff08\u5199\uff09\u4ee5\u5916\uff0c\u5176\u4ed6\u64cd\u4f5c\u548c\u8868\u64cd\u4f5c\u65e0\u5f02\u3002"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var vEntities = v_repository.Where(u => u.Id >10).ToList();\n")),(0,i.kt)("h2",{id:"9124-\u89c6\u56fe\u6700\u4f73\u8bfb\u53d6\u65b9\u5f0f-"},"9.12.4 \u89c6\u56fe\u6700\u4f73\u8bfb\u53d6\u65b9\u5f0f \u2714"),(0,i.kt)("p",null,"\u7531\u4e8e\u89c6\u56fe\u662f\u865a\u62df\u8868\uff0c\u4e0d\u5e94\u8be5\u5bf9\u5176\u8fdb\u884c\u5199\u64cd\u4f5c\uff0c\u6240\u4ee5\u5e94\u8be5\u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u53ea\u8bfb\u4ed3\u50a8\u521d\u59cb\u5316\u89c6\u56fe"),"\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11,13,16}",showLineNumbers:!0,"":!0,"{11,13,16}":!0},"using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing Furion.DynamicApiController;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\nnamespace Furion.Application.Persons\n{\n public class FurionService : IDynamicApiController\n {\n private readonly IReadableRepository _readableRepository;\n\n public FurionService(IRepository repository)\n {\n // \u521d\u59cb\u5316\u53ea\u8bfb\u4ed3\u50a8\n _readableRepository = repository.Constraint>();\n }\n\n /// \n /// \u8bfb\u53d6\u89c6\u56fe\n /// \n /// \n public async Task> GetVPerson()\n {\n var list = await _readableRepository.AsQueryable().ToListAsync();\n return list;\n }\n }\n}\n")),(0,i.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},".Constraint")," \u65b9\u6cd5\u53ef\u4ee5\u5c06\u4ed3\u50a8\u7ea6\u675f\u4e3a\u7279\u5b9a\u4ed3\u50a8\uff0c\u5982\u53ea\u8bfb\u4ed3\u50a8\uff0c\u53ef\u8bfb\u53ef\u5199\u4ed3\u50a8\uff0c\u53ea\u65b0\u589e\u4ed3\u50a8\u7b49\u3002")),(0,i.kt)("h2",{id:"9125-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.12.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/3653278d.8bc48f2c.js b/handbook/build/assets/js/3653278d.8bc48f2c.js deleted file mode 100644 index 0dc3dfa851..0000000000 --- a/handbook/build/assets/js/3653278d.8bc48f2c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[7132],{3614:function(e,n,t){t.r(n),t.d(n,{assets:function(){return c},contentTitle:function(){return u},default:function(){return d},frontMatter:function(){return s},metadata:function(){return l},toc:function(){return p}});var r=t(3117),o=t(102),i=(t(7294),t(3905)),a=["components"],s={id:"dbcontext-view",title:"9.12 \u89c6\u56fe\u64cd\u4f5c",sidebar_label:"9.12 \u89c6\u56fe\u64cd\u4f5c"},u=void 0,l={unversionedId:"dbcontext-view",id:"dbcontext-view",title:"9.12 \u89c6\u56fe\u64cd\u4f5c",description:"9.12.1 \u5173\u4e8e\u89c6\u56fe",source:"@site/docs/dbcontext-view.mdx",sourceDirName:".",slug:"/dbcontext-view",permalink:"/furion/docs/dbcontext-view",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-view.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"dbcontext-view",title:"9.12 \u89c6\u56fe\u64cd\u4f5c",sidebar_label:"9.12 \u89c6\u56fe\u64cd\u4f5c"},sidebar:"docs",previous:{title:"9.11 \u9ad8\u7ea7\u67e5\u8be2\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-hight-query"},next:{title:"9.13 \u5b58\u50a8\u8fc7\u7a0b\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-proc"}},c={},p=[{value:"9.12.1 \u5173\u4e8e\u89c6\u56fe",id:"9121-\u5173\u4e8e\u89c6\u56fe",level:2},{value:"9.12.2 \u89c6\u56fe\u7684\u4f7f\u7528",id:"9122-\u89c6\u56fe\u7684\u4f7f\u7528",level:2},{value:"9.12.2.1 \u521b\u5efa\u89c6\u56fe SQL",id:"91221-\u521b\u5efa\u89c6\u56fe-sql",level:3},{value:"9.12.2.2 \u89c6\u56fe\u6a21\u578b",id:"91222-\u89c6\u56fe\u6a21\u578b",level:3},{value:"9.12.3 \u89c6\u56fe\u4f7f\u7528",id:"9123-\u89c6\u56fe\u4f7f\u7528",level:2},{value:"9.12.4 \u89c6\u56fe\u6700\u4f73\u8bfb\u53d6\u65b9\u5f0f \u2714",id:"9124-\u89c6\u56fe\u6700\u4f73\u8bfb\u53d6\u65b9\u5f0f-",level:2},{value:"9.12.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9125-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:p};function d(e){var n=e.components,t=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"9121-\u5173\u4e8e\u89c6\u56fe"},"9.12.1 \u5173\u4e8e\u89c6\u56fe"),(0,i.kt)("p",null,"\u89c6\u56fe\u662f\u6570\u636e\u5e93\u4e2d\u975e\u5e38\u91cd\u8981\u7684\u5bf9\u8c61\uff0c\u662f\u4e00\u5f20\u865a\u62df\u8868\uff0c\u901a\u8fc7\u89c6\u56fe\u6211\u4eec\u53ef\u4ee5\u5bf9\u7ed3\u679c\u8fdb\u884c\u7b5b\u9009\u7f13\u5b58\uff0c\u540c\u65f6\u8fd8\u80fd\u5b9e\u73b0\u9897\u7c92\u5316\u6743\u9650\u63a7\u5236\uff0c\u5982\u63a7\u5236\u6307\u5b9a\u884c\uff0c\u6307\u5b9a\u5217\u3002"),(0,i.kt)("h2",{id:"9122-\u89c6\u56fe\u7684\u4f7f\u7528"},"9.12.2 \u89c6\u56fe\u7684\u4f7f\u7528"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e2d\u5b9e\u73b0\u89c6\u56fe\u7684\u64cd\u4f5c\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700\u8981\u521b\u5efa\u89c6\u56fe\u6a21\u578b\uff0c\u5e76\u7ee7\u627f ",(0,i.kt)("inlineCode",{parentName:"p"},"EntityNotKey")," \u57fa\u7c7b\u5373\u53ef\u3002\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,i.kt)("h3",{id:"91221-\u521b\u5efa\u89c6\u56fe-sql"},"9.12.2.1 \u521b\u5efa\u89c6\u56fe ",(0,i.kt)("inlineCode",{parentName:"h3"},"SQL")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sql",metastring:"showLineNumbers",showLineNumbers:!0},"CREATE VIEW V_Person AS\nSELECT Id,Name,Age,Address FROM person\n")),(0,i.kt)("h3",{id:"91222-\u89c6\u56fe\u6a21\u578b"},"9.12.2.2 \u89c6\u56fe\u6a21\u578b"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,10}",showLineNumbers:!0,"":!0,"{5,10}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Core\n{\n public class V_Person : EntityNotKey\n {\n /// \n /// \u914d\u7f6e\u89c6\u56fe\u540d\n /// \n public V_Person() : base("V_Person")\n {\n }\n\n /// \n /// \u4e3b\u952eId\n /// \n public int Id { get; set; }\n\n /// \n /// \u59d3\u540d\n /// \n public string Name { get; set; }\n\n /// \n /// \u5e74\u9f84\n /// \n public int Age { get; set; }\n\n /// \n /// \u4f4f\u5740\n /// \n public string Address { get; set; }\n }\n}\n')),(0,i.kt)("admonition",{title:"\u89c6\u56fe\u540d\u79f0",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u89c6\u56fe\u5b9e\u4f53\u53ea\u9700\u8981\u7ee7\u627f ",(0,i.kt)("inlineCode",{parentName:"p"},"EntityNotKey")," \u57fa\u7c7b\u5e76\u7f16\u5199\u65e0\u53c2\u6784\u9020\u51fd\u6570\u7ee7\u627f ",(0,i.kt)("inlineCode",{parentName:"p"},'base("\u89c6\u56fe\u540d\u79f0")')," \u5373\u53ef\u3002")),(0,i.kt)("h2",{id:"9123-\u89c6\u56fe\u4f7f\u7528"},"9.12.3 \u89c6\u56fe\u4f7f\u7528"),(0,i.kt)("p",null,"\u89c6\u56fe\u9664\u4e86\u4e0d\u80fd\u64cd\u4f5c\uff08\u5199\uff09\u4ee5\u5916\uff0c\u5176\u4ed6\u64cd\u4f5c\u548c\u8868\u64cd\u4f5c\u65e0\u5f02\u3002"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var vEntities = v_repository.Where(u => u.Id >10).ToList();\n")),(0,i.kt)("h2",{id:"9124-\u89c6\u56fe\u6700\u4f73\u8bfb\u53d6\u65b9\u5f0f-"},"9.12.4 \u89c6\u56fe\u6700\u4f73\u8bfb\u53d6\u65b9\u5f0f \u2714"),(0,i.kt)("p",null,"\u7531\u4e8e\u89c6\u56fe\u662f\u865a\u62df\u8868\uff0c\u4e0d\u5e94\u8be5\u5bf9\u5176\u8fdb\u884c\u5199\u64cd\u4f5c\uff0c\u6240\u4ee5\u5e94\u8be5\u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u53ea\u8bfb\u4ed3\u50a8\u521d\u59cb\u5316\u89c6\u56fe"),"\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11,13,16}",showLineNumbers:!0,"":!0,"{11,13,16}":!0},"using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing Furion.DynamicApiController;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\nnamespace Furion.Application.Persons\n{\n public class FurionService : IDynamicApiController\n {\n private readonly IReadableRepository _readableRepository;\n\n public FurionService(IRepository repository)\n {\n // \u521d\u59cb\u5316\u53ea\u8bfb\u4ed3\u50a8\n _readableRepository = repository.Constraint>();\n }\n\n /// \n /// \u8bfb\u53d6\u89c6\u56fe\n /// \n /// \n public async Task> GetVPerson()\n {\n var list = await _readableRepository.AsQueryable().ToListAsync();\n return list;\n }\n }\n}\n")),(0,i.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},".Constraint")," \u65b9\u6cd5\u53ef\u4ee5\u5c06\u4ed3\u50a8\u7ea6\u675f\u4e3a\u7279\u5b9a\u4ed3\u50a8\uff0c\u5982\u53ea\u8bfb\u4ed3\u50a8\uff0c\u53ef\u8bfb\u53ef\u5199\u4ed3\u50a8\uff0c\u53ea\u65b0\u589e\u4ed3\u50a8\u7b49\u3002")),(0,i.kt)("h2",{id:"9125-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.12.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}d.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return c},kt:function(){return d}});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function a(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var u=r.createContext({}),l=function(e){var n=r.useContext(u),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},c=function(e){var n=l(e.components);return r.createElement(u.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},m=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),m=l(t),d=o,y=m["".concat(u,".").concat(d)]||m[d]||p[d]||i;return t?r.createElement(y,a(a({ref:n},c),{},{components:t})):r.createElement(y,a({ref:n},c))}));function d(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=m;var s={};for(var u in n)hasOwnProperty.call(n,u)&&(s[u]=n[u]);s.originalType=e,s.mdxType="string"==typeof e?e:o,a[1]=s;for(var l=2;l=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var i=n.createContext({}),c=function(e){var t=n.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(i.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},b=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,i=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),b=c(r),d=o,m=b["".concat(i,".").concat(d)]||b[d]||p[d]||a;return r?n.createElement(m,l(l({ref:t},u),{},{components:r})):n.createElement(m,l({ref:t},u))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,l=new Array(a);l[0]=b;var s={};for(var i in t)hasOwnProperty.call(t,i)&&(s[i]=t[i]);s.originalType=e,s.mdxType="string"==typeof e?e:o,l[1]=s;for(var c=2;cSql \u4ed3\u50a8",id:"24-\u83b7\u53d6-sql-\u4ed3\u50a8",level:2},{value:"2.5 \u83b7\u53d6 Sql \u5b9a\u4f4d\u5668\u4ed3\u50a8",id:"25-\u83b7\u53d6-sql-\u5b9a\u4f4d\u5668\u4ed3\u50a8",level:2},{value:"2.6 \u83b7\u53d6 Sql \u4ee3\u7406\u5bf9\u8c61",id:"26-\u83b7\u53d6-sql-\u4ee3\u7406\u5bf9\u8c61",level:2},{value:"2.7 \u83b7\u53d6\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"27-\u83b7\u53d6\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:2},{value:"2.8 \u83b7\u53d6\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"28-\u83b7\u53d6\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:2},{value:"2.9 \u521b\u5efa\u65b0\u7684\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"29-\u521b\u5efa\u65b0\u7684\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:2},{value:"2.10 \u521b\u5efa\u65b0\u7684\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"210-\u521b\u5efa\u65b0\u7684\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:2},{value:"2.11 \u6839\u636e\u5b9a\u4f4d\u5668\u7c7b\u578b\u83b7\u53d6\u4ed3\u50a8",id:"211-\u6839\u636e\u5b9a\u4f4d\u5668\u7c7b\u578b\u83b7\u53d6\u4ed3\u50a8",level:2},{value:"2.12 \u83b7\u53d6 \u4e3b\u4ece\u5e93 \u4ed3\u50a8",id:"212-\u83b7\u53d6-\u4e3b\u4ece\u5e93-\u4ed3\u50a8",level:2},{value:"2.13 \u83b7\u53d6 Sql \u4e3b\u5e93\u5b9a\u4f4d\u5668\u4ed3\u50a8",id:"213-\u83b7\u53d6-sql-\u4e3b\u5e93\u5b9a\u4f4d\u5668\u4ed3\u50a8",level:2},{value:"2.14 \u83b7\u53d6\u7279\u5b9a\u5b9a\u4f4d\u5668\u4ed3\u50a8",id:"214-\u83b7\u53d6\u7279\u5b9a\u5b9a\u4f4d\u5668\u4ed3\u50a8",level:2}],b={toc:p};function d(e){var t=e.components,r=(0,o.Z)(e,l);return(0,a.kt)("wrapper",(0,n.Z)({},b,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"21-\u83b7\u53d6\u975e\u6cdb\u578b\u4ed3\u50a8"},"2.1 \u83b7\u53d6\u975e\u6cdb\u578b\u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var repository = Db.GetRepository();\n")),(0,a.kt)("h2",{id:"22-\u83b7\u53d6\u6cdb\u578b\u4ed3\u50a8"},"2.2 \u83b7\u53d6\u6cdb\u578b\u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var entityRepository = Db.GetRepository();\n")),(0,a.kt)("h2",{id:"23-\u83b7\u53d6\u5e26\u5b9a\u4f4d\u5668\u6cdb\u578b\u4ed3\u50a8"},"2.3 \u83b7\u53d6\u5e26\u5b9a\u4f4d\u5668\u6cdb\u578b\u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var locatorRepository = Db.GetRepository();\n")),(0,a.kt)("h2",{id:"24-\u83b7\u53d6-sql-\u4ed3\u50a8"},"2.4 \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Sql")," \u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var sqlRepository = Db.GetSqlRepository();\n")),(0,a.kt)("h2",{id:"25-\u83b7\u53d6-sql-\u5b9a\u4f4d\u5668\u4ed3\u50a8"},"2.5 \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Sql")," \u5b9a\u4f4d\u5668\u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var sqlLocatorRepository = Db.GetSqlRepository();\n")),(0,a.kt)("h2",{id:"26-\u83b7\u53d6-sql-\u4ee3\u7406\u5bf9\u8c61"},"2.6 \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Sql")," \u4ee3\u7406\u5bf9\u8c61"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var sqlProxy= Db.GetSqlProxy();\n")),(0,a.kt)("h2",{id:"27-\u83b7\u53d6\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.7 \u83b7\u53d6\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var dbContext = Db.GetDbContext();\n")),(0,a.kt)("h2",{id:"28-\u83b7\u53d6\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.8 \u83b7\u53d6\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var locatorDbContext = Db.GetDbContext();\nvar locatorDbContext2 = Db.GetDbContext(typeof(TDbContextLocator));\n")),(0,a.kt)("h2",{id:"29-\u521b\u5efa\u65b0\u7684\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.9 \u521b\u5efa\u65b0\u7684\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var dbContext = Db.GetNewDbContext();\n")),(0,a.kt)("h2",{id:"210-\u521b\u5efa\u65b0\u7684\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.10 \u521b\u5efa\u65b0\u7684\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var locatorDbContext = Db.GetNewDbContext();\nvar locatorDbContext2 = Db.GetNewDbContext(typeof(TDbContextLocator));\n")),(0,a.kt)("h2",{id:"211-\u6839\u636e\u5b9a\u4f4d\u5668\u7c7b\u578b\u83b7\u53d6\u4ed3\u50a8"},"2.11 \u6839\u636e\u5b9a\u4f4d\u5668\u7c7b\u578b\u83b7\u53d6\u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var repository = Db.GetRepository(dbContextLocatorType);\n")),(0,a.kt)("h2",{id:"212-\u83b7\u53d6-\u4e3b\u4ece\u5e93-\u4ed3\u50a8"},"2.12 \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"\u4e3b\u4ece\u5e93")," \u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var msRepository = Db.GetMSRepository();\n")),(0,a.kt)("h2",{id:"213-\u83b7\u53d6-sql-\u4e3b\u5e93\u5b9a\u4f4d\u5668\u4ed3\u50a8"},"2.13 \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Sql")," \u4e3b\u5e93\u5b9a\u4f4d\u5668\u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var msLocatorRepository = Db.GetMSRepository();\n")),(0,a.kt)("h2",{id:"214-\u83b7\u53d6\u7279\u5b9a\u5b9a\u4f4d\u5668\u4ed3\u50a8"},"2.14 \u83b7\u53d6\u7279\u5b9a\u5b9a\u4f4d\u5668\u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var msLocatorRepository = Db.GetDbRepository();\n")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/3a136e85.cdf57f74.js b/handbook/build/assets/js/3a136e85.cdf57f74.js deleted file mode 100644 index a399651dd2..0000000000 --- a/handbook/build/assets/js/3a136e85.cdf57f74.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[1254],{1540:function(e,t,r){r.r(t),r.d(t,{assets:function(){return u},contentTitle:function(){return i},default:function(){return d},frontMatter:function(){return s},metadata:function(){return c},toc:function(){return p}});var n=r(3117),o=r(102),a=(r(7294),r(3905)),l=["components"],s={id:"db",title:"2. Db \u9759\u6001\u7c7b",sidebar_label:"2. Db \u9759\u6001\u7c7b"},i=void 0,c={unversionedId:"global/db",id:"global/db",title:"2. Db \u9759\u6001\u7c7b",description:"2.1 \u83b7\u53d6\u975e\u6cdb\u578b\u4ed3\u50a8",source:"@site/docs/global/db.mdx",sourceDirName:"global",slug:"/global/db",permalink:"/furion/docs/global/db",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/global/db.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"db",title:"2. Db \u9759\u6001\u7c7b",sidebar_label:"2. Db \u9759\u6001\u7c7b"},sidebar:"global",previous:{title:"1. App \u9759\u6001\u7c7b",permalink:"/furion/docs/global/app"},next:{title:"3. DataValidator \u9759\u6001\u7c7b",permalink:"/furion/docs/global/datavalidator"}},u={},p=[{value:"2.1 \u83b7\u53d6\u975e\u6cdb\u578b\u4ed3\u50a8",id:"21-\u83b7\u53d6\u975e\u6cdb\u578b\u4ed3\u50a8",level:2},{value:"2.2 \u83b7\u53d6\u6cdb\u578b\u4ed3\u50a8",id:"22-\u83b7\u53d6\u6cdb\u578b\u4ed3\u50a8",level:2},{value:"2.3 \u83b7\u53d6\u5e26\u5b9a\u4f4d\u5668\u6cdb\u578b\u4ed3\u50a8",id:"23-\u83b7\u53d6\u5e26\u5b9a\u4f4d\u5668\u6cdb\u578b\u4ed3\u50a8",level:2},{value:"2.4 \u83b7\u53d6 Sql \u4ed3\u50a8",id:"24-\u83b7\u53d6-sql-\u4ed3\u50a8",level:2},{value:"2.5 \u83b7\u53d6 Sql \u5b9a\u4f4d\u5668\u4ed3\u50a8",id:"25-\u83b7\u53d6-sql-\u5b9a\u4f4d\u5668\u4ed3\u50a8",level:2},{value:"2.6 \u83b7\u53d6 Sql \u4ee3\u7406\u5bf9\u8c61",id:"26-\u83b7\u53d6-sql-\u4ee3\u7406\u5bf9\u8c61",level:2},{value:"2.7 \u83b7\u53d6\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"27-\u83b7\u53d6\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:2},{value:"2.8 \u83b7\u53d6\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"28-\u83b7\u53d6\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:2},{value:"2.9 \u521b\u5efa\u65b0\u7684\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"29-\u521b\u5efa\u65b0\u7684\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:2},{value:"2.10 \u521b\u5efa\u65b0\u7684\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"210-\u521b\u5efa\u65b0\u7684\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:2},{value:"2.11 \u6839\u636e\u5b9a\u4f4d\u5668\u7c7b\u578b\u83b7\u53d6\u4ed3\u50a8",id:"211-\u6839\u636e\u5b9a\u4f4d\u5668\u7c7b\u578b\u83b7\u53d6\u4ed3\u50a8",level:2},{value:"2.12 \u83b7\u53d6 \u4e3b\u4ece\u5e93 \u4ed3\u50a8",id:"212-\u83b7\u53d6-\u4e3b\u4ece\u5e93-\u4ed3\u50a8",level:2},{value:"2.13 \u83b7\u53d6 Sql \u4e3b\u5e93\u5b9a\u4f4d\u5668\u4ed3\u50a8",id:"213-\u83b7\u53d6-sql-\u4e3b\u5e93\u5b9a\u4f4d\u5668\u4ed3\u50a8",level:2},{value:"2.14 \u83b7\u53d6\u7279\u5b9a\u5b9a\u4f4d\u5668\u4ed3\u50a8",id:"214-\u83b7\u53d6\u7279\u5b9a\u5b9a\u4f4d\u5668\u4ed3\u50a8",level:2}],b={toc:p};function d(e){var t=e.components,r=(0,o.Z)(e,l);return(0,a.kt)("wrapper",(0,n.Z)({},b,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"21-\u83b7\u53d6\u975e\u6cdb\u578b\u4ed3\u50a8"},"2.1 \u83b7\u53d6\u975e\u6cdb\u578b\u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var repository = Db.GetRepository();\n")),(0,a.kt)("h2",{id:"22-\u83b7\u53d6\u6cdb\u578b\u4ed3\u50a8"},"2.2 \u83b7\u53d6\u6cdb\u578b\u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var entityRepository = Db.GetRepository();\n")),(0,a.kt)("h2",{id:"23-\u83b7\u53d6\u5e26\u5b9a\u4f4d\u5668\u6cdb\u578b\u4ed3\u50a8"},"2.3 \u83b7\u53d6\u5e26\u5b9a\u4f4d\u5668\u6cdb\u578b\u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var locatorRepository = Db.GetRepository();\n")),(0,a.kt)("h2",{id:"24-\u83b7\u53d6-sql-\u4ed3\u50a8"},"2.4 \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Sql")," \u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var sqlRepository = Db.GetSqlRepository();\n")),(0,a.kt)("h2",{id:"25-\u83b7\u53d6-sql-\u5b9a\u4f4d\u5668\u4ed3\u50a8"},"2.5 \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Sql")," \u5b9a\u4f4d\u5668\u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var sqlLocatorRepository = Db.GetSqlRepository();\n")),(0,a.kt)("h2",{id:"26-\u83b7\u53d6-sql-\u4ee3\u7406\u5bf9\u8c61"},"2.6 \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Sql")," \u4ee3\u7406\u5bf9\u8c61"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var sqlProxy= Db.GetSqlProxy();\n")),(0,a.kt)("h2",{id:"27-\u83b7\u53d6\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.7 \u83b7\u53d6\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var dbContext = Db.GetDbContext();\n")),(0,a.kt)("h2",{id:"28-\u83b7\u53d6\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.8 \u83b7\u53d6\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var locatorDbContext = Db.GetDbContext();\nvar locatorDbContext2 = Db.GetDbContext(typeof(TDbContextLocator));\n")),(0,a.kt)("h2",{id:"29-\u521b\u5efa\u65b0\u7684\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.9 \u521b\u5efa\u65b0\u7684\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var dbContext = Db.GetNewDbContext();\n")),(0,a.kt)("h2",{id:"210-\u521b\u5efa\u65b0\u7684\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.10 \u521b\u5efa\u65b0\u7684\u5b9a\u4f4d\u5668\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var locatorDbContext = Db.GetNewDbContext();\nvar locatorDbContext2 = Db.GetNewDbContext(typeof(TDbContextLocator));\n")),(0,a.kt)("h2",{id:"211-\u6839\u636e\u5b9a\u4f4d\u5668\u7c7b\u578b\u83b7\u53d6\u4ed3\u50a8"},"2.11 \u6839\u636e\u5b9a\u4f4d\u5668\u7c7b\u578b\u83b7\u53d6\u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var repository = Db.GetRepository(dbContextLocatorType);\n")),(0,a.kt)("h2",{id:"212-\u83b7\u53d6-\u4e3b\u4ece\u5e93-\u4ed3\u50a8"},"2.12 \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"\u4e3b\u4ece\u5e93")," \u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var msRepository = Db.GetMSRepository();\n")),(0,a.kt)("h2",{id:"213-\u83b7\u53d6-sql-\u4e3b\u5e93\u5b9a\u4f4d\u5668\u4ed3\u50a8"},"2.13 \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Sql")," \u4e3b\u5e93\u5b9a\u4f4d\u5668\u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var msLocatorRepository = Db.GetMSRepository();\n")),(0,a.kt)("h2",{id:"214-\u83b7\u53d6\u7279\u5b9a\u5b9a\u4f4d\u5668\u4ed3\u50a8"},"2.14 \u83b7\u53d6\u7279\u5b9a\u5b9a\u4f4d\u5668\u4ed3\u50a8"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var msLocatorRepository = Db.GetDbRepository();\n")))}d.isMDXComponent=!0},3905:function(e,t,r){r.d(t,{Zo:function(){return u},kt:function(){return d}});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var i=n.createContext({}),c=function(e){var t=n.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(i.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},b=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,i=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),b=c(r),d=o,m=b["".concat(i,".").concat(d)]||b[d]||p[d]||a;return r?n.createElement(m,l(l({ref:t},u),{},{components:r})):n.createElement(m,l({ref:t},u))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,l=new Array(a);l[0]=b;var s={};for(var i in t)hasOwnProperty.call(t,i)&&(s[i]=t[i]);s.originalType=e,s.mdxType="string"==typeof e?e:o,l[1]=s;for(var c=2;c=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},u=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),m=c(n),f=a,d=m["".concat(l,".").concat(f)]||m[f]||p[f]||o;return n?r.createElement(d,s(s({ref:t},u),{},{components:n})):r.createElement(d,s({ref:t},u))}));function f(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,s=new Array(o);s[0]=m;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i.mdxType="string"==typeof e?e:a,s[1]=i;for(var c=2;c {\n Console.WriteLine("\u6211\u662f\u52a8\u6001\u7684");\n await Task.CompletedTask;\n});\n')),(0,o.kt)("h2",{id:"92-\u53d1\u9001\u6d88\u606f"},"9.2 \u53d1\u9001\u6d88\u606f"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await MessageCenter.PublishAsync("messageId", new {});\n\n// \u8bf8\u591a\u91cd\u8f7d\n')),(0,o.kt)("h2",{id:"93-\u53d6\u6d88\u8ba2\u9605"},"9.3 \u53d6\u6d88\u8ba2\u9605"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'MessageCenter.Unsubscribe("messageId");\n')))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/3d66e15d.dfbcc1cc.js b/handbook/build/assets/js/3d66e15d.dfbcc1cc.js deleted file mode 100644 index 5e909d2fc7..0000000000 --- a/handbook/build/assets/js/3d66e15d.dfbcc1cc.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4012],{938:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return l},default:function(){return f},frontMatter:function(){return i},metadata:function(){return c},toc:function(){return p}});var r=n(3117),a=n(102),o=(n(7294),n(3905)),s=["components"],i={id:"messagecenter",title:"9. MessageCenter \u9759\u6001\u7c7b",sidebar_label:"9. MessageCenter \u9759\u6001\u7c7b"},l=void 0,c={unversionedId:"global/messagecenter",id:"global/messagecenter",title:"9. MessageCenter \u9759\u6001\u7c7b",description:"9.1 \u52a8\u6001\u8ba2\u9605\u6d88\u606f",source:"@site/docs/global/messagecenter.mdx",sourceDirName:"global",slug:"/global/messagecenter",permalink:"/furion/docs/global/messagecenter",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/global/messagecenter.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1661825584,formattedLastUpdatedAt:"Aug 30, 2022",frontMatter:{id:"messagecenter",title:"9. MessageCenter \u9759\u6001\u7c7b",sidebar_label:"9. MessageCenter \u9759\u6001\u7c7b"},sidebar:"global",previous:{title:"8. L \u9759\u6001\u7c7b",permalink:"/furion/docs/global/l"},next:{title:"10. JSON \u9759\u6001\u7c7b",permalink:"/furion/docs/global/json"}},u={},p=[{value:"9.1 \u52a8\u6001\u8ba2\u9605\u6d88\u606f",id:"91-\u52a8\u6001\u8ba2\u9605\u6d88\u606f",level:2},{value:"9.2 \u53d1\u9001\u6d88\u606f",id:"92-\u53d1\u9001\u6d88\u606f",level:2},{value:"9.3 \u53d6\u6d88\u8ba2\u9605",id:"93-\u53d6\u6d88\u8ba2\u9605",level:2}],m={toc:p};function f(e){var t=e.components,n=(0,a.Z)(e,s);return(0,o.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"91-\u52a8\u6001\u8ba2\u9605\u6d88\u606f"},"9.1 \u52a8\u6001\u8ba2\u9605\u6d88\u606f"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'MessageCenter.Subscribe("messageId", async (ctx) => {\n Console.WriteLine("\u6211\u662f\u52a8\u6001\u7684");\n await Task.CompletedTask;\n});\n')),(0,o.kt)("h2",{id:"92-\u53d1\u9001\u6d88\u606f"},"9.2 \u53d1\u9001\u6d88\u606f"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await MessageCenter.PublishAsync("messageId", new {});\n\n// \u8bf8\u591a\u91cd\u8f7d\n')),(0,o.kt)("h2",{id:"93-\u53d6\u6d88\u8ba2\u9605"},"9.3 \u53d6\u6d88\u8ba2\u9605"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'MessageCenter.Unsubscribe("messageId");\n')))}f.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return u},kt:function(){return f}});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function s(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},u=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),m=c(n),f=a,d=m["".concat(l,".").concat(f)]||m[f]||p[f]||o;return n?r.createElement(d,s(s({ref:t},u),{},{components:n})):r.createElement(d,s({ref:t},u))}));function f(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,s=new Array(o);s[0]=m;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i.mdxType="string"==typeof e?e:a,s[1]=i;for(var c=2;cCookie \u4f7f\u7528",id:"3221-cookie-\u4f7f\u7528",level:3},{value:"32.2.2 Session \u4f7f\u7528",id:"3222-session-\u4f7f\u7528",level:3},{value:"32.2.3 Query Strings \u4f7f\u7528",id:"3223-query-strings-\u4f7f\u7528",level:3},{value:"32.2.4 HttpContext.Items \u4f7f\u7528",id:"3224-httpcontextitems-\u4f7f\u7528",level:3},{value:"32.2.5 Cache \u65b9\u5f0f",id:"3225-cache-\u65b9\u5f0f",level:3},{value:"32.2.6 AsyncLocal<T> \u65b9\u5f0f",id:"3226-asynclocalt-\u65b9\u5f0f",level:3},{value:"32.3 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"323-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:u};function m(e){var n=e.components,t=(0,i.Z)(e,s);return(0,o.kt)("wrapper",(0,a.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"321-\u5173\u4e8e\u4f1a\u8bdd\u548c\u72b6\u6001\u7ba1\u7406"},"32.1 \u5173\u4e8e\u4f1a\u8bdd\u548c\u72b6\u6001\u7ba1\u7406"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"HTTP")," \u662f\u65e0\u72b6\u6001\u7684\u534f\u8bae\u3002 \u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"HTTP")," \u8bf7\u6c42\u662f\u4e0d\u4fdd\u7559\u7528\u6237\u503c\u7684\u72ec\u7acb\u6d88\u606f\u3002\u4f46\u662f\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u51e0\u79cd\u65b9\u5f0f\u4fdd\u7559\u8bf7\u6c42\u7528\u6237\u6570\u636e\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Cookie"),"\uff1a\u901a\u5e38\u5b58\u50a8\u5728\u5ba2\u6237\u7aef\u7684\u6570\u636e\uff0c\u8bf7\u6c42\u65f6\u5e26\u56de\u670d\u52a1\u7aef"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Session"),"\uff1a\u5b58\u50a8\u5728\u670d\u52a1\u7aef\u7684\u6570\u636e\uff08\u53ef\u4ee5\u5728\u5b58\u50a8\u5728\u5185\u5b58\u3001\u8fdb\u7a0b\u7b49\u4ecb\u8d28\u4e2d\uff09"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Query Strings"),"\uff1a\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"li"},"Http")," \u8bf7\u6c42\u5730\u5740\u53c2\u6570\u5171\u4eab"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"HttpContext.Items"),"\uff1a\u5b58\u50a8\u5728\u670d\u52a1\u7aef\uff0c\u53ea\u5728\u8bf7\u6c42\u58f0\u660e\u5468\u671f\u5185\u4f7f\u7528\uff0c\u8bf7\u6c42\u7ed3\u675f\u81ea\u52a8\u9500\u6bc1"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Cache"),"\uff1a\u670d\u52a1\u7aef\u7f13\u5b58\uff0c\u5305\u62ec\u5185\u5b58\u7f13\u5b58\u3001\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58\u3001IO \u7f13\u5b58\u3001\u5e8f\u5217\u5316\u7f13\u5b58\u4ee5\u53ca\u6570\u636e\u5e93\u7f13\u5b58"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"AsyncLocal"),"\uff1a\u901a\u8fc7\u5f02\u6b65\u63a7\u5236\u6d41\u5b9e\u73b0\u672c\u5730\u6570\u636e\u5171\u4eab\uff0c\u8de8\u7ebf\u7a0b")),(0,o.kt)("h2",{id:"322-\u5982\u4f55\u4f7f\u7528"},"32.2 \u5982\u4f55\u4f7f\u7528"),(0,o.kt)("h3",{id:"3221-cookie-\u4f7f\u7528"},"32.2.1 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Cookie")," \u4f7f\u7528"),(0,o.kt)("p",null,"\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"Cookie")," \u975e\u5e38\u7b80\u5355\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u8bfb\u53d6 Cookies\nvar value = httpContext.Request.Cookies["key"];\n\n// \u8bbe\u7f6e Cookies\nvar option = new CookieOptions();\noption.Expires = DateTime.Now.AddMilliseconds(10);\nhttpContext.Response.Cookies.Append(key, value, option);\n\n// \u5220\u9664 Cookies\nhttpContext.Response.Cookies.Delete(key);\n')),(0,o.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"httpContext")," \u53ef\u4ee5\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"IHttpContextAccessor")," \u83b7\u53d6\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"App.HttpContext")," \u83b7\u53d6\u3002")),(0,o.kt)("p",null,"\u6211\u4eec\u8fd8\u53ef\u4ee5\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"Cookie")," \u5b9e\u73b0\u6388\u6743\u529f\u80fd\u53ca\u5355\u70b9\u767b\u5f55\uff08SSO\uff09\uff1a",(0,o.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/security/cookie-sharing?view=aspnetcore-5.0"},"\u7f51\u7ad9\u5171\u4eab Cookie")),(0,o.kt)("h3",{id:"3222-session-\u4f7f\u7528"},"32.2.2 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Session")," \u4f7f\u7528"),(0,o.kt)("p",null,"\u5728\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"Session")," \u4e4b\u524d\uff0c\u5fc5\u987b\u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"p"},"Session")," \u670d\u52a1\uff1a\uff08\u5982\u679c"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,7-12,32,37,39}",showLineNumbers:!0,"":!0,"{1,5,7-12,32,37,39}":!0},'public class Startup\n{\n public void ConfigureServices(IServiceCollection services)\n {\n // services.AddDistributedMemoryCache(); \u6846\u67b6\u5185\u90e8\u5df2\u7ecf\u9ed8\u8ba4\u6ce8\u518c\n\n services.AddSession(options =>\n {\n options.IdleTimeout = TimeSpan.FromSeconds(10);\n options.Cookie.HttpOnly = true;\n options.Cookie.IsEssential = true;\n }); // \u6ce8\u610f\u5728\u63a7\u5236\u5668\u4e4b\u524d\u6ce8\u518c\uff01\uff01\uff01\uff01\n\n services.AddControllersWithViews();\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n if (env.IsDevelopment())\n {\n app.UseDeveloperExceptionPage();\n }\n else\n {\n app.UseExceptionHandler("/Home/Error");\n app.UseHsts();\n }\n\n app.UseHttpsRedirection();\n app.UseStaticFiles();\n\n app.UseRouting();\n\n app.UseAuthentication();\n app.UseAuthorization();\n\n app.UseSession();\n\n app.UseEndpoints(endpoints =>\n {\n endpoints.MapDefaultControllerRoute();\n endpoints.MapRazorPages();\n });\n }\n}\n')),(0,o.kt)("admonition",{title:"\u4e2d\u95f4\u4ef6\u6ce8\u518c\u987a\u5e8f",type:"important"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"app.UseSession()")," \u5fc5\u987b\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"app.UseRouting()")," \u548c ",(0,o.kt)("inlineCode",{parentName:"p"},"app.UseEndpoints()")," ",(0,o.kt)("strong",{parentName:"p"},"\u4e4b\u95f4"),"\u6ce8\u518c\uff01")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u5e38\u89c1\u4f8b\u5b50\uff1a")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u8bfb\u53d6 Session\nvar byteArr = httpContext.Session.Get("key"); // \u8fd4\u56de byte[]\nvar str = httpContext.Session.GetString("key"); // \u8fd4\u56de string[]\nvar num = httpContext.Session.GetInt32("key"); // \u8fd4\u56de int\n\n// \u8bbe\u7f6e Session\nhttpContext.Session.SetString("key", "value"); // \u8bbe\u7f6e\u5b57\u7b26\u4e32\nhttpContext.Session.SetInt32("key", 1); // \u8bbe\u7f6e int \u7c7b\u578b\n')),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u81ea\u5b9a\u4e49\u8bbe\u7f6e\u4efb\u610f\u7c7b\u578b\u62d3\u5c55\uff1a"))),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public static class SessionExtensions\n{\n public static void Set(this ISession session, string key, T value)\n {\n session.SetString(key, JsonSerializer.Serialize(value));\n }\n\n public static T Get(this ISession session, string key)\n {\n var value = session.GetString(key);\n return value == null ? default : JsonSerializer.Deserialize(value);\n }\n}\n")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u9632\u6b62 ",(0,o.kt)("inlineCode",{parentName:"li"},"Session ID")," \u6539\u53d8\u6216 ",(0,o.kt)("inlineCode",{parentName:"li"},"Session")," \u5931\u6548")),(0,o.kt)("p",null,"\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"ConfigureServices")," \u914d\u7f6e\u5373\u53ef\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.Configure(options =>\n{\n \u3000\u3000options.CheckConsentNeeded = context => false; // \u9ed8\u8ba4\u4e3atrue\uff0c\u6539\u4e3afalse\n\u3000\u3000 options.MinimumSameSitePolicy = SameSiteMode.None;\n});\n")),(0,o.kt)("h3",{id:"3223-query-strings-\u4f7f\u7528"},"32.2.3 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Query Strings")," \u4f7f\u7528"),(0,o.kt)("p",null,"\u8be5\u65b9\u5f0f\u4f7f\u7528\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700 ",(0,o.kt)("inlineCode",{parentName:"p"},'httpContext.Request.Query["key"]')," \u5373\u53ef\u3002"),(0,o.kt)("h3",{id:"3224-httpcontextitems-\u4f7f\u7528"},"32.2.4 ",(0,o.kt)("inlineCode",{parentName:"h3"},"HttpContext.Items")," \u4f7f\u7528"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5bf9\u8c61\u63d0\u4f9b\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"Items")," \u96c6\u5408\u5c5e\u6027\uff0c\u53ef\u4ee5\u8ba9\u6211\u4eec\u5728\u5355\u6b21\u8bf7\u6c42\u95f4\u5171\u4eab\u6570\u636e\uff0c\u8bf7\u6c42\u7ed3\u675f\u7acb\u5373\u9500\u6bc1\uff0c\u53ef\u4ee5\u5b58\u50a8\u4efb\u4f55\u6570\u636e\u3002\u4f7f\u7528\u4e5f\u975e\u5e38\u7b80\u5355\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u8bfb\u53d6\nvar value = httpContext.Items["key"];\n\n// \u6dfb\u52a0\nhttpContext.Items["key"] = "\u4efb\u4f55\u503c\u5305\u62ec\u5bf9\u8c61";\n\n// \u5220\u9664\nhttpContext.Items.Remove("key");\n')),(0,o.kt)("h3",{id:"3225-cache-\u65b9\u5f0f"},"32.2.5 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Cache")," \u65b9\u5f0f"),(0,o.kt)("p",null,"\u53c2\u89c1 ",(0,o.kt)("a",{parentName:"p",href:"/docs/cache"},"\u5206\u5e03\u5f0f\u7f13\u5b58")," \u6587\u6863"),(0,o.kt)("h3",{id:"3226-asynclocalt-\u65b9\u5f0f"},"32.2.6 ",(0,o.kt)("inlineCode",{parentName:"h3"},"AsyncLocal")," \u65b9\u5f0f"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"AsyncLocal")," \u53ef\u4ee5\u8bf4\u662f\u8fdb\u7a0b\u5185\u5171\u4eab\u6570\u636e\u7684\u5927\u5229\u5668\uff0c\u53ef\u4ee5\u901a\u8fc7\u8be5\u7c7b\u5b9e\u73b0\u8de8\u7ebf\u7a0b\u3001\u5f02\u6b65\u63a7\u5236\u6d41\u4e2d\u5171\u4eab\u6570\u636e\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"using System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nclass Example\n{\n static AsyncLocal _asyncLocalString = new AsyncLocal();\n\n static ThreadLocal _threadLocalString = new ThreadLocal();\n\n static async Task AsyncMethodA()\n {\n // Start multiple async method calls, with different AsyncLocal values.\n // We also set ThreadLocal values, to demonstrate how the two mechanisms differ.\n _asyncLocalString.Value = \"Value 1\";\n _threadLocalString.Value = \"Value 1\";\n var t1 = AsyncMethodB(\"Value 1\");\n\n _asyncLocalString.Value = \"Value 2\";\n _threadLocalString.Value = \"Value 2\";\n var t2 = AsyncMethodB(\"Value 2\");\n\n // Await both calls\n await t1;\n await t2;\n }\n\n static async Task AsyncMethodB(string expectedValue)\n {\n Console.WriteLine(\"Entering AsyncMethodB.\");\n Console.WriteLine(\" Expected '{0}', AsyncLocal value is '{1}', ThreadLocal value is '{2}'\",\n expectedValue, _asyncLocalString.Value, _threadLocalString.Value);\n await Task.Delay(100);\n Console.WriteLine(\"Exiting AsyncMethodB.\");\n Console.WriteLine(\" Expected '{0}', got '{1}', ThreadLocal value is '{2}'\",\n expectedValue, _asyncLocalString.Value, _threadLocalString.Value);\n }\n\n static async Task Main(string[] args)\n {\n await AsyncMethodA();\n }\n}\n// The example displays the following output:\n// Entering AsyncMethodB.\n// Expected 'Value 1', AsyncLocal value is 'Value 1', ThreadLocal value is 'Value 1'\n// Entering AsyncMethodB.\n// Expected 'Value 2', AsyncLocal value is 'Value 2', ThreadLocal value is 'Value 2'\n// Exiting AsyncMethodB.\n// Expected 'Value 2', got 'Value 2', ThreadLocal value is ''\n// Exiting AsyncMethodB.\n// Expected 'Value 1', got 'Value 1', ThreadLocal value is ''\n")),(0,o.kt)("p",null,"\u4e3a\u4e86\u7b80\u5316\u64cd\u4f5c\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Furion v2.18+")," \u7248\u672c\u5b9e\u73b0\u4e86\u8f7b\u91cf\u7ea7\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"CallContext")," \u9759\u6001\u7c7b\uff0c\u5185\u90e8\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"AsyncLocal")," \u5b9e\u73b0\uff0c\u4f7f\u7528\u5982\u4e0b\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'CallContext.SetLocalValue("name", "Furion");\nCallContext.GetLocalValue("name");\n\nCallContext.SetLocalValue("count", 1);\nCallContext.GetLocalValue("count");\n')),(0,o.kt)("p",null,"\u4e86\u89e3\u66f4\u591a ",(0,o.kt)("inlineCode",{parentName:"p"},"AsyncLocal")," \u77e5\u8bc6\uff1a",(0,o.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.asynclocal-1?redirectedfrom=MSDN&view=net-5.0"},"https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.asynclocal-1?redirectedfrom=MSDN&view=net-5.0")),(0,o.kt)("h2",{id:"323-\u53cd\u9988\u4e0e\u5efa\u8bae"},"32.3 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return c},kt:function(){return m}});var a=t(7294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function s(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=a.createContext({}),p=function(e){var n=a.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},c=function(e){var n=p(e.components);return a.createElement(l.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},d=a.forwardRef((function(e,n){var t=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,c=r(e,["components","mdxType","originalType","parentName"]),d=p(t),m=i,k=d["".concat(l,".").concat(m)]||d[m]||u[m]||o;return t?a.createElement(k,s(s({ref:n},c),{},{components:t})):a.createElement(k,s({ref:n},c))}));function m(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var o=t.length,s=new Array(o);s[0]=d;var r={};for(var l in n)hasOwnProperty.call(n,l)&&(r[l]=n[l]);r.originalType=e,r.mdxType="string"==typeof e?e:i,s[1]=r;for(var p=2;p=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=a.createContext({}),p=function(e){var n=a.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},c=function(e){var n=p(e.components);return a.createElement(l.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},d=a.forwardRef((function(e,n){var t=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,c=r(e,["components","mdxType","originalType","parentName"]),d=p(t),m=i,k=d["".concat(l,".").concat(m)]||d[m]||u[m]||o;return t?a.createElement(k,s(s({ref:n},c),{},{components:t})):a.createElement(k,s({ref:n},c))}));function m(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var o=t.length,s=new Array(o);s[0]=d;var r={};for(var l in n)hasOwnProperty.call(n,l)&&(r[l]=n[l]);r.originalType=e,r.mdxType="string"==typeof e?e:i,s[1]=r;for(var p=2;pCookie \u4f7f\u7528",id:"3221-cookie-\u4f7f\u7528",level:3},{value:"32.2.2 Session \u4f7f\u7528",id:"3222-session-\u4f7f\u7528",level:3},{value:"32.2.3 Query Strings \u4f7f\u7528",id:"3223-query-strings-\u4f7f\u7528",level:3},{value:"32.2.4 HttpContext.Items \u4f7f\u7528",id:"3224-httpcontextitems-\u4f7f\u7528",level:3},{value:"32.2.5 Cache \u65b9\u5f0f",id:"3225-cache-\u65b9\u5f0f",level:3},{value:"32.2.6 AsyncLocal<T> \u65b9\u5f0f",id:"3226-asynclocalt-\u65b9\u5f0f",level:3},{value:"32.3 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"323-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:u};function m(e){var n=e.components,t=(0,i.Z)(e,s);return(0,o.kt)("wrapper",(0,a.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"321-\u5173\u4e8e\u4f1a\u8bdd\u548c\u72b6\u6001\u7ba1\u7406"},"32.1 \u5173\u4e8e\u4f1a\u8bdd\u548c\u72b6\u6001\u7ba1\u7406"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"HTTP")," \u662f\u65e0\u72b6\u6001\u7684\u534f\u8bae\u3002 \u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"HTTP")," \u8bf7\u6c42\u662f\u4e0d\u4fdd\u7559\u7528\u6237\u503c\u7684\u72ec\u7acb\u6d88\u606f\u3002\u4f46\u662f\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u51e0\u79cd\u65b9\u5f0f\u4fdd\u7559\u8bf7\u6c42\u7528\u6237\u6570\u636e\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Cookie"),"\uff1a\u901a\u5e38\u5b58\u50a8\u5728\u5ba2\u6237\u7aef\u7684\u6570\u636e\uff0c\u8bf7\u6c42\u65f6\u5e26\u56de\u670d\u52a1\u7aef"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Session"),"\uff1a\u5b58\u50a8\u5728\u670d\u52a1\u7aef\u7684\u6570\u636e\uff08\u53ef\u4ee5\u5728\u5b58\u50a8\u5728\u5185\u5b58\u3001\u8fdb\u7a0b\u7b49\u4ecb\u8d28\u4e2d\uff09"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Query Strings"),"\uff1a\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"li"},"Http")," \u8bf7\u6c42\u5730\u5740\u53c2\u6570\u5171\u4eab"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"HttpContext.Items"),"\uff1a\u5b58\u50a8\u5728\u670d\u52a1\u7aef\uff0c\u53ea\u5728\u8bf7\u6c42\u58f0\u660e\u5468\u671f\u5185\u4f7f\u7528\uff0c\u8bf7\u6c42\u7ed3\u675f\u81ea\u52a8\u9500\u6bc1"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Cache"),"\uff1a\u670d\u52a1\u7aef\u7f13\u5b58\uff0c\u5305\u62ec\u5185\u5b58\u7f13\u5b58\u3001\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58\u3001IO \u7f13\u5b58\u3001\u5e8f\u5217\u5316\u7f13\u5b58\u4ee5\u53ca\u6570\u636e\u5e93\u7f13\u5b58"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"AsyncLocal"),"\uff1a\u901a\u8fc7\u5f02\u6b65\u63a7\u5236\u6d41\u5b9e\u73b0\u672c\u5730\u6570\u636e\u5171\u4eab\uff0c\u8de8\u7ebf\u7a0b")),(0,o.kt)("h2",{id:"322-\u5982\u4f55\u4f7f\u7528"},"32.2 \u5982\u4f55\u4f7f\u7528"),(0,o.kt)("h3",{id:"3221-cookie-\u4f7f\u7528"},"32.2.1 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Cookie")," \u4f7f\u7528"),(0,o.kt)("p",null,"\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"Cookie")," \u975e\u5e38\u7b80\u5355\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u8bfb\u53d6 Cookies\nvar value = httpContext.Request.Cookies["key"];\n\n// \u8bbe\u7f6e Cookies\nvar option = new CookieOptions();\noption.Expires = DateTime.Now.AddMilliseconds(10);\nhttpContext.Response.Cookies.Append(key, value, option);\n\n// \u5220\u9664 Cookies\nhttpContext.Response.Cookies.Delete(key);\n')),(0,o.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"httpContext")," \u53ef\u4ee5\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"IHttpContextAccessor")," \u83b7\u53d6\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"App.HttpContext")," \u83b7\u53d6\u3002")),(0,o.kt)("p",null,"\u6211\u4eec\u8fd8\u53ef\u4ee5\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"Cookie")," \u5b9e\u73b0\u6388\u6743\u529f\u80fd\u53ca\u5355\u70b9\u767b\u5f55\uff08SSO\uff09\uff1a",(0,o.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/security/cookie-sharing?view=aspnetcore-5.0"},"\u7f51\u7ad9\u5171\u4eab Cookie")),(0,o.kt)("h3",{id:"3222-session-\u4f7f\u7528"},"32.2.2 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Session")," \u4f7f\u7528"),(0,o.kt)("p",null,"\u5728\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"Session")," \u4e4b\u524d\uff0c\u5fc5\u987b\u6ce8\u518c ",(0,o.kt)("inlineCode",{parentName:"p"},"Session")," \u670d\u52a1\uff1a\uff08\u5982\u679c"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,7-12,32,37,39}",showLineNumbers:!0,"":!0,"{1,5,7-12,32,37,39}":!0},'public class Startup\n{\n public void ConfigureServices(IServiceCollection services)\n {\n // services.AddDistributedMemoryCache(); \u6846\u67b6\u5185\u90e8\u5df2\u7ecf\u9ed8\u8ba4\u6ce8\u518c\n\n services.AddSession(options =>\n {\n options.IdleTimeout = TimeSpan.FromSeconds(10);\n options.Cookie.HttpOnly = true;\n options.Cookie.IsEssential = true;\n }); // \u6ce8\u610f\u5728\u63a7\u5236\u5668\u4e4b\u524d\u6ce8\u518c\uff01\uff01\uff01\uff01\n\n services.AddControllersWithViews();\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n if (env.IsDevelopment())\n {\n app.UseDeveloperExceptionPage();\n }\n else\n {\n app.UseExceptionHandler("/Home/Error");\n app.UseHsts();\n }\n\n app.UseHttpsRedirection();\n app.UseStaticFiles();\n\n app.UseRouting();\n\n app.UseAuthentication();\n app.UseAuthorization();\n\n app.UseSession();\n\n app.UseEndpoints(endpoints =>\n {\n endpoints.MapDefaultControllerRoute();\n endpoints.MapRazorPages();\n });\n }\n}\n')),(0,o.kt)("admonition",{title:"\u4e2d\u95f4\u4ef6\u6ce8\u518c\u987a\u5e8f",type:"important"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"app.UseSession()")," \u5fc5\u987b\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"app.UseRouting()")," \u548c ",(0,o.kt)("inlineCode",{parentName:"p"},"app.UseEndpoints()")," ",(0,o.kt)("strong",{parentName:"p"},"\u4e4b\u95f4"),"\u6ce8\u518c\uff01")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u5e38\u89c1\u4f8b\u5b50\uff1a")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u8bfb\u53d6 Session\nvar byteArr = httpContext.Session.Get("key"); // \u8fd4\u56de byte[]\nvar str = httpContext.Session.GetString("key"); // \u8fd4\u56de string[]\nvar num = httpContext.Session.GetInt32("key"); // \u8fd4\u56de int\n\n// \u8bbe\u7f6e Session\nhttpContext.Session.SetString("key", "value"); // \u8bbe\u7f6e\u5b57\u7b26\u4e32\nhttpContext.Session.SetInt32("key", 1); // \u8bbe\u7f6e int \u7c7b\u578b\n')),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u81ea\u5b9a\u4e49\u8bbe\u7f6e\u4efb\u610f\u7c7b\u578b\u62d3\u5c55\uff1a"))),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public static class SessionExtensions\n{\n public static void Set(this ISession session, string key, T value)\n {\n session.SetString(key, JsonSerializer.Serialize(value));\n }\n\n public static T Get(this ISession session, string key)\n {\n var value = session.GetString(key);\n return value == null ? default : JsonSerializer.Deserialize(value);\n }\n}\n")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u9632\u6b62 ",(0,o.kt)("inlineCode",{parentName:"li"},"Session ID")," \u6539\u53d8\u6216 ",(0,o.kt)("inlineCode",{parentName:"li"},"Session")," \u5931\u6548")),(0,o.kt)("p",null,"\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"ConfigureServices")," \u914d\u7f6e\u5373\u53ef\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.Configure(options =>\n{\n \u3000\u3000options.CheckConsentNeeded = context => false; // \u9ed8\u8ba4\u4e3atrue\uff0c\u6539\u4e3afalse\n\u3000\u3000 options.MinimumSameSitePolicy = SameSiteMode.None;\n});\n")),(0,o.kt)("h3",{id:"3223-query-strings-\u4f7f\u7528"},"32.2.3 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Query Strings")," \u4f7f\u7528"),(0,o.kt)("p",null,"\u8be5\u65b9\u5f0f\u4f7f\u7528\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700 ",(0,o.kt)("inlineCode",{parentName:"p"},'httpContext.Request.Query["key"]')," \u5373\u53ef\u3002"),(0,o.kt)("h3",{id:"3224-httpcontextitems-\u4f7f\u7528"},"32.2.4 ",(0,o.kt)("inlineCode",{parentName:"h3"},"HttpContext.Items")," \u4f7f\u7528"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5bf9\u8c61\u63d0\u4f9b\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"Items")," \u96c6\u5408\u5c5e\u6027\uff0c\u53ef\u4ee5\u8ba9\u6211\u4eec\u5728\u5355\u6b21\u8bf7\u6c42\u95f4\u5171\u4eab\u6570\u636e\uff0c\u8bf7\u6c42\u7ed3\u675f\u7acb\u5373\u9500\u6bc1\uff0c\u53ef\u4ee5\u5b58\u50a8\u4efb\u4f55\u6570\u636e\u3002\u4f7f\u7528\u4e5f\u975e\u5e38\u7b80\u5355\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u8bfb\u53d6\nvar value = httpContext.Items["key"];\n\n// \u6dfb\u52a0\nhttpContext.Items["key"] = "\u4efb\u4f55\u503c\u5305\u62ec\u5bf9\u8c61";\n\n// \u5220\u9664\nhttpContext.Items.Remove("key");\n')),(0,o.kt)("h3",{id:"3225-cache-\u65b9\u5f0f"},"32.2.5 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Cache")," \u65b9\u5f0f"),(0,o.kt)("p",null,"\u53c2\u89c1 ",(0,o.kt)("a",{parentName:"p",href:"/docs/cache"},"\u5206\u5e03\u5f0f\u7f13\u5b58")," \u6587\u6863"),(0,o.kt)("h3",{id:"3226-asynclocalt-\u65b9\u5f0f"},"32.2.6 ",(0,o.kt)("inlineCode",{parentName:"h3"},"AsyncLocal")," \u65b9\u5f0f"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"AsyncLocal")," \u53ef\u4ee5\u8bf4\u662f\u8fdb\u7a0b\u5185\u5171\u4eab\u6570\u636e\u7684\u5927\u5229\u5668\uff0c\u53ef\u4ee5\u901a\u8fc7\u8be5\u7c7b\u5b9e\u73b0\u8de8\u7ebf\u7a0b\u3001\u5f02\u6b65\u63a7\u5236\u6d41\u4e2d\u5171\u4eab\u6570\u636e\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"using System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nclass Example\n{\n static AsyncLocal _asyncLocalString = new AsyncLocal();\n\n static ThreadLocal _threadLocalString = new ThreadLocal();\n\n static async Task AsyncMethodA()\n {\n // Start multiple async method calls, with different AsyncLocal values.\n // We also set ThreadLocal values, to demonstrate how the two mechanisms differ.\n _asyncLocalString.Value = \"Value 1\";\n _threadLocalString.Value = \"Value 1\";\n var t1 = AsyncMethodB(\"Value 1\");\n\n _asyncLocalString.Value = \"Value 2\";\n _threadLocalString.Value = \"Value 2\";\n var t2 = AsyncMethodB(\"Value 2\");\n\n // Await both calls\n await t1;\n await t2;\n }\n\n static async Task AsyncMethodB(string expectedValue)\n {\n Console.WriteLine(\"Entering AsyncMethodB.\");\n Console.WriteLine(\" Expected '{0}', AsyncLocal value is '{1}', ThreadLocal value is '{2}'\",\n expectedValue, _asyncLocalString.Value, _threadLocalString.Value);\n await Task.Delay(100);\n Console.WriteLine(\"Exiting AsyncMethodB.\");\n Console.WriteLine(\" Expected '{0}', got '{1}', ThreadLocal value is '{2}'\",\n expectedValue, _asyncLocalString.Value, _threadLocalString.Value);\n }\n\n static async Task Main(string[] args)\n {\n await AsyncMethodA();\n }\n}\n// The example displays the following output:\n// Entering AsyncMethodB.\n// Expected 'Value 1', AsyncLocal value is 'Value 1', ThreadLocal value is 'Value 1'\n// Entering AsyncMethodB.\n// Expected 'Value 2', AsyncLocal value is 'Value 2', ThreadLocal value is 'Value 2'\n// Exiting AsyncMethodB.\n// Expected 'Value 2', got 'Value 2', ThreadLocal value is ''\n// Exiting AsyncMethodB.\n// Expected 'Value 1', got 'Value 1', ThreadLocal value is ''\n")),(0,o.kt)("p",null,"\u4e3a\u4e86\u7b80\u5316\u64cd\u4f5c\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Furion v2.18+")," \u7248\u672c\u5b9e\u73b0\u4e86\u8f7b\u91cf\u7ea7\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"CallContext")," \u9759\u6001\u7c7b\uff0c\u5185\u90e8\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"AsyncLocal")," \u5b9e\u73b0\uff0c\u4f7f\u7528\u5982\u4e0b\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'CallContext.SetLocalValue("name", "Furion");\nCallContext.GetLocalValue("name");\n\nCallContext.SetLocalValue("count", 1);\nCallContext.GetLocalValue("count");\n')),(0,o.kt)("p",null,"\u4e86\u89e3\u66f4\u591a ",(0,o.kt)("inlineCode",{parentName:"p"},"AsyncLocal")," \u77e5\u8bc6\uff1a",(0,o.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.asynclocal-1?redirectedfrom=MSDN&view=net-5.0"},"https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.asynclocal-1?redirectedfrom=MSDN&view=net-5.0")),(0,o.kt)("h2",{id:"323-\u53cd\u9988\u4e0e\u5efa\u8bae"},"32.3 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/3eb8904d.9ae5fa04.js b/handbook/build/assets/js/3eb8904d.9ae5fa04.js new file mode 100644 index 0000000000..0eea98a107 --- /dev/null +++ b/handbook/build/assets/js/3eb8904d.9ae5fa04.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[5887],{3905:function(e,n,t){t.d(n,{Zo:function(){return d},kt:function(){return c}});var r=t(7294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function o(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var p=r.createContext({}),s=function(e){var n=r.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},d=function(e){var n=s(e.components);return r.createElement(p.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},u=r.forwardRef((function(e,n){var t=e.components,i=e.mdxType,a=e.originalType,p=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),u=s(t),c=i,k=u["".concat(p,".").concat(c)]||u[c]||m[c]||a;return t?r.createElement(k,o(o({ref:n},d),{},{components:t})):r.createElement(k,o({ref:n},d))}));function c(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var a=t.length,o=new Array(a);o[0]=u;var l={};for(var p in n)hasOwnProperty.call(n,p)&&(l[p]=n[p]);l.originalType=e,l.mdxType="string"==typeof e?e:i,o[1]=l;for(var s=2;sOops.Oh \u91cd\u8f7d\u65b9\u6cd5",id:"752-oopsoh-\u91cd\u8f7d\u65b9\u6cd5",level:3},{value:"7.6 \u6700\u4f73\u5b9e\u8df5 \ud83e\udd17",id:"76-\u6700\u4f73\u5b9e\u8df5-",level:2},{value:"7.6.1 \u521b\u5efa\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b",id:"761-\u521b\u5efa\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b",level:3},{value:"7.6.2 \u5173\u4e8e [ErrorCodeItemMetadata]",id:"762-\u5173\u4e8e-errorcodeitemmetadata",level:3},{value:"7.6.3 \u9759\u6001\u5f02\u5e38\u7c7b\u4f7f\u7528",id:"763-\u9759\u6001\u5f02\u5e38\u7c7b\u4f7f\u7528",level:3},{value:"7.6.4 \u5f02\u5e38\u65b9\u6cd5\u91cd\u8bd5",id:"764-\u5f02\u5e38\u65b9\u6cd5\u91cd\u8bd5",level:3},{value:"7.6.5 \u66f4\u591a\u4f8b\u5b50",id:"765-\u66f4\u591a\u4f8b\u5b50",level:3},{value:"7.7 \u591a\u4e2a\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b",id:"77-\u591a\u4e2a\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b",level:2},{value:"7.8 IErrorCodeTypeProvider \u63d0\u4f9b\u5668",id:"78-ierrorcodetypeprovider-\u63d0\u4f9b\u5668",level:2},{value:"7.9 appsetting.json \u4e2d\u914d\u7f6e",id:"79-appsettingjson-\u4e2d\u914d\u7f6e",level:2},{value:"\u4f7f\u7528\u793a\u4f8b",id:"\u4f7f\u7528\u793a\u4f8b",level:4},{value:"7.10 [IfException] \u4f7f\u7528",id:"710-ifexception-\u4f7f\u7528",level:2},{value:"7.10.1 \u4f7f\u7528\u793a\u4f8b",id:"7101-\u4f7f\u7528\u793a\u4f8b",level:3},{value:"7.10.2 \u66f4\u591a\u4f8b\u5b50",id:"7102-\u66f4\u591a\u4f8b\u5b50",level:3},{value:"7.11 \u5f02\u5e38\u6d88\u606f\u4f18\u5148\u7ea7",id:"711-\u5f02\u5e38\u6d88\u606f\u4f18\u5148\u7ea7",level:2},{value:"7.12 \u591a\u8bed\u8a00\u652f\u6301",id:"712-\u591a\u8bed\u8a00\u652f\u6301",level:2},{value:"7.13 \u89c4\u8303\u5316\u7ed3\u679c\u5f02\u5e38\u5904\u7406",id:"713-\u89c4\u8303\u5316\u7ed3\u679c\u5f02\u5e38\u5904\u7406",level:2},{value:"7.14 \u5168\u5c40\u5f02\u5e38\u5904\u7406\u63d0\u4f9b\u5668",id:"714-\u5168\u5c40\u5f02\u5e38\u5904\u7406\u63d0\u4f9b\u5668",level:2},{value:"7.15 FriendlyExceptionSettings \u914d\u7f6e",id:"715-friendlyexceptionsettings-\u914d\u7f6e",level:2},{value:"7.16 BadPageResult \u9519\u8bef\u9875",id:"716-badpageresult-\u9519\u8bef\u9875",level:2},{value:"7.17 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"717-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:u};function k(e){var n=e.components,t=(0,i.Z)(e,l);return(0,a.kt)("wrapper",(0,r.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"71-\u4ec0\u4e48\u662f\u5f02\u5e38"},"7.1 \u4ec0\u4e48\u662f\u5f02\u5e38"),(0,a.kt)("p",null,"\u5f02\u5e38\u4e00\u822c\u662f\u6307\u8fd0\u884c\u671f\uff08\u6b64\u5904\u7279\u6307 ",(0,a.kt)("inlineCode",{parentName:"p"},"Exception")," \u7c7b\uff09\u4f1a\u53d1\u751f\u7684\u5bfc\u81f4\u7a0b\u5e8f\u610f\u5916\u4e2d\u6b62\u7684\u95ee\u9898\uff0c\u662f\u4e00\u79cd\u5bf9\u95ee\u9898\u7684\u63cf\u8ff0\u540e\u7684\u5c01\u88c5\u5bf9\u8c61\u3002"),(0,a.kt)("p",null,"\u5728\u8fc7\u53bb\u5f00\u53d1\u4e2d\uff0c\u901a\u5e38\u5f02\u5e38\u7531\u7cfb\u7edf\u8fd0\u884c\u65f6\u51fa\u9519\u629b\u51fa\uff0c\u4f46\u73b0\u5728\u7684\u5f00\u53d1\u8fc7\u7a0b\u4e2d\uff0c\u6211\u4eec\u5e94\u5728\u7a0b\u5e8f\u5f00\u53d1\u4e2d\u5408\u7406\u7684\u629b\u51fa\u5f02\u5e38\uff0c\u6bd4\u5982\u66f4\u65b0\u4e00\u6761\u4e0d\u5b58\u5728\u7684\u5b9e\u4f53\uff0c\u6216\u67e5\u8be2\u4e00\u4e2a\u4e0d\u5b58\u5728\u7684\u6570\u636e\u7b49\u7b49\u3002"),(0,a.kt)("h2",{id:"72-\u5904\u7406\u5f02\u5e38\u65b9\u5f0f"},"7.2 \u5904\u7406\u5f02\u5e38\u65b9\u5f0f"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u5904\u7406\uff0c\u76f4\u63a5\u4e2d\u65ad\u7a0b\u5e8f\u6267\u884c\uff08\u4e0d\u63a8\u8350\uff09"),(0,a.kt)("li",{parentName:"ul"},"\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"li"},"try catch finally")," \u5904\u7406\uff08\u4e0d\u63a8\u8350\uff09"),(0,a.kt)("li",{parentName:"ul"},"\u5168\u5c40\u7edf\u4e00\u5904\u7406\uff0c\u5e76\u8bb0\u5f55\u5f02\u5e38\u4fe1\u606f",(0,a.kt)("strong",{parentName:"li"},"\uff08\u63a8\u8350\uff09")),(0,a.kt)("li",{parentName:"ul"},"\u5f02\u5e38\u6ce8\u89e3\u65b9\u5f0f\u5904\u7406\uff0c\u652f\u6301",(0,a.kt)("strong",{parentName:"li"},"\u672c\u5730\u5316")," ",(0,a.kt)("strong",{parentName:"li"},"\uff08\u63a8\u8350\uff09"))),(0,a.kt)("h2",{id:"73-\u4ec0\u4e48\u662f\u53cb\u597d\u5f02\u5e38\u5904\u7406"},"7.3 \u4ec0\u4e48\u662f\u53cb\u597d\u5f02\u5e38\u5904\u7406"),(0,a.kt)("h3",{id:"731-\u975e\u53cb\u597d\u5f02\u5e38\u5904\u7406"},"7.3.1 \u975e\u53cb\u597d\u5f02\u5e38\u5904\u7406"),(0,a.kt)("p",null,"\u5728\u4e86\u89e3\u53cb\u597d\u5f02\u5e38\u5904\u7406\u4e4b\u524d\u53ef\u4ee5\u770b\u770b\u975e\u53cb\u597d\u5f02\u5e38\u5904\u7406\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5bf9\u7ec8\u7aef\u7528\u6237\u629b\u51fa ",(0,a.kt)("inlineCode",{parentName:"li"},"500\u72b6\u6001\u7801")," \u5806\u6808\u4fe1\u606f"),(0,a.kt)("li",{parentName:"ul"},"\u5927\u91cf\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"try catch")," \u4ee3\u7801\uff0c\u6c61\u67d3\u6b63\u5e38\u4e1a\u52a1\u903b\u8f91"),(0,a.kt)("li",{parentName:"ul"},"\u6ca1\u6709\u89c4\u8303\u5316\u7684\u5f02\u5e38\u72b6\u6001\u7801\u548c\u5f02\u5e38\u6d88\u606f\u7ba1\u7406"),(0,a.kt)("li",{parentName:"ul"},"\u6ca1\u6709\u5f02\u5e38\u65e5\u5fd7\u6536\u96c6\u8bb0\u5f55"),(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u652f\u6301\u5f02\u5e38\u6d88\u606f\u672c\u5730\u5316\u5904\u7406"),(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u652f\u6301\u5f02\u5e38\u7b56\u7565\uff0c\u5931\u8d25\u540e\u7a0b\u5e8f\u7acb\u5373\u7ec8\u6b62"),(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u652f\u6301\u5206\u5e03\u5f0f\u4e8b\u52a1 CAP"),(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u652f\u6301\u5f02\u5e38\u4f20\u64ad"),(0,a.kt)("li",{parentName:"ul"},"\u8fd4\u56de\u7684\u5f02\u5e38\u683c\u5f0f\u6742\u4e71")),(0,a.kt)("h3",{id:"732-\u53cb\u597d\u5f02\u5e38\u5904\u7406"},"7.3.2 \u53cb\u597d\u5f02\u5e38\u5904\u7406"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5bf9\u7ec8\u7aef\u7528\u6237\u63d0\u793a\u53cb\u597d"),(0,a.kt)("li",{parentName:"ul"},"\u5bf9\u540e\u7aef\u5f00\u53d1\u4eba\u5458\u63d0\u4f9b\u8be6\u7ec6\u7684\u5f02\u5e38\u5806\u6808"),(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u5e72\u6270\u6b63\u5e38\u4e1a\u52a1\u903b\u8f91\u4ee3\u7801\uff0c\u5982 \u6ca1\u6709 ",(0,a.kt)("inlineCode",{parentName:"li"},"try catch")," \u4ee3\u7801"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u5f02\u5e38\u72b6\u6001\u7801\u591a\u65b9\u8bbe\u7f6e"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u5f02\u5e38\u6d88\u606f\u672c\u5730\u5316"),(0,a.kt)("li",{parentName:"ul"},"\u5f02\u5e38\u4fe1\u606f\u7edf\u4e00\u914d\u7f6e\u7ba1\u7406"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u5f02\u5e38\u7b56\u7565\uff0c\u5982\u91cd\u8bd5"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u5f02\u5e38\u65e5\u5fd7\u6536\u96c6\u8bb0\u5f55"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301 CAP \u5206\u5e03\u5f0f\u4e8b\u52a1\u5173\u8054"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u5185\u90e8\u5f02\u5e38\u5916\u90e8\u4f20\u64ad"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u8fd4\u56de\u7edf\u4e00\u7684\u5f02\u5e38\u683c\u5f0f\u6570\u636e")),(0,a.kt)("h2",{id:"74-\u53cb\u597d\u5f02\u5e38\u5904\u7406\u4f7f\u7528\u793a\u4f8b"},"7.4 \u53cb\u597d\u5f02\u5e38\u5904\u7406\u4f7f\u7528\u793a\u4f8b"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u7684\u53cb\u597d\u5f02\u5e38\u5904\u7406\u65b9\u5f0f\u3002"),(0,a.kt)("admonition",{title:"\u5907\u6ce8",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},".AddFriendlyException()")," \u9ed8\u8ba4\u5df2\u7ecf\u96c6\u6210\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"AddInject()")," \u4e2d\u4e86\uff0c\u65e0\u9700\u518d\u6b21\u6ce8\u518c\u3002\u4e5f\u5c31\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"7.4.1")," \u7ae0\u8282\u53ef\u4e0d\u914d\u7f6e\u3002")),(0,a.kt)("h3",{id:"741-\u6ce8\u518c\u53cb\u597d\u5f02\u5e38\u670d\u52a1"},"7.4.1 \u6ce8\u518c\u53cb\u597d\u5f02\u5e38\u670d\u52a1"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {11} title="Furion.Web.Core\\FurWebCoreStartup.cs"',showLineNumbers:!0,"":!0,"{11}":!0,title:'"Furion.Web.Core\\FurWebCoreStartup.cs"'},"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.Web.Core\n{\n [AppStartup(800)]\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddControllers()\n .AddFriendlyException();\n }\n }\n}\n")),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},".AddFriendlyException()")," \u9700\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"services.AddControllers()")," \u4e4b\u540e\u6ce8\u518c\u3002")),(0,a.kt)("h3",{id:"742-\u4e24\u4e2a\u4f8b\u5b50"},"7.4.2 \u4e24\u4e2a\u4f8b\u5b50"),(0,a.kt)("h4",{id:"\u7b80\u5355\u629b\u4e2a\u5f02\u5e38"},"\u7b80\u5355\u629b\u4e2a\u5f02\u5e38"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,12}",showLineNumbers:!0,"":!0,"{2,12}":!0},'using Furion.DynamicApiController;\nusing Furion.FriendlyException;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public int Get(int id)\n {\n if (id < 3)\n {\n throw Oops.Oh($"{id} \u4e0d\u80fd\u5c0f\u4e8e3");\n }\n\n return id;\n }\n }\n}\n')),(0,a.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,a.kt)("img",{src:(0,o.Z)("img/yhyc1.gif")}),(0,a.kt)("h4",{id:"\u629b\u51fa\u7279\u5b9a\u7c7b\u578b\u5f02\u5e38"},"\u629b\u51fa\u7279\u5b9a\u7c7b\u578b\u5f02\u5e38"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,13}",showLineNumbers:!0,"":!0,"{2,13}":!0},'using Furion.DynamicApiController;\nusing Furion.FriendlyException;\nusing System;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public int Get(int id)\n {\n if (id < 3)\n {\n throw Oops.Oh($"{id} \u4e0d\u80fd\u5c0f\u4e8e3\u3002", typeof(InvalidOperationException));\n }\n\n return id;\n }\n }\n}\n')),(0,a.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,a.kt)("img",{src:(0,o.Z)("img/yhyc2.png")}),(0,a.kt)("h2",{id:"75-\u5173\u4e8e-oopsoh"},"7.5 \u5173\u4e8e Oops.Oh"),(0,a.kt)("p",null,"\u901a\u8fc7\u4e0a\u9762\u7684\u4f8b\u5b50\u53ef\u4ee5\u770b\u51fa\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Oops.Oh(errorMessage)")," \u53ef\u4ee5\u7ed3\u5408 ",(0,a.kt)("inlineCode",{parentName:"p"},"throw")," \u629b\u51fa\u5f02\u5e38\u3002\u5bf9\u4e8e\u719f\u6089",(0,a.kt)("inlineCode",{parentName:"p"},"C#"),"\u7684\u4eba\u5458\u6765\u8bf4\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"throw")," \u540e\u9762\u53ea\u80fd ",(0,a.kt)("inlineCode",{parentName:"p"},"Exception")," \u5b9e\u4f8b\u3002",(0,a.kt)("inlineCode",{parentName:"p"},"Oops.Oh(...)")," \u65b9\u6cd5\u8fd4\u56de\u6b63\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"Exception")," \u5b9e\u4f8b\u3002"),(0,a.kt)("h3",{id:"751-\u4e3a\u4ec0\u4e48\u8d77\u8fd9\u4e2a\u540d\u5b57"},"7.5.1 \u4e3a\u4ec0\u4e48\u8d77\u8fd9\u4e2a\u540d\u5b57\uff1f"),(0,a.kt)("p",null,"\u8fd9\u4e2a\u540d\u5b57\u6765\u6e90\u4e8e\u4e00\u4e2a\u82f1\u8bed\u53e5\u5b50\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"Oh, Oops!"),"\uff0c\u610f\u601d\u662f ",(0,a.kt)("strong",{parentName:"p"},"\u5662\uff08\u54ce\uff09\uff0c\u51fa\u9519\u4e86\uff01"),"\uff0c\u6240\u4ee5\u5c31\u6709\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"Oops.Oh"),"\u3002"),(0,a.kt)("h3",{id:"752-oopsoh-\u91cd\u8f7d\u65b9\u6cd5"},"7.5.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Oops.Oh")," \u91cd\u8f7d\u65b9\u6cd5"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,22,30,39}",showLineNumbers:!0,"":!0,"{13,22,30,39}":!0},'using System;\n\nnamespace Furion.FriendlyException\n{\n public static class Oops\n {\n /// \n /// \u629b\u51fa\u5b57\u7b26\u4e32\u5f02\u5e38\n /// \n /// \u5f02\u5e38\u6d88\u606f\n /// String.Format \u53c2\u6570\n /// \u5f02\u5e38\u5b9e\u4f8b\n public static Exception Oh(string errorMessage, params object[] args);\n\n /// \n /// \u629b\u51fa\u5b57\u7b26\u4e32\u5f02\u5e38\n /// \n /// \u5f02\u5e38\u6d88\u606f\n /// \u5177\u4f53\u5f02\u5e38\u7c7b\u578b\n /// String.Format \u53c2\u6570\n /// \u5f02\u5e38\u5b9e\u4f8b\n public static Exception Oh(string errorMessage, Type exceptionType, params object[] args);\n\n /// \n /// \u629b\u51fa\u9519\u8bef\u7801\u5f02\u5e38\n /// \n /// \u9519\u8bef\u7801\n /// String.Format \u53c2\u6570\n /// \u5f02\u5e38\u5b9e\u4f8b\n public static Exception Oh(object errorCode, params object[] args);\n\n /// \n /// \u629b\u51fa\u9519\u8bef\u7801\u5f02\u5e38\n /// \n /// \u9519\u8bef\u7801\n /// \u5177\u4f53\u5f02\u5e38\u7c7b\u578b\n /// String.Format \u53c2\u6570\n /// \u5f02\u5e38\u5b9e\u4f8b\n public static Exception Oh(object errorCode, Type exceptionType, params object[] args);\n }\n}\n')),(0,a.kt)("h2",{id:"76-\u6700\u4f73\u5b9e\u8df5-"},"7.6 \u6700\u4f73\u5b9e\u8df5 \ud83e\udd17"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u4e14\u89c4\u8303\u5316\u7684\u53cb\u597d\u5f02\u5e38\u5904\u7406\u65b9\u5f0f\uff0c\u901a\u8fc7\u8fd9\u4e2a\u65b9\u5f0f\u53ef\u4ee5\u65b9\u4fbf\u7ba1\u7406\u5f02\u5e38\u72b6\u6001\u7801\u3001\u5f02\u5e38\u4fe1\u606f\u53ca\u5f02\u5e38\u672c\u5730\u5316\u3002"),(0,a.kt)("h3",{id:"761-\u521b\u5efa\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b"},"7.6.1 \u521b\u5efa\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b"),(0,a.kt)("p",null,"\u5b9e\u73b0\u81ea\u5b9a\u4e49\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b\u5fc5\u987b\u9075\u5faa\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u7c7b\u578b\u5fc5\u987b\u662f\u516c\u5f00\u4e14\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"Enum")," \u679a\u4e3e\u7c7b\u578b"),(0,a.kt)("li",{parentName:"ul"},"\u679a\u4e3e\u7c7b\u578b\u5fc5\u987b\u8d34\u6709 ",(0,a.kt)("inlineCode",{parentName:"li"},"[ErrorCodeType]")," \u7279\u6027"),(0,a.kt)("li",{parentName:"ul"},"\u679a\u4e3e\u4e2d\u6bcf\u4e00\u9879\u5fc5\u987b\u8d34\u6709 ",(0,a.kt)("inlineCode",{parentName:"li"},"[ErrorCodeItemMetadata]")," \u7279\u6027")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,8,11,14,17}",showLineNumbers:!0,"":!0,"{1,5,8,11,14,17}":!0},'using Furion.FriendlyException;\n\nnamespace Furion.Application\n{\n [ErrorCodeType]\n public enum ErrorCodes\n {\n [ErrorCodeItemMetadata("{0} \u4e0d\u80fd\u5c0f\u4e8e {1}")]\n z1000,\n\n [ErrorCodeItemMetadata("\u6570\u636e\u4e0d\u5b58\u5728")]\n x1000,\n\n [ErrorCodeItemMetadata("{0} \u53d1\u73b0 {1} \u4e2a\u5f02\u5e38", "\u767e\u5c0f\u50e7", 2)]\n x1001,\n\n [ErrorCodeItemMetadata("\u670d\u52a1\u5668\u8fd0\u884c\u5f02\u5e38", ErrorCode = "Error")]\n SERVER_ERROR\n }\n}\n')),(0,a.kt)("admonition",{type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"[ErrorCodeType]")," \u7279\u6027\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"IErrorCodeTypeProvider")," \u63d0\u4f9b\u5668\u63a5\u53e3\u6765\u63d0\u4f9b\u5f02\u5e38\u4fe1\u606f\u626b\u63cf\uff0c\u8fd9\u91cc\u7528\u7684\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"[ErrorCodeType]")," \u7279\u6027\u7c7b\u3002")),(0,a.kt)("h3",{id:"762-\u5173\u4e8e-errorcodeitemmetadata"},"7.6.2 \u5173\u4e8e ",(0,a.kt)("inlineCode",{parentName:"h3"},"[ErrorCodeItemMetadata]")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86",(0,a.kt)("inlineCode",{parentName:"p"},"[ErrorCodeItemMetadata]")," \u7279\u6027\u7528\u6765\u6807\u8bc6",(0,a.kt)("strong",{parentName:"p"},"\u679a\u4e3e\u5b57\u6bb5"),"\u5f02\u5e38\u5143\u6570\u636e\uff0c\u8be5\u7279\u6027\u652f\u6301\u4f20\u5165 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6d88\u606f\u5185\u5bb9")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"\u683c\u5f0f\u5316\u53c2\u6570"),"\u3002\u6700\u7ec8\u4f1a\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"String.Format(\u6d88\u606f\u5185\u5bb9\uff0c\u683c\u5f0f\u5316\u53c2\u6570)")," \u8fdb\u884c\u683c\u5f0f\u5316\u3002"),(0,a.kt)("p",null,"\u5982\u679c\u6d88\u606f\u5185\u5bb9\u4e2d\u5305\u542b",(0,a.kt)("inlineCode",{parentName:"p"},"\u683c\u5f0f\u5316\u5360\u4f4d\u7b26"),"\u4f46\u672a\u6307\u5b9a",(0,a.kt)("inlineCode",{parentName:"p"},"\u683c\u5f0f\u5316\u53c2\u6570"),"\uff0c\u90a3\u4e48\u4f1a\u67e5\u627e\u5f02\u5e38\u6240\u5728\u65b9\u6cd5\u662f\u5426\u8d34\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},"[IfException]")," \u7279\u6027\u4e14\u542b\u6709\u683c\u5f0f\u5316\u53c2\u6570\uff0c\u63a5\u7740\u5c31\u4f1a\u67e5\u627e ",(0,a.kt)("inlineCode",{parentName:"p"},"Oops.Oh")," \u4e2d\u6307\u5b9a\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u683c\u5f0f\u5316\u53c2\u6570"),"\u3002"),(0,a.kt)("h3",{id:"763-\u9759\u6001\u5f02\u5e38\u7c7b\u4f7f\u7528"},"7.6.3 \u9759\u6001\u5f02\u5e38\u7c7b\u4f7f\u7528"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,12}",showLineNumbers:!0,"":!0,"{2,12}":!0},"using Furion.DynamicApiController;\nusing Furion.FriendlyException;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public int Get(int id)\n {\n if (id < 3)\n {\n throw Oops.Oh(ErrorCodes.z1000, id, 3);\n }\n\n return id;\n }\n }\n}\n")),(0,a.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,a.kt)("img",{src:(0,o.Z)("img/yhyc3.gif")}),(0,a.kt)("h3",{id:"764-\u5f02\u5e38\u65b9\u6cd5\u91cd\u8bd5"},"7.6.4 \u5f02\u5e38\u65b9\u6cd5\u91cd\u8bd5"),(0,a.kt)("admonition",{title:"\u8c03\u6574\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"v2.17.0+")," \u7248\u672c\u4e0b\u9762\u65b9\u6cd5\u8bf7\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Retry.Invoke()")," \u66ff\u4ee3\u3002")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"Oops.Retry(() => {\n // Do.....\n}, 3, 1000);\n\n// \u5e26\u8fd4\u56de\u503c\nvar value = Oops.Retry(() => {\n // Do.....\n}, 3, 1000);\n\n// \u53ea\u6709\u7279\u5b9a\u5f02\u5e38\u624d\u76d1\u542c\nOops.Retry(() => {\n\n}, 3, 1000, typeof(ArgumentNullException));\n")),(0,a.kt)("h3",{id:"765-\u66f4\u591a\u4f8b\u5b50"},"7.6.5 \u66f4\u591a\u4f8b\u5b50"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6}",showLineNumbers:!0,"":!0,"{6}":!0},'throw Oops.Oh(1000);\nthrow Oops.Oh(ErrorCodes.x1000);\nthrow Oops.Oh("\u54c8\u54c8\u54c8\u54c8");\nthrow Oops.Oh(errorCode: "x1001");\nthrow Oops.Oh(1000, typeof(Exception));\nthrow Oops.Oh(1000).StatusCode(400); // \u8bbe\u7f6e\u9519\u8bef\u7801\nthrow Oops.Oh(1000).WithData(new Model {}); // \u8bbe\u7f6e\u989d\u5916\u6570\u636e\nthrow Oops.Bah("\u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef"); // \u629b\u51fa\u4e1a\u52a1\u5f02\u5e38\uff0c\u72b6\u6001\u7801\u4e3a 400\nthrow Oops.Bah(1000);\n')),(0,a.kt)("h2",{id:"77-\u591a\u4e2a\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b"},"7.7 \u591a\u4e2a\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5-6,21-22}",showLineNumbers:!0,"":!0,"{5-6,21-22}":!0},'using Furion.FriendlyException;\n\nnamespace Furion.Application\n{\n [ErrorCodeType]\n public enum ErrorCodes\n {\n [ErrorCodeItemMetadata("{0} \u4e0d\u80fd\u5c0f\u4e8e {1}")]\n z1000,\n\n [ErrorCodeItemMetadata("\u6570\u636e\u4e0d\u5b58\u5728")]\n x1000,\n\n [ErrorCodeItemMetadata("{0} \u53d1\u73b0 {1} \u4e2a\u5f02\u5e38", "\u767e\u5c0f\u50e7", 2)]\n x1001,\n\n [ErrorCodeItemMetadata("\u670d\u52a1\u5668\u8fd0\u884c\u5f02\u5e38", ErrorCode = "Error")]\n SERVER_ERROR\n }\n\n [ErrorCodeType]\n public enum UserErrorCodes\n {\n [ErrorCodeItemMetadata("\u7528\u6237\u6570\u636e\u4e0d\u5b58\u5728")]\n u1000,\n\n [ErrorCodeItemMetadata("\u5176\u4ed6\u5f02\u5e38")]\n u1001\n }\n}\n')),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u591a\u4e2a\u5f02\u5e38\u9759\u6001\u7c7b\u4e2d\u4e5f\u5fc5\u987b\u4fdd\u8bc1\u5e38\u91cf\u503c\u552f\u4e00\u6027\uff0c\u4e0d\u53ef\u91cd\u590d\u3002")),(0,a.kt)("h2",{id:"78-ierrorcodetypeprovider-\u63d0\u4f9b\u5668"},"7.8 ",(0,a.kt)("inlineCode",{parentName:"h2"},"IErrorCodeTypeProvider")," \u63d0\u4f9b\u5668"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u8fd8\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"IErrorCodeTypeProvider")," \u5f02\u5e38\u6d88\u606f\u63d0\u4f9b\u5668\u63a5\u53e3\uff0c\u65b9\u4fbf\u5728\u4e0d\u80fd\u8d34 ",(0,a.kt)("inlineCode",{parentName:"p"},"[ErrorCodeType]")," \u7279\u6027\u60c5\u51b5\u4e0b\u4f7f\u7528\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6,8-11}",showLineNumbers:!0,"":!0,"{2,6,8-11}":!0},"using Furion.FriendlyException;\nusing System;\n\nnamespace Furion.Application\n{\n public class CustomErrorCodeTypeProvider : IErrorCodeTypeProvider\n {\n public Type[] Definitions => new[] {\n typeof(ErrorCodes),\n typeof(ErrorCodes2)\n };\n }\n}\n")),(0,a.kt)("p",null,"\u542f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IErrorCodeTypeProvider")," \u63d0\u4f9b\u5668\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {11} title="Furion.Web.Core\\FurWebCoreStartup.cs"',showLineNumbers:!0,"":!0,"{11}":!0,title:'"Furion.Web.Core\\FurWebCoreStartup.cs"'},"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.Web.Core\n{\n [AppStartup(800)]\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddControllers()\n .AddFriendlyException();\n }\n }\n}\n")),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u53ea\u6709\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IErrorCodeTypeProvider")," \u65b9\u5f0f\u624d\u9700\u4f7f\u7528\u6cdb\u578b\u65b9\u5f0f\u6ce8\u518c\u3002\u901a\u8fc7\u4e0a\u9762\u7684\u65b9\u5f0f\u6ce8\u518c\u53ef\u4ee5\u540c\u65f6\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"p"},"IErrorCodeTypeProvider")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"[ErrorCodeType]")," \u65b9\u5f0f\u3002")),(0,a.kt)("h2",{id:"79-appsettingjson-\u4e2d\u914d\u7f6e"},"7.9 ",(0,a.kt)("inlineCode",{parentName:"h2"},"appsetting.json")," \u4e2d\u914d\u7f6e"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u8fd8\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u7684\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e\u5f02\u5e38\uff0c\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\u53ef\u4ee5\u5b9e\u73b0\u5f02\u5e38\u4fe1\u606f\u540e\u671f\u914d\u7f6e\uff0c\u4e5f\u5c31\u662f\u65e0\u9700\u5728\u5f00\u53d1\u9636\u6bb5\u9884\u5148\u5b9a\u4e49\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers {2-8} title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,"{2-8}":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "ErrorCodeMessageSettings": {\n "Definitions": [\n ["5000", "{0} \u4e0d\u80fd\u5c0f\u4e8e {1}"],\n ["5001", "\u6211\u53eb {0} \u540d\u5b57", "\u767e\u5c0f\u50e7"],\n ["5002", "Oops! \u51fa\u9519\u4e86"]\n ]\n }\n}\n')),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Definitions")," \u7c7b\u578b\u4e3a\u4e8c\u7ef4\u6570\u7ec4\uff0c\u4e8c\u7ef4\u6570\u7ec4\u4e2d\u7684\u6bcf\u4e00\u4e2a\u6570\u7ec4\u7b2c\u4e00\u4e2a\u53c2\u6570\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"ErrorCode")," \u4e5f\u5c31\u662f\u9519\u8bef\u7801\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"ErrorMessage")," \u6d88\u606f\u5185\u5bb9\uff0c\u5269\u4f59\u53c2\u6570\u4f5c\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"ErrorMessage")," \u7684\u683c\u5f0f\u5316\u53c2\u6570\u3002"),(0,a.kt)("h4",{id:"\u4f7f\u7528\u793a\u4f8b"},"\u4f7f\u7528\u793a\u4f8b"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,12}",showLineNumbers:!0,"":!0,"{2,12}":!0},"using Furion.DynamicApiController;\nusing Furion.FriendlyException;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public int Get(int id)\n {\n if (id < 3)\n {\n throw Oops.Oh(5000, id, 3); // \u53ef\u4ee5\u5c06 5000\u4f5c\u4e3a\u5e38\u91cf\u914d\u7f6e\u8d77\u6765\n }\n\n return id;\n }\n }\n}\n")),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"[ErrorCodeType]")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"IErrorCodeTypeProvider")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u53ef\u4ee5\u540c\u65f6\u4f7f\u7528\u3002")),(0,a.kt)("h2",{id:"710-ifexception-\u4f7f\u7528"},"7.10 ",(0,a.kt)("inlineCode",{parentName:"h2"},"[IfException]")," \u4f7f\u7528"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"[IfException]")," \u7279\u6027\u53ef\u4ee5",(0,a.kt)("strong",{parentName:"p"},"\u8986\u76d6\u9ed8\u8ba4\u6d88\u606f\u914d\u7f6e"),"\u3002\u4e5f\u5c31\u662f\u8986\u76d6 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5f02\u5e38\u6d88\u606f\u7c7b\u578b")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u4e2d\u7684\u914d\u7f6e\u3002"),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"[IfException]")," \u53ea\u80fd\u8d34\u5728\u65b9\u6cd5\u4e0a\uff0c\u652f\u6301\u591a\u4e2a\u3002")),(0,a.kt)("h3",{id:"7101-\u4f7f\u7528\u793a\u4f8b"},"7.10.1 \u4f7f\u7528\u793a\u4f8b"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5f02\u5e38\u6d88\u606f\u7c7b\u5b9a\u4e49")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4}",showLineNumbers:!0,"":!0,"{1,4}":!0},'[ErrorCodeType]\npublic enum ErrorCodes\n{\n [ErrorCodeItemMetadata("{0} \u4e0d\u80fd\u5c0f\u4e8e {1}")]\n z1000\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u8986\u76d6\u9ed8\u8ba4\u914d\u7f6e")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8}",showLineNumbers:!0,"":!0,"{8}":!0},'using Furion.DynamicApiController;\nusing Furion.FriendlyException;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n [IfException(ErrorCodes.z1000, ErrorMessage = "\u6211\u8986\u76d6\u4e86\u9ed8\u8ba4\u7684\uff1a{0} \u4e0d\u80fd\u5c0f\u4e8e {1}")]\n public int Get(int id)\n {\n if (id < 3)\n {\n throw Oops.Oh(ErrorCodes.z1000, id, 3);\n }\n\n return id;\n }\n }\n}\n')),(0,a.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,a.kt)("img",{src:(0,o.Z)("img/yhyc4.png")}),(0,a.kt)("h3",{id:"7102-\u66f4\u591a\u4f8b\u5b50"},"7.10.2 \u66f4\u591a\u4f8b\u5b50"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,8-11}",showLineNumbers:!0,"":!0,"{2,8-11}":!0},'using Furion.DynamicApiController;\nusing Furion.FriendlyException;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n [IfException(typeof(ExceptionType), ErrorMessage = "\u7279\u5b9a\u5f02\u5e38\u7c7b\u578b\u5168\u5c40\u62e6\u622a")]\n [IfException(ErrorMessage = "\u5168\u5c40\u5f02\u5e38\u62e6\u622a")]\n [IfException(ErrorCodes.z1000, ErrorMessage = "\u6211\u8986\u76d6\u4e86\u9ed8\u8ba4\u7684\uff1a{0} \u4e0d\u80fd\u5c0f\u4e8e {1}")]\n [IfException(ErrorCodes.x1001, "\u683c\u5f0f\u5316\u53c2\u65701", "\u683c\u5f0f\u5316\u53c2\u65702", ErrorMessage = "\u6211\u8986\u76d6\u4e86\u9ed8\u8ba4\u7684\uff1a{0} \u4e0d\u80fd\u5c0f\u4e8e {1}")]\n [IfException(ErrorCodes.x1000, "\u683c\u5f0f\u5316\u53c2\u65701", "\u683c\u5f0f\u5316\u53c2\u65702")]\n [IfException(ErrorCodes.SERVER_ERROR, "\u683c\u5f0f\u5316\u53c2\u65701", "\u683c\u5f0f\u5316\u53c2\u65702")]\n public int Get(int id)\n {\n if (id < 3)\n {\n throw Oops.Oh(ErrorCodes.z1000, id, 3);\n }\n\n return id;\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u683c\u5f0f\u5316\u6d41\u7a0b",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u6d88\u606f\u5185\u5bb9\u4e2d\u5305\u542b",(0,a.kt)("inlineCode",{parentName:"p"},"\u683c\u5f0f\u5316\u5360\u4f4d\u7b26"),"\u4f46\u672a\u6307\u5b9a",(0,a.kt)("inlineCode",{parentName:"p"},"\u683c\u5f0f\u5316\u53c2\u6570"),"\uff0c\u90a3\u4e48\u4f1a\u67e5\u627e\u5f02\u5e38\u6240\u5728\u65b9\u6cd5\u662f\u5426\u8d34\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},"[IfException]")," \u7279\u6027\u4e14\u542b\u6709\u683c\u5f0f\u5316\u53c2\u6570\uff0c\u63a5\u7740\u5c31\u4f1a\u67e5\u627e ",(0,a.kt)("inlineCode",{parentName:"p"},"Oops.Oh")," \u4e2d\u6307\u5b9a\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u683c\u5f0f\u5316\u53c2\u6570"),"\u3002")),(0,a.kt)("h2",{id:"711-\u5f02\u5e38\u6d88\u606f\u4f18\u5148\u7ea7"},"7.11 \u5f02\u5e38\u6d88\u606f\u4f18\u5148\u7ea7"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"[ErrorCodeItemMetadata]")," -> ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," -> ",(0,a.kt)("inlineCode",{parentName:"p"},"[IfException]"),"\u3002",(0,a.kt)("strong",{parentName:"p"},"\uff08\u4f4e -> \u9ad8\uff09")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"[IfException]")," \u4f1a\u8986\u76d6 ",(0,a.kt)("inlineCode",{parentName:"li"},"appsettings.json")," \u5b9a\u4e49\u7684\u72b6\u6001\u7801\u6d88\u606f\u3002"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"appsettings.json")," \u4f1a\u8986\u76d6 ",(0,a.kt)("inlineCode",{parentName:"li"},"[ErrorCodeItemMetadata]")," \u5b9a\u4e49\u7684\u6d88\u606f\u3002")),(0,a.kt)("h2",{id:"712-\u591a\u8bed\u8a00\u652f\u6301"},"7.12 \u591a\u8bed\u8a00\u652f\u6301"),(0,a.kt)("p",null,"\u53c2\u89c1 ",(0,a.kt)("a",{parentName:"p",href:"./local-language"},"\u3010\u5168\u7403\u5316\u548c\u672c\u5730\u5316\uff08\u591a\u8bed\u8a00\uff09\u3011")," \u7ae0\u8282"),(0,a.kt)("h2",{id:"713-\u89c4\u8303\u5316\u7ed3\u679c\u5f02\u5e38\u5904\u7406"},"7.13 \u89c4\u8303\u5316\u7ed3\u679c\u5f02\u5e38\u5904\u7406"),(0,a.kt)("admonition",{title:"\u67e5\u770b\u89c4\u8303\u5316\u7ed3\u679c\u6587\u6863",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u9700\u81ea\u5b9a\u4e49\u89c4\u8303\u5316\u7ed3\u679c\u53ef\u67e5\u9605 \u3010",(0,a.kt)("a",{parentName:"p",href:"/furion/docs/specification-document#67-%E7%BB%9F%E4%B8%80%E8%BF%94%E5%9B%9E%E5%80%BC%E6%A8%A1%E5%9E%8B%E8%A7%84%E8%8C%83%E5%8C%96%E7%BB%93%E6%9E%9Capi-%E8%BF%94%E5%9B%9E%E5%80%BC"},"6.7 \u7edf\u4e00\u8fd4\u56de\u503c\u6a21\u578b"),"\u3011")),(0,a.kt)("h2",{id:"714-\u5168\u5c40\u5f02\u5e38\u5904\u7406\u63d0\u4f9b\u5668"},"7.14 \u5168\u5c40\u5f02\u5e38\u5904\u7406\u63d0\u4f9b\u5668"),(0,a.kt)("p",null,"\u901a\u5e38\u6211\u4eec\u9700\u8981\u5728\u5f02\u5e38\u6355\u83b7\u7684\u65f6\u5019\u5199\u65e5\u5fd7\uff0c\u8fd9\u65f6\u5019\u5c31\u9700\u8981\u4f7f\u7528\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"IGlobalExceptionHandler")," \u5f02\u5e38\u5b9a\u4e49\u5904\u7406\u7a0b\u5e8f\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8}",showLineNumbers:!0,"":!0,"{8}":!0},"using Furion.DependencyInjection;\nusing Furion.FriendlyException;\nusing Microsoft.AspNetCore.Mvc.Filters;\nusing System.Threading.Tasks;\n\nnamespace Furion.Application\n{\n public class LogExceptionHandler : IGlobalExceptionHandler, ISingleton\n {\n public Task OnExceptionAsync(ExceptionContext context)\n {\n // \u5199\u65e5\u5fd7\n\n return Task.CompletedTask;\n }\n }\n}\n")),(0,a.kt)("h2",{id:"715-friendlyexceptionsettings-\u914d\u7f6e"},"7.15 ",(0,a.kt)("inlineCode",{parentName:"h2"},"FriendlyExceptionSettings")," \u914d\u7f6e"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"HideErrorCode"),"\uff1a\u9690\u85cf\u9519\u8bef\u7801\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"false")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"DefaultErrorCode"),"\uff1a\u9ed8\u8ba4\u9519\u8bef\u7801\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"DefaultErrorMessage"),"\uff1a\u9ed8\u8ba4\u9519\u8bef\u6d88\u606f\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ThrowBah"),"\uff1a\u662f\u5426\u5c06 ",(0,a.kt)("inlineCode",{parentName:"li"},"Oops.Oh")," \u9ed8\u8ba4\u629b\u51fa\u4e3a\u4e1a\u52a1\u5f02\u5e38\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"false"),"\uff0c\u8bbe\u7f6e ",(0,a.kt)("inlineCode",{parentName:"li"},"true")," \u4e4b\u540e ",(0,a.kt)("inlineCode",{parentName:"li"},"Oops.Oh")," \u9ed8\u8ba4\u8fdb\u5165 ",(0,a.kt)("inlineCode",{parentName:"li"},"OnValidateFailed")," \u5904\u7406\uff0c\u800c\u4e0d\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"OnException")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"LogError"),"\uff1a\u662f\u5426\u8f93\u51fa\u5f02\u5e38\u65e5\u5fd7\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"true"))),(0,a.kt)("p",null,"\u914d\u7f6e\u793a\u4f8b"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "FriendlyExceptionSettings": {\n "DefaultErrorMessage": "\u7cfb\u7edf\u5f02\u5e38\uff0c\u8bf7\u8054\u7cfb\u7ba1\u7406\u5458"\n }\n}\n')),(0,a.kt)("h2",{id:"716-badpageresult-\u9519\u8bef\u9875"},"7.16 ",(0,a.kt)("inlineCode",{parentName:"h2"},"BadPageResult")," \u9519\u8bef\u9875"),(0,a.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 3.6.1 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u5728\u8be5\u7248\u672c\u4e4b\u540e\u5185\u7f6e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"BadPageResult")," \u9519\u8bef\u7ed3\u679c\u7c7b\u578b\uff0c\u8be5\u7c7b\u578b\u6d3e\u751f\u81ea ",(0,a.kt)("inlineCode",{parentName:"p"},"IActionResult"),"\uff0c\u5982\u9700\u8fd4\u56de\u53ea\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Action")," \u4e2d\u8fd4\u56de\u5373\u53ef\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers{1,7}","showLineNumbers{1,7}":!0},"using Furion.FriendlyException;\n\npublic IActionResult Add(Person person)\n{\n if(!ModelState.IsValid)\n {\n return new BadPageResult();\n }\n}\n")),(0,a.kt)("img",{src:(0,o.Z)("img/er1.png")}),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"BadPageResult")," \u66f4\u591a\u914d\u7f6e",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u6784\u9020\u51fd\u6570 ",(0,a.kt)("inlineCode",{parentName:"li"},"statusCode"),"\uff1a\u72b6\u6001\u7801\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"int")," \u7c7b\uff0c\u9ed8\u8ba4 400"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Title"),"\uff1a\u9875\u9762\u6807\u9898\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"ModelState Invalid")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Description"),"\uff1a\u9875\u9762\u63cf\u8ff0\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"User data verification failed. Please input it correctly.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Code"),"\uff1a\u8be6\u7ec6\u9519\u8bef\u4ee3\u7801\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"li"},"\u4ee3\u7801"),"\uff0c\u9ed8\u8ba4\u7a7a\u5b57\u7b26\u4e32"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"CodeLang"),"\uff1a\u8be6\u7ec6\u9519\u8bef\u4ee3\u7801\u8bed\u8a00\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"json")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Base64Icon"),"\uff1a\u9875\u9762\u56fe\u6807\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u5e26\u9ed8\u8ba4\u503c\uff0c\u81ea\u5b9a\u4e49\u5fc5\u987b\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"base64")," \u683c\u5f0f\u56fe\u6807")))),(0,a.kt)("h2",{id:"717-\u53cd\u9988\u4e0e\u5efa\u8bae"},"7.17 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/3eb8904d.f4f55df5.js b/handbook/build/assets/js/3eb8904d.f4f55df5.js deleted file mode 100644 index e3c7565394..0000000000 --- a/handbook/build/assets/js/3eb8904d.f4f55df5.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[5887],{5298:function(e,n,t){t.r(n),t.d(n,{assets:function(){return m},contentTitle:function(){return s},default:function(){return k},frontMatter:function(){return p},metadata:function(){return d},toc:function(){return u}});var r=t(3117),i=t(102),a=(t(7294),t(3905)),o=t(1402),l=["components"],p={id:"friendly-exception",title:"7. \u53cb\u597d\u5f02\u5e38\u5904\u7406",sidebar_label:"7. \u53cb\u597d\u5f02\u5e38\u5904\u7406"},s=void 0,d={unversionedId:"friendly-exception",id:"friendly-exception",title:"7. \u53cb\u597d\u5f02\u5e38\u5904\u7406",description:"",source:"@site/docs/friendly-exception.mdx",sourceDirName:".",slug:"/friendly-exception",permalink:"/furion/docs/friendly-exception",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/friendly-exception.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1661480282,formattedLastUpdatedAt:"Aug 26, 2022",frontMatter:{id:"friendly-exception",title:"7. \u53cb\u597d\u5f02\u5e38\u5904\u7406",sidebar_label:"7. \u53cb\u597d\u5f02\u5e38\u5904\u7406"},sidebar:"docs",previous:{title:"6. \u89c4\u8303\u5316\u63a5\u53e3\u6587\u6863 (Swagger)",permalink:"/furion/docs/specification-document"},next:{title:"8. \u6570\u636e\u6821\u9a8c",permalink:"/furion/docs/data-validation"}},m={},u=[{value:"7.1 \u4ec0\u4e48\u662f\u5f02\u5e38",id:"71-\u4ec0\u4e48\u662f\u5f02\u5e38",level:2},{value:"7.2 \u5904\u7406\u5f02\u5e38\u65b9\u5f0f",id:"72-\u5904\u7406\u5f02\u5e38\u65b9\u5f0f",level:2},{value:"7.3 \u4ec0\u4e48\u662f\u53cb\u597d\u5f02\u5e38\u5904\u7406",id:"73-\u4ec0\u4e48\u662f\u53cb\u597d\u5f02\u5e38\u5904\u7406",level:2},{value:"7.3.1 \u975e\u53cb\u597d\u5f02\u5e38\u5904\u7406",id:"731-\u975e\u53cb\u597d\u5f02\u5e38\u5904\u7406",level:3},{value:"7.3.2 \u53cb\u597d\u5f02\u5e38\u5904\u7406",id:"732-\u53cb\u597d\u5f02\u5e38\u5904\u7406",level:3},{value:"7.4 \u53cb\u597d\u5f02\u5e38\u5904\u7406\u4f7f\u7528\u793a\u4f8b",id:"74-\u53cb\u597d\u5f02\u5e38\u5904\u7406\u4f7f\u7528\u793a\u4f8b",level:2},{value:"7.4.1 \u6ce8\u518c\u53cb\u597d\u5f02\u5e38\u670d\u52a1",id:"741-\u6ce8\u518c\u53cb\u597d\u5f02\u5e38\u670d\u52a1",level:3},{value:"7.4.2 \u4e24\u4e2a\u4f8b\u5b50",id:"742-\u4e24\u4e2a\u4f8b\u5b50",level:3},{value:"\u7b80\u5355\u629b\u4e2a\u5f02\u5e38",id:"\u7b80\u5355\u629b\u4e2a\u5f02\u5e38",level:4},{value:"\u629b\u51fa\u7279\u5b9a\u7c7b\u578b\u5f02\u5e38",id:"\u629b\u51fa\u7279\u5b9a\u7c7b\u578b\u5f02\u5e38",level:4},{value:"7.5 \u5173\u4e8e Oops.Oh",id:"75-\u5173\u4e8e-oopsoh",level:2},{value:"7.5.1 \u4e3a\u4ec0\u4e48\u8d77\u8fd9\u4e2a\u540d\u5b57\uff1f",id:"751-\u4e3a\u4ec0\u4e48\u8d77\u8fd9\u4e2a\u540d\u5b57",level:3},{value:"7.5.2 Oops.Oh \u91cd\u8f7d\u65b9\u6cd5",id:"752-oopsoh-\u91cd\u8f7d\u65b9\u6cd5",level:3},{value:"7.6 \u6700\u4f73\u5b9e\u8df5 \ud83e\udd17",id:"76-\u6700\u4f73\u5b9e\u8df5-",level:2},{value:"7.6.1 \u521b\u5efa\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b",id:"761-\u521b\u5efa\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b",level:3},{value:"7.6.2 \u5173\u4e8e [ErrorCodeItemMetadata]",id:"762-\u5173\u4e8e-errorcodeitemmetadata",level:3},{value:"7.6.3 \u9759\u6001\u5f02\u5e38\u7c7b\u4f7f\u7528",id:"763-\u9759\u6001\u5f02\u5e38\u7c7b\u4f7f\u7528",level:3},{value:"7.6.4 \u5f02\u5e38\u65b9\u6cd5\u91cd\u8bd5",id:"764-\u5f02\u5e38\u65b9\u6cd5\u91cd\u8bd5",level:3},{value:"7.6.5 \u66f4\u591a\u4f8b\u5b50",id:"765-\u66f4\u591a\u4f8b\u5b50",level:3},{value:"7.7 \u591a\u4e2a\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b",id:"77-\u591a\u4e2a\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b",level:2},{value:"7.8 IErrorCodeTypeProvider \u63d0\u4f9b\u5668",id:"78-ierrorcodetypeprovider-\u63d0\u4f9b\u5668",level:2},{value:"7.9 appsetting.json \u4e2d\u914d\u7f6e",id:"79-appsettingjson-\u4e2d\u914d\u7f6e",level:2},{value:"\u4f7f\u7528\u793a\u4f8b",id:"\u4f7f\u7528\u793a\u4f8b",level:4},{value:"7.10 [IfException] \u4f7f\u7528",id:"710-ifexception-\u4f7f\u7528",level:2},{value:"7.10.1 \u4f7f\u7528\u793a\u4f8b",id:"7101-\u4f7f\u7528\u793a\u4f8b",level:3},{value:"7.10.2 \u66f4\u591a\u4f8b\u5b50",id:"7102-\u66f4\u591a\u4f8b\u5b50",level:3},{value:"7.11 \u5f02\u5e38\u6d88\u606f\u4f18\u5148\u7ea7",id:"711-\u5f02\u5e38\u6d88\u606f\u4f18\u5148\u7ea7",level:2},{value:"7.12 \u591a\u8bed\u8a00\u652f\u6301",id:"712-\u591a\u8bed\u8a00\u652f\u6301",level:2},{value:"7.13 \u89c4\u8303\u5316\u7ed3\u679c\u5f02\u5e38\u5904\u7406",id:"713-\u89c4\u8303\u5316\u7ed3\u679c\u5f02\u5e38\u5904\u7406",level:2},{value:"7.14 \u5168\u5c40\u5f02\u5e38\u5904\u7406\u63d0\u4f9b\u5668",id:"714-\u5168\u5c40\u5f02\u5e38\u5904\u7406\u63d0\u4f9b\u5668",level:2},{value:"7.15 FriendlyExceptionSettings \u914d\u7f6e",id:"715-friendlyexceptionsettings-\u914d\u7f6e",level:2},{value:"7.16 BadPageResult \u9519\u8bef\u9875",id:"716-badpageresult-\u9519\u8bef\u9875",level:2},{value:"7.17 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"717-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:u};function k(e){var n=e.components,t=(0,i.Z)(e,l);return(0,a.kt)("wrapper",(0,r.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"71-\u4ec0\u4e48\u662f\u5f02\u5e38"},"7.1 \u4ec0\u4e48\u662f\u5f02\u5e38"),(0,a.kt)("p",null,"\u5f02\u5e38\u4e00\u822c\u662f\u6307\u8fd0\u884c\u671f\uff08\u6b64\u5904\u7279\u6307 ",(0,a.kt)("inlineCode",{parentName:"p"},"Exception")," \u7c7b\uff09\u4f1a\u53d1\u751f\u7684\u5bfc\u81f4\u7a0b\u5e8f\u610f\u5916\u4e2d\u6b62\u7684\u95ee\u9898\uff0c\u662f\u4e00\u79cd\u5bf9\u95ee\u9898\u7684\u63cf\u8ff0\u540e\u7684\u5c01\u88c5\u5bf9\u8c61\u3002"),(0,a.kt)("p",null,"\u5728\u8fc7\u53bb\u5f00\u53d1\u4e2d\uff0c\u901a\u5e38\u5f02\u5e38\u7531\u7cfb\u7edf\u8fd0\u884c\u65f6\u51fa\u9519\u629b\u51fa\uff0c\u4f46\u73b0\u5728\u7684\u5f00\u53d1\u8fc7\u7a0b\u4e2d\uff0c\u6211\u4eec\u5e94\u5728\u7a0b\u5e8f\u5f00\u53d1\u4e2d\u5408\u7406\u7684\u629b\u51fa\u5f02\u5e38\uff0c\u6bd4\u5982\u66f4\u65b0\u4e00\u6761\u4e0d\u5b58\u5728\u7684\u5b9e\u4f53\uff0c\u6216\u67e5\u8be2\u4e00\u4e2a\u4e0d\u5b58\u5728\u7684\u6570\u636e\u7b49\u7b49\u3002"),(0,a.kt)("h2",{id:"72-\u5904\u7406\u5f02\u5e38\u65b9\u5f0f"},"7.2 \u5904\u7406\u5f02\u5e38\u65b9\u5f0f"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u5904\u7406\uff0c\u76f4\u63a5\u4e2d\u65ad\u7a0b\u5e8f\u6267\u884c\uff08\u4e0d\u63a8\u8350\uff09"),(0,a.kt)("li",{parentName:"ul"},"\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"li"},"try catch finally")," \u5904\u7406\uff08\u4e0d\u63a8\u8350\uff09"),(0,a.kt)("li",{parentName:"ul"},"\u5168\u5c40\u7edf\u4e00\u5904\u7406\uff0c\u5e76\u8bb0\u5f55\u5f02\u5e38\u4fe1\u606f",(0,a.kt)("strong",{parentName:"li"},"\uff08\u63a8\u8350\uff09")),(0,a.kt)("li",{parentName:"ul"},"\u5f02\u5e38\u6ce8\u89e3\u65b9\u5f0f\u5904\u7406\uff0c\u652f\u6301",(0,a.kt)("strong",{parentName:"li"},"\u672c\u5730\u5316")," ",(0,a.kt)("strong",{parentName:"li"},"\uff08\u63a8\u8350\uff09"))),(0,a.kt)("h2",{id:"73-\u4ec0\u4e48\u662f\u53cb\u597d\u5f02\u5e38\u5904\u7406"},"7.3 \u4ec0\u4e48\u662f\u53cb\u597d\u5f02\u5e38\u5904\u7406"),(0,a.kt)("h3",{id:"731-\u975e\u53cb\u597d\u5f02\u5e38\u5904\u7406"},"7.3.1 \u975e\u53cb\u597d\u5f02\u5e38\u5904\u7406"),(0,a.kt)("p",null,"\u5728\u4e86\u89e3\u53cb\u597d\u5f02\u5e38\u5904\u7406\u4e4b\u524d\u53ef\u4ee5\u770b\u770b\u975e\u53cb\u597d\u5f02\u5e38\u5904\u7406\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5bf9\u7ec8\u7aef\u7528\u6237\u629b\u51fa ",(0,a.kt)("inlineCode",{parentName:"li"},"500\u72b6\u6001\u7801")," \u5806\u6808\u4fe1\u606f"),(0,a.kt)("li",{parentName:"ul"},"\u5927\u91cf\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"try catch")," \u4ee3\u7801\uff0c\u6c61\u67d3\u6b63\u5e38\u4e1a\u52a1\u903b\u8f91"),(0,a.kt)("li",{parentName:"ul"},"\u6ca1\u6709\u89c4\u8303\u5316\u7684\u5f02\u5e38\u72b6\u6001\u7801\u548c\u5f02\u5e38\u6d88\u606f\u7ba1\u7406"),(0,a.kt)("li",{parentName:"ul"},"\u6ca1\u6709\u5f02\u5e38\u65e5\u5fd7\u6536\u96c6\u8bb0\u5f55"),(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u652f\u6301\u5f02\u5e38\u6d88\u606f\u672c\u5730\u5316\u5904\u7406"),(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u652f\u6301\u5f02\u5e38\u7b56\u7565\uff0c\u5931\u8d25\u540e\u7a0b\u5e8f\u7acb\u5373\u7ec8\u6b62"),(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u652f\u6301\u5206\u5e03\u5f0f\u4e8b\u52a1 CAP"),(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u652f\u6301\u5f02\u5e38\u4f20\u64ad"),(0,a.kt)("li",{parentName:"ul"},"\u8fd4\u56de\u7684\u5f02\u5e38\u683c\u5f0f\u6742\u4e71")),(0,a.kt)("h3",{id:"732-\u53cb\u597d\u5f02\u5e38\u5904\u7406"},"7.3.2 \u53cb\u597d\u5f02\u5e38\u5904\u7406"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5bf9\u7ec8\u7aef\u7528\u6237\u63d0\u793a\u53cb\u597d"),(0,a.kt)("li",{parentName:"ul"},"\u5bf9\u540e\u7aef\u5f00\u53d1\u4eba\u5458\u63d0\u4f9b\u8be6\u7ec6\u7684\u5f02\u5e38\u5806\u6808"),(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u5e72\u6270\u6b63\u5e38\u4e1a\u52a1\u903b\u8f91\u4ee3\u7801\uff0c\u5982 \u6ca1\u6709 ",(0,a.kt)("inlineCode",{parentName:"li"},"try catch")," \u4ee3\u7801"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u5f02\u5e38\u72b6\u6001\u7801\u591a\u65b9\u8bbe\u7f6e"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u5f02\u5e38\u6d88\u606f\u672c\u5730\u5316"),(0,a.kt)("li",{parentName:"ul"},"\u5f02\u5e38\u4fe1\u606f\u7edf\u4e00\u914d\u7f6e\u7ba1\u7406"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u5f02\u5e38\u7b56\u7565\uff0c\u5982\u91cd\u8bd5"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u5f02\u5e38\u65e5\u5fd7\u6536\u96c6\u8bb0\u5f55"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301 CAP \u5206\u5e03\u5f0f\u4e8b\u52a1\u5173\u8054"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u5185\u90e8\u5f02\u5e38\u5916\u90e8\u4f20\u64ad"),(0,a.kt)("li",{parentName:"ul"},"\u652f\u6301\u8fd4\u56de\u7edf\u4e00\u7684\u5f02\u5e38\u683c\u5f0f\u6570\u636e")),(0,a.kt)("h2",{id:"74-\u53cb\u597d\u5f02\u5e38\u5904\u7406\u4f7f\u7528\u793a\u4f8b"},"7.4 \u53cb\u597d\u5f02\u5e38\u5904\u7406\u4f7f\u7528\u793a\u4f8b"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u7684\u53cb\u597d\u5f02\u5e38\u5904\u7406\u65b9\u5f0f\u3002"),(0,a.kt)("admonition",{title:"\u5907\u6ce8",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},".AddFriendlyException()")," \u9ed8\u8ba4\u5df2\u7ecf\u96c6\u6210\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"AddInject()")," \u4e2d\u4e86\uff0c\u65e0\u9700\u518d\u6b21\u6ce8\u518c\u3002\u4e5f\u5c31\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"7.4.1")," \u7ae0\u8282\u53ef\u4e0d\u914d\u7f6e\u3002")),(0,a.kt)("h3",{id:"741-\u6ce8\u518c\u53cb\u597d\u5f02\u5e38\u670d\u52a1"},"7.4.1 \u6ce8\u518c\u53cb\u597d\u5f02\u5e38\u670d\u52a1"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {11} title="Furion.Web.Core\\FurWebCoreStartup.cs"',showLineNumbers:!0,"":!0,"{11}":!0,title:'"Furion.Web.Core\\FurWebCoreStartup.cs"'},"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.Web.Core\n{\n [AppStartup(800)]\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddControllers()\n .AddFriendlyException();\n }\n }\n}\n")),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},".AddFriendlyException()")," \u9700\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"services.AddControllers()")," \u4e4b\u540e\u6ce8\u518c\u3002")),(0,a.kt)("h3",{id:"742-\u4e24\u4e2a\u4f8b\u5b50"},"7.4.2 \u4e24\u4e2a\u4f8b\u5b50"),(0,a.kt)("h4",{id:"\u7b80\u5355\u629b\u4e2a\u5f02\u5e38"},"\u7b80\u5355\u629b\u4e2a\u5f02\u5e38"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,12}",showLineNumbers:!0,"":!0,"{2,12}":!0},'using Furion.DynamicApiController;\nusing Furion.FriendlyException;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public int Get(int id)\n {\n if (id < 3)\n {\n throw Oops.Oh($"{id} \u4e0d\u80fd\u5c0f\u4e8e3");\n }\n\n return id;\n }\n }\n}\n')),(0,a.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,a.kt)("img",{src:(0,o.Z)("img/yhyc1.gif")}),(0,a.kt)("h4",{id:"\u629b\u51fa\u7279\u5b9a\u7c7b\u578b\u5f02\u5e38"},"\u629b\u51fa\u7279\u5b9a\u7c7b\u578b\u5f02\u5e38"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,13}",showLineNumbers:!0,"":!0,"{2,13}":!0},'using Furion.DynamicApiController;\nusing Furion.FriendlyException;\nusing System;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public int Get(int id)\n {\n if (id < 3)\n {\n throw Oops.Oh($"{id} \u4e0d\u80fd\u5c0f\u4e8e3\u3002", typeof(InvalidOperationException));\n }\n\n return id;\n }\n }\n}\n')),(0,a.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,a.kt)("img",{src:(0,o.Z)("img/yhyc2.png")}),(0,a.kt)("h2",{id:"75-\u5173\u4e8e-oopsoh"},"7.5 \u5173\u4e8e Oops.Oh"),(0,a.kt)("p",null,"\u901a\u8fc7\u4e0a\u9762\u7684\u4f8b\u5b50\u53ef\u4ee5\u770b\u51fa\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Oops.Oh(errorMessage)")," \u53ef\u4ee5\u7ed3\u5408 ",(0,a.kt)("inlineCode",{parentName:"p"},"throw")," \u629b\u51fa\u5f02\u5e38\u3002\u5bf9\u4e8e\u719f\u6089",(0,a.kt)("inlineCode",{parentName:"p"},"C#"),"\u7684\u4eba\u5458\u6765\u8bf4\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"throw")," \u540e\u9762\u53ea\u80fd ",(0,a.kt)("inlineCode",{parentName:"p"},"Exception")," \u5b9e\u4f8b\u3002",(0,a.kt)("inlineCode",{parentName:"p"},"Oops.Oh(...)")," \u65b9\u6cd5\u8fd4\u56de\u6b63\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"Exception")," \u5b9e\u4f8b\u3002"),(0,a.kt)("h3",{id:"751-\u4e3a\u4ec0\u4e48\u8d77\u8fd9\u4e2a\u540d\u5b57"},"7.5.1 \u4e3a\u4ec0\u4e48\u8d77\u8fd9\u4e2a\u540d\u5b57\uff1f"),(0,a.kt)("p",null,"\u8fd9\u4e2a\u540d\u5b57\u6765\u6e90\u4e8e\u4e00\u4e2a\u82f1\u8bed\u53e5\u5b50\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"Oh, Oops!"),"\uff0c\u610f\u601d\u662f ",(0,a.kt)("strong",{parentName:"p"},"\u5662\uff08\u54ce\uff09\uff0c\u51fa\u9519\u4e86\uff01"),"\uff0c\u6240\u4ee5\u5c31\u6709\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"Oops.Oh"),"\u3002"),(0,a.kt)("h3",{id:"752-oopsoh-\u91cd\u8f7d\u65b9\u6cd5"},"7.5.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Oops.Oh")," \u91cd\u8f7d\u65b9\u6cd5"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,22,30,39}",showLineNumbers:!0,"":!0,"{13,22,30,39}":!0},'using System;\n\nnamespace Furion.FriendlyException\n{\n public static class Oops\n {\n /// \n /// \u629b\u51fa\u5b57\u7b26\u4e32\u5f02\u5e38\n /// \n /// \u5f02\u5e38\u6d88\u606f\n /// String.Format \u53c2\u6570\n /// \u5f02\u5e38\u5b9e\u4f8b\n public static Exception Oh(string errorMessage, params object[] args);\n\n /// \n /// \u629b\u51fa\u5b57\u7b26\u4e32\u5f02\u5e38\n /// \n /// \u5f02\u5e38\u6d88\u606f\n /// \u5177\u4f53\u5f02\u5e38\u7c7b\u578b\n /// String.Format \u53c2\u6570\n /// \u5f02\u5e38\u5b9e\u4f8b\n public static Exception Oh(string errorMessage, Type exceptionType, params object[] args);\n\n /// \n /// \u629b\u51fa\u9519\u8bef\u7801\u5f02\u5e38\n /// \n /// \u9519\u8bef\u7801\n /// String.Format \u53c2\u6570\n /// \u5f02\u5e38\u5b9e\u4f8b\n public static Exception Oh(object errorCode, params object[] args);\n\n /// \n /// \u629b\u51fa\u9519\u8bef\u7801\u5f02\u5e38\n /// \n /// \u9519\u8bef\u7801\n /// \u5177\u4f53\u5f02\u5e38\u7c7b\u578b\n /// String.Format \u53c2\u6570\n /// \u5f02\u5e38\u5b9e\u4f8b\n public static Exception Oh(object errorCode, Type exceptionType, params object[] args);\n }\n}\n')),(0,a.kt)("h2",{id:"76-\u6700\u4f73\u5b9e\u8df5-"},"7.6 \u6700\u4f73\u5b9e\u8df5 \ud83e\udd17"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u4e14\u89c4\u8303\u5316\u7684\u53cb\u597d\u5f02\u5e38\u5904\u7406\u65b9\u5f0f\uff0c\u901a\u8fc7\u8fd9\u4e2a\u65b9\u5f0f\u53ef\u4ee5\u65b9\u4fbf\u7ba1\u7406\u5f02\u5e38\u72b6\u6001\u7801\u3001\u5f02\u5e38\u4fe1\u606f\u53ca\u5f02\u5e38\u672c\u5730\u5316\u3002"),(0,a.kt)("h3",{id:"761-\u521b\u5efa\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b"},"7.6.1 \u521b\u5efa\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b"),(0,a.kt)("p",null,"\u5b9e\u73b0\u81ea\u5b9a\u4e49\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b\u5fc5\u987b\u9075\u5faa\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u7c7b\u578b\u5fc5\u987b\u662f\u516c\u5f00\u4e14\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"Enum")," \u679a\u4e3e\u7c7b\u578b"),(0,a.kt)("li",{parentName:"ul"},"\u679a\u4e3e\u7c7b\u578b\u5fc5\u987b\u8d34\u6709 ",(0,a.kt)("inlineCode",{parentName:"li"},"[ErrorCodeType]")," \u7279\u6027"),(0,a.kt)("li",{parentName:"ul"},"\u679a\u4e3e\u4e2d\u6bcf\u4e00\u9879\u5fc5\u987b\u8d34\u6709 ",(0,a.kt)("inlineCode",{parentName:"li"},"[ErrorCodeItemMetadata]")," \u7279\u6027")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,8,11,14,17}",showLineNumbers:!0,"":!0,"{1,5,8,11,14,17}":!0},'using Furion.FriendlyException;\n\nnamespace Furion.Application\n{\n [ErrorCodeType]\n public enum ErrorCodes\n {\n [ErrorCodeItemMetadata("{0} \u4e0d\u80fd\u5c0f\u4e8e {1}")]\n z1000,\n\n [ErrorCodeItemMetadata("\u6570\u636e\u4e0d\u5b58\u5728")]\n x1000,\n\n [ErrorCodeItemMetadata("{0} \u53d1\u73b0 {1} \u4e2a\u5f02\u5e38", "\u767e\u5c0f\u50e7", 2)]\n x1001,\n\n [ErrorCodeItemMetadata("\u670d\u52a1\u5668\u8fd0\u884c\u5f02\u5e38", ErrorCode = "Error")]\n SERVER_ERROR\n }\n}\n')),(0,a.kt)("admonition",{type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"[ErrorCodeType]")," \u7279\u6027\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"IErrorCodeTypeProvider")," \u63d0\u4f9b\u5668\u63a5\u53e3\u6765\u63d0\u4f9b\u5f02\u5e38\u4fe1\u606f\u626b\u63cf\uff0c\u8fd9\u91cc\u7528\u7684\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"[ErrorCodeType]")," \u7279\u6027\u7c7b\u3002")),(0,a.kt)("h3",{id:"762-\u5173\u4e8e-errorcodeitemmetadata"},"7.6.2 \u5173\u4e8e ",(0,a.kt)("inlineCode",{parentName:"h3"},"[ErrorCodeItemMetadata]")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86",(0,a.kt)("inlineCode",{parentName:"p"},"[ErrorCodeItemMetadata]")," \u7279\u6027\u7528\u6765\u6807\u8bc6",(0,a.kt)("strong",{parentName:"p"},"\u679a\u4e3e\u5b57\u6bb5"),"\u5f02\u5e38\u5143\u6570\u636e\uff0c\u8be5\u7279\u6027\u652f\u6301\u4f20\u5165 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6d88\u606f\u5185\u5bb9")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"\u683c\u5f0f\u5316\u53c2\u6570"),"\u3002\u6700\u7ec8\u4f1a\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"String.Format(\u6d88\u606f\u5185\u5bb9\uff0c\u683c\u5f0f\u5316\u53c2\u6570)")," \u8fdb\u884c\u683c\u5f0f\u5316\u3002"),(0,a.kt)("p",null,"\u5982\u679c\u6d88\u606f\u5185\u5bb9\u4e2d\u5305\u542b",(0,a.kt)("inlineCode",{parentName:"p"},"\u683c\u5f0f\u5316\u5360\u4f4d\u7b26"),"\u4f46\u672a\u6307\u5b9a",(0,a.kt)("inlineCode",{parentName:"p"},"\u683c\u5f0f\u5316\u53c2\u6570"),"\uff0c\u90a3\u4e48\u4f1a\u67e5\u627e\u5f02\u5e38\u6240\u5728\u65b9\u6cd5\u662f\u5426\u8d34\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},"[IfException]")," \u7279\u6027\u4e14\u542b\u6709\u683c\u5f0f\u5316\u53c2\u6570\uff0c\u63a5\u7740\u5c31\u4f1a\u67e5\u627e ",(0,a.kt)("inlineCode",{parentName:"p"},"Oops.Oh")," \u4e2d\u6307\u5b9a\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u683c\u5f0f\u5316\u53c2\u6570"),"\u3002"),(0,a.kt)("h3",{id:"763-\u9759\u6001\u5f02\u5e38\u7c7b\u4f7f\u7528"},"7.6.3 \u9759\u6001\u5f02\u5e38\u7c7b\u4f7f\u7528"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,12}",showLineNumbers:!0,"":!0,"{2,12}":!0},"using Furion.DynamicApiController;\nusing Furion.FriendlyException;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public int Get(int id)\n {\n if (id < 3)\n {\n throw Oops.Oh(ErrorCodes.z1000, id, 3);\n }\n\n return id;\n }\n }\n}\n")),(0,a.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,a.kt)("img",{src:(0,o.Z)("img/yhyc3.gif")}),(0,a.kt)("h3",{id:"764-\u5f02\u5e38\u65b9\u6cd5\u91cd\u8bd5"},"7.6.4 \u5f02\u5e38\u65b9\u6cd5\u91cd\u8bd5"),(0,a.kt)("admonition",{title:"\u8c03\u6574\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"v2.17.0+")," \u7248\u672c\u4e0b\u9762\u65b9\u6cd5\u8bf7\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Retry.Invoke()")," \u66ff\u4ee3\u3002")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"Oops.Retry(() => {\n // Do.....\n}, 3, 1000);\n\n// \u5e26\u8fd4\u56de\u503c\nvar value = Oops.Retry(() => {\n // Do.....\n}, 3, 1000);\n\n// \u53ea\u6709\u7279\u5b9a\u5f02\u5e38\u624d\u76d1\u542c\nOops.Retry(() => {\n\n}, 3, 1000, typeof(ArgumentNullException));\n")),(0,a.kt)("h3",{id:"765-\u66f4\u591a\u4f8b\u5b50"},"7.6.5 \u66f4\u591a\u4f8b\u5b50"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6}",showLineNumbers:!0,"":!0,"{6}":!0},'throw Oops.Oh(1000);\nthrow Oops.Oh(ErrorCodes.x1000);\nthrow Oops.Oh("\u54c8\u54c8\u54c8\u54c8");\nthrow Oops.Oh(errorCode: "x1001");\nthrow Oops.Oh(1000, typeof(Exception));\nthrow Oops.Oh(1000).StatusCode(400); // \u8bbe\u7f6e\u9519\u8bef\u7801\nthrow Oops.Oh(1000).WithData(new Model {}); // \u8bbe\u7f6e\u989d\u5916\u6570\u636e\nthrow Oops.Bah("\u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef"); // \u629b\u51fa\u4e1a\u52a1\u5f02\u5e38\uff0c\u72b6\u6001\u7801\u4e3a 400\nthrow Oops.Bah(1000);\n')),(0,a.kt)("h2",{id:"77-\u591a\u4e2a\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b"},"7.7 \u591a\u4e2a\u5f02\u5e38\u4fe1\u606f\u7c7b\u578b"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5-6,21-22}",showLineNumbers:!0,"":!0,"{5-6,21-22}":!0},'using Furion.FriendlyException;\n\nnamespace Furion.Application\n{\n [ErrorCodeType]\n public enum ErrorCodes\n {\n [ErrorCodeItemMetadata("{0} \u4e0d\u80fd\u5c0f\u4e8e {1}")]\n z1000,\n\n [ErrorCodeItemMetadata("\u6570\u636e\u4e0d\u5b58\u5728")]\n x1000,\n\n [ErrorCodeItemMetadata("{0} \u53d1\u73b0 {1} \u4e2a\u5f02\u5e38", "\u767e\u5c0f\u50e7", 2)]\n x1001,\n\n [ErrorCodeItemMetadata("\u670d\u52a1\u5668\u8fd0\u884c\u5f02\u5e38", ErrorCode = "Error")]\n SERVER_ERROR\n }\n\n [ErrorCodeType]\n public enum UserErrorCodes\n {\n [ErrorCodeItemMetadata("\u7528\u6237\u6570\u636e\u4e0d\u5b58\u5728")]\n u1000,\n\n [ErrorCodeItemMetadata("\u5176\u4ed6\u5f02\u5e38")]\n u1001\n }\n}\n')),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u591a\u4e2a\u5f02\u5e38\u9759\u6001\u7c7b\u4e2d\u4e5f\u5fc5\u987b\u4fdd\u8bc1\u5e38\u91cf\u503c\u552f\u4e00\u6027\uff0c\u4e0d\u53ef\u91cd\u590d\u3002")),(0,a.kt)("h2",{id:"78-ierrorcodetypeprovider-\u63d0\u4f9b\u5668"},"7.8 ",(0,a.kt)("inlineCode",{parentName:"h2"},"IErrorCodeTypeProvider")," \u63d0\u4f9b\u5668"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u8fd8\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"IErrorCodeTypeProvider")," \u5f02\u5e38\u6d88\u606f\u63d0\u4f9b\u5668\u63a5\u53e3\uff0c\u65b9\u4fbf\u5728\u4e0d\u80fd\u8d34 ",(0,a.kt)("inlineCode",{parentName:"p"},"[ErrorCodeType]")," \u7279\u6027\u60c5\u51b5\u4e0b\u4f7f\u7528\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6,8-11}",showLineNumbers:!0,"":!0,"{2,6,8-11}":!0},"using Furion.FriendlyException;\nusing System;\n\nnamespace Furion.Application\n{\n public class CustomErrorCodeTypeProvider : IErrorCodeTypeProvider\n {\n public Type[] Definitions => new[] {\n typeof(ErrorCodes),\n typeof(ErrorCodes2)\n };\n }\n}\n")),(0,a.kt)("p",null,"\u542f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IErrorCodeTypeProvider")," \u63d0\u4f9b\u5668\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {11} title="Furion.Web.Core\\FurWebCoreStartup.cs"',showLineNumbers:!0,"":!0,"{11}":!0,title:'"Furion.Web.Core\\FurWebCoreStartup.cs"'},"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.Web.Core\n{\n [AppStartup(800)]\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddControllers()\n .AddFriendlyException();\n }\n }\n}\n")),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u53ea\u6709\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IErrorCodeTypeProvider")," \u65b9\u5f0f\u624d\u9700\u4f7f\u7528\u6cdb\u578b\u65b9\u5f0f\u6ce8\u518c\u3002\u901a\u8fc7\u4e0a\u9762\u7684\u65b9\u5f0f\u6ce8\u518c\u53ef\u4ee5\u540c\u65f6\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"p"},"IErrorCodeTypeProvider")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"[ErrorCodeType]")," \u65b9\u5f0f\u3002")),(0,a.kt)("h2",{id:"79-appsettingjson-\u4e2d\u914d\u7f6e"},"7.9 ",(0,a.kt)("inlineCode",{parentName:"h2"},"appsetting.json")," \u4e2d\u914d\u7f6e"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u8fd8\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u7684\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e\u5f02\u5e38\uff0c\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\u53ef\u4ee5\u5b9e\u73b0\u5f02\u5e38\u4fe1\u606f\u540e\u671f\u914d\u7f6e\uff0c\u4e5f\u5c31\u662f\u65e0\u9700\u5728\u5f00\u53d1\u9636\u6bb5\u9884\u5148\u5b9a\u4e49\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers {2-8} title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,"{2-8}":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "ErrorCodeMessageSettings": {\n "Definitions": [\n ["5000", "{0} \u4e0d\u80fd\u5c0f\u4e8e {1}"],\n ["5001", "\u6211\u53eb {0} \u540d\u5b57", "\u767e\u5c0f\u50e7"],\n ["5002", "Oops! \u51fa\u9519\u4e86"]\n ]\n }\n}\n')),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Definitions")," \u7c7b\u578b\u4e3a\u4e8c\u7ef4\u6570\u7ec4\uff0c\u4e8c\u7ef4\u6570\u7ec4\u4e2d\u7684\u6bcf\u4e00\u4e2a\u6570\u7ec4\u7b2c\u4e00\u4e2a\u53c2\u6570\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"ErrorCode")," \u4e5f\u5c31\u662f\u9519\u8bef\u7801\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"ErrorMessage")," \u6d88\u606f\u5185\u5bb9\uff0c\u5269\u4f59\u53c2\u6570\u4f5c\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"ErrorMessage")," \u7684\u683c\u5f0f\u5316\u53c2\u6570\u3002"),(0,a.kt)("h4",{id:"\u4f7f\u7528\u793a\u4f8b"},"\u4f7f\u7528\u793a\u4f8b"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,12}",showLineNumbers:!0,"":!0,"{2,12}":!0},"using Furion.DynamicApiController;\nusing Furion.FriendlyException;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public int Get(int id)\n {\n if (id < 3)\n {\n throw Oops.Oh(5000, id, 3); // \u53ef\u4ee5\u5c06 5000\u4f5c\u4e3a\u5e38\u91cf\u914d\u7f6e\u8d77\u6765\n }\n\n return id;\n }\n }\n}\n")),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"[ErrorCodeType]")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"IErrorCodeTypeProvider")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u53ef\u4ee5\u540c\u65f6\u4f7f\u7528\u3002")),(0,a.kt)("h2",{id:"710-ifexception-\u4f7f\u7528"},"7.10 ",(0,a.kt)("inlineCode",{parentName:"h2"},"[IfException]")," \u4f7f\u7528"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"[IfException]")," \u7279\u6027\u53ef\u4ee5",(0,a.kt)("strong",{parentName:"p"},"\u8986\u76d6\u9ed8\u8ba4\u6d88\u606f\u914d\u7f6e"),"\u3002\u4e5f\u5c31\u662f\u8986\u76d6 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5f02\u5e38\u6d88\u606f\u7c7b\u578b")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u4e2d\u7684\u914d\u7f6e\u3002"),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"[IfException]")," \u53ea\u80fd\u8d34\u5728\u65b9\u6cd5\u4e0a\uff0c\u652f\u6301\u591a\u4e2a\u3002")),(0,a.kt)("h3",{id:"7101-\u4f7f\u7528\u793a\u4f8b"},"7.10.1 \u4f7f\u7528\u793a\u4f8b"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5f02\u5e38\u6d88\u606f\u7c7b\u5b9a\u4e49")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4}",showLineNumbers:!0,"":!0,"{1,4}":!0},'[ErrorCodeType]\npublic enum ErrorCodes\n{\n [ErrorCodeItemMetadata("{0} \u4e0d\u80fd\u5c0f\u4e8e {1}")]\n z1000\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u8986\u76d6\u9ed8\u8ba4\u914d\u7f6e")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8}",showLineNumbers:!0,"":!0,"{8}":!0},'using Furion.DynamicApiController;\nusing Furion.FriendlyException;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n [IfException(ErrorCodes.z1000, ErrorMessage = "\u6211\u8986\u76d6\u4e86\u9ed8\u8ba4\u7684\uff1a{0} \u4e0d\u80fd\u5c0f\u4e8e {1}")]\n public int Get(int id)\n {\n if (id < 3)\n {\n throw Oops.Oh(ErrorCodes.z1000, id, 3);\n }\n\n return id;\n }\n }\n}\n')),(0,a.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,a.kt)("img",{src:(0,o.Z)("img/yhyc4.png")}),(0,a.kt)("h3",{id:"7102-\u66f4\u591a\u4f8b\u5b50"},"7.10.2 \u66f4\u591a\u4f8b\u5b50"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,8-11}",showLineNumbers:!0,"":!0,"{2,8-11}":!0},'using Furion.DynamicApiController;\nusing Furion.FriendlyException;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n [IfException(typeof(ExceptionType), ErrorMessage = "\u7279\u5b9a\u5f02\u5e38\u7c7b\u578b\u5168\u5c40\u62e6\u622a")]\n [IfException(ErrorMessage = "\u5168\u5c40\u5f02\u5e38\u62e6\u622a")]\n [IfException(ErrorCodes.z1000, ErrorMessage = "\u6211\u8986\u76d6\u4e86\u9ed8\u8ba4\u7684\uff1a{0} \u4e0d\u80fd\u5c0f\u4e8e {1}")]\n [IfException(ErrorCodes.x1001, "\u683c\u5f0f\u5316\u53c2\u65701", "\u683c\u5f0f\u5316\u53c2\u65702", ErrorMessage = "\u6211\u8986\u76d6\u4e86\u9ed8\u8ba4\u7684\uff1a{0} \u4e0d\u80fd\u5c0f\u4e8e {1}")]\n [IfException(ErrorCodes.x1000, "\u683c\u5f0f\u5316\u53c2\u65701", "\u683c\u5f0f\u5316\u53c2\u65702")]\n [IfException(ErrorCodes.SERVER_ERROR, "\u683c\u5f0f\u5316\u53c2\u65701", "\u683c\u5f0f\u5316\u53c2\u65702")]\n public int Get(int id)\n {\n if (id < 3)\n {\n throw Oops.Oh(ErrorCodes.z1000, id, 3);\n }\n\n return id;\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u683c\u5f0f\u5316\u6d41\u7a0b",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u6d88\u606f\u5185\u5bb9\u4e2d\u5305\u542b",(0,a.kt)("inlineCode",{parentName:"p"},"\u683c\u5f0f\u5316\u5360\u4f4d\u7b26"),"\u4f46\u672a\u6307\u5b9a",(0,a.kt)("inlineCode",{parentName:"p"},"\u683c\u5f0f\u5316\u53c2\u6570"),"\uff0c\u90a3\u4e48\u4f1a\u67e5\u627e\u5f02\u5e38\u6240\u5728\u65b9\u6cd5\u662f\u5426\u8d34\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},"[IfException]")," \u7279\u6027\u4e14\u542b\u6709\u683c\u5f0f\u5316\u53c2\u6570\uff0c\u63a5\u7740\u5c31\u4f1a\u67e5\u627e ",(0,a.kt)("inlineCode",{parentName:"p"},"Oops.Oh")," \u4e2d\u6307\u5b9a\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u683c\u5f0f\u5316\u53c2\u6570"),"\u3002")),(0,a.kt)("h2",{id:"711-\u5f02\u5e38\u6d88\u606f\u4f18\u5148\u7ea7"},"7.11 \u5f02\u5e38\u6d88\u606f\u4f18\u5148\u7ea7"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"[ErrorCodeItemMetadata]")," -> ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," -> ",(0,a.kt)("inlineCode",{parentName:"p"},"[IfException]"),"\u3002",(0,a.kt)("strong",{parentName:"p"},"\uff08\u4f4e -> \u9ad8\uff09")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"[IfException]")," \u4f1a\u8986\u76d6 ",(0,a.kt)("inlineCode",{parentName:"li"},"appsettings.json")," \u5b9a\u4e49\u7684\u72b6\u6001\u7801\u6d88\u606f\u3002"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"appsettings.json")," \u4f1a\u8986\u76d6 ",(0,a.kt)("inlineCode",{parentName:"li"},"[ErrorCodeItemMetadata]")," \u5b9a\u4e49\u7684\u6d88\u606f\u3002")),(0,a.kt)("h2",{id:"712-\u591a\u8bed\u8a00\u652f\u6301"},"7.12 \u591a\u8bed\u8a00\u652f\u6301"),(0,a.kt)("p",null,"\u53c2\u89c1 ",(0,a.kt)("a",{parentName:"p",href:"./local-language"},"\u3010\u5168\u7403\u5316\u548c\u672c\u5730\u5316\uff08\u591a\u8bed\u8a00\uff09\u3011")," \u7ae0\u8282"),(0,a.kt)("h2",{id:"713-\u89c4\u8303\u5316\u7ed3\u679c\u5f02\u5e38\u5904\u7406"},"7.13 \u89c4\u8303\u5316\u7ed3\u679c\u5f02\u5e38\u5904\u7406"),(0,a.kt)("admonition",{title:"\u67e5\u770b\u89c4\u8303\u5316\u7ed3\u679c\u6587\u6863",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u9700\u81ea\u5b9a\u4e49\u89c4\u8303\u5316\u7ed3\u679c\u53ef\u67e5\u9605 \u3010",(0,a.kt)("a",{parentName:"p",href:"/furion/docs/specification-document#67-%E7%BB%9F%E4%B8%80%E8%BF%94%E5%9B%9E%E5%80%BC%E6%A8%A1%E5%9E%8B%E8%A7%84%E8%8C%83%E5%8C%96%E7%BB%93%E6%9E%9Capi-%E8%BF%94%E5%9B%9E%E5%80%BC"},"6.7 \u7edf\u4e00\u8fd4\u56de\u503c\u6a21\u578b"),"\u3011")),(0,a.kt)("h2",{id:"714-\u5168\u5c40\u5f02\u5e38\u5904\u7406\u63d0\u4f9b\u5668"},"7.14 \u5168\u5c40\u5f02\u5e38\u5904\u7406\u63d0\u4f9b\u5668"),(0,a.kt)("p",null,"\u901a\u5e38\u6211\u4eec\u9700\u8981\u5728\u5f02\u5e38\u6355\u83b7\u7684\u65f6\u5019\u5199\u65e5\u5fd7\uff0c\u8fd9\u65f6\u5019\u5c31\u9700\u8981\u4f7f\u7528\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"IGlobalExceptionHandler")," \u5f02\u5e38\u5b9a\u4e49\u5904\u7406\u7a0b\u5e8f\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8}",showLineNumbers:!0,"":!0,"{8}":!0},"using Furion.DependencyInjection;\nusing Furion.FriendlyException;\nusing Microsoft.AspNetCore.Mvc.Filters;\nusing System.Threading.Tasks;\n\nnamespace Furion.Application\n{\n public class LogExceptionHandler : IGlobalExceptionHandler, ISingleton\n {\n public Task OnExceptionAsync(ExceptionContext context)\n {\n // \u5199\u65e5\u5fd7\n\n return Task.CompletedTask;\n }\n }\n}\n")),(0,a.kt)("h2",{id:"715-friendlyexceptionsettings-\u914d\u7f6e"},"7.15 ",(0,a.kt)("inlineCode",{parentName:"h2"},"FriendlyExceptionSettings")," \u914d\u7f6e"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"HideErrorCode"),"\uff1a\u9690\u85cf\u9519\u8bef\u7801\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"false")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"DefaultErrorCode"),"\uff1a\u9ed8\u8ba4\u9519\u8bef\u7801\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"DefaultErrorMessage"),"\uff1a\u9ed8\u8ba4\u9519\u8bef\u6d88\u606f\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ThrowBah"),"\uff1a\u662f\u5426\u5c06 ",(0,a.kt)("inlineCode",{parentName:"li"},"Oops.Oh")," \u9ed8\u8ba4\u629b\u51fa\u4e3a\u4e1a\u52a1\u5f02\u5e38\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"false"),"\uff0c\u8bbe\u7f6e ",(0,a.kt)("inlineCode",{parentName:"li"},"true")," \u4e4b\u540e ",(0,a.kt)("inlineCode",{parentName:"li"},"Oops.Oh")," \u9ed8\u8ba4\u8fdb\u5165 ",(0,a.kt)("inlineCode",{parentName:"li"},"OnValidateFailed")," \u5904\u7406\uff0c\u800c\u4e0d\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"OnException"))),(0,a.kt)("p",null,"\u914d\u7f6e\u793a\u4f8b"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "FriendlyExceptionSettings": {\n "DefaultErrorMessage": "\u7cfb\u7edf\u5f02\u5e38\uff0c\u8bf7\u8054\u7cfb\u7ba1\u7406\u5458"\n }\n}\n')),(0,a.kt)("h2",{id:"716-badpageresult-\u9519\u8bef\u9875"},"7.16 ",(0,a.kt)("inlineCode",{parentName:"h2"},"BadPageResult")," \u9519\u8bef\u9875"),(0,a.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 3.6.1 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u5728\u8be5\u7248\u672c\u4e4b\u540e\u5185\u7f6e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"BadPageResult")," \u9519\u8bef\u7ed3\u679c\u7c7b\u578b\uff0c\u8be5\u7c7b\u578b\u6d3e\u751f\u81ea ",(0,a.kt)("inlineCode",{parentName:"p"},"IActionResult"),"\uff0c\u5982\u9700\u8fd4\u56de\u53ea\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Action")," \u4e2d\u8fd4\u56de\u5373\u53ef\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers{1,7}","showLineNumbers{1,7}":!0},"using Furion.FriendlyException;\n\npublic IActionResult Add(Person person)\n{\n if(!ModelState.IsValid)\n {\n return new BadPageResult();\n }\n}\n")),(0,a.kt)("img",{src:(0,o.Z)("img/er1.png")}),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"BadPageResult")," \u66f4\u591a\u914d\u7f6e",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u6784\u9020\u51fd\u6570 ",(0,a.kt)("inlineCode",{parentName:"li"},"statusCode"),"\uff1a\u72b6\u6001\u7801\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"int")," \u7c7b\uff0c\u9ed8\u8ba4 400"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Title"),"\uff1a\u9875\u9762\u6807\u9898\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"ModelState Invalid")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Description"),"\uff1a\u9875\u9762\u63cf\u8ff0\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"User data verification failed. Please input it correctly.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Code"),"\uff1a\u8be6\u7ec6\u9519\u8bef\u4ee3\u7801\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"li"},"\u4ee3\u7801"),"\uff0c\u9ed8\u8ba4\u7a7a\u5b57\u7b26\u4e32"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"CodeLang"),"\uff1a\u8be6\u7ec6\u9519\u8bef\u4ee3\u7801\u8bed\u8a00\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"json")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Base64Icon"),"\uff1a\u9875\u9762\u56fe\u6807\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u5e26\u9ed8\u8ba4\u503c\uff0c\u81ea\u5b9a\u4e49\u5fc5\u987b\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"base64")," \u683c\u5f0f\u56fe\u6807")))),(0,a.kt)("h2",{id:"717-\u53cd\u9988\u4e0e\u5efa\u8bae"},"7.17 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}k.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return d},kt:function(){return c}});var r=t(7294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function o(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var p=r.createContext({}),s=function(e){var n=r.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},d=function(e){var n=s(e.components);return r.createElement(p.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},u=r.forwardRef((function(e,n){var t=e.components,i=e.mdxType,a=e.originalType,p=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),u=s(t),c=i,k=u["".concat(p,".").concat(c)]||u[c]||m[c]||a;return t?r.createElement(k,o(o({ref:n},d),{},{components:t})):r.createElement(k,o({ref:n},d))}));function c(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var a=t.length,o=new Array(a);o[0]=u;var l={};for(var p in n)hasOwnProperty.call(n,p)&&(l[p]=n[p]);l.originalType=e,l.mdxType="string"==typeof e?e:i,o[1]=l;for(var s=2;s=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var m=a.createContext({}),l=function(e){var t=a.useContext(m),n=t;return e&&(n="function"==typeof e?e(t):p(p({},t),e)),n},s=function(e){var t=l(e.components);return a.createElement(m.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,m=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=l(n),k=r,c=d["".concat(m,".").concat(k)]||d[k]||u[k]||i;return n?a.createElement(c,p(p({ref:t},s),{},{components:n})):a.createElement(c,p({ref:t},s))}));function k(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,p=new Array(i);p[0]=d;var o={};for(var m in t)hasOwnProperty.call(t,m)&&(o[m]=t[m]);o.originalType=e,o.mdxType="string"==typeof e?e:r,p[1]=o;for(var l=2;lpm2",id:"3461-\u5173\u4e8e-pm2",level:2},{value:"34.6.2 \u5982\u4f55\u5b89\u88c5",id:"3462-\u5982\u4f55\u5b89\u88c5",level:2},{value:"34.6.3 \u6258\u7ba1 .NET5/6 \u5e94\u7528\u7a0b\u5e8f",id:"3463-\u6258\u7ba1-net56-\u5e94\u7528\u7a0b\u5e8f",level:2},{value:"34.6.3.1 \u975e\u5355\u6587\u4ef6/\u975e\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f",id:"34631-\u975e\u5355\u6587\u4ef6\u975e\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f",level:3},{value:"34.6.3.2 \u5355\u6587\u4ef6/\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f",id:"34632-\u5355\u6587\u4ef6\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f",level:3},{value:"34.6.3.3 \u542f\u7528\u5e94\u7528\u7a0b\u5e8f",id:"34633-\u542f\u7528\u5e94\u7528\u7a0b\u5e8f",level:3},{value:"34.6.4 pm2 \u5e38\u89c1\u64cd\u4f5c",id:"3464-pm2-\u5e38\u89c1\u64cd\u4f5c",level:2},{value:"34.6.4.1 \u5b9e\u65f6\u76d1\u542c\u8fd0\u884c\u72b6\u6001",id:"34641-\u5b9e\u65f6\u76d1\u542c\u8fd0\u884c\u72b6\u6001",level:3},{value:"34.6.4.2 \u663e\u793a\u8fd0\u884c\u65e5\u5fd7",id:"34642-\u663e\u793a\u8fd0\u884c\u65e5\u5fd7",level:3},{value:"34.6.4.3 \u67e5\u770b\u5e94\u7528\u4fe1\u606f",id:"34643-\u67e5\u770b\u5e94\u7528\u4fe1\u606f",level:3},{value:"34.6.4.4 \u968f\u673a\u542f\u52a8",id:"34644-\u968f\u673a\u542f\u52a8",level:3},{value:"34.6.4.5 \u96c6\u7fa4\u6a21\u5f0f\uff08\u8d1f\u8f7d\u5747\u8861\uff09",id:"34645-\u96c6\u7fa4\u6a21\u5f0f\u8d1f\u8f7d\u5747\u8861",level:3},{value:"34.6.4.6 \u5176\u4ed6\u64cd\u4f5c",id:"34646-\u5176\u4ed6\u64cd\u4f5c",level:3},{value:"34.6.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"3465-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],k={toc:d};function c(e){var t=e.components,n=(0,r.Z)(e,o);return(0,i.kt)("wrapper",(0,a.Z)({},k,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"3461-\u5173\u4e8e-pm2"},"34.6.1 \u5173\u4e8e ",(0,i.kt)("inlineCode",{parentName:"h2"},"pm2")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"pm2")," \u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"NodeJS")," \u5e73\u53f0\u9ad8\u7ea7\u751f\u4ea7\u6d41\u7a0b\u7ba1\u7406\u5668\uff0c\u4e5f\u662f\u4e00\u4e2a\u5b88\u62a4\u8fdb\u7a0b\u7ba1\u7406\u5668\uff0c\u5b83\u80fd\u591f\u7ba1\u7406\u548c\u4fdd\u6301\u5e94\u7528\u7a0b\u5e8f 7","*","24 \u5c0f\u65f6\u5728\u7ebf\u3002"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"pm2")," \u4f18\u70b9:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u7b80\u5355\u6613\u7528"),(0,i.kt)("li",{parentName:"ul"},"\u8de8\u5e73\u53f0"),(0,i.kt)("li",{parentName:"ul"},"\u5bb9\u5668\u96c6\u6210"),(0,i.kt)("li",{parentName:"ul"},"\u5185\u7f6e\u96c6\u7fa4\u3001\u8d1f\u8f7d\u5747\u8861"),(0,i.kt)("li",{parentName:"ul"},"\u652f\u6301\u6a21\u5757\u7cfb\u7edf"),(0,i.kt)("li",{parentName:"ul"},"\u652f\u6301\u5b9e\u65f6\u76d1\u6d4b"),(0,i.kt)("li",{parentName:"ul"},"\u652f\u6301\u65e5\u5fd7\u7ba1\u7406"),(0,i.kt)("li",{parentName:"ul"},"\u652f\u6301\u5173\u952e\u6307\u6807\u76d1\u63a7\n....")),(0,i.kt)("p",null,"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"p"},"pm2")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://pm2.keymetrics.io/"},"https://pm2.keymetrics.io/"),"\u3002"),(0,i.kt)("h2",{id:"3462-\u5982\u4f55\u5b89\u88c5"},"34.6.2 \u5982\u4f55\u5b89\u88c5"),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("strong",{parentName:"li"},"\u7cfb\u7edf\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"strong"},"NodeJS")," \u73af\u5883 ",(0,i.kt)("a",{parentName:"strong",href:"https://nodejs.org/en/"},"https://nodejs.org/en/")))),(0,i.kt)("p",null,"\u76f8\u4fe1\u5927\u90e8\u5206\u4eba\u7535\u8111\u90fd\u5df2\u7ecf\u5b89\u88c5\u3002"),(0,i.kt)("ol",{start:2},(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("strong",{parentName:"li"},"\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"strong"},"npm")," \u6216 ",(0,i.kt)("inlineCode",{parentName:"strong"},"yarn")," \u5168\u5c40\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"strong"},"pm2")," \u5de5\u5177"))),(0,i.kt)("p",null,"npm:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"npm install pm2@latest -g\n")),(0,i.kt)("p",null,"yarn:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"yarn global add pm2\n")),(0,i.kt)("h2",{id:"3463-\u6258\u7ba1-net56-\u5e94\u7528\u7a0b\u5e8f"},"34.6.3 \u6258\u7ba1 ",(0,i.kt)("inlineCode",{parentName:"h2"},".NET5/6")," \u5e94\u7528\u7a0b\u5e8f"),(0,i.kt)("h3",{id:"34631-\u975e\u5355\u6587\u4ef6\u975e\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f"},"34.6.3.1 \u975e\u5355\u6587\u4ef6/\u975e\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f"),(0,i.kt)("p",null,"\u8fd9\u79cd\u6a21\u5f0f\u7684\u7279\u70b9\u5c31\u662f\u9700\u8981\u670d\u52a1\u5668\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET5/6")," \u7684\u73af\u5883"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 start --name xxx dotnet -- xxx.dll\n")),(0,i.kt)("admonition",{title:"\u6307\u5b9a\u7aef\u53e3",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u9700\u6307\u5b9a\u7aef\u53e3\uff0c\u53ef\u4f7f\u7528\u4e0b\u5217\u547d\u4ee4\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 start --name xxx dotnet -- PMS.Web.Entry.dll --urls=https://localhost:8089\n")),(0,i.kt)("p",{parentName:"admonition"},"\u6ce8\u610f ",(0,i.kt)("inlineCode",{parentName:"p"},"--")," \u540e\u9762\u53ef\u4ee5\u5199\u5b8c\u6574\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"dotnet")," \u547d\u4ee4\u3002")),(0,i.kt)("admonition",{title:"\u547d\u4ee4\u8bf4\u660e",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"xxx.dll")," \u4e3a\u9879\u76ee\u53d1\u5e03\u540e\u7684\u542f\u52a8\u5c42\u540d\u79f0\u3002"),(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"--name")," \u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"pm2")," \u4e2d\u7684\u552f\u4e00\u6807\u8bc6\u3002")),(0,i.kt)("admonition",{title:"\u7ec8\u7aef\u8bf4\u660e",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"\u6ce8\u610f\uff1a\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"--")," \u4f20\u9012\u53c2\u6570\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"powershell")," \u7ec8\u7aef\u4e0b\u65e0\u6548\uff0c\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"cmd")," \u7ec8\u7aef\u4e0b\u624d\u884c\u3002\u6bd4\u5982\u51fa\u73b0\u8fd9\u6837\u7684\u9519\u8bef\uff1a"),(0,i.kt)("img",{src:(0,p.Z)("img/pm2err.png")})),(0,i.kt)("h3",{id:"34632-\u5355\u6587\u4ef6\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f"},"34.6.3.2 \u5355\u6587\u4ef6/\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f"),(0,i.kt)("p",null,"\u8fd9\u79cd\u6a21\u5f0f\u7684\u7279\u70b9\u5c31\u662f\u65e0\u9700\u670d\u52a1\u5668\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET")," \u4efb\u4f55\u73af\u5883\uff0c\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"/furion/docs/singlefile"},"\u5355\u6587\u4ef6\u53d1\u5e03\u6587\u6863")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 start --name xxx PMS.Web.Entry.exe\n")),(0,i.kt)("admonition",{title:"\u6307\u5b9a\u7aef\u53e3",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u9700\u6307\u5b9a\u7aef\u53e3\uff0c\u53ef\u4f7f\u7528\u4e0b\u5217\u547d\u4ee4\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 start --name xxx PMS.Web.Entry.exe -- --urls=https://localhost:8089\n")),(0,i.kt)("p",{parentName:"admonition"},"\u6ce8\u610f ",(0,i.kt)("inlineCode",{parentName:"p"},"--")," \u540e\u9762\u53ef\u4ee5\u5199\u5b8c\u6574\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"dotnet")," \u547d\u4ee4\u3002")),(0,i.kt)("admonition",{title:"\u547d\u4ee4\u8bf4\u660e",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"xxx.exe")," \u4e3a\u9879\u76ee\u53d1\u5e03\u540e\u7684\u542f\u52a8\u5c42\u540d\u79f0\uff0c\u5982\u679c\u540d\u79f0\u5305\u542b ",(0,i.kt)("inlineCode",{parentName:"p"},"\u7a7a\u683c"),"\uff0c\u5219\u4f7f\u7528\u53cc\u5f15\u53f7\u5305\u88f9\uff0c\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},'"x xx.exe"'),"\u3002"),(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"--name")," \u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"pm2")," \u4e2d\u7684\u552f\u4e00\u6807\u8bc6\u3002")),(0,i.kt)("admonition",{title:"\u7ec8\u7aef\u8bf4\u660e",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"\u6ce8\u610f\uff1a\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"--")," \u4f20\u9012\u53c2\u6570\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"powershell")," \u7ec8\u7aef\u4e0b\u65e0\u6548\uff0c\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"cmd")," \u7ec8\u7aef\u4e0b\u624d\u884c\u3002"),(0,i.kt)("img",{src:(0,p.Z)("img/pm2err.png")})),(0,i.kt)("h3",{id:"34633-\u542f\u7528\u5e94\u7528\u7a0b\u5e8f"},"34.6.3.3 \u542f\u7528\u5e94\u7528\u7a0b\u5e8f"),(0,i.kt)("p",null,"\u6267\u884c\u4e0a\u8ff0\u547d\u4ee4\u540e\u4f1a\u663e\u793a\u542f\u52a8\u6210\u529f\u65e5\u5fd7\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"PS C:\\Users\\bqrjsoft\\Desktop\\pms> pm2 start --name pms PMS.Web.Entry.exe\n[PM2] Starting C:\\Users\\bqrjsoft\\Desktop\\pms\\PMS.Web.Entry.exe in fork_mode (1 instance)\n[PM2] Done.\n\u250c\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 id \u2502 name \u2502 namespace \u2502 version \u2502 mode \u2502 pid \u2502 uptime \u2502 \u21ba \u2502 status \u2502 cpu \u2502 mem \u2502 user \u2502 watching \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 0 \u2502 pms \u2502 default \u2502 N/A \u2502 fork \u2502 41764 \u2502 0s \u2502 0 \u2502 online \u2502 0% \u2502 85.0mb \u2502 bqrjsoft \u2502 disabled \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\nPS C:\\Users\\bqrjsoft\\Desktop\\pms>\n")),(0,i.kt)("img",{src:(0,p.Z)("img/sf30.png")}),(0,i.kt)("admonition",{title:"\u5173\u4e8e\u7aef\u53e3",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u7a0b\u5e8f\u9ed8\u8ba4\u7aef\u53e3\u90fd\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"5000"),"\uff0c\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"http://localhost:5000"),"\u3002")),(0,i.kt)("h2",{id:"3464-pm2-\u5e38\u89c1\u64cd\u4f5c"},"34.6.4 ",(0,i.kt)("inlineCode",{parentName:"h2"},"pm2")," \u5e38\u89c1\u64cd\u4f5c"),(0,i.kt)("h3",{id:"34641-\u5b9e\u65f6\u76d1\u542c\u8fd0\u884c\u72b6\u6001"},"34.6.4.1 \u5b9e\u65f6\u76d1\u542c\u8fd0\u884c\u72b6\u6001"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 monit\n")),(0,i.kt)("img",{src:(0,p.Z)("img/sf4.png")}),(0,i.kt)("h3",{id:"34642-\u663e\u793a\u8fd0\u884c\u65e5\u5fd7"},"34.6.4.2 \u663e\u793a\u8fd0\u884c\u65e5\u5fd7"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 logs\n")),(0,i.kt)("img",{src:(0,p.Z)("img/sf5.png")}),(0,i.kt)("h3",{id:"34643-\u67e5\u770b\u5e94\u7528\u4fe1\u606f"},"34.6.4.3 \u67e5\u770b\u5e94\u7528\u4fe1\u606f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 info pms\n")),(0,i.kt)("p",null,"\u6ce8\u610f\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"pms")," \u4e3a\u60a8\u914d\u7f6e\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"--name")," \u540d\u79f0\u3002"),(0,i.kt)("img",{src:(0,p.Z)("img/sf6.png")}),(0,i.kt)("h3",{id:"34644-\u968f\u673a\u542f\u52a8"},"34.6.4.4 \u968f\u673a\u542f\u52a8"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 startup\npm2 save\n")),(0,i.kt)("admonition",{type:"tip"},(0,i.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Windows")," \u4e0b\u968f\u673a\u542f\u52a8"),(0,i.kt)("p",{parentName:"admonition"},"\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://www.npmjs.com/package/pm2-windows-startup"},"pm2-windows-startup"),"\u3002"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"npm install pm2-windows-startup -g\npm2-startup install\npm2 save\n"))),(0,i.kt)("h3",{id:"34645-\u96c6\u7fa4\u6a21\u5f0f\u8d1f\u8f7d\u5747\u8861"},"34.6.4.5 \u96c6\u7fa4\u6a21\u5f0f\uff08\u8d1f\u8f7d\u5747\u8861\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u975e\u5355\u6587\u4ef6/\u975e\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},'pm2 start "xxx.dll" -i max\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u5355\u6587\u4ef6/\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 start xxx.exe -i max\n")),(0,i.kt)("h3",{id:"34646-\u5176\u4ed6\u64cd\u4f5c"},"34.6.4.6 \u5176\u4ed6\u64cd\u4f5c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"// \u91cd\u542f\u5e94\u7528\npm2 restart app_name\n\n// \u91cd\u8f7d\u5e94\u7528\npm2 reload app_name\n\n// \u505c\u6b62\u5e94\u7528\npm2 stop app_name\n\n// \u5220\u9664\u5e94\u7528\npm2 delete app_name\n")),(0,i.kt)("p",null,"\u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"p"},"pm2")," \u6587\u6863\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://pm2.keymetrics.io/docs/usage/quick-start/"},"https://pm2.keymetrics.io/docs/usage/quick-start/")),(0,i.kt)("h2",{id:"3465-\u53cd\u9988\u4e0e\u5efa\u8bae"},"34.6.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/40a433d4.66306be6.js b/handbook/build/assets/js/40a433d4.66306be6.js deleted file mode 100644 index 3baceada0d..0000000000 --- a/handbook/build/assets/js/40a433d4.66306be6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[2205],{1470:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return l},default:function(){return c},frontMatter:function(){return m},metadata:function(){return s},toc:function(){return d}});var a=n(3117),r=n(102),i=(n(7294),n(3905)),p=n(1402),o=["components"],m={id:"pm2",title:"34.6 pm2 \u90e8\u7f72",sidebar_label:"34.6 pm2 \u90e8\u7f72"},l=void 0,s={unversionedId:"pm2",id:"pm2",title:"34.6 pm2 \u90e8\u7f72",description:"",source:"@site/docs/pm2.mdx",sourceDirName:".",slug:"/pm2",permalink:"/furion/docs/pm2",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/pm2.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1660021283,formattedLastUpdatedAt:"Aug 9, 2022",frontMatter:{id:"pm2",title:"34.6 pm2 \u90e8\u7f72",sidebar_label:"34.6 pm2 \u90e8\u7f72"},sidebar:"docs",previous:{title:"34.5. \u5355\u6587\u4ef6\u53d1\u5e03",permalink:"/furion/docs/singlefile"},next:{title:"35.1 Docker \u73af\u5883\u6301\u7eed\u90e8\u7f72",permalink:"/furion/docs/deploy-docker-auto"}},u={},d=[{value:"34.6.1 \u5173\u4e8e pm2",id:"3461-\u5173\u4e8e-pm2",level:2},{value:"34.6.2 \u5982\u4f55\u5b89\u88c5",id:"3462-\u5982\u4f55\u5b89\u88c5",level:2},{value:"34.6.3 \u6258\u7ba1 .NET5/6 \u5e94\u7528\u7a0b\u5e8f",id:"3463-\u6258\u7ba1-net56-\u5e94\u7528\u7a0b\u5e8f",level:2},{value:"34.6.3.1 \u975e\u5355\u6587\u4ef6/\u975e\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f",id:"34631-\u975e\u5355\u6587\u4ef6\u975e\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f",level:3},{value:"34.6.3.2 \u5355\u6587\u4ef6/\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f",id:"34632-\u5355\u6587\u4ef6\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f",level:3},{value:"34.6.3.3 \u542f\u7528\u5e94\u7528\u7a0b\u5e8f",id:"34633-\u542f\u7528\u5e94\u7528\u7a0b\u5e8f",level:3},{value:"34.6.4 pm2 \u5e38\u89c1\u64cd\u4f5c",id:"3464-pm2-\u5e38\u89c1\u64cd\u4f5c",level:2},{value:"34.6.4.1 \u5b9e\u65f6\u76d1\u542c\u8fd0\u884c\u72b6\u6001",id:"34641-\u5b9e\u65f6\u76d1\u542c\u8fd0\u884c\u72b6\u6001",level:3},{value:"34.6.4.2 \u663e\u793a\u8fd0\u884c\u65e5\u5fd7",id:"34642-\u663e\u793a\u8fd0\u884c\u65e5\u5fd7",level:3},{value:"34.6.4.3 \u67e5\u770b\u5e94\u7528\u4fe1\u606f",id:"34643-\u67e5\u770b\u5e94\u7528\u4fe1\u606f",level:3},{value:"34.6.4.4 \u968f\u673a\u542f\u52a8",id:"34644-\u968f\u673a\u542f\u52a8",level:3},{value:"34.6.4.5 \u96c6\u7fa4\u6a21\u5f0f\uff08\u8d1f\u8f7d\u5747\u8861\uff09",id:"34645-\u96c6\u7fa4\u6a21\u5f0f\u8d1f\u8f7d\u5747\u8861",level:3},{value:"34.6.4.6 \u5176\u4ed6\u64cd\u4f5c",id:"34646-\u5176\u4ed6\u64cd\u4f5c",level:3},{value:"34.6.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"3465-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],k={toc:d};function c(e){var t=e.components,n=(0,r.Z)(e,o);return(0,i.kt)("wrapper",(0,a.Z)({},k,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"3461-\u5173\u4e8e-pm2"},"34.6.1 \u5173\u4e8e ",(0,i.kt)("inlineCode",{parentName:"h2"},"pm2")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"pm2")," \u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"NodeJS")," \u5e73\u53f0\u9ad8\u7ea7\u751f\u4ea7\u6d41\u7a0b\u7ba1\u7406\u5668\uff0c\u4e5f\u662f\u4e00\u4e2a\u5b88\u62a4\u8fdb\u7a0b\u7ba1\u7406\u5668\uff0c\u5b83\u80fd\u591f\u7ba1\u7406\u548c\u4fdd\u6301\u5e94\u7528\u7a0b\u5e8f 7","*","24 \u5c0f\u65f6\u5728\u7ebf\u3002"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"pm2")," \u4f18\u70b9:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u7b80\u5355\u6613\u7528"),(0,i.kt)("li",{parentName:"ul"},"\u8de8\u5e73\u53f0"),(0,i.kt)("li",{parentName:"ul"},"\u5bb9\u5668\u96c6\u6210"),(0,i.kt)("li",{parentName:"ul"},"\u5185\u7f6e\u96c6\u7fa4\u3001\u8d1f\u8f7d\u5747\u8861"),(0,i.kt)("li",{parentName:"ul"},"\u652f\u6301\u6a21\u5757\u7cfb\u7edf"),(0,i.kt)("li",{parentName:"ul"},"\u652f\u6301\u5b9e\u65f6\u76d1\u6d4b"),(0,i.kt)("li",{parentName:"ul"},"\u652f\u6301\u65e5\u5fd7\u7ba1\u7406"),(0,i.kt)("li",{parentName:"ul"},"\u652f\u6301\u5173\u952e\u6307\u6807\u76d1\u63a7\n....")),(0,i.kt)("p",null,"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"p"},"pm2")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://pm2.keymetrics.io/"},"https://pm2.keymetrics.io/"),"\u3002"),(0,i.kt)("h2",{id:"3462-\u5982\u4f55\u5b89\u88c5"},"34.6.2 \u5982\u4f55\u5b89\u88c5"),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("strong",{parentName:"li"},"\u7cfb\u7edf\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"strong"},"NodeJS")," \u73af\u5883 ",(0,i.kt)("a",{parentName:"strong",href:"https://nodejs.org/en/"},"https://nodejs.org/en/")))),(0,i.kt)("p",null,"\u76f8\u4fe1\u5927\u90e8\u5206\u4eba\u7535\u8111\u90fd\u5df2\u7ecf\u5b89\u88c5\u3002"),(0,i.kt)("ol",{start:2},(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("strong",{parentName:"li"},"\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"strong"},"npm")," \u6216 ",(0,i.kt)("inlineCode",{parentName:"strong"},"yarn")," \u5168\u5c40\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"strong"},"pm2")," \u5de5\u5177"))),(0,i.kt)("p",null,"npm:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"npm install pm2@latest -g\n")),(0,i.kt)("p",null,"yarn:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"yarn global add pm2\n")),(0,i.kt)("h2",{id:"3463-\u6258\u7ba1-net56-\u5e94\u7528\u7a0b\u5e8f"},"34.6.3 \u6258\u7ba1 ",(0,i.kt)("inlineCode",{parentName:"h2"},".NET5/6")," \u5e94\u7528\u7a0b\u5e8f"),(0,i.kt)("h3",{id:"34631-\u975e\u5355\u6587\u4ef6\u975e\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f"},"34.6.3.1 \u975e\u5355\u6587\u4ef6/\u975e\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f"),(0,i.kt)("p",null,"\u8fd9\u79cd\u6a21\u5f0f\u7684\u7279\u70b9\u5c31\u662f\u9700\u8981\u670d\u52a1\u5668\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET5/6")," \u7684\u73af\u5883"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 start --name xxx dotnet -- xxx.dll\n")),(0,i.kt)("admonition",{title:"\u6307\u5b9a\u7aef\u53e3",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u9700\u6307\u5b9a\u7aef\u53e3\uff0c\u53ef\u4f7f\u7528\u4e0b\u5217\u547d\u4ee4\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 start --name xxx dotnet -- PMS.Web.Entry.dll --urls=https://localhost:8089\n")),(0,i.kt)("p",{parentName:"admonition"},"\u6ce8\u610f ",(0,i.kt)("inlineCode",{parentName:"p"},"--")," \u540e\u9762\u53ef\u4ee5\u5199\u5b8c\u6574\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"dotnet")," \u547d\u4ee4\u3002")),(0,i.kt)("admonition",{title:"\u547d\u4ee4\u8bf4\u660e",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"xxx.dll")," \u4e3a\u9879\u76ee\u53d1\u5e03\u540e\u7684\u542f\u52a8\u5c42\u540d\u79f0\u3002"),(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"--name")," \u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"pm2")," \u4e2d\u7684\u552f\u4e00\u6807\u8bc6\u3002")),(0,i.kt)("admonition",{title:"\u7ec8\u7aef\u8bf4\u660e",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"\u6ce8\u610f\uff1a\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"--")," \u4f20\u9012\u53c2\u6570\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"powershell")," \u7ec8\u7aef\u4e0b\u65e0\u6548\uff0c\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"cmd")," \u7ec8\u7aef\u4e0b\u624d\u884c\u3002\u6bd4\u5982\u51fa\u73b0\u8fd9\u6837\u7684\u9519\u8bef\uff1a"),(0,i.kt)("img",{src:(0,p.Z)("img/pm2err.png")})),(0,i.kt)("h3",{id:"34632-\u5355\u6587\u4ef6\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f"},"34.6.3.2 \u5355\u6587\u4ef6/\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f"),(0,i.kt)("p",null,"\u8fd9\u79cd\u6a21\u5f0f\u7684\u7279\u70b9\u5c31\u662f\u65e0\u9700\u670d\u52a1\u5668\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET")," \u4efb\u4f55\u73af\u5883\uff0c\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"/furion/docs/singlefile"},"\u5355\u6587\u4ef6\u53d1\u5e03\u6587\u6863")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 start --name xxx PMS.Web.Entry.exe\n")),(0,i.kt)("admonition",{title:"\u6307\u5b9a\u7aef\u53e3",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u9700\u6307\u5b9a\u7aef\u53e3\uff0c\u53ef\u4f7f\u7528\u4e0b\u5217\u547d\u4ee4\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 start --name xxx PMS.Web.Entry.exe -- --urls=https://localhost:8089\n")),(0,i.kt)("p",{parentName:"admonition"},"\u6ce8\u610f ",(0,i.kt)("inlineCode",{parentName:"p"},"--")," \u540e\u9762\u53ef\u4ee5\u5199\u5b8c\u6574\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"dotnet")," \u547d\u4ee4\u3002")),(0,i.kt)("admonition",{title:"\u547d\u4ee4\u8bf4\u660e",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"xxx.exe")," \u4e3a\u9879\u76ee\u53d1\u5e03\u540e\u7684\u542f\u52a8\u5c42\u540d\u79f0\uff0c\u5982\u679c\u540d\u79f0\u5305\u542b ",(0,i.kt)("inlineCode",{parentName:"p"},"\u7a7a\u683c"),"\uff0c\u5219\u4f7f\u7528\u53cc\u5f15\u53f7\u5305\u88f9\uff0c\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},'"x xx.exe"'),"\u3002"),(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"--name")," \u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"pm2")," \u4e2d\u7684\u552f\u4e00\u6807\u8bc6\u3002")),(0,i.kt)("admonition",{title:"\u7ec8\u7aef\u8bf4\u660e",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"\u6ce8\u610f\uff1a\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"--")," \u4f20\u9012\u53c2\u6570\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"powershell")," \u7ec8\u7aef\u4e0b\u65e0\u6548\uff0c\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"cmd")," \u7ec8\u7aef\u4e0b\u624d\u884c\u3002"),(0,i.kt)("img",{src:(0,p.Z)("img/pm2err.png")})),(0,i.kt)("h3",{id:"34633-\u542f\u7528\u5e94\u7528\u7a0b\u5e8f"},"34.6.3.3 \u542f\u7528\u5e94\u7528\u7a0b\u5e8f"),(0,i.kt)("p",null,"\u6267\u884c\u4e0a\u8ff0\u547d\u4ee4\u540e\u4f1a\u663e\u793a\u542f\u52a8\u6210\u529f\u65e5\u5fd7\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"PS C:\\Users\\bqrjsoft\\Desktop\\pms> pm2 start --name pms PMS.Web.Entry.exe\n[PM2] Starting C:\\Users\\bqrjsoft\\Desktop\\pms\\PMS.Web.Entry.exe in fork_mode (1 instance)\n[PM2] Done.\n\u250c\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 id \u2502 name \u2502 namespace \u2502 version \u2502 mode \u2502 pid \u2502 uptime \u2502 \u21ba \u2502 status \u2502 cpu \u2502 mem \u2502 user \u2502 watching \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 0 \u2502 pms \u2502 default \u2502 N/A \u2502 fork \u2502 41764 \u2502 0s \u2502 0 \u2502 online \u2502 0% \u2502 85.0mb \u2502 bqrjsoft \u2502 disabled \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\nPS C:\\Users\\bqrjsoft\\Desktop\\pms>\n")),(0,i.kt)("img",{src:(0,p.Z)("img/sf30.png")}),(0,i.kt)("admonition",{title:"\u5173\u4e8e\u7aef\u53e3",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u7a0b\u5e8f\u9ed8\u8ba4\u7aef\u53e3\u90fd\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"5000"),"\uff0c\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"http://localhost:5000"),"\u3002")),(0,i.kt)("h2",{id:"3464-pm2-\u5e38\u89c1\u64cd\u4f5c"},"34.6.4 ",(0,i.kt)("inlineCode",{parentName:"h2"},"pm2")," \u5e38\u89c1\u64cd\u4f5c"),(0,i.kt)("h3",{id:"34641-\u5b9e\u65f6\u76d1\u542c\u8fd0\u884c\u72b6\u6001"},"34.6.4.1 \u5b9e\u65f6\u76d1\u542c\u8fd0\u884c\u72b6\u6001"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 monit\n")),(0,i.kt)("img",{src:(0,p.Z)("img/sf4.png")}),(0,i.kt)("h3",{id:"34642-\u663e\u793a\u8fd0\u884c\u65e5\u5fd7"},"34.6.4.2 \u663e\u793a\u8fd0\u884c\u65e5\u5fd7"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 logs\n")),(0,i.kt)("img",{src:(0,p.Z)("img/sf5.png")}),(0,i.kt)("h3",{id:"34643-\u67e5\u770b\u5e94\u7528\u4fe1\u606f"},"34.6.4.3 \u67e5\u770b\u5e94\u7528\u4fe1\u606f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 info pms\n")),(0,i.kt)("p",null,"\u6ce8\u610f\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"pms")," \u4e3a\u60a8\u914d\u7f6e\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"--name")," \u540d\u79f0\u3002"),(0,i.kt)("img",{src:(0,p.Z)("img/sf6.png")}),(0,i.kt)("h3",{id:"34644-\u968f\u673a\u542f\u52a8"},"34.6.4.4 \u968f\u673a\u542f\u52a8"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 startup\npm2 save\n")),(0,i.kt)("admonition",{type:"tip"},(0,i.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Windows")," \u4e0b\u968f\u673a\u542f\u52a8"),(0,i.kt)("p",{parentName:"admonition"},"\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://www.npmjs.com/package/pm2-windows-startup"},"pm2-windows-startup"),"\u3002"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"npm install pm2-windows-startup -g\npm2-startup install\npm2 save\n"))),(0,i.kt)("h3",{id:"34645-\u96c6\u7fa4\u6a21\u5f0f\u8d1f\u8f7d\u5747\u8861"},"34.6.4.5 \u96c6\u7fa4\u6a21\u5f0f\uff08\u8d1f\u8f7d\u5747\u8861\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u975e\u5355\u6587\u4ef6/\u975e\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},'pm2 start "xxx.dll" -i max\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u5355\u6587\u4ef6/\u72ec\u7acb\u53d1\u5e03\u6a21\u5f0f")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"pm2 start xxx.exe -i max\n")),(0,i.kt)("h3",{id:"34646-\u5176\u4ed6\u64cd\u4f5c"},"34.6.4.6 \u5176\u4ed6\u64cd\u4f5c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"// \u91cd\u542f\u5e94\u7528\npm2 restart app_name\n\n// \u91cd\u8f7d\u5e94\u7528\npm2 reload app_name\n\n// \u505c\u6b62\u5e94\u7528\npm2 stop app_name\n\n// \u5220\u9664\u5e94\u7528\npm2 delete app_name\n")),(0,i.kt)("p",null,"\u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"p"},"pm2")," \u6587\u6863\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://pm2.keymetrics.io/docs/usage/quick-start/"},"https://pm2.keymetrics.io/docs/usage/quick-start/")),(0,i.kt)("h2",{id:"3465-\u53cd\u9988\u4e0e\u5efa\u8bae"},"34.6.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return k}});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function p(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var m=a.createContext({}),l=function(e){var t=a.useContext(m),n=t;return e&&(n="function"==typeof e?e(t):p(p({},t),e)),n},s=function(e){var t=l(e.components);return a.createElement(m.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,m=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=l(n),k=r,c=d["".concat(m,".").concat(k)]||d[k]||u[k]||i;return n?a.createElement(c,p(p({ref:t},s),{},{components:n})):a.createElement(c,p({ref:t},s))}));function k(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,p=new Array(i);p[0]=d;var o={};for(var m in t)hasOwnProperty.call(t,m)&&(o[m]=t[m]);o.originalType=e,o.mdxType="string"==typeof e?e:r,p[1]=o;for(var l=2;lIComponent",id:"324-icomponent",level:2},{value:"3.2.4.1 IServiceComponent",id:"3241-iservicecomponent",level:3},{value:"3.2.4.2 IApplicationComponent",id:"3242-iapplicationcomponent",level:3},{value:"3.2.4.3 IWebComponent",id:"3243-iwebcomponent",level:3},{value:"3.2.4.3 \u6ce8\u518c\u7ec4\u4ef6",id:"3243-\u6ce8\u518c\u7ec4\u4ef6",level:3},{value:"3.2.5 \u7ec4\u4ef6\u8bbe\u8ba1\u539f\u5219",id:"325-\u7ec4\u4ef6\u8bbe\u8ba1\u539f\u5219",level:2},{value:"3.2.5.1 \u804c\u8d23\u5355\u4e00\u6027",id:"3251-\u804c\u8d23\u5355\u4e00\u6027",level:3},{value:"3.2.5.2 \u7ea6\u5b9a\u5927\u4e8e\u914d\u7f6e",id:"3252-\u7ea6\u5b9a\u5927\u4e8e\u914d\u7f6e",level:3},{value:"3.2.6 [DependsOn] \u8be6\u89e3",id:"326-dependson-\u8be6\u89e3",level:2},{value:"3.2.6.1 \u914d\u7f6e\u4ecb\u7ecd",id:"3261-\u914d\u7f6e\u4ecb\u7ecd",level:3},{value:"3.2.6.2 \u91cd\u590d\u4f9d\u8d56\u95ee\u9898",id:"3262-\u91cd\u590d\u4f9d\u8d56\u95ee\u9898",level:3},{value:"3.2.6.3 \u5faa\u73af\u4f9d\u8d56\u95ee\u9898",id:"3263-\u5faa\u73af\u4f9d\u8d56\u95ee\u9898",level:3},{value:"3.2.7 ComponentContext \u8be6\u89e3",id:"327-componentcontext-\u8be6\u89e3",level:2},{value:"3.2.7.1 \u5c5e\u6027\u4ecb\u7ecd",id:"3271-\u5c5e\u6027\u4ecb\u7ecd",level:3},{value:"3.2.7.2 \u53c2\u6570\u914d\u7f6e/\u83b7\u53d6",id:"3272-\u53c2\u6570\u914d\u7f6e\u83b7\u53d6",level:3},{value:"\u4f8b\u5b50\u8bf4\u660e",id:"\u4f8b\u5b50\u8bf4\u660e",level:4},{value:"3.2.8 \u5b9e\u73b0 Startup.cs \u6a21\u5f0f",id:"328-\u5b9e\u73b0-startupcs-\u6a21\u5f0f",level:2},{value:"3.2.9 \u6700\u4f73\u5b9e\u8df5\uff1f",id:"329-\u6700\u4f73\u5b9e\u8df5",level:2},{value:"3.2.10 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"3210-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:d};function u(e){var n=e.components,t=(0,p.Z)(e,a);return(0,i.kt)("wrapper",(0,o.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"321-\u5386\u53f2\u80cc\u666f"},"3.2.1 \u5386\u53f2\u80cc\u666f"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET Core 2+")," \u4e4b\u540e\uff0c\u5fae\u8f6f\u521b\u9020\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u6a21\u5f0f\uff0c\u5728\u8fd9\u6837\u7684\u6a21\u5f0f\u4e2d\uff0c\u9700\u8981\u4efb\u4f55\u670d\u52a1\u6216\u8005\u4e2d\u95f4\u4ef6\u5904\u7406\uff0c\u53ea\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u6587\u4ef6\u7684\u4e24\u4e2a\u65b9\u6cd5\uff08",(0,i.kt)("inlineCode",{parentName:"p"},"ConfigureServices")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"Configure"),"\uff09\u4e2d\u914d\u7f6e\u5373\u53ef\u3002"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u4f46\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},".NET6")," \u4e4b\u540e\uff0c\u5fae\u8f6f\u4e0d\u518d\u63a8\u8350\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Startup.cs")," \u6a21\u5f0f\u3002")),(0,i.kt)("p",null,"\u5728\u8fd9\u91cc\uff0c\u4e0d\u9610\u8ff0 ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7684\u4f18\u70b9\uff0c\u5c31\u5217\u4e3e\u51e0\u4e2a\u6bd4\u8f83\u660e\u663e\u7684\u7f3a\u70b9\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\u5fc5\u987b\u653e\u5728\u542f\u52a8\u5c42\u4e14\u4e3b\u673a\u542f\u52a8\u65f6\u9700\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"li"},".UseStartup<>")," \u8fdb\u884c\u6ce8\u518c\uff0c\u6b64\u95ee\u9898\u5728 ",(0,i.kt)("inlineCode",{parentName:"li"},"Furion")," \u5df2\u89e3\u51b3 ",(0,i.kt)("inlineCode",{parentName:"li"},"AppStartup")),(0,i.kt)("li",{parentName:"ul"},"\u914d\u7f6e\u670d\u52a1\u5f88\u5bb9\u6613\u7f16\u5199\u51fa\u53c8\u81ed\u53c8\u957f\u7684 ",(0,i.kt)("inlineCode",{parentName:"li"},"service.AddXXX()")," \u548c ",(0,i.kt)("inlineCode",{parentName:"li"},"app.AddXXX()")," \u4ee3\u7801\uff0c\u4e0d\u7ba1\u662f\u9605\u8bfb\u6027\u548c\u7075\u6d3b\u6027\u5927\u5927\u51cf\u5206"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u5bf9\u670d\u52a1\u6ce8\u518c\u548c\u4e2d\u95f4\u4ef6\u6ce8\u518c\u6709\u987a\u5e8f\u8981\u6c42\uff0c\u4e0d\u540c\u7684\u987a\u5e8f\u53ef\u80fd\u4ea7\u751f\u4e0d\u540c\u7684\u6548\u679c\uff0c\u751a\u81f3\u51fa\u73b0\u5f02\u5e38")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u4e0d\u80fd\u5b9e\u73b0\u6a21\u5757\u5316\u81ea\u52a8\u88c5\u8f7d\u6ce8\u518c\uff0c\u6dfb\u52a0\u65b0\u7684\u6a21\u5757\u9700\u8981\u624b\u52a8\u6ce8\u518c\uff0c\u6ce8\u518c\u53c8\u5f97\u8003\u8651\u6a21\u5757\u5316\u4e4b\u95f4\u4f9d\u8d56\u987a\u5e8f\u95ee\u9898")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u4e0d\u80fd\u5bf9\u6a21\u5757\u6ce8\u518c\u8fdb\u884c\u76d1\u89c6\uff0c\u6bd4\u5982\u52a0\u8f7d\u4e4b\u524d\uff0c\u52a0\u8f7d\u5931\u8d25\uff0c\u52a0\u8f7d\u4e4b\u540e"))),(0,i.kt)("h2",{id:"322-\u5148\u770b\u4e00\u4e2a\u4f8b\u5b50"},"3.2.2 \u5148\u770b\u4e00\u4e2a\u4f8b\u5b50"),(0,i.kt)("p",null,"\u5728\u4e00\u4e2a\u5927\u578b\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET Core")," \u9879\u76ee\u4e2d\uff0c\u4f1a\u7ecf\u5e38\u770b\u5230\u8fd9\u6837\u7684\u4ee3\u7801\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {12-26,31-50}",showLineNumbers:!0,"{12-26,31-50}":!0},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Furion.Web.Core;\n\npublic sealed class FurWebCoreStartup : AppStartup\n{\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddCorsAccessor();\n services.AddControllers().AddInject();\n services.AddRemoteRequest();\n services.AddEventBus();\n services.AddAppLocalization();\n services.AddViewEngine();\n services.AddSensitiveDetection();\n services.AddVirtualFileServer();\n services.AddX();\n services.AddXX();\n services.AddXXX();\n services.AddXXXX();\n services.AddXXXXX();\n services.AddXXXXXX();\n // .....\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n if (env.IsDevelopment())\n {\n app.UseDeveloperExceptionPage();\n }\n app.UseHttpsRedirection();\n app.UseRouting();\n app.UseCorsAccessor();\n app.UseAuthentication();\n app.UseAuthorization();\n app.UseInject();\n app.UseX();\n app.UseXX();\n app.UseXXX();\n app.UseXXXX();\n app.UseXXXXX();\n app.UseXXXXXX();\n app.UseEndpoints(endpoints =>\n {\n endpoints.MapControllers();\n });\n }\n}\n")),(0,i.kt)("p",null,"\u53ef\u80fd\u5bf9\u4e8e\u5927\u90e8\u5206 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET")," \u5f00\u53d1\u8005\u6765\u8bf4\u8c8c\u4f3c\u6ca1\u6709\u4efb\u4f55\u95ee\u9898\uff0c\u4f46\u662f\u4ed4\u7ec6\u77a7\u77a7\uff0c\u8fd9\u91cc\u5145\u65a5\u7740\u5927\u91cf\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},".AddXXXX()")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},".UseXXXX()"),"\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u771f\u7684\u7f8e\u89c2\uff0c\u771f\u7684\u597d\u5417"),"\uff1f\u800c\u4e14\u7a0d\u6709\u4e0d\u614e\u79fb\u52a8\u4e86\u5b83\u4eec\u7684\u6ce8\u518c\u987a\u5e8f\u53ef\u80fd\u4f1a\u5f15\u53d1\u707e\u96be\uff0c\u8fd8\u6709\u53ef\u80fd\u591a\u4e2a\u670d\u52a1\u4e4b\u95f4\u76f8\u4e92\u4f9d\u8d56\uff0c\u8981\u4e48\u5168\u90e8\u79fb\u9664\uff0c\u8981\u4e48\u5168\u90e8\u4fdd\u7559\uff0c\u672a\u6765\u66ff\u4ee3\u4f60\u5f00\u53d1\u5c97\u4f4d\u7684\u4eba\u77e5\u9053\u5417\uff1f"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u8bd5\u95ee\uff0c\u8fd9\u4e2a\u95ee\u9898\u662f\u65e0\u89e3\u5417\uff1f")),(0,i.kt)("h2",{id:"323-\u5f53\u7136\u6709\u89e3"},"3.2.3 \u5f53\u7136\u6709\u89e3"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 3.7.3+")," \u7248\u672c\u4e4b\u540e\uff0c\u501f\u52a9 ",(0,i.kt)("inlineCode",{parentName:"p"},"Docker-Compose")," \u7684\u8bbe\u8ba1\u7406\u5ff5\uff0c\u63a8\u51fa\u4e86\u5168\u65b0\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Component \u7ec4\u4ef6\u5316")," \u6a21\u5f0f\uff0c\u901a\u8fc7\u7ec4\u4ef6\u5316\u5f00\u53d1\u53ef\u4ee5\u5b9e\u73b0\u7ec4\u4ef6\u4e4b\u95f4\u76f8\u4e92\u4f9d\u8d56\uff0c\u76f8\u4e92\u94fe\u63a5\uff0c\u8fd8\u53ef\u4ee5\u5171\u4eab\u53c2\u6570\uff0c\u4f60\u4ec5\u4ec5\u9700\u8981\u7f16\u5199\u4e00\u4e2a\u5165\u53e3\u7ec4\u4ef6\u5373\u53ef\u3002"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u5148\u770b\u4e00\u4e2a\u4f8b\u5b50\uff1a")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u521b\u5efa ",(0,i.kt)("inlineCode",{parentName:"li"},"EntryServiceComponent")," \u5165\u53e3\u670d\u52a1\u7ec4\u4ef6")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6}",showLineNumbers:!0,"{2,6}":!0},"// \u521b\u5efa\u5165\u53e3\u670d\u52a1\u7ec4\u4ef6\u5b9e\u73b0 IServeComponent \u63a5\u53e3\npublic sealed class EntryServiceComponent : IServiceComponent\n{\n public void Load(IServiceCollection services, ComponentContext componentContext)\n {\n // \u505a\u4efb\u4f55\u4f60\u60f3\u505a\u7684\u4e8b\u60c5\uff0c\u5982 service.AddYourInitService(); \u5982\u6dfb\u52a0\u4f60\u7684\u6a21\u5757\u521d\u59cb\u5316\u914d\u7f6e\n }\n}\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"li"},"AddComponent<>")," \u6ce8\u518c\u5165\u53e3\u7ec4\u4ef6")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},"// \u901a\u8fc7 .AddComponent \u6ce8\u518c\u4e00\u4e2a\u5165\u53e3\u670d\u52a1\u7ec4\u4ef6\nServe.Run(RunOptions.Default.AddComponent());\n")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u6a21\u62df\u5b9e\u9645\u9879\u76ee\u7684\u5f00\u53d1\u9700\u6c42\uff1a")),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},"\u9700\u8981\u6dfb\u52a0\u8de8\u57df\u670d\u52a1\uff0c\u521b\u5efa ",(0,i.kt)("inlineCode",{parentName:"li"},"CorsServiceComponent")," \u7ec4\u4ef6")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"{1,5}":!0},"public sealed class CorsServiceComponent : IServiceComponent\n{\n public void Load(IServiceCollection services, ComponentContext componentContext)\n {\n services.AddCorsAccessor();\n }\n}\n")),(0,i.kt)("ol",{start:2},(0,i.kt)("li",{parentName:"ol"},"\u9700\u8981\u6dfb\u52a0\u52a8\u6001 ",(0,i.kt)("inlineCode",{parentName:"li"},"WebAPI")," \u670d\u52a1\uff0c\u521b\u5efa ",(0,i.kt)("inlineCode",{parentName:"li"},"DynamicApiServiceComponent")," \u7ec4\u4ef6")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"{1,5}":!0},"public sealed class DynamicApiServiceComponent : IServiceComponent\n{\n public void Load(IServiceCollection services, ComponentContext componentContext)\n {\n services.AddDynamicApiControllers();\n }\n}\n")),(0,i.kt)("ol",{start:3},(0,i.kt)("li",{parentName:"ol"},"\u9700\u8981\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"li"},"XXX")," \u7b2c\u4e09\u65b9\u670d\u52a1\uff0c\u521b\u5efa ",(0,i.kt)("inlineCode",{parentName:"li"},"XXXServiceComponent")," \u7ec4\u4ef6")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"{1,5}":!0},"public sealed class XXXServiceComponent : IServiceComponent\n{\n public void Load(IServiceCollection services, ComponentContext componentContext)\n {\n services.AddXXX();\n }\n}\n")),(0,i.kt)("p",null,"\u6709\u4e86\u8fd9\u4e48\u591a\u670d\u52a1\u7ec4\u4ef6\uff0c\u90a3\u600e\u4e48\u5c06\u5b83\u4eec\u5173\u8054\u8d77\u6765\u5462\uff0c\u800c\u4e14\u80fd\u591f\u6b63\u786e\u7684\u5904\u7406\u5b83\u4eec\u7684\u987a\u5e8f\u5462\uff1f\u6bd4\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"AddXXX()")," \u5fc5\u987b\u7b49 ",(0,i.kt)("inlineCode",{parentName:"p"},"AddDynamicApiControllers()")," \u6ce8\u518c\u624d\u80fd\u6ce8\u518c\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"XXXServiceComponent")," \u6dfb\u52a0\u4f9d\u8d56\u5373\u53ef\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-3}",showLineNumbers:!0,"{1-3}":!0},"[DependsOn(\n typeof(DynamicApiServiceComponent)\n)]\npublic sealed class XXXServiceComponent : IServiceComponent\n{\n // ....\n}\n")),(0,i.kt)("p",null,"\u8fd9\u6837\u8868\u793a ",(0,i.kt)("inlineCode",{parentName:"p"},"XXXServiceComponent")," \u4f9d\u8d56 ",(0,i.kt)("inlineCode",{parentName:"p"},"DynamicApiServiceComponent")," \u7ec4\u4ef6\uff0c\u53ea\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"DynamicApiServiceComponent")," \u5b8c\u6210\u6ce8\u518c\u624d\u4f1a\u6ce8\u518c ",(0,i.kt)("inlineCode",{parentName:"p"},"XXXServiceComponent"),"\u3002"),(0,i.kt)("p",null,"\u90a3\u4e48\u6700\u540e\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"EntryServiceComponent")," \u7684\u4ee3\u7801\u5c06\u4f1a\u662f\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-4}",showLineNumbers:!0,"{1-4}":!0},"[DependsOn(\n typeof(CorsServiceComponent),\n typeof(XXXServiceComponent)\n)]\npublic sealed class EntryServiceComponent : IServiceComponent\n{\n // ....\n}\n")),(0,i.kt)("p",null,"\u6700\u540e\u751f\u6210\u7684\u8c03\u7528\u987a\u5e8f\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"AddCorsAccessor()")," -> ",(0,i.kt)("inlineCode",{parentName:"p"},"AddDynamicApiControllers()")," -> ",(0,i.kt)("inlineCode",{parentName:"p"},"AddXXX()")," -> ",(0,i.kt)("inlineCode",{parentName:"p"},"AddEntry()"),"\u3002"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u770b\u5230\u8fd9\u91cc\uff0c\u662f\u5426\u5df2\u627e\u5230\u7b54\u6848\uff1a\u6bcf\u4e00\u4e2a\u9879\u76ee\u53ea\u6709\u4e00\u4e2a\u5165\u53e3\u7ec4\u4ef6\uff0c\u6bcf\u4e2a\u7ec4\u4ef6\u53ea\u505a\u4e00\u4ef6\u4e8b\uff0c\u7ec4\u4ef6\u4e4b\u95f4\u53ef\u4ee5\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"strong"},"DependsOn")," \u914d\u7f6e\u4f9d\u8d56\uff0c\u7ec4\u4ef6\u4e4b\u95f4\u8fd8\u80fd\u5171\u4eab\u4e0a\u4e0b\u6587\u6570\u636e ",(0,i.kt)("inlineCode",{parentName:"strong"},"ComponentContext"),"\u3002")),(0,i.kt)("p",null,"\u6ca1\u9519\uff0c\u8fd9\u5c31\u662f Furion \u76ee\u524d\u80fd\u591f\u60f3\u5230\u7684\u6700\u4f18\u89e3\u51b3\u65b9\u6848\u3002"),(0,i.kt)("h2",{id:"324-icomponent"},"3.2.4 ",(0,i.kt)("inlineCode",{parentName:"h2"},"IComponent")),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 3.7.3+")," \u7248\u672c\uff0c\u65b0\u589e\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Components")," \u6a21\u5757\uff0c\u8be5\u6a21\u5757\u7684\u6839\u63a5\u53e3\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"IComponent"),"\uff0c\u542b\u6709\u4e24\u4e2a\u6d3e\u751f\u63a5\u53e3 ",(0,i.kt)("inlineCode",{parentName:"p"},"IServiceComponent")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"IApplicationComponent"),"\u3002"),(0,i.kt)("h3",{id:"3241-iservicecomponent"},"3.2.4.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"IServiceComponent")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"IServiceComponent")," \u63a5\u53e3\u7b80\u79f0",(0,i.kt)("strong",{parentName:"p"},"\u670d\u52a1\u7ec4\u4ef6"),"\u5bf9\u5e94\u7684\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"ConfigureService"),"\uff0c\u63a5\u53e3\u7b7e\u540d\u4e3a\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,13}",showLineNumbers:!0,"{6,13}":!0},'namespace System;\n\n/// \n/// \u670d\u52a1\u7ec4\u4ef6\u4f9d\u8d56\u63a5\u53e3\n/// \npublic interface IServiceComponent : IComponent\n{\n /// \n /// \u88c5\u8f7d\u670d\u52a1\n /// \n /// \n /// \u7ec4\u4ef6\u4e0a\u4e0b\u6587\n void Load(IServiceCollection services, ComponentContext componentContext);\n}\n')),(0,i.kt)("p",null,"\u9700\u8981\u6ce8\u518c\u670d\u52a1\u53ef\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Load")," \u65b9\u6cd5\u4e2d\u6ce8\u518c\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"3242-iapplicationcomponent"},"3.2.4.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"IApplicationComponent")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"IApplicationComponent")," \u63a5\u53e3\u7b80\u79f0",(0,i.kt)("strong",{parentName:"p"},"\u4e2d\u95f4\u4ef6\u7ec4\u4ef6"),"\u5bf9\u5e94\u7684\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Configure"),"\uff0c\u63a5\u53e3\u7b7e\u540d\u4e3a\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,14}",showLineNumbers:!0,"{6,14}":!0},'namespace System;\n\n/// \n/// \u5e94\u7528\u4e2d\u95f4\u4ef6\u63a5\u53e3\n/// \npublic interface IApplicationComponent : IComponent\n{\n /// \n /// \u88c5\u7f6e\u4e2d\u95f4\u4ef6\n /// \n /// \n /// \n /// \u7ec4\u4ef6\u4e0a\u4e0b\u6587\n void Load(IApplicationBuilder app, IWebHostEnvironment env, ComponentContext componentContext);\n}\n')),(0,i.kt)("p",null,"\u9700\u8981\u6ce8\u518c\u4e2d\u95f4\u4ef6\u53ef\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Load")," \u65b9\u6cd5\u4e2d\u6ce8\u518c\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"3243-iwebcomponent"},"3.2.4.3 ",(0,i.kt)("inlineCode",{parentName:"h3"},"IWebComponent")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"IWebComponent")," \u63a5\u53e3\u7b80\u79f0",(0,i.kt)("strong",{parentName:"p"}," ",(0,i.kt)("inlineCode",{parentName:"strong"},"Web")," \u7ec4\u4ef6"),"\u5bf9\u5e94\u7684\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"WebApplicationBuilder"),"\uff0c\u63a5\u53e3\u7b7e\u540d\u4e3a\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,13}",showLineNumbers:!0,"{6,13}":!0},'namespace System;\n\n/// \n/// WebApplicationBuilder \u7ec4\u4ef6\u4f9d\u8d56\u63a5\u53e3\n/// \npublic interface IWebComponent : IComponent\n{\n /// \n /// \u88c5\u7f6e Web \u5e94\u7528\u6784\u5efa\u5668\n /// \n /// \n /// \u7ec4\u4ef6\u4e0a\u4e0b\u6587\n void Load(WebApplicationBuilder builder, ComponentContext componentContext);\n}\n')),(0,i.kt)("p",null,"\u9700\u8981\u6ce8\u518c\u4e2d\u95f4\u4ef6\u53ef\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Load")," \u65b9\u6cd5\u4e2d\u6ce8\u518c\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"3243-\u6ce8\u518c\u7ec4\u4ef6"},"3.2.4.3 \u6ce8\u518c\u7ec4\u4ef6"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u591a\u79cd\u6ce8\u518c\u7ec4\u4ef6\u7684\u65b9\u5f0f\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u65b9\u5f0f\u4e00")),(0,i.kt)("p",null,"\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"RunOptions"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"LegacyRunOptions"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"GenericRunOptions")," \u65b9\u5f0f\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2-3,7}",showLineNumbers:!0,"{2-3,7}":!0},"Serve.Run(RunOptions.Default\n .AddComponent()\n .UseComponent());\n\n// .NET6+ \u8fd8\u652f\u6301 AddWebComponent();\nServe.Run(RunOptions.Default\n .AddWebComponent());\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u65b9\u5f0f\u4e8c")),(0,i.kt)("p",null,"\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"services.AddComponent")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"app.UseComponent")," \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,8}",showLineNumbers:!0,"{2,5,8}":!0},"// \u670d\u52a1\u7ec4\u4ef6\nservice.AddComponent();\n\n// \u4e2d\u95f4\u4ef6\u7ec4\u4ef6\napp.UseComponent();\n\n// .NET6+ \u8fd8\u652f\u6301 AddWebComponent();\nbuilder.AddWebComponent();\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u65b9\u5f0f\u4e09")),(0,i.kt)("p",null,"\u7ec4\u4ef6\u6ce8\u518c\u53ef\u4ee5\u4f20\u9012\u53c2\u6570\uff0c\u901a\u8fc7\u6700\u540e\u7684\u53c2\u6570\u6307\u5b9a\u3002"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,8}",showLineNumbers:!0,"{2,5,8}":!0},"// \u670d\u52a1\u7ec4\u4ef6\nservice.AddComponent(options);\n\n// \u4e2d\u95f4\u4ef6\u7ec4\u4ef6\napp.UseComponent(options);\n\n// .NET6+ \u8fd8\u652f\u6301 AddWebComponent();\nbuilder.AddWebComponent(options);\n")),(0,i.kt)("admonition",{type:"tip"},(0,i.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u7c7b\u578b ",(0,i.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Type")," \u6ce8\u518c\u65b9\u5f0f"),(0,i.kt)("p",{parentName:"admonition"},"\u9664\u4e86\u63d0\u4f9b\u6cdb\u578b\u6ce8\u518c\u7ec4\u4ef6\u7684\u65b9\u5f0f\uff0c\u8fd8\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},".AddComponent(typeof(XXXComponent))")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},".UseComponent(typeof(XXXComponent))")," \u65b9\u5f0f\u3002")),(0,i.kt)("h2",{id:"325-\u7ec4\u4ef6\u8bbe\u8ba1\u539f\u5219"},"3.2.5 \u7ec4\u4ef6\u8bbe\u8ba1\u539f\u5219"),(0,i.kt)("h3",{id:"3251-\u804c\u8d23\u5355\u4e00\u6027"},"3.2.5.1 \u804c\u8d23\u5355\u4e00\u6027"),(0,i.kt)("p",null,"\u7ec4\u4ef6\u7684\u8bbe\u8ba1\u7406\u5e94\u9075\u5faa",(0,i.kt)("strong",{parentName:"p"},"\u804c\u8d23\u5355\u4e00\u6027\u539f\u5219"),"\uff0c\u5177\u6709\u5355\u4e00\u6027\u53c8\u6709\u804c\u8d23\u660e\u786e\u6027\uff0c\u901a\u4fd7\u70b9\u8bf4\u6bcf\u4e00\u4e2a\u7ec4\u4ef6\u5c3d\u53ef\u80fd\u7684\u53ea\u505a\u4e00\u4ef6\u4e8b\uff0c\u5982\u679c\u7ec4\u4ef6\u4e4b\u95f4\u6709\u4f9d\u8d56\uff0c\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"[DependsOn]")," \u58f0\u660e\u914d\u7f6e\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"{1,5}":!0},'[DependsOn(\n typeof(OtherServiceComponent),\n "Other.Assembly;Other.Assembly.OtherServiceComponent"\n)]\npublic sealed class YourServiceComponent : IServiceComponent\n{\n public void Load(IServiceCollection services, ComponentContext componentContext)\n {\n services.AddXXX();\n }\n}\n')),(0,i.kt)("h3",{id:"3252-\u7ea6\u5b9a\u5927\u4e8e\u914d\u7f6e"},"3.2.5.2 \u7ea6\u5b9a\u5927\u4e8e\u914d\u7f6e"),(0,i.kt)("p",null,"\u7531\u4e8e\u7ec4\u4ef6\u901a\u5e38\u5305\u542b\u670d\u52a1\u548c\u4e2d\u95f4\u4ef6\u4e24\u4e2a\u6ce8\u518c\uff0c\u6240\u4ee5\u63a8\u8350\u7ec4\u4ef6\u7c7b\u7684\u547d\u540d\u7edf\u4e00\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"XXXComponent.cs"),"\uff0c\u7136\u540e\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"XXXComponent.cs")," \u4e2d\u5206\u522b\u5199 ",(0,i.kt)("inlineCode",{parentName:"p"},"IServiceComponent")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"IApplicationComponent")," \u7ec4\u4ef6\u3002"),(0,i.kt)("p",null,"\u5c3d\u53ef\u80fd\u6bcf\u4e00\u4e2a\u670d\u52a1\u7ec4\u4ef6\uff08",(0,i.kt)("inlineCode",{parentName:"p"},"IServiceComponent"),"\uff09\u4ee5 ",(0,i.kt)("inlineCode",{parentName:"p"},"ServiceComponent")," \u7ed3\u5c3e\uff0c\u6bcf\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\uff08",(0,i.kt)("inlineCode",{parentName:"p"},"IApplicationComponent"),"\uff09\u4ee5 ",(0,i.kt)("inlineCode",{parentName:"p"},"ApplicationComponent")," \u7ed3\u5c3e\u3002\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {3-4,9-10,15-16} title="XXXComponent.cs"',showLineNumbers:!0,"{3-4,9-10,15-16}":!0,title:'"XXXComponent.cs"'},"namespace Your.Components;\n\n// \u670d\u52a1\u7ec4\u4ef6\npublic sealed class XXXServiceComponent : IServiceComponent\n{\n // ....\n}\n\n// \u4e2d\u95f4\u4ef6\u7ec4\u4ef6\npublic sealed class XXXApplicationComponent : IApplicationComponent\n{\n // ....\n}\n\n// WebApplicationBuilder \u7ec4\u4ef6\npublic sealed class XXXWebComponent : IWebComponent\n{\n // ....\n}\n")),(0,i.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u6ca1\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"IServiceComponent")," \u6216 ",(0,i.kt)("inlineCode",{parentName:"p"},"IApplicationComponent"),"\uff0c\u5219\u5199\u5176\u4e00\u5373\u53ef\u3002")),(0,i.kt)("h2",{id:"326-dependson-\u8be6\u89e3"},"3.2.6 ",(0,i.kt)("inlineCode",{parentName:"h2"},"[DependsOn]")," \u8be6\u89e3"),(0,i.kt)("p",null,"\u7531\u4e8e\u7ec4\u4ef6\u548c\u7ec4\u4ef6\u4e4b\u95f4\u5b58\u5728\u4f9d\u8d56\u65b9\u5f0f\uff0c\u751a\u81f3\u6ca1\u6709\u4f9d\u8d56\u5173\u7cfb\u4f46\u652f\u6301\u5524\u9192\u5176\u4ed6\u7ec4\u4ef6\u529f\u80fd\uff0c\u6240\u4ee5 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"[DependsOn]")," \u7279\u6027\u3002"),(0,i.kt)("h3",{id:"3261-\u914d\u7f6e\u4ecb\u7ecd"},"3.2.6.1 \u914d\u7f6e\u4ecb\u7ecd"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"DependsOn"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"DependComponents"),"\uff1a\u914d\u7f6e\u7ec4\u4ef6\u4f9d\u8d56\u5173\u7cfb\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Type[]")," \u7c7b\u578b\uff0c\u4e00\u65e6\u914d\u7f6e\u4e86\u4f9d\u8d56\u5173\u7cfb\uff0c\u90a3\u4e48\u88ab\u4f9d\u8d56\u7684\u7ec4\u4ef6\u4f1a\u5148\u4e8e\u5f53\u524d\u7ec4\u4ef6\u6ce8\u518c"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Links"),"\uff1a\u914d\u7f6e\u7ec4\u4ef6\u94fe\u63a5\u5173\u7cfb\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Type[]")," \u7c7b\u578b\uff0c\u8be5\u914d\u7f6e\u4e3b\u8981\u89e3\u51b3\u4e00\u4e9b\u7ec4\u4ef6\u5e76\u4e0d\u662f\u4ece ",(0,i.kt)("inlineCode",{parentName:"li"},"\u6839\u7ec4\u4ef6")," \u8fdb\u884c\u914d\u7f6e\uff0c\u800c\u662f\u5904\u4e8e\u548c ",(0,i.kt)("inlineCode",{parentName:"li"},"\u6839\u7ec4\u4ef6")," \u5e73\u884c\u7684\u60c5\u51b5\uff0c\u7c7b\u4f3c\u591a\u5165\u53e3\u7ec4\u4ef6")))),(0,i.kt)("admonition",{title:"\u6784\u9020\u51fd\u6570\u8bf4\u660e",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"DependComponents")," \u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"DependsOnAttribute")," \u7279\u6027\u7684\u9ed8\u8ba4\u6784\u9020\u51fd\u6570\uff0c\u652f\u6301 ",(0,i.kt)("inlineCode",{parentName:"p"},"Type")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"String")," \u7c7b\u578b\uff0c\u5982\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2-4}",showLineNumbers:!0,"{2-4}":!0},'[DependsOn(\n typeof(XXXComponent),\n typeof(XXXXComponent),\n "\u7a0b\u5e8f\u96c6;\u7c7b\u578b\u5b8c\u6574\u9650\u5b9a\u540d" // \u4f1a\u81ea\u52a8\u52a0\u8f7d\u7a0b\u5e8f\u96c6\u4e2d\u7279\u5b9a\u7684\u7ec4\u4ef6\uff0c\u540e\u7eed\u6a21\u5757\u5316\u5f00\u53d1\u975e\u5e38\u65b9\u4fbf\n)]\n')),(0,i.kt)("p",{parentName:"admonition"},"\u5982\u9700\u914d\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"Links"),"\uff0c\u53ea\u9700\u8981\u8fd9\u6837\u63a5\u53e3\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-6}",showLineNumbers:!0,"{3-6}":!0},"[DependsOn(\n typeof(XXXComponent),\n Links = new object[]{\n typeof(XXXComponent),\n typeof(XXXXComponent)\n }\n)]\n"))),(0,i.kt)("h3",{id:"3262-\u91cd\u590d\u4f9d\u8d56\u95ee\u9898"},"3.2.6.2 \u91cd\u590d\u4f9d\u8d56\u95ee\u9898"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u5df2\u7ecf\u5904\u7406\u4e86\u7ec4\u4ef6\u91cd\u590d\u4f9d\u8d56\u95ee\u9898\uff0c\u4f1a\u81ea\u52a8\u751f\u6210\u597d\u6700\u4f73\u7684\u6ce8\u518c\u987a\u5e8f\u5e76\u53bb\u9664\u91cd\u590d\u4f9d\u8d56\u6ce8\u518c\u95ee\u9898\u3002"),(0,i.kt)("h3",{id:"3263-\u5faa\u73af\u4f9d\u8d56\u95ee\u9898"},"3.2.6.3 \u5faa\u73af\u4f9d\u8d56\u95ee\u9898"),(0,i.kt)("p",null,"\u5faa\u73af\u4f9d\u8d56\u5b9e\u9645\u4e0a\u662f\u4e00\u79cd\u9519\u8bef\u6ce8\u518c\u7ec4\u4ef6\u7684\u65b9\u5f0f\uff0c\u4f1a\u5bfc\u81f4\u51fa\u73b0\u5185\u5b58\u6ea2\u51fa\u60c5\u51b5\uff0c\u65e9\u671f\u7ec4\u4ef6\u5316\u7248\u672c\u6846\u67b6\u5904\u7406\u4e86\u5faa\u73af\u4f9d\u8d56\u95ee\u9898\uff0c\u4e5f\u5c31\u662f\u4e3b\u52a8\u5ffd\u7565\u6216\u62a5\u9519\uff0c\u4f46\u662f\u8003\u8651\u6b64\u884c\u4e3a\u672c\u8eab\u5e26\u6709\u6f5c\u5728\u7684\u5b89\u5168\u95ee\u9898\uff0c\u6240\u4ee5\u79fb\u9664\u4e86\u5faa\u73af\u4f9d\u8d56\u5904\u7406\uff0c\u800c\u662f\u9009\u62e9\u5728\u5f00\u53d1\u9636\u6bb5\u629b\u51fa\u5f02\u5e38\u65b9\u5f0f\u3002"),(0,i.kt)("h2",{id:"327-componentcontext-\u8be6\u89e3"},"3.2.7 ",(0,i.kt)("inlineCode",{parentName:"h2"},"ComponentContext")," \u8be6\u89e3"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"ComponentContext")," \u662f\u7ec4\u4ef6\u6ce8\u518c ",(0,i.kt)("inlineCode",{parentName:"p"},"Load")," \u65b9\u6cd5\u7684\u6700\u540e\u53c2\u6570\uff0c\u8be5\u53c2\u6570\u63d0\u4f9b\u4e86\u7ec4\u4ef6\u4e4b\u95f4\u7684\u4e00\u4e9b\u5143\u6570\u636e\u3002"),(0,i.kt)("h3",{id:"3271-\u5c5e\u6027\u4ecb\u7ecd"},"3.2.7.1 \u5c5e\u6027\u4ecb\u7ecd"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ComponentContext"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ComponentType"),"\uff1a\u7ec4\u4ef6\u7c7b\u578b\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Type")," \u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"CalledContext"),"\uff1a\u4e0a\u7ea7\u7ec4\u4ef6\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"ComponentContext")," \u7c7b\u578b\uff0c\u4e5f\u5c31\u662f ",(0,i.kt)("inlineCode",{parentName:"li"},"DependsOn")," \u4e2d\u7684\u7ec4\u4ef6\u4e0a\u4e0b\u6587\uff0c\u5982\u679c\u6ca1\u6709\u5219\u662f\u524d\u4e00\u4e2a\u7ec4\u4ef6\u7684\u4e0a\u4e0b\u6587"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"RootContext"),"\uff1a\u6839\u7ec4\u4ef6/\u5165\u53e3\u7ec4\u4ef6\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"ComponentContext")," \u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"DependComponents"),"\uff1a\u7ec4\u4ef6\u4f9d\u8d56\u7684\u6240\u6709\u7ec4\u4ef6\u5217\u8868\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Type[]")," \u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"LinkComponents"),"\uff1a\u7ec4\u4ef6\u94fe\u63a5\u7684\u6240\u6709\u7ec4\u4ef6\u5217\u8868\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Type[]")," \u7c7b\u578b")))),(0,i.kt)("h3",{id:"3272-\u53c2\u6570\u914d\u7f6e\u83b7\u53d6"},"3.2.7.2 \u53c2\u6570\u914d\u7f6e/\u83b7\u53d6"),(0,i.kt)("p",null,"\u5728\u6ce8\u518c\u7ec4\u4ef6\u5c0f\u8282\u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},".AddComponent")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},".UseComponent")," \u6700\u540e\u7684\u53c2\u6570\u6765\u6307\u5b9a\u7ec4\u4ef6\u7684\u53c2\u6570\uff0c\u90a3\u4e48\u5982\u4f55\u5728\u7ec4\u4ef6\u4e2d\u83b7\u53d6\u4f60\u4f20\u9012\u7684\u53c2\u6570\u5462\uff1f"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"ComponentContext")," \u63d0\u4f9b\u4e86\u591a\u79cd\u65b9\u6cd5\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"GetProperty()"),"\uff1a\u83b7\u53d6\u7ec4\u4ef6\u7684\u53c2\u6570"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"GetProperty(Type)"),"\uff1a\u901a\u8fc7\u7c7b\u578b\u83b7\u53d6\u7ec4\u4ef6\u53c2\u6570"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"GetProperty(string)"),"\uff1a\u901a\u8fc7\u6307\u5b9a ",(0,i.kt)("inlineCode",{parentName:"li"},"key")," \u83b7\u53d6"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"GetProperties()"),"\uff1a\u83b7\u53d6\u7ec4\u4ef6\u6240\u6709\u53c2\u6570\u5217\u8868\uff08\u5305\u62ec\u4f9d\u8d56\uff0c\u94fe\u63a5\u7b49\uff09"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SetProperty(object)"),"\uff1a\u8bbe\u7f6e\u7279\u5b9a\u7ec4\u4ef6\u53c2\u6570"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SetProperty(Type, object)"),"\uff1a\u8bbe\u7f6e\u7279\u5b9a\u7c7b\u578b\u7ec4\u4ef6\u7684\u53c2\u6570"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SetProperty(string, object)"),"\uff1a\u8bbe\u7f6e\u6307\u5b9a ",(0,i.kt)("inlineCode",{parentName:"li"},"key")," \u7684\u53c2\u6570\u503c")),(0,i.kt)("h4",{id:"\u4f8b\u5b50\u8bf4\u660e"},"\u4f8b\u5b50\u8bf4\u660e"),(0,i.kt)("p",null,"\u6ce8\u518c\u65f6\u4f20\u5165 ",(0,i.kt)("inlineCode",{parentName:"p"},"EntryOption")," \u53c2\u6570"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"service.AddComponent(new EntryOption {});\n")),(0,i.kt)("p",null,"\u5728\u7ec4\u4ef6\u5185\u90e8\u83b7\u53d6\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,7}",showLineNumbers:!0,"{5,7}":!0},"public sealed class EntryServiceComponent : IServiceComponent\n{\n public void Load(IServiceCollection services, ComponentContext componentContext)\n {\n var options = componentContext.GetProperty();\n\n services.AddXXXX(options);\n }\n}\n")),(0,i.kt)("p",null,"\u9664\u6b64\u4e4b\u5916\uff0c\u8fd8\u53ef\u4ee5\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"componentContext.SetProperty(new xxxOptions{})")," \u6765\u8bbe\u7f6e\u4e0b\u6e38\u7ec4\u4ef6\u7684\u53c2\u6570\u3002"),(0,i.kt)("h2",{id:"328-\u5b9e\u73b0-startupcs-\u6a21\u5f0f"},"3.2.8 \u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Startup.cs")," \u6a21\u5f0f"),(0,i.kt)("p",null,"\u7ec4\u4ef6\u6a21\u5f0f\u662f\u975e\u5e38\u5f3a\u5927\u4e14\u7075\u6d3b\u7684\uff0c\u6211\u4eec\u4e5f\u53ef\u4ee5\u901a\u8fc7\u7ec4\u4ef6\u7684\u6a21\u5f0f\u6a21\u62df\u51fa\u4f20\u7edf\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs"),"\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {1,6-7,11,16-21} title="StartupComponent"',showLineNumbers:!0,"{1,6-7,11,16-21}":!0,title:'"StartupComponent"'},"// \u6a21\u62df ConfigureService\npublic sealed class StartupServiceComponent : IServiceComponent\n{\n public void Load(IServiceCollection services, ComponentContext componentContext)\n {\n services.AddControllers()\n .AddInject();\n }\n}\n\n// \u6a21\u62df Configure\npublic sealed class StartupApplicationComponent : IApplicationComponent\n{\n public void Load(IApplicationBuilder app, IWebHostEnvironment env, ComponentContext componentContext)\n {\n app.UseRouting();\n app.UseInject(string.Empty);\n app.UseEndpoints(endpoints =>\n {\n endpoints.MapControllers();\n });\n }\n}\n")),(0,i.kt)("p",null,"\u53ea\u9700\u8981\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"service.AddComponent()")," \u6ce8\u518c\u5373\u53ef\uff0c\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Serve.Run()")," \u6a21\u5f0f\u5c06\u66f4\u7b80\u5355\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2-3}",showLineNumbers:!0,"{2-3}":!0},"Serve.Run(RunOptions.Default\n .AddComponent()\n .UseComponent());\n")),(0,i.kt)("p",null,"\u662f\u4e0d\u662f\u5f88\u7075\u6d3b\u554a~"),(0,i.kt)("h2",{id:"329-\u6700\u4f73\u5b9e\u8df5"},"3.2.9 \u6700\u4f73\u5b9e\u8df5\uff1f"),(0,i.kt)("p",null,"\u5728\u5199\u6700\u4f73\u5b9e\u8df5\u65f6\u662f\u6700\u75db\u82e6\u7684\uff0c\u56e0\u4e3a\u6700\u4f73\u5b9e\u8df5\u5e94\u8be5\u662f\u628a\u5fae\u8f6f\u5e95\u5c42\u6240\u6709\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"service.AddXXX")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"app.AddXXX")," \u72ec\u7acb\u6210\u4e00\u4e2a\u4e2a\u7ec4\u4ef6\uff0c\u6bd4\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"servers.AddControllers()")," \u5bf9\u5e94\u4e00\u4e2a ",(0,i.kt)("inlineCode",{parentName:"p"},"ControllersServiceComponent"),"\u3002"),(0,i.kt)("p",null,"\u8fd9\u6837\u505a\u7684\u8bdd\u5de5\u4f5c\u91cf\u662f\u975e\u5e38\u5927\u7684\uff0c\u4f46\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u7ec4\u4ef6\u5316\u5c31\u65e0\u6cd5\u5f7b\u5e95\u3002"),(0,i.kt)("p",null,"\u6240\u4ee5\u73b0\u9636\u6bb5\u6682\u65f6\u91c7\u7528\u81ea\u7531\u5b9a\u5236\u7ec4\u4ef6\u65b9\u5f0f\uff0c\u6bd4\u5982\u81ea\u5df1\u5728\u9879\u76ee\u4e2d\u7f16\u5199 ",(0,i.kt)("inlineCode",{parentName:"p"},"ControllersServiceComponent")," \u8fd9\u7c7b\u7ec4\u4ef6\u3002"),(0,i.kt)("h2",{id:"3210-\u53cd\u9988\u4e0e\u5efa\u8bae"},"3.2.10 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}u.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return s},kt:function(){return u}});var o=t(7294);function p(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function a(e){for(var n=1;n=0||(p[t]=e[t]);return p}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(p[t]=e[t])}return p}var l=o.createContext({}),m=function(e){var n=o.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},s=function(e){var n=m(e.components);return o.createElement(l.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},c=o.forwardRef((function(e,n){var t=e.components,p=e.mdxType,i=e.originalType,l=e.parentName,s=r(e,["components","mdxType","originalType","parentName"]),c=m(t),u=p,C=c["".concat(l,".").concat(u)]||c[u]||d[u]||i;return t?o.createElement(C,a(a({ref:n},s),{},{components:t})):o.createElement(C,a({ref:n},s))}));function u(e,n){var t=arguments,p=n&&n.mdxType;if("string"==typeof e||p){var i=t.length,a=new Array(i);a[0]=c;var r={};for(var l in n)hasOwnProperty.call(n,l)&&(r[l]=n[l]);r.originalType=e,r.mdxType="string"==typeof e?e:p,a[1]=r;for(var m=2;m=0||(p[t]=e[t]);return p}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(p[t]=e[t])}return p}var l=o.createContext({}),m=function(e){var n=o.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},s=function(e){var n=m(e.components);return o.createElement(l.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},c=o.forwardRef((function(e,n){var t=e.components,p=e.mdxType,i=e.originalType,l=e.parentName,s=r(e,["components","mdxType","originalType","parentName"]),c=m(t),u=p,C=c["".concat(l,".").concat(u)]||c[u]||d[u]||i;return t?o.createElement(C,a(a({ref:n},s),{},{components:t})):o.createElement(C,a({ref:n},s))}));function u(e,n){var t=arguments,p=n&&n.mdxType;if("string"==typeof e||p){var i=t.length,a=new Array(i);a[0]=c;var r={};for(var l in n)hasOwnProperty.call(n,l)&&(r[l]=n[l]);r.originalType=e,r.mdxType="string"==typeof e?e:p,a[1]=r;for(var m=2;mIComponent",id:"324-icomponent",level:2},{value:"3.2.4.1 IServiceComponent",id:"3241-iservicecomponent",level:3},{value:"3.2.4.2 IApplicationComponent",id:"3242-iapplicationcomponent",level:3},{value:"3.2.4.3 IWebComponent",id:"3243-iwebcomponent",level:3},{value:"3.2.4.3 \u6ce8\u518c\u7ec4\u4ef6",id:"3243-\u6ce8\u518c\u7ec4\u4ef6",level:3},{value:"3.2.5 \u7ec4\u4ef6\u8bbe\u8ba1\u539f\u5219",id:"325-\u7ec4\u4ef6\u8bbe\u8ba1\u539f\u5219",level:2},{value:"3.2.5.1 \u804c\u8d23\u5355\u4e00\u6027",id:"3251-\u804c\u8d23\u5355\u4e00\u6027",level:3},{value:"3.2.5.2 \u7ea6\u5b9a\u5927\u4e8e\u914d\u7f6e",id:"3252-\u7ea6\u5b9a\u5927\u4e8e\u914d\u7f6e",level:3},{value:"3.2.6 [DependsOn] \u8be6\u89e3",id:"326-dependson-\u8be6\u89e3",level:2},{value:"3.2.6.1 \u914d\u7f6e\u4ecb\u7ecd",id:"3261-\u914d\u7f6e\u4ecb\u7ecd",level:3},{value:"3.2.6.2 \u91cd\u590d\u4f9d\u8d56\u95ee\u9898",id:"3262-\u91cd\u590d\u4f9d\u8d56\u95ee\u9898",level:3},{value:"3.2.6.3 \u5faa\u73af\u4f9d\u8d56\u95ee\u9898",id:"3263-\u5faa\u73af\u4f9d\u8d56\u95ee\u9898",level:3},{value:"3.2.7 ComponentContext \u8be6\u89e3",id:"327-componentcontext-\u8be6\u89e3",level:2},{value:"3.2.7.1 \u5c5e\u6027\u4ecb\u7ecd",id:"3271-\u5c5e\u6027\u4ecb\u7ecd",level:3},{value:"3.2.7.2 \u53c2\u6570\u914d\u7f6e/\u83b7\u53d6",id:"3272-\u53c2\u6570\u914d\u7f6e\u83b7\u53d6",level:3},{value:"\u4f8b\u5b50\u8bf4\u660e",id:"\u4f8b\u5b50\u8bf4\u660e",level:4},{value:"3.2.8 \u5b9e\u73b0 Startup.cs \u6a21\u5f0f",id:"328-\u5b9e\u73b0-startupcs-\u6a21\u5f0f",level:2},{value:"3.2.9 \u6700\u4f73\u5b9e\u8df5\uff1f",id:"329-\u6700\u4f73\u5b9e\u8df5",level:2},{value:"3.2.10 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"3210-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:d};function u(e){var n=e.components,t=(0,p.Z)(e,a);return(0,i.kt)("wrapper",(0,o.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"321-\u5386\u53f2\u80cc\u666f"},"3.2.1 \u5386\u53f2\u80cc\u666f"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET Core 2+")," \u4e4b\u540e\uff0c\u5fae\u8f6f\u521b\u9020\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u6a21\u5f0f\uff0c\u5728\u8fd9\u6837\u7684\u6a21\u5f0f\u4e2d\uff0c\u9700\u8981\u4efb\u4f55\u670d\u52a1\u6216\u8005\u4e2d\u95f4\u4ef6\u5904\u7406\uff0c\u53ea\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u6587\u4ef6\u7684\u4e24\u4e2a\u65b9\u6cd5\uff08",(0,i.kt)("inlineCode",{parentName:"p"},"ConfigureServices")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"Configure"),"\uff09\u4e2d\u914d\u7f6e\u5373\u53ef\u3002"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u4f46\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},".NET6")," \u4e4b\u540e\uff0c\u5fae\u8f6f\u4e0d\u518d\u63a8\u8350\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Startup.cs")," \u6a21\u5f0f\u3002")),(0,i.kt)("p",null,"\u5728\u8fd9\u91cc\uff0c\u4e0d\u9610\u8ff0 ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7684\u4f18\u70b9\uff0c\u5c31\u5217\u4e3e\u51e0\u4e2a\u6bd4\u8f83\u660e\u663e\u7684\u7f3a\u70b9\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\u5fc5\u987b\u653e\u5728\u542f\u52a8\u5c42\u4e14\u4e3b\u673a\u542f\u52a8\u65f6\u9700\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"li"},".UseStartup<>")," \u8fdb\u884c\u6ce8\u518c\uff0c\u6b64\u95ee\u9898\u5728 ",(0,i.kt)("inlineCode",{parentName:"li"},"Furion")," \u5df2\u89e3\u51b3 ",(0,i.kt)("inlineCode",{parentName:"li"},"AppStartup")),(0,i.kt)("li",{parentName:"ul"},"\u914d\u7f6e\u670d\u52a1\u5f88\u5bb9\u6613\u7f16\u5199\u51fa\u53c8\u81ed\u53c8\u957f\u7684 ",(0,i.kt)("inlineCode",{parentName:"li"},"service.AddXXX()")," \u548c ",(0,i.kt)("inlineCode",{parentName:"li"},"app.AddXXX()")," \u4ee3\u7801\uff0c\u4e0d\u7ba1\u662f\u9605\u8bfb\u6027\u548c\u7075\u6d3b\u6027\u5927\u5927\u51cf\u5206"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u5bf9\u670d\u52a1\u6ce8\u518c\u548c\u4e2d\u95f4\u4ef6\u6ce8\u518c\u6709\u987a\u5e8f\u8981\u6c42\uff0c\u4e0d\u540c\u7684\u987a\u5e8f\u53ef\u80fd\u4ea7\u751f\u4e0d\u540c\u7684\u6548\u679c\uff0c\u751a\u81f3\u51fa\u73b0\u5f02\u5e38")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u4e0d\u80fd\u5b9e\u73b0\u6a21\u5757\u5316\u81ea\u52a8\u88c5\u8f7d\u6ce8\u518c\uff0c\u6dfb\u52a0\u65b0\u7684\u6a21\u5757\u9700\u8981\u624b\u52a8\u6ce8\u518c\uff0c\u6ce8\u518c\u53c8\u5f97\u8003\u8651\u6a21\u5757\u5316\u4e4b\u95f4\u4f9d\u8d56\u987a\u5e8f\u95ee\u9898")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u4e0d\u80fd\u5bf9\u6a21\u5757\u6ce8\u518c\u8fdb\u884c\u76d1\u89c6\uff0c\u6bd4\u5982\u52a0\u8f7d\u4e4b\u524d\uff0c\u52a0\u8f7d\u5931\u8d25\uff0c\u52a0\u8f7d\u4e4b\u540e"))),(0,i.kt)("h2",{id:"322-\u5148\u770b\u4e00\u4e2a\u4f8b\u5b50"},"3.2.2 \u5148\u770b\u4e00\u4e2a\u4f8b\u5b50"),(0,i.kt)("p",null,"\u5728\u4e00\u4e2a\u5927\u578b\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET Core")," \u9879\u76ee\u4e2d\uff0c\u4f1a\u7ecf\u5e38\u770b\u5230\u8fd9\u6837\u7684\u4ee3\u7801\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {12-26,31-50}",showLineNumbers:!0,"{12-26,31-50}":!0},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Furion.Web.Core;\n\npublic sealed class FurWebCoreStartup : AppStartup\n{\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddCorsAccessor();\n services.AddControllers().AddInject();\n services.AddRemoteRequest();\n services.AddEventBus();\n services.AddAppLocalization();\n services.AddViewEngine();\n services.AddSensitiveDetection();\n services.AddVirtualFileServer();\n services.AddX();\n services.AddXX();\n services.AddXXX();\n services.AddXXXX();\n services.AddXXXXX();\n services.AddXXXXXX();\n // .....\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n if (env.IsDevelopment())\n {\n app.UseDeveloperExceptionPage();\n }\n app.UseHttpsRedirection();\n app.UseRouting();\n app.UseCorsAccessor();\n app.UseAuthentication();\n app.UseAuthorization();\n app.UseInject();\n app.UseX();\n app.UseXX();\n app.UseXXX();\n app.UseXXXX();\n app.UseXXXXX();\n app.UseXXXXXX();\n app.UseEndpoints(endpoints =>\n {\n endpoints.MapControllers();\n });\n }\n}\n")),(0,i.kt)("p",null,"\u53ef\u80fd\u5bf9\u4e8e\u5927\u90e8\u5206 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET")," \u5f00\u53d1\u8005\u6765\u8bf4\u8c8c\u4f3c\u6ca1\u6709\u4efb\u4f55\u95ee\u9898\uff0c\u4f46\u662f\u4ed4\u7ec6\u77a7\u77a7\uff0c\u8fd9\u91cc\u5145\u65a5\u7740\u5927\u91cf\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},".AddXXXX()")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},".UseXXXX()"),"\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u771f\u7684\u7f8e\u89c2\uff0c\u771f\u7684\u597d\u5417"),"\uff1f\u800c\u4e14\u7a0d\u6709\u4e0d\u614e\u79fb\u52a8\u4e86\u5b83\u4eec\u7684\u6ce8\u518c\u987a\u5e8f\u53ef\u80fd\u4f1a\u5f15\u53d1\u707e\u96be\uff0c\u8fd8\u6709\u53ef\u80fd\u591a\u4e2a\u670d\u52a1\u4e4b\u95f4\u76f8\u4e92\u4f9d\u8d56\uff0c\u8981\u4e48\u5168\u90e8\u79fb\u9664\uff0c\u8981\u4e48\u5168\u90e8\u4fdd\u7559\uff0c\u672a\u6765\u66ff\u4ee3\u4f60\u5f00\u53d1\u5c97\u4f4d\u7684\u4eba\u77e5\u9053\u5417\uff1f"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u8bd5\u95ee\uff0c\u8fd9\u4e2a\u95ee\u9898\u662f\u65e0\u89e3\u5417\uff1f")),(0,i.kt)("h2",{id:"323-\u5f53\u7136\u6709\u89e3"},"3.2.3 \u5f53\u7136\u6709\u89e3"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 3.7.3+")," \u7248\u672c\u4e4b\u540e\uff0c\u501f\u52a9 ",(0,i.kt)("inlineCode",{parentName:"p"},"Docker-Compose")," \u7684\u8bbe\u8ba1\u7406\u5ff5\uff0c\u63a8\u51fa\u4e86\u5168\u65b0\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Component \u7ec4\u4ef6\u5316")," \u6a21\u5f0f\uff0c\u901a\u8fc7\u7ec4\u4ef6\u5316\u5f00\u53d1\u53ef\u4ee5\u5b9e\u73b0\u7ec4\u4ef6\u4e4b\u95f4\u76f8\u4e92\u4f9d\u8d56\uff0c\u76f8\u4e92\u94fe\u63a5\uff0c\u8fd8\u53ef\u4ee5\u5171\u4eab\u53c2\u6570\uff0c\u4f60\u4ec5\u4ec5\u9700\u8981\u7f16\u5199\u4e00\u4e2a\u5165\u53e3\u7ec4\u4ef6\u5373\u53ef\u3002"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u5148\u770b\u4e00\u4e2a\u4f8b\u5b50\uff1a")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u521b\u5efa ",(0,i.kt)("inlineCode",{parentName:"li"},"EntryServiceComponent")," \u5165\u53e3\u670d\u52a1\u7ec4\u4ef6")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6}",showLineNumbers:!0,"{2,6}":!0},"// \u521b\u5efa\u5165\u53e3\u670d\u52a1\u7ec4\u4ef6\u5b9e\u73b0 IServeComponent \u63a5\u53e3\npublic sealed class EntryServiceComponent : IServiceComponent\n{\n public void Load(IServiceCollection services, ComponentContext componentContext)\n {\n // \u505a\u4efb\u4f55\u4f60\u60f3\u505a\u7684\u4e8b\u60c5\uff0c\u5982 service.AddYourInitService(); \u5982\u6dfb\u52a0\u4f60\u7684\u6a21\u5757\u521d\u59cb\u5316\u914d\u7f6e\n }\n}\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"li"},"AddComponent<>")," \u6ce8\u518c\u5165\u53e3\u7ec4\u4ef6")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},"// \u901a\u8fc7 .AddComponent \u6ce8\u518c\u4e00\u4e2a\u5165\u53e3\u670d\u52a1\u7ec4\u4ef6\nServe.Run(RunOptions.Default.AddComponent());\n")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u6a21\u62df\u5b9e\u9645\u9879\u76ee\u7684\u5f00\u53d1\u9700\u6c42\uff1a")),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},"\u9700\u8981\u6dfb\u52a0\u8de8\u57df\u670d\u52a1\uff0c\u521b\u5efa ",(0,i.kt)("inlineCode",{parentName:"li"},"CorsServiceComponent")," \u7ec4\u4ef6")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"{1,5}":!0},"public sealed class CorsServiceComponent : IServiceComponent\n{\n public void Load(IServiceCollection services, ComponentContext componentContext)\n {\n services.AddCorsAccessor();\n }\n}\n")),(0,i.kt)("ol",{start:2},(0,i.kt)("li",{parentName:"ol"},"\u9700\u8981\u6dfb\u52a0\u52a8\u6001 ",(0,i.kt)("inlineCode",{parentName:"li"},"WebAPI")," \u670d\u52a1\uff0c\u521b\u5efa ",(0,i.kt)("inlineCode",{parentName:"li"},"DynamicApiServiceComponent")," \u7ec4\u4ef6")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"{1,5}":!0},"public sealed class DynamicApiServiceComponent : IServiceComponent\n{\n public void Load(IServiceCollection services, ComponentContext componentContext)\n {\n services.AddDynamicApiControllers();\n }\n}\n")),(0,i.kt)("ol",{start:3},(0,i.kt)("li",{parentName:"ol"},"\u9700\u8981\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"li"},"XXX")," \u7b2c\u4e09\u65b9\u670d\u52a1\uff0c\u521b\u5efa ",(0,i.kt)("inlineCode",{parentName:"li"},"XXXServiceComponent")," \u7ec4\u4ef6")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"{1,5}":!0},"public sealed class XXXServiceComponent : IServiceComponent\n{\n public void Load(IServiceCollection services, ComponentContext componentContext)\n {\n services.AddXXX();\n }\n}\n")),(0,i.kt)("p",null,"\u6709\u4e86\u8fd9\u4e48\u591a\u670d\u52a1\u7ec4\u4ef6\uff0c\u90a3\u600e\u4e48\u5c06\u5b83\u4eec\u5173\u8054\u8d77\u6765\u5462\uff0c\u800c\u4e14\u80fd\u591f\u6b63\u786e\u7684\u5904\u7406\u5b83\u4eec\u7684\u987a\u5e8f\u5462\uff1f\u6bd4\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"AddXXX()")," \u5fc5\u987b\u7b49 ",(0,i.kt)("inlineCode",{parentName:"p"},"AddDynamicApiControllers()")," \u6ce8\u518c\u624d\u80fd\u6ce8\u518c\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"XXXServiceComponent")," \u6dfb\u52a0\u4f9d\u8d56\u5373\u53ef\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-3}",showLineNumbers:!0,"{1-3}":!0},"[DependsOn(\n typeof(DynamicApiServiceComponent)\n)]\npublic sealed class XXXServiceComponent : IServiceComponent\n{\n // ....\n}\n")),(0,i.kt)("p",null,"\u8fd9\u6837\u8868\u793a ",(0,i.kt)("inlineCode",{parentName:"p"},"XXXServiceComponent")," \u4f9d\u8d56 ",(0,i.kt)("inlineCode",{parentName:"p"},"DynamicApiServiceComponent")," \u7ec4\u4ef6\uff0c\u53ea\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"DynamicApiServiceComponent")," \u5b8c\u6210\u6ce8\u518c\u624d\u4f1a\u6ce8\u518c ",(0,i.kt)("inlineCode",{parentName:"p"},"XXXServiceComponent"),"\u3002"),(0,i.kt)("p",null,"\u90a3\u4e48\u6700\u540e\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"EntryServiceComponent")," \u7684\u4ee3\u7801\u5c06\u4f1a\u662f\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-4}",showLineNumbers:!0,"{1-4}":!0},"[DependsOn(\n typeof(CorsServiceComponent),\n typeof(XXXServiceComponent)\n)]\npublic sealed class EntryServiceComponent : IServiceComponent\n{\n // ....\n}\n")),(0,i.kt)("p",null,"\u6700\u540e\u751f\u6210\u7684\u8c03\u7528\u987a\u5e8f\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"AddCorsAccessor()")," -> ",(0,i.kt)("inlineCode",{parentName:"p"},"AddDynamicApiControllers()")," -> ",(0,i.kt)("inlineCode",{parentName:"p"},"AddXXX()")," -> ",(0,i.kt)("inlineCode",{parentName:"p"},"AddEntry()"),"\u3002"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u770b\u5230\u8fd9\u91cc\uff0c\u662f\u5426\u5df2\u627e\u5230\u7b54\u6848\uff1a\u6bcf\u4e00\u4e2a\u9879\u76ee\u53ea\u6709\u4e00\u4e2a\u5165\u53e3\u7ec4\u4ef6\uff0c\u6bcf\u4e2a\u7ec4\u4ef6\u53ea\u505a\u4e00\u4ef6\u4e8b\uff0c\u7ec4\u4ef6\u4e4b\u95f4\u53ef\u4ee5\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"strong"},"DependsOn")," \u914d\u7f6e\u4f9d\u8d56\uff0c\u7ec4\u4ef6\u4e4b\u95f4\u8fd8\u80fd\u5171\u4eab\u4e0a\u4e0b\u6587\u6570\u636e ",(0,i.kt)("inlineCode",{parentName:"strong"},"ComponentContext"),"\u3002")),(0,i.kt)("p",null,"\u6ca1\u9519\uff0c\u8fd9\u5c31\u662f Furion \u76ee\u524d\u80fd\u591f\u60f3\u5230\u7684\u6700\u4f18\u89e3\u51b3\u65b9\u6848\u3002"),(0,i.kt)("h2",{id:"324-icomponent"},"3.2.4 ",(0,i.kt)("inlineCode",{parentName:"h2"},"IComponent")),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 3.7.3+")," \u7248\u672c\uff0c\u65b0\u589e\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Components")," \u6a21\u5757\uff0c\u8be5\u6a21\u5757\u7684\u6839\u63a5\u53e3\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"IComponent"),"\uff0c\u542b\u6709\u4e24\u4e2a\u6d3e\u751f\u63a5\u53e3 ",(0,i.kt)("inlineCode",{parentName:"p"},"IServiceComponent")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"IApplicationComponent"),"\u3002"),(0,i.kt)("h3",{id:"3241-iservicecomponent"},"3.2.4.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"IServiceComponent")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"IServiceComponent")," \u63a5\u53e3\u7b80\u79f0",(0,i.kt)("strong",{parentName:"p"},"\u670d\u52a1\u7ec4\u4ef6"),"\u5bf9\u5e94\u7684\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"ConfigureService"),"\uff0c\u63a5\u53e3\u7b7e\u540d\u4e3a\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,13}",showLineNumbers:!0,"{6,13}":!0},'namespace System;\n\n/// \n/// \u670d\u52a1\u7ec4\u4ef6\u4f9d\u8d56\u63a5\u53e3\n/// \npublic interface IServiceComponent : IComponent\n{\n /// \n /// \u88c5\u8f7d\u670d\u52a1\n /// \n /// \n /// \u7ec4\u4ef6\u4e0a\u4e0b\u6587\n void Load(IServiceCollection services, ComponentContext componentContext);\n}\n')),(0,i.kt)("p",null,"\u9700\u8981\u6ce8\u518c\u670d\u52a1\u53ef\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Load")," \u65b9\u6cd5\u4e2d\u6ce8\u518c\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"3242-iapplicationcomponent"},"3.2.4.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"IApplicationComponent")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"IApplicationComponent")," \u63a5\u53e3\u7b80\u79f0",(0,i.kt)("strong",{parentName:"p"},"\u4e2d\u95f4\u4ef6\u7ec4\u4ef6"),"\u5bf9\u5e94\u7684\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Configure"),"\uff0c\u63a5\u53e3\u7b7e\u540d\u4e3a\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,14}",showLineNumbers:!0,"{6,14}":!0},'namespace System;\n\n/// \n/// \u5e94\u7528\u4e2d\u95f4\u4ef6\u63a5\u53e3\n/// \npublic interface IApplicationComponent : IComponent\n{\n /// \n /// \u88c5\u7f6e\u4e2d\u95f4\u4ef6\n /// \n /// \n /// \n /// \u7ec4\u4ef6\u4e0a\u4e0b\u6587\n void Load(IApplicationBuilder app, IWebHostEnvironment env, ComponentContext componentContext);\n}\n')),(0,i.kt)("p",null,"\u9700\u8981\u6ce8\u518c\u4e2d\u95f4\u4ef6\u53ef\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Load")," \u65b9\u6cd5\u4e2d\u6ce8\u518c\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"3243-iwebcomponent"},"3.2.4.3 ",(0,i.kt)("inlineCode",{parentName:"h3"},"IWebComponent")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"IWebComponent")," \u63a5\u53e3\u7b80\u79f0",(0,i.kt)("strong",{parentName:"p"}," ",(0,i.kt)("inlineCode",{parentName:"strong"},"Web")," \u7ec4\u4ef6"),"\u5bf9\u5e94\u7684\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"WebApplicationBuilder"),"\uff0c\u63a5\u53e3\u7b7e\u540d\u4e3a\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,13}",showLineNumbers:!0,"{6,13}":!0},'namespace System;\n\n/// \n/// WebApplicationBuilder \u7ec4\u4ef6\u4f9d\u8d56\u63a5\u53e3\n/// \npublic interface IWebComponent : IComponent\n{\n /// \n /// \u88c5\u7f6e Web \u5e94\u7528\u6784\u5efa\u5668\n /// \n /// \n /// \u7ec4\u4ef6\u4e0a\u4e0b\u6587\n void Load(WebApplicationBuilder builder, ComponentContext componentContext);\n}\n')),(0,i.kt)("p",null,"\u9700\u8981\u6ce8\u518c\u4e2d\u95f4\u4ef6\u53ef\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Load")," \u65b9\u6cd5\u4e2d\u6ce8\u518c\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"3243-\u6ce8\u518c\u7ec4\u4ef6"},"3.2.4.3 \u6ce8\u518c\u7ec4\u4ef6"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u591a\u79cd\u6ce8\u518c\u7ec4\u4ef6\u7684\u65b9\u5f0f\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u65b9\u5f0f\u4e00")),(0,i.kt)("p",null,"\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"RunOptions"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"LegacyRunOptions"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"GenericRunOptions")," \u65b9\u5f0f\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2-3,7}",showLineNumbers:!0,"{2-3,7}":!0},"Serve.Run(RunOptions.Default\n .AddComponent()\n .UseComponent());\n\n// .NET6+ \u8fd8\u652f\u6301 AddWebComponent();\nServe.Run(RunOptions.Default\n .AddWebComponent());\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u65b9\u5f0f\u4e8c")),(0,i.kt)("p",null,"\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"services.AddComponent")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"app.UseComponent")," \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,8}",showLineNumbers:!0,"{2,5,8}":!0},"// \u670d\u52a1\u7ec4\u4ef6\nservice.AddComponent();\n\n// \u4e2d\u95f4\u4ef6\u7ec4\u4ef6\napp.UseComponent();\n\n// .NET6+ \u8fd8\u652f\u6301 AddWebComponent();\nbuilder.AddWebComponent();\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u65b9\u5f0f\u4e09")),(0,i.kt)("p",null,"\u7ec4\u4ef6\u6ce8\u518c\u53ef\u4ee5\u4f20\u9012\u53c2\u6570\uff0c\u901a\u8fc7\u6700\u540e\u7684\u53c2\u6570\u6307\u5b9a\u3002"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,8}",showLineNumbers:!0,"{2,5,8}":!0},"// \u670d\u52a1\u7ec4\u4ef6\nservice.AddComponent(options);\n\n// \u4e2d\u95f4\u4ef6\u7ec4\u4ef6\napp.UseComponent(options);\n\n// .NET6+ \u8fd8\u652f\u6301 AddWebComponent();\nbuilder.AddWebComponent(options);\n")),(0,i.kt)("admonition",{type:"tip"},(0,i.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u7c7b\u578b ",(0,i.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Type")," \u6ce8\u518c\u65b9\u5f0f"),(0,i.kt)("p",{parentName:"admonition"},"\u9664\u4e86\u63d0\u4f9b\u6cdb\u578b\u6ce8\u518c\u7ec4\u4ef6\u7684\u65b9\u5f0f\uff0c\u8fd8\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},".AddComponent(typeof(XXXComponent))")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},".UseComponent(typeof(XXXComponent))")," \u65b9\u5f0f\u3002")),(0,i.kt)("h2",{id:"325-\u7ec4\u4ef6\u8bbe\u8ba1\u539f\u5219"},"3.2.5 \u7ec4\u4ef6\u8bbe\u8ba1\u539f\u5219"),(0,i.kt)("h3",{id:"3251-\u804c\u8d23\u5355\u4e00\u6027"},"3.2.5.1 \u804c\u8d23\u5355\u4e00\u6027"),(0,i.kt)("p",null,"\u7ec4\u4ef6\u7684\u8bbe\u8ba1\u7406\u5e94\u9075\u5faa",(0,i.kt)("strong",{parentName:"p"},"\u804c\u8d23\u5355\u4e00\u6027\u539f\u5219"),"\uff0c\u5177\u6709\u5355\u4e00\u6027\u53c8\u6709\u804c\u8d23\u660e\u786e\u6027\uff0c\u901a\u4fd7\u70b9\u8bf4\u6bcf\u4e00\u4e2a\u7ec4\u4ef6\u5c3d\u53ef\u80fd\u7684\u53ea\u505a\u4e00\u4ef6\u4e8b\uff0c\u5982\u679c\u7ec4\u4ef6\u4e4b\u95f4\u6709\u4f9d\u8d56\uff0c\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"[DependsOn]")," \u58f0\u660e\u914d\u7f6e\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"{1,5}":!0},'[DependsOn(\n typeof(OtherServiceComponent),\n "Other.Assembly;Other.Assembly.OtherServiceComponent"\n)]\npublic sealed class YourServiceComponent : IServiceComponent\n{\n public void Load(IServiceCollection services, ComponentContext componentContext)\n {\n services.AddXXX();\n }\n}\n')),(0,i.kt)("h3",{id:"3252-\u7ea6\u5b9a\u5927\u4e8e\u914d\u7f6e"},"3.2.5.2 \u7ea6\u5b9a\u5927\u4e8e\u914d\u7f6e"),(0,i.kt)("p",null,"\u7531\u4e8e\u7ec4\u4ef6\u901a\u5e38\u5305\u542b\u670d\u52a1\u548c\u4e2d\u95f4\u4ef6\u4e24\u4e2a\u6ce8\u518c\uff0c\u6240\u4ee5\u63a8\u8350\u7ec4\u4ef6\u7c7b\u7684\u547d\u540d\u7edf\u4e00\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"XXXComponent.cs"),"\uff0c\u7136\u540e\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"XXXComponent.cs")," \u4e2d\u5206\u522b\u5199 ",(0,i.kt)("inlineCode",{parentName:"p"},"IServiceComponent")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"IApplicationComponent")," \u7ec4\u4ef6\u3002"),(0,i.kt)("p",null,"\u5c3d\u53ef\u80fd\u6bcf\u4e00\u4e2a\u670d\u52a1\u7ec4\u4ef6\uff08",(0,i.kt)("inlineCode",{parentName:"p"},"IServiceComponent"),"\uff09\u4ee5 ",(0,i.kt)("inlineCode",{parentName:"p"},"ServiceComponent")," \u7ed3\u5c3e\uff0c\u6bcf\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\uff08",(0,i.kt)("inlineCode",{parentName:"p"},"IApplicationComponent"),"\uff09\u4ee5 ",(0,i.kt)("inlineCode",{parentName:"p"},"ApplicationComponent")," \u7ed3\u5c3e\u3002\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {3-4,9-10,15-16} title="XXXComponent.cs"',showLineNumbers:!0,"{3-4,9-10,15-16}":!0,title:'"XXXComponent.cs"'},"namespace Your.Components;\n\n// \u670d\u52a1\u7ec4\u4ef6\npublic sealed class XXXServiceComponent : IServiceComponent\n{\n // ....\n}\n\n// \u4e2d\u95f4\u4ef6\u7ec4\u4ef6\npublic sealed class XXXApplicationComponent : IApplicationComponent\n{\n // ....\n}\n\n// WebApplicationBuilder \u7ec4\u4ef6\npublic sealed class XXXWebComponent : IWebComponent\n{\n // ....\n}\n")),(0,i.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u6ca1\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"IServiceComponent")," \u6216 ",(0,i.kt)("inlineCode",{parentName:"p"},"IApplicationComponent"),"\uff0c\u5219\u5199\u5176\u4e00\u5373\u53ef\u3002")),(0,i.kt)("h2",{id:"326-dependson-\u8be6\u89e3"},"3.2.6 ",(0,i.kt)("inlineCode",{parentName:"h2"},"[DependsOn]")," \u8be6\u89e3"),(0,i.kt)("p",null,"\u7531\u4e8e\u7ec4\u4ef6\u548c\u7ec4\u4ef6\u4e4b\u95f4\u5b58\u5728\u4f9d\u8d56\u65b9\u5f0f\uff0c\u751a\u81f3\u6ca1\u6709\u4f9d\u8d56\u5173\u7cfb\u4f46\u652f\u6301\u5524\u9192\u5176\u4ed6\u7ec4\u4ef6\u529f\u80fd\uff0c\u6240\u4ee5 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"[DependsOn]")," \u7279\u6027\u3002"),(0,i.kt)("h3",{id:"3261-\u914d\u7f6e\u4ecb\u7ecd"},"3.2.6.1 \u914d\u7f6e\u4ecb\u7ecd"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"DependsOn"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"DependComponents"),"\uff1a\u914d\u7f6e\u7ec4\u4ef6\u4f9d\u8d56\u5173\u7cfb\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Type[]")," \u7c7b\u578b\uff0c\u4e00\u65e6\u914d\u7f6e\u4e86\u4f9d\u8d56\u5173\u7cfb\uff0c\u90a3\u4e48\u88ab\u4f9d\u8d56\u7684\u7ec4\u4ef6\u4f1a\u5148\u4e8e\u5f53\u524d\u7ec4\u4ef6\u6ce8\u518c"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Links"),"\uff1a\u914d\u7f6e\u7ec4\u4ef6\u94fe\u63a5\u5173\u7cfb\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Type[]")," \u7c7b\u578b\uff0c\u8be5\u914d\u7f6e\u4e3b\u8981\u89e3\u51b3\u4e00\u4e9b\u7ec4\u4ef6\u5e76\u4e0d\u662f\u4ece ",(0,i.kt)("inlineCode",{parentName:"li"},"\u6839\u7ec4\u4ef6")," \u8fdb\u884c\u914d\u7f6e\uff0c\u800c\u662f\u5904\u4e8e\u548c ",(0,i.kt)("inlineCode",{parentName:"li"},"\u6839\u7ec4\u4ef6")," \u5e73\u884c\u7684\u60c5\u51b5\uff0c\u7c7b\u4f3c\u591a\u5165\u53e3\u7ec4\u4ef6")))),(0,i.kt)("admonition",{title:"\u6784\u9020\u51fd\u6570\u8bf4\u660e",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"DependComponents")," \u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"DependsOnAttribute")," \u7279\u6027\u7684\u9ed8\u8ba4\u6784\u9020\u51fd\u6570\uff0c\u652f\u6301 ",(0,i.kt)("inlineCode",{parentName:"p"},"Type")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"String")," \u7c7b\u578b\uff0c\u5982\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2-4}",showLineNumbers:!0,"{2-4}":!0},'[DependsOn(\n typeof(XXXComponent),\n typeof(XXXXComponent),\n "\u7a0b\u5e8f\u96c6;\u7c7b\u578b\u5b8c\u6574\u9650\u5b9a\u540d" // \u4f1a\u81ea\u52a8\u52a0\u8f7d\u7a0b\u5e8f\u96c6\u4e2d\u7279\u5b9a\u7684\u7ec4\u4ef6\uff0c\u540e\u7eed\u6a21\u5757\u5316\u5f00\u53d1\u975e\u5e38\u65b9\u4fbf\n)]\n')),(0,i.kt)("p",{parentName:"admonition"},"\u5982\u9700\u914d\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"Links"),"\uff0c\u53ea\u9700\u8981\u8fd9\u6837\u63a5\u53e3\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-6}",showLineNumbers:!0,"{3-6}":!0},"[DependsOn(\n typeof(XXXComponent),\n Links = new object[]{\n typeof(XXXComponent),\n typeof(XXXXComponent)\n }\n)]\n"))),(0,i.kt)("h3",{id:"3262-\u91cd\u590d\u4f9d\u8d56\u95ee\u9898"},"3.2.6.2 \u91cd\u590d\u4f9d\u8d56\u95ee\u9898"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u5df2\u7ecf\u5904\u7406\u4e86\u7ec4\u4ef6\u91cd\u590d\u4f9d\u8d56\u95ee\u9898\uff0c\u4f1a\u81ea\u52a8\u751f\u6210\u597d\u6700\u4f73\u7684\u6ce8\u518c\u987a\u5e8f\u5e76\u53bb\u9664\u91cd\u590d\u4f9d\u8d56\u6ce8\u518c\u95ee\u9898\u3002"),(0,i.kt)("h3",{id:"3263-\u5faa\u73af\u4f9d\u8d56\u95ee\u9898"},"3.2.6.3 \u5faa\u73af\u4f9d\u8d56\u95ee\u9898"),(0,i.kt)("p",null,"\u5faa\u73af\u4f9d\u8d56\u5b9e\u9645\u4e0a\u662f\u4e00\u79cd\u9519\u8bef\u6ce8\u518c\u7ec4\u4ef6\u7684\u65b9\u5f0f\uff0c\u4f1a\u5bfc\u81f4\u51fa\u73b0\u5185\u5b58\u6ea2\u51fa\u60c5\u51b5\uff0c\u65e9\u671f\u7ec4\u4ef6\u5316\u7248\u672c\u6846\u67b6\u5904\u7406\u4e86\u5faa\u73af\u4f9d\u8d56\u95ee\u9898\uff0c\u4e5f\u5c31\u662f\u4e3b\u52a8\u5ffd\u7565\u6216\u62a5\u9519\uff0c\u4f46\u662f\u8003\u8651\u6b64\u884c\u4e3a\u672c\u8eab\u5e26\u6709\u6f5c\u5728\u7684\u5b89\u5168\u95ee\u9898\uff0c\u6240\u4ee5\u79fb\u9664\u4e86\u5faa\u73af\u4f9d\u8d56\u5904\u7406\uff0c\u800c\u662f\u9009\u62e9\u5728\u5f00\u53d1\u9636\u6bb5\u629b\u51fa\u5f02\u5e38\u65b9\u5f0f\u3002"),(0,i.kt)("h2",{id:"327-componentcontext-\u8be6\u89e3"},"3.2.7 ",(0,i.kt)("inlineCode",{parentName:"h2"},"ComponentContext")," \u8be6\u89e3"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"ComponentContext")," \u662f\u7ec4\u4ef6\u6ce8\u518c ",(0,i.kt)("inlineCode",{parentName:"p"},"Load")," \u65b9\u6cd5\u7684\u6700\u540e\u53c2\u6570\uff0c\u8be5\u53c2\u6570\u63d0\u4f9b\u4e86\u7ec4\u4ef6\u4e4b\u95f4\u7684\u4e00\u4e9b\u5143\u6570\u636e\u3002"),(0,i.kt)("h3",{id:"3271-\u5c5e\u6027\u4ecb\u7ecd"},"3.2.7.1 \u5c5e\u6027\u4ecb\u7ecd"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ComponentContext"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ComponentType"),"\uff1a\u7ec4\u4ef6\u7c7b\u578b\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Type")," \u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"CalledContext"),"\uff1a\u4e0a\u7ea7\u7ec4\u4ef6\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"ComponentContext")," \u7c7b\u578b\uff0c\u4e5f\u5c31\u662f ",(0,i.kt)("inlineCode",{parentName:"li"},"DependsOn")," \u4e2d\u7684\u7ec4\u4ef6\u4e0a\u4e0b\u6587\uff0c\u5982\u679c\u6ca1\u6709\u5219\u662f\u524d\u4e00\u4e2a\u7ec4\u4ef6\u7684\u4e0a\u4e0b\u6587"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"RootContext"),"\uff1a\u6839\u7ec4\u4ef6/\u5165\u53e3\u7ec4\u4ef6\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"ComponentContext")," \u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"DependComponents"),"\uff1a\u7ec4\u4ef6\u4f9d\u8d56\u7684\u6240\u6709\u7ec4\u4ef6\u5217\u8868\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Type[]")," \u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"LinkComponents"),"\uff1a\u7ec4\u4ef6\u94fe\u63a5\u7684\u6240\u6709\u7ec4\u4ef6\u5217\u8868\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Type[]")," \u7c7b\u578b")))),(0,i.kt)("h3",{id:"3272-\u53c2\u6570\u914d\u7f6e\u83b7\u53d6"},"3.2.7.2 \u53c2\u6570\u914d\u7f6e/\u83b7\u53d6"),(0,i.kt)("p",null,"\u5728\u6ce8\u518c\u7ec4\u4ef6\u5c0f\u8282\u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},".AddComponent")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},".UseComponent")," \u6700\u540e\u7684\u53c2\u6570\u6765\u6307\u5b9a\u7ec4\u4ef6\u7684\u53c2\u6570\uff0c\u90a3\u4e48\u5982\u4f55\u5728\u7ec4\u4ef6\u4e2d\u83b7\u53d6\u4f60\u4f20\u9012\u7684\u53c2\u6570\u5462\uff1f"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"ComponentContext")," \u63d0\u4f9b\u4e86\u591a\u79cd\u65b9\u6cd5\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"GetProperty()"),"\uff1a\u83b7\u53d6\u7ec4\u4ef6\u7684\u53c2\u6570"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"GetProperty(Type)"),"\uff1a\u901a\u8fc7\u7c7b\u578b\u83b7\u53d6\u7ec4\u4ef6\u53c2\u6570"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"GetProperty(string)"),"\uff1a\u901a\u8fc7\u6307\u5b9a ",(0,i.kt)("inlineCode",{parentName:"li"},"key")," \u83b7\u53d6"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"GetProperties()"),"\uff1a\u83b7\u53d6\u7ec4\u4ef6\u6240\u6709\u53c2\u6570\u5217\u8868\uff08\u5305\u62ec\u4f9d\u8d56\uff0c\u94fe\u63a5\u7b49\uff09"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SetProperty(object)"),"\uff1a\u8bbe\u7f6e\u7279\u5b9a\u7ec4\u4ef6\u53c2\u6570"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SetProperty(Type, object)"),"\uff1a\u8bbe\u7f6e\u7279\u5b9a\u7c7b\u578b\u7ec4\u4ef6\u7684\u53c2\u6570"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SetProperty(string, object)"),"\uff1a\u8bbe\u7f6e\u6307\u5b9a ",(0,i.kt)("inlineCode",{parentName:"li"},"key")," \u7684\u53c2\u6570\u503c")),(0,i.kt)("h4",{id:"\u4f8b\u5b50\u8bf4\u660e"},"\u4f8b\u5b50\u8bf4\u660e"),(0,i.kt)("p",null,"\u6ce8\u518c\u65f6\u4f20\u5165 ",(0,i.kt)("inlineCode",{parentName:"p"},"EntryOption")," \u53c2\u6570"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"service.AddComponent(new EntryOption {});\n")),(0,i.kt)("p",null,"\u5728\u7ec4\u4ef6\u5185\u90e8\u83b7\u53d6\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,7}",showLineNumbers:!0,"{5,7}":!0},"public sealed class EntryServiceComponent : IServiceComponent\n{\n public void Load(IServiceCollection services, ComponentContext componentContext)\n {\n var options = componentContext.GetProperty();\n\n services.AddXXXX(options);\n }\n}\n")),(0,i.kt)("p",null,"\u9664\u6b64\u4e4b\u5916\uff0c\u8fd8\u53ef\u4ee5\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"componentContext.SetProperty(new xxxOptions{})")," \u6765\u8bbe\u7f6e\u4e0b\u6e38\u7ec4\u4ef6\u7684\u53c2\u6570\u3002"),(0,i.kt)("h2",{id:"328-\u5b9e\u73b0-startupcs-\u6a21\u5f0f"},"3.2.8 \u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Startup.cs")," \u6a21\u5f0f"),(0,i.kt)("p",null,"\u7ec4\u4ef6\u6a21\u5f0f\u662f\u975e\u5e38\u5f3a\u5927\u4e14\u7075\u6d3b\u7684\uff0c\u6211\u4eec\u4e5f\u53ef\u4ee5\u901a\u8fc7\u7ec4\u4ef6\u7684\u6a21\u5f0f\u6a21\u62df\u51fa\u4f20\u7edf\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs"),"\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {1,6-7,11,16-21} title="StartupComponent"',showLineNumbers:!0,"{1,6-7,11,16-21}":!0,title:'"StartupComponent"'},"// \u6a21\u62df ConfigureService\npublic sealed class StartupServiceComponent : IServiceComponent\n{\n public void Load(IServiceCollection services, ComponentContext componentContext)\n {\n services.AddControllers()\n .AddInject();\n }\n}\n\n// \u6a21\u62df Configure\npublic sealed class StartupApplicationComponent : IApplicationComponent\n{\n public void Load(IApplicationBuilder app, IWebHostEnvironment env, ComponentContext componentContext)\n {\n app.UseRouting();\n app.UseInject(string.Empty);\n app.UseEndpoints(endpoints =>\n {\n endpoints.MapControllers();\n });\n }\n}\n")),(0,i.kt)("p",null,"\u53ea\u9700\u8981\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"service.AddComponent()")," \u6ce8\u518c\u5373\u53ef\uff0c\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Serve.Run()")," \u6a21\u5f0f\u5c06\u66f4\u7b80\u5355\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2-3}",showLineNumbers:!0,"{2-3}":!0},"Serve.Run(RunOptions.Default\n .AddComponent()\n .UseComponent());\n")),(0,i.kt)("p",null,"\u662f\u4e0d\u662f\u5f88\u7075\u6d3b\u554a~"),(0,i.kt)("h2",{id:"329-\u6700\u4f73\u5b9e\u8df5"},"3.2.9 \u6700\u4f73\u5b9e\u8df5\uff1f"),(0,i.kt)("p",null,"\u5728\u5199\u6700\u4f73\u5b9e\u8df5\u65f6\u662f\u6700\u75db\u82e6\u7684\uff0c\u56e0\u4e3a\u6700\u4f73\u5b9e\u8df5\u5e94\u8be5\u662f\u628a\u5fae\u8f6f\u5e95\u5c42\u6240\u6709\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"service.AddXXX")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"app.AddXXX")," \u72ec\u7acb\u6210\u4e00\u4e2a\u4e2a\u7ec4\u4ef6\uff0c\u6bd4\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"servers.AddControllers()")," \u5bf9\u5e94\u4e00\u4e2a ",(0,i.kt)("inlineCode",{parentName:"p"},"ControllersServiceComponent"),"\u3002"),(0,i.kt)("p",null,"\u8fd9\u6837\u505a\u7684\u8bdd\u5de5\u4f5c\u91cf\u662f\u975e\u5e38\u5927\u7684\uff0c\u4f46\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u7ec4\u4ef6\u5316\u5c31\u65e0\u6cd5\u5f7b\u5e95\u3002"),(0,i.kt)("p",null,"\u6240\u4ee5\u73b0\u9636\u6bb5\u6682\u65f6\u91c7\u7528\u81ea\u7531\u5b9a\u5236\u7ec4\u4ef6\u65b9\u5f0f\uff0c\u6bd4\u5982\u81ea\u5df1\u5728\u9879\u76ee\u4e2d\u7f16\u5199 ",(0,i.kt)("inlineCode",{parentName:"p"},"ControllersServiceComponent")," \u8fd9\u7c7b\u7ec4\u4ef6\u3002"),(0,i.kt)("h2",{id:"3210-\u53cd\u9988\u4e0e\u5efa\u8bae"},"3.2.10 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/4972.006d6232.js b/handbook/build/assets/js/4972.006d6232.js new file mode 100644 index 0000000000..2c76ff4cdd --- /dev/null +++ b/handbook/build/assets/js/4972.006d6232.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4972],{4972:function(e,t,n){n.r(t),n.d(t,{default:function(){return i}});var a=n(7294),o=n(5999),l=n(833),r=n(7302);function i(){return a.createElement(a.Fragment,null,a.createElement(l.d,{title:(0,o.I)({id:"theme.NotFound.title",message:"Page Not Found"})}),a.createElement(r.Z,null,a.createElement("main",{className:"container margin-vert--xl"},a.createElement("div",{className:"row"},a.createElement("div",{className:"col col--6 col--offset-3"},a.createElement("h1",{className:"hero__title"},a.createElement(o.Z,{id:"theme.NotFound.title",description:"The title of the 404 page"},"Page Not Found")),a.createElement("p",null,a.createElement(o.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page"},"We could not find what you were looking for.")),a.createElement("p",null,a.createElement(o.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page"},"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.")))))))}}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/4ad72136.3768d2a2.js b/handbook/build/assets/js/4ad72136.3768d2a2.js new file mode 100644 index 0000000000..2a53da3ac5 --- /dev/null +++ b/handbook/build/assets/js/4ad72136.3768d2a2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[9532],{3905:function(e,t,r){r.d(t,{Zo:function(){return p},kt:function(){return d}});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),u=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},p=function(e){var t=u(e.components);return n.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},s=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),s=u(r),d=o,f=s["".concat(c,".").concat(d)]||s[d]||m[d]||i;return r?n.createElement(f,a(a({ref:t},p),{},{components:r})):n.createElement(f,a({ref:t},p))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=s;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var u=2;u")," \u4ed3\u50a8\u65b9\u5f0f\u5728\u6784\u9020\u51fd\u6570\u4e2d\u521d\u59cb\u5316\uff0c",(0,i.kt)("strong",{parentName:"li"},"\u907f\u514d\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Db.GetRepository")," \u65b9\u5f0f"),"\u3002"),(0,i.kt)("li",{parentName:"ul"},"\u8bf7\u4ee5",(0,i.kt)("strong",{parentName:"li"},"\u5f02\u6b65\u65b9\u5f0f"),"\u8c03\u7528\u6240\u6709\u6570\u636e\u8bbf\u95ee api\u3002"),(0,i.kt)("li",{parentName:"ul"},"\u68c0\u7d22\u7684\u6570\u636e\u4e0d\u662f\u5fc5\u9700\u7684\u3002 \u7f16\u5199\u67e5\u8be2\u4ee5",(0,i.kt)("strong",{parentName:"li"},"\u4ec5\u8fd4\u56de\u5f53\u524d HTTP \u8bf7\u6c42\u6240\u5fc5\u9700\u7684\u6570\u636e"),"\u3002"),(0,i.kt)("li",{parentName:"ul"},"\u5982\u679c\u6570\u636e\u53ef\u4ee5\u63a5\u53d7\uff0c\u8bf7\u8003\u8651",(0,i.kt)("strong",{parentName:"li"},"\u7f13\u5b58\u7ecf\u5e38\u8bbf\u95ee\u7684\u4ece\u6570\u636e\u5e93\u6216\u8fdc\u7a0b\u670d\u52a1\u68c0\u7d22\u7684\u6570\u636e"),"\u3002 \u4f7f\u7528 MemoryCache \u6216 microsoft.web.distributedcache \uff0c\u5177\u4f53\u53d6\u51b3\u4e8e\u65b9\u6848\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u5c3d\u91cf\u51cf\u5c11\u7f51\u7edc\u5f80\u8fd4\u6b21\u6570"),"\u3002 \u76ee\u6807\u662f\u4f7f\u7528\u5355\u4e2a\u8c03\u7528\u800c\u4e0d\u662f\u591a\u4e2a\u8c03\u7528\u6765\u68c0\u7d22\u6240\u9700\u6570\u636e\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u5982\u679c\u5f53\u524d\u8bf7\u6c42\u53ea\u6709\u6570\u636e\u67e5\u8be2\uff0c\u8bf7\u4f7f\u7528\u65e0\u8ddf\u8e2a\u67e5\u8be2\u65b9\u5f0f"),"\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u5982\u679c\u8bf7\u6c42\u4e2d\u542b\u6709\u64cd\u4f5c\u6570\u636e\u65f6\uff0c\u8bf7\u4e0d\u8981\u5728 Entity Framework Core \u4e2d\u4f7f\u7528\u65e0\u8ddf\u8e2a\u67e5\u8be2"),"\u3002 EF Core \u53ef\u4ee5\u66f4\u6709\u6548\u5730\u8fd4\u56de\u65e0\u8ddf\u8e2a\u67e5\u8be2\u7684\u7ed3\u679c\u3002 \u7b5b\u9009\u548c\u805a\u5408 LINQ \u67e5\u8be2\uff08\u4f8b\u5982\uff0c .Where \u4f7f\u7528.Select\u3001\u6216.Sum \u8bed\u53e5\uff09\uff0c\u4ee5\u4fbf\u6570\u636e\u5e93\u6267\u884c\u7b5b\u9009\u3002"),(0,i.kt)("li",{parentName:"ul"},"\u5bf9\u4e8e\u9700\u8981\u8fdb\u884c\u590d\u6742\u903b\u8f91\u8ba1\u7b97\u67e5\u8be2\u6570\u636e\u60c5\u51b5\uff0c\u8bf7\u5c3d\u53ef\u80fd\u5728\u8fd4\u56de\u67e5\u8be2\u540e\u518d\u5728\u5ba2\u6237\u7aef\u8ba1\u7b97\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u4e0d\u8981\u5bf9\u96c6\u5408\u4f7f\u7528\u6295\u5f71\u67e5\u8be2"),'\uff0c\u8fd9\u53ef\u80fd\u4f1a\u5bfc\u81f4\u6267\u884c "N + 1" \u4e2a SQL \u67e5\u8be2\u3002'),(0,i.kt)("li",{parentName:"ul"},"\u4f7f\u7528 \xb7DbContextPool\xb7 \u6c60\u6765\u7ba1\u7406 DbContext\uff0c\u7c7b\u4f3c ADO.NET \u7684\u8fde\u63a5\u6c60\u3002"),(0,i.kt)("li",{parentName:"ul"},"\u624b\u52a8\u6216\u663e\u5f0f\u7f16\u8bd1\u7684\u67e5\u8be2 API\uff0c\u5141\u8bb8\u5e94\u7528\u7a0b\u5e8f\u7f13\u5b58\u67e5\u8be2\u8f6c\u6362\uff0c\u4f7f\u5176\u53ef\u4ec5\u88ab\u8ba1\u7b97\u4e00\u6b21\u5e76\u6267\u884c\u591a\u6b21\u3002")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// Create an explicitly compiled query\nprivate static Func _customerById =\n EF.CompileQuery((CustomerContext db, int id) =>\n db.Customers\n .Include(c => c.Address)\n .Single(c => c.Id == id));\n\n// Use the compiled query by invoking it\nusing (var db = new CustomerContext())\n{\n var customer = _customerById(db, 147);\n}\n")),(0,i.kt)("h2",{id:"9292-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.29.2 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/4ad72136.61d6cae6.js b/handbook/build/assets/js/4ad72136.61d6cae6.js deleted file mode 100644 index b23bddce01..0000000000 --- a/handbook/build/assets/js/4ad72136.61d6cae6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[9532],{5562:function(e,t,r){r.r(t),r.d(t,{assets:function(){return p},contentTitle:function(){return c},default:function(){return d},frontMatter:function(){return l},metadata:function(){return u},toc:function(){return m}});var n=r(3117),o=r(102),i=(r(7294),r(3905)),a=["components"],l={id:"efcore-recommend",title:"9.29 EFCore \u6700\u4f73\u5b9e\u8df5",sidebar_label:"9.29 EFCore \u6700\u4f73\u5b9e\u8df5"},c=void 0,u={unversionedId:"efcore-recommend",id:"efcore-recommend",title:"9.29 EFCore \u6700\u4f73\u5b9e\u8df5",description:"9.29.1 EFCore \u9ad8\u6027\u80fd",source:"@site/docs/efcore-recommend.mdx",sourceDirName:".",slug:"/efcore-recommend",permalink:"/furion/docs/efcore-recommend",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/efcore-recommend.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"efcore-recommend",title:"9.29 EFCore \u6700\u4f73\u5b9e\u8df5",sidebar_label:"9.29 EFCore \u6700\u4f73\u5b9e\u8df5"},sidebar:"docs",previous:{title:"9.28 \u5206\u8868\u5206\u5e93",permalink:"/furion/docs/split-db"},next:{title:"10.1 SqlSugar \u96c6\u6210",permalink:"/furion/docs/sqlsugar"}},p={},m=[{value:"9.29.1 EFCore \u9ad8\u6027\u80fd",id:"9291-efcore-\u9ad8\u6027\u80fd",level:2},{value:"9.29.2 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9292-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],s={toc:m};function d(e){var t=e.components,r=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"9291-efcore-\u9ad8\u6027\u80fd"},"9.29.1 EFCore \u9ad8\u6027\u80fd"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\uff0c\u9ed8\u8ba4\u63a8\u8350\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"EFCore")," \u64cd\u4f5c\u6570\u636e\u5e93\uff0c\u4f46\u5f88\u591a\u670b\u53cb\u5bf9 ",(0,i.kt)("inlineCode",{parentName:"p"},"EFCore")," \u4f7f\u7528\u4e0d\u5f53\uff0c\u7279\u610f\u7f16\u5199\u6b64\u6587\u6863\u8bf4\u660e\u3002"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u5c3d\u53ef\u80fd\u7684\u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"li"},"IRepository/IRepository")," \u4ed3\u50a8\u65b9\u5f0f\u5728\u6784\u9020\u51fd\u6570\u4e2d\u521d\u59cb\u5316\uff0c",(0,i.kt)("strong",{parentName:"li"},"\u907f\u514d\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Db.GetRepository")," \u65b9\u5f0f"),"\u3002"),(0,i.kt)("li",{parentName:"ul"},"\u8bf7\u4ee5",(0,i.kt)("strong",{parentName:"li"},"\u5f02\u6b65\u65b9\u5f0f"),"\u8c03\u7528\u6240\u6709\u6570\u636e\u8bbf\u95ee api\u3002"),(0,i.kt)("li",{parentName:"ul"},"\u68c0\u7d22\u7684\u6570\u636e\u4e0d\u662f\u5fc5\u9700\u7684\u3002 \u7f16\u5199\u67e5\u8be2\u4ee5",(0,i.kt)("strong",{parentName:"li"},"\u4ec5\u8fd4\u56de\u5f53\u524d HTTP \u8bf7\u6c42\u6240\u5fc5\u9700\u7684\u6570\u636e"),"\u3002"),(0,i.kt)("li",{parentName:"ul"},"\u5982\u679c\u6570\u636e\u53ef\u4ee5\u63a5\u53d7\uff0c\u8bf7\u8003\u8651",(0,i.kt)("strong",{parentName:"li"},"\u7f13\u5b58\u7ecf\u5e38\u8bbf\u95ee\u7684\u4ece\u6570\u636e\u5e93\u6216\u8fdc\u7a0b\u670d\u52a1\u68c0\u7d22\u7684\u6570\u636e"),"\u3002 \u4f7f\u7528 MemoryCache \u6216 microsoft.web.distributedcache \uff0c\u5177\u4f53\u53d6\u51b3\u4e8e\u65b9\u6848\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u5c3d\u91cf\u51cf\u5c11\u7f51\u7edc\u5f80\u8fd4\u6b21\u6570"),"\u3002 \u76ee\u6807\u662f\u4f7f\u7528\u5355\u4e2a\u8c03\u7528\u800c\u4e0d\u662f\u591a\u4e2a\u8c03\u7528\u6765\u68c0\u7d22\u6240\u9700\u6570\u636e\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u5982\u679c\u5f53\u524d\u8bf7\u6c42\u53ea\u6709\u6570\u636e\u67e5\u8be2\uff0c\u8bf7\u4f7f\u7528\u65e0\u8ddf\u8e2a\u67e5\u8be2\u65b9\u5f0f"),"\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u5982\u679c\u8bf7\u6c42\u4e2d\u542b\u6709\u64cd\u4f5c\u6570\u636e\u65f6\uff0c\u8bf7\u4e0d\u8981\u5728 Entity Framework Core \u4e2d\u4f7f\u7528\u65e0\u8ddf\u8e2a\u67e5\u8be2"),"\u3002 EF Core \u53ef\u4ee5\u66f4\u6709\u6548\u5730\u8fd4\u56de\u65e0\u8ddf\u8e2a\u67e5\u8be2\u7684\u7ed3\u679c\u3002 \u7b5b\u9009\u548c\u805a\u5408 LINQ \u67e5\u8be2\uff08\u4f8b\u5982\uff0c .Where \u4f7f\u7528.Select\u3001\u6216.Sum \u8bed\u53e5\uff09\uff0c\u4ee5\u4fbf\u6570\u636e\u5e93\u6267\u884c\u7b5b\u9009\u3002"),(0,i.kt)("li",{parentName:"ul"},"\u5bf9\u4e8e\u9700\u8981\u8fdb\u884c\u590d\u6742\u903b\u8f91\u8ba1\u7b97\u67e5\u8be2\u6570\u636e\u60c5\u51b5\uff0c\u8bf7\u5c3d\u53ef\u80fd\u5728\u8fd4\u56de\u67e5\u8be2\u540e\u518d\u5728\u5ba2\u6237\u7aef\u8ba1\u7b97\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u4e0d\u8981\u5bf9\u96c6\u5408\u4f7f\u7528\u6295\u5f71\u67e5\u8be2"),'\uff0c\u8fd9\u53ef\u80fd\u4f1a\u5bfc\u81f4\u6267\u884c "N + 1" \u4e2a SQL \u67e5\u8be2\u3002'),(0,i.kt)("li",{parentName:"ul"},"\u4f7f\u7528 \xb7DbContextPool\xb7 \u6c60\u6765\u7ba1\u7406 DbContext\uff0c\u7c7b\u4f3c ADO.NET \u7684\u8fde\u63a5\u6c60\u3002"),(0,i.kt)("li",{parentName:"ul"},"\u624b\u52a8\u6216\u663e\u5f0f\u7f16\u8bd1\u7684\u67e5\u8be2 API\uff0c\u5141\u8bb8\u5e94\u7528\u7a0b\u5e8f\u7f13\u5b58\u67e5\u8be2\u8f6c\u6362\uff0c\u4f7f\u5176\u53ef\u4ec5\u88ab\u8ba1\u7b97\u4e00\u6b21\u5e76\u6267\u884c\u591a\u6b21\u3002")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// Create an explicitly compiled query\nprivate static Func _customerById =\n EF.CompileQuery((CustomerContext db, int id) =>\n db.Customers\n .Include(c => c.Address)\n .Single(c => c.Id == id));\n\n// Use the compiled query by invoking it\nusing (var db = new CustomerContext())\n{\n var customer = _customerById(db, 147);\n}\n")),(0,i.kt)("h2",{id:"9292-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.29.2 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}d.isMDXComponent=!0},3905:function(e,t,r){r.d(t,{Zo:function(){return p},kt:function(){return d}});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),u=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},p=function(e){var t=u(e.components);return n.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},s=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),s=u(r),d=o,f=s["".concat(c,".").concat(d)]||s[d]||m[d]||i;return r?n.createElement(f,a(a({ref:t},p),{},{components:r})):n.createElement(f,a({ref:t},p))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=s;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var u=2;u=0||(r[a]=t[a]);return r}(t,e);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(t);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(t,a)&&(r[a]=t[a])}return r}var m=n.createContext({}),d=function(t){var e=n.useContext(m),a=e;return t&&(a="function"==typeof t?t(e):i(i({},e),t)),a},g=function(t){var e=d(t.components);return n.createElement(m.Provider,{value:e},t.children)},k={inlineCode:"code",wrapper:function(t){var e=t.children;return n.createElement(n.Fragment,{},e)}},u=n.forwardRef((function(t,e){var a=t.components,r=t.mdxType,l=t.originalType,m=t.parentName,g=p(t,["components","mdxType","originalType","parentName"]),u=d(a),o=r,N=u["".concat(m,".").concat(o)]||u[o]||k[o]||l;return a?n.createElement(N,i(i({ref:e},g),{},{components:a})):n.createElement(N,i({ref:e},g))}));function o(t,e){var a=arguments,r=e&&e.mdxType;if("string"==typeof t||r){var l=a.length,i=new Array(l);i[0]=u;var p={};for(var m in e)hasOwnProperty.call(e,m)&&(p[m]=e[m]);p.originalType=t,p.mdxType="string"==typeof t?t:r,i[1]=p;for(var d=2;dBenchmarkDotNet",id:"3633-benchmarkdotnet",level:2},{value:"36.3.3.1 \u5982\u4f55\u4f7f\u7528",id:"36331-\u5982\u4f55\u4f7f\u7528",level:3},{value:"36.3.3.2 \u67e5\u770b\u7ed3\u679c",id:"36332-\u67e5\u770b\u7ed3\u679c",level:3},{value:"36.3.3.3 \u5bfc\u51fa\u62a5\u8868",id:"36333-\u5bfc\u51fa\u62a5\u8868",level:3},{value:"36.3.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"3634-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],o={toc:u};function N(t){var e=t.components,a=(0,r.Z)(t,p);return(0,l.kt)("wrapper",(0,n.Z)({},o,a,{components:e,mdxType:"MDXLayout"}),(0,l.kt)("h2",{id:"3631-\u57fa\u51c6\u6d4b\u8bd5"},"36.3.1 \u57fa\u51c6\u6d4b\u8bd5"),(0,l.kt)("p",null,"\u57fa\u51c6\u6d4b\u8bd5\uff08benchmarking\uff09\u662f\u4e00\u79cd\u6d4b\u91cf\u548c\u8bc4\u4f30\u8f6f\u4ef6\u6027\u80fd\u6307\u6807\u7684\u6d3b\u52a8\u3002\u4f60\u53ef\u4ee5\u5728\u67d0\u4e2a\u65f6\u5019\u901a\u8fc7\u57fa\u51c6\u6d4b\u8bd5\u5efa\u7acb\u4e00\u4e2a\u5df2\u77e5\u7684\u6027\u80fd\u6c34\u5e73\uff08\u79f0\u4e3a\u57fa\u51c6\u7ebf\uff09\uff0c\u5f53\u7cfb\u7edf\u7684\u8f6f\u786c\u4ef6\u73af\u5883\u53d1\u751f\u53d8\u5316\u4e4b\u540e\u518d\u8fdb\u884c\u4e00\u6b21\u57fa\u51c6\u6d4b\u8bd5\u4ee5\u786e\u5b9a\u90a3\u4e9b\u53d8\u5316\u5bf9\u6027\u80fd\u7684\u5f71\u54cd\u3002\u8fd9\u662f\u57fa\u51c6\u6d4b\u8bd5\u6700\u5e38\u89c1\u7684\u7528\u9014\u3002\u5176\u4ed6\u7528\u9014\u5305\u62ec\u6d4b\u5b9a\u67d0\u79cd\u8d1f\u8f7d\u6c34\u5e73\u4e0b\u7684\u6027\u80fd\u6781\u9650\u3001\u7ba1\u7406\u7cfb\u7edf\u6216\u73af\u5883\u7684\u53d8\u5316\u3001\u53d1\u73b0\u53ef\u80fd\u5bfc\u81f4\u6027\u80fd\u95ee\u9898\u7684\u6761\u4ef6\uff0c\u7b49\u7b49\u3002"),(0,l.kt)("h2",{id:"3632-\u57fa\u51c6\u6d4b\u8bd5\u7279\u8d28\u53ca\u610f\u4e49"},"36.3.2 \u57fa\u51c6\u6d4b\u8bd5\u7279\u8d28\u53ca\u610f\u4e49"),(0,l.kt)("h3",{id:"36321-\u7279\u8d28"},"36.3.2.1 \u7279\u8d28"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u53ef\u91cd\u590d\u6027"),"\uff1a\u53ef\u8fdb\u884c\u91cd\u590d\u6027\u7684\u6d4b\u8bd5\uff0c\u8fd9\u6837\u505a\u6709\u5229\u4e8e\u6bd4\u8f83\u6bcf\u6b21\u7684\u6d4b\u8bd5\u7ed3\u679c\uff0c\u5f97\u5230\u6027\u80fd\u7ed3\u679c\u7684\u957f\u671f\u53d8\u5316\u8d8b\u52bf\uff0c\u4e3a\u7cfb\u7edf\u8c03\u4f18\u548c\u4e0a\u7ebf\u524d\u7684\u5bb9\u91cf\u89c4\u5212\u505a\u53c2\u8003\u3002"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u53ef\u89c2\u6d4b\u6027"),"\uff1a\u901a\u8fc7\u5168\u65b9\u4f4d\u7684\u76d1\u63a7\uff08\u5305\u62ec\u6d4b\u8bd5\u5f00\u59cb\u5230\u7ed3\u675f\uff0c\u6267\u884c\u673a\u3001\u670d\u52a1\u5668\u3001\u6570\u636e\u5e93\uff09\uff0c\u53ca\u65f6\u4e86\u89e3\u548c\u5206\u6790\u6d4b\u8bd5\u8fc7\u7a0b\u53d1\u751f\u4e86\u4ec0\u4e48\u3002"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u53ef\u5c55\u793a\u6027"),"\uff1a\u76f8\u5173\u4eba\u5458\u53ef\u4ee5\u76f4\u89c2\u660e\u4e86\u7684\u4e86\u89e3\u6d4b\u8bd5\u7ed3\u679c\uff08web \u754c\u9762\u3001\u4eea\u8868\u76d8\u3001\u6298\u7ebf\u56fe\u6811\u72b6\u56fe\u7b49\u5f62\u5f0f\uff09\u3002"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u771f\u5b9e\u6027"),"\uff1a\u6d4b\u8bd5\u7684\u7ed3\u679c\u53cd\u6620\u4e86\u5ba2\u6237\u4f53\u9a8c\u5230\u7684\u771f\u5b9e\u7684\u60c5\u51b5\uff08\u771f\u5b9e\u51c6\u786e\u7684\u4e1a\u52a1\u573a\u666f+\u4e0e\u751f\u4ea7\u4e00\u81f4\u7684\u914d\u7f6e+\u5408\u7406\u6b63\u786e\u7684\u6d4b\u8bd5\u65b9\u6cd5\uff09\u3002"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u53ef\u6267\u884c\u6027"),"\uff1a\u76f8\u5173\u4eba\u5458\u53ef\u4ee5\u5feb\u901f\u7684\u8fdb\u884c\u6d4b\u8bd5\u9a8c\u8bc1\u4fee\u6539\u8c03\u4f18\uff08\u53ef\u5b9a\u4f4d\u53ef\u5206\u6790\uff09\u3002")),(0,l.kt)("h3",{id:"36322-\u610f\u4e49"},"36.3.2.2 \u610f\u4e49"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u4e3a\u5bb9\u91cf\u89c4\u5212\u786e\u5b9a\u7cfb\u7edf\u548c\u5e94\u7528\u7a0b\u5e8f\u7684\u6781\u9650\uff1b"),(0,l.kt)("li",{parentName:"ul"},"\u4e3a\u914d\u7f6e\u6d4b\u8bd5\u7684\u53c2\u6570\u548c\u914d\u7f6e\u9009\u9879\u63d0\u4f9b\u53c2\u8003\u4f9d\u636e\uff1b"),(0,l.kt)("li",{parentName:"ul"},"\u4e3a\u9a8c\u6536\u6d4b\u8bd5\u786e\u5b9a\u7cfb\u7edf\u662f\u5426\u5177\u5907\u81ea\u5df1\u6240\u5ba3\u79f0\u7684\u80fd\u529b\uff1b"),(0,l.kt)("li",{parentName:"ul"},"\u4e3a\u6027\u80fd\u57fa\u7ebf\u7684\u5efa\u7acb\u63d0\u4f9b\u957f\u671f\u7684\u6570\u636e\u7edf\u8ba1\u6765\u6e90\u4ee5\u53ca\u6bd4\u8f83\u57fa\u51c6\uff1b")),(0,l.kt)("h2",{id:"3633-benchmarkdotnet"},"36.3.3 ",(0,l.kt)("inlineCode",{parentName:"h2"},"BenchmarkDotNet")),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"BenchmarkDotNet")," \u662f ",(0,l.kt)("inlineCode",{parentName:"p"},".NET")," \u5e73\u53f0\u63d0\u4f9b\u7684\u57fa\u51c6\u6d4b\u8bd5\u5de5\u5177\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"BenchmarkDotNet")," \u53ef\u5e2e\u52a9\u60a8\u5c06\u65b9\u6cd5\u8f6c\u6362\u4e3a\u57fa\u51c6\uff0c\u8ddf\u8e2a\u5176\u6027\u80fd\uff0c\u5e76\u5171\u4eab\u53ef\u91cd\u590d\u7684\u6d4b\u91cf\u5b9e\u9a8c\u3002",(0,l.kt)("inlineCode",{parentName:"p"},"BenchmarkDotNet")," \u53ef\u4fdd\u62a4\u60a8\u514d\u53d7\u6d41\u884c\u7684\u57fa\u51c6\u6d4b\u8bd5\u9519\u8bef\uff0c\u5e76\u5728\u57fa\u51c6\u8bbe\u8ba1\u6216\u83b7\u5f97\u7684\u6d4b\u91cf\u4e2d\u51fa\u73b0\u95ee\u9898\u65f6\u8b66\u544a\u60a8\u3002\u7ed3\u679c\u4ee5\u7528\u6237\u53cb\u597d\u7684\u5f62\u5f0f\u5448\u73b0\uff0c\u7a81\u51fa\u663e\u793a\u4e86\u6709\u5173\u5b9e\u9a8c\u7684\u6240\u6709\u91cd\u8981\u4e8b\u5b9e\u3002"),(0,l.kt)("h3",{id:"36331-\u5982\u4f55\u4f7f\u7528"},"36.3.3.1 \u5982\u4f55\u4f7f\u7528"),(0,l.kt)("p",null,"\u521b\u5efa\u4e00\u4e2a ",(0,l.kt)("inlineCode",{parentName:"p"},"\u63a7\u5236\u53f0")," \u5e94\u7528\u7a0b\u5e8f\uff0c\u5e76\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5b89\u88c5 ",(0,l.kt)("a",{parentName:"p",href:"https://www.nuget.org/packages/BenchmarkDotNet/"},"BenchmarkDotNet")," \u62d3\u5c55\u5305\u3002\u7f16\u5199\u6d4b\u8bd5\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-4,22,25,33}",showLineNumbers:!0,"":!0,"{3-4,22,25,33}":!0},"using System;\nusing System.Security.Cryptography;\nusing BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Running;\n\nnamespace MyBenchmarks\n{\n public class Md5VsSha256\n {\n private const int N = 10000;\n private readonly byte[] data;\n\n private readonly SHA256 sha256 = SHA256.Create();\n private readonly MD5 md5 = MD5.Create();\n\n public Md5VsSha256()\n {\n data = new byte[N];\n new Random(42).NextBytes(data);\n }\n\n [Benchmark]\n public byte[] Sha256() => sha256.ComputeHash(data);\n\n [Benchmark]\n public byte[] Md5() => md5.ComputeHash(data);\n }\n\n public class Program\n {\n public static void Main(string[] args)\n {\n var summary = BenchmarkRunner.Run();\n }\n }\n}\n")),(0,l.kt)("h3",{id:"36332-\u67e5\u770b\u7ed3\u679c"},"36.3.3.2 \u67e5\u770b\u7ed3\u679c"),(0,l.kt)("p",null,"\u8fd0\u884c\u63a7\u5236\u5668\u7a0b\u5e8f\uff0c\u5c06\u5f97\u5230\u4ee5\u4e0b\u7ed3\u679c"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"BenchmarkDotNet=v0.12.0, OS=Windows 10.0.17763.805 (1809/October2018Update/Redstone5)\nIntel Core i7-7700K CPU 4.20GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores\n [Host] : .NET Framework 4.7.2 (4.7.3468.0), X64 RyuJIT\n Net472 : .NET Framework 4.7.2 (4.7.3468.0), X64 RyuJIT\n NetCoreApp30 : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), X64 RyuJIT\n CoreRt30 : .NET CoreRT 1.0.28236.02 @Commit: 741d61493c560ba96e8151f9e56876d4d3828489, X64 AOT\n Mono : Mono 6.4.0 (Visual Studio), X64\n")),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Method"),(0,l.kt)("th",{parentName:"tr",align:null},"Runtime"),(0,l.kt)("th",{parentName:"tr",align:null},"N"),(0,l.kt)("th",{parentName:"tr",align:"right"},"Mean"),(0,l.kt)("th",{parentName:"tr",align:"right"},"Error"),(0,l.kt)("th",{parentName:"tr",align:"right"},"StdDev"),(0,l.kt)("th",{parentName:"tr",align:"right"},"Ratio"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},".NET 4.7.2"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"7.735 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.1913 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.4034 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.00")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},".NET Core 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"3.989 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0796 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0745 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.50")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},"CoreRt 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"4.091 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0811 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.1562 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.53")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},"Mono"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"13.117 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.2485 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.5019 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.70")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},".NET 4.7.2"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"2.872 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0552 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0737 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.00")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},".NET Core 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.848 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0348 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0326 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.64")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},"CoreRt 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.817 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0359 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0427 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.63")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},"Mono"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"3.574 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0678 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0753 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.24")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},".NET 4.7.2"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"74.509 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.5787 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"4.6052 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.00")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},".NET Core 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"36.049 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.7151 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.0025 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.49")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},"CoreRt 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"36.253 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.7076 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.7571 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.49")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},"Mono"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"116.350 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"2.2555 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"3.0110 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.58")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},".NET 4.7.2"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"17.308 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.3361 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.4250 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.00")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},".NET Core 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"15.726 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.2064 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.1930 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.90")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},"CoreRt 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"15.627 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.2631 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.2461 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.89")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},"Mono"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"30.205 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.5868 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.6522 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.74")))),(0,l.kt)("h3",{id:"36333-\u5bfc\u51fa\u62a5\u8868"},"36.3.3.3 \u5bfc\u51fa\u62a5\u8868"),(0,l.kt)("p",null,"\u4e5f\u53ef\u4ee5\u5bfc\u51fa\u5404\u79cd\u56fe\u8868"),(0,l.kt)("img",{src:(0,i.Z)("img/bm1.png")}),(0,l.kt)("h2",{id:"3634-\u53cd\u9988\u4e0e\u5efa\u8bae"},"36.3.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,l.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,l.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,l.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,l.kt)("hr",null),(0,l.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,l.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,l.kt)("inlineCode",{parentName:"p"},"BenchmarkDotNet")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,l.kt)("a",{parentName:"p",href:"https://benchmarkdotnet.org/"},"BenchmarkDotNet \u5b98\u7f51"),"\u3002")))}N.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/4b6c538b.d9f39463.js b/handbook/build/assets/js/4b6c538b.d9f39463.js deleted file mode 100644 index 7db09d5034..0000000000 --- a/handbook/build/assets/js/4b6c538b.d9f39463.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[2009],{8479:function(t,e,a){a.r(e),a.d(e,{assets:function(){return k},contentTitle:function(){return d},default:function(){return N},frontMatter:function(){return m},metadata:function(){return g},toc:function(){return u}});var n=a(3117),r=a(102),l=(a(7294),a(3905)),i=a(1402),p=["components"],m={id:"benchmark",title:"36.3 \u57fa\u51c6\u6d4b\u8bd5",sidebar_label:"36.3 \u57fa\u51c6\u6d4b\u8bd5"},d=void 0,g={unversionedId:"benchmark",id:"benchmark",title:"36.3 \u57fa\u51c6\u6d4b\u8bd5",description:"",source:"@site/docs/benchmark.mdx",sourceDirName:".",slug:"/benchmark",permalink:"/furion/docs/benchmark",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/benchmark.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"benchmark",title:"36.3 \u57fa\u51c6\u6d4b\u8bd5",sidebar_label:"36.3 \u57fa\u51c6\u6d4b\u8bd5"},sidebar:"docs",previous:{title:"36.2 \u8d1f\u8f7d\u538b\u6d4b",permalink:"/furion/docs/performance"},next:{title:"36.4 \u5e76\u53d1\u6d4b\u8bd5",permalink:"/furion/docs/bingfa"}},k={},u=[{value:"36.3.1 \u57fa\u51c6\u6d4b\u8bd5",id:"3631-\u57fa\u51c6\u6d4b\u8bd5",level:2},{value:"36.3.2 \u57fa\u51c6\u6d4b\u8bd5\u7279\u8d28\u53ca\u610f\u4e49",id:"3632-\u57fa\u51c6\u6d4b\u8bd5\u7279\u8d28\u53ca\u610f\u4e49",level:2},{value:"36.3.2.1 \u7279\u8d28",id:"36321-\u7279\u8d28",level:3},{value:"36.3.2.2 \u610f\u4e49",id:"36322-\u610f\u4e49",level:3},{value:"36.3.3 BenchmarkDotNet",id:"3633-benchmarkdotnet",level:2},{value:"36.3.3.1 \u5982\u4f55\u4f7f\u7528",id:"36331-\u5982\u4f55\u4f7f\u7528",level:3},{value:"36.3.3.2 \u67e5\u770b\u7ed3\u679c",id:"36332-\u67e5\u770b\u7ed3\u679c",level:3},{value:"36.3.3.3 \u5bfc\u51fa\u62a5\u8868",id:"36333-\u5bfc\u51fa\u62a5\u8868",level:3},{value:"36.3.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"3634-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],o={toc:u};function N(t){var e=t.components,a=(0,r.Z)(t,p);return(0,l.kt)("wrapper",(0,n.Z)({},o,a,{components:e,mdxType:"MDXLayout"}),(0,l.kt)("h2",{id:"3631-\u57fa\u51c6\u6d4b\u8bd5"},"36.3.1 \u57fa\u51c6\u6d4b\u8bd5"),(0,l.kt)("p",null,"\u57fa\u51c6\u6d4b\u8bd5\uff08benchmarking\uff09\u662f\u4e00\u79cd\u6d4b\u91cf\u548c\u8bc4\u4f30\u8f6f\u4ef6\u6027\u80fd\u6307\u6807\u7684\u6d3b\u52a8\u3002\u4f60\u53ef\u4ee5\u5728\u67d0\u4e2a\u65f6\u5019\u901a\u8fc7\u57fa\u51c6\u6d4b\u8bd5\u5efa\u7acb\u4e00\u4e2a\u5df2\u77e5\u7684\u6027\u80fd\u6c34\u5e73\uff08\u79f0\u4e3a\u57fa\u51c6\u7ebf\uff09\uff0c\u5f53\u7cfb\u7edf\u7684\u8f6f\u786c\u4ef6\u73af\u5883\u53d1\u751f\u53d8\u5316\u4e4b\u540e\u518d\u8fdb\u884c\u4e00\u6b21\u57fa\u51c6\u6d4b\u8bd5\u4ee5\u786e\u5b9a\u90a3\u4e9b\u53d8\u5316\u5bf9\u6027\u80fd\u7684\u5f71\u54cd\u3002\u8fd9\u662f\u57fa\u51c6\u6d4b\u8bd5\u6700\u5e38\u89c1\u7684\u7528\u9014\u3002\u5176\u4ed6\u7528\u9014\u5305\u62ec\u6d4b\u5b9a\u67d0\u79cd\u8d1f\u8f7d\u6c34\u5e73\u4e0b\u7684\u6027\u80fd\u6781\u9650\u3001\u7ba1\u7406\u7cfb\u7edf\u6216\u73af\u5883\u7684\u53d8\u5316\u3001\u53d1\u73b0\u53ef\u80fd\u5bfc\u81f4\u6027\u80fd\u95ee\u9898\u7684\u6761\u4ef6\uff0c\u7b49\u7b49\u3002"),(0,l.kt)("h2",{id:"3632-\u57fa\u51c6\u6d4b\u8bd5\u7279\u8d28\u53ca\u610f\u4e49"},"36.3.2 \u57fa\u51c6\u6d4b\u8bd5\u7279\u8d28\u53ca\u610f\u4e49"),(0,l.kt)("h3",{id:"36321-\u7279\u8d28"},"36.3.2.1 \u7279\u8d28"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u53ef\u91cd\u590d\u6027"),"\uff1a\u53ef\u8fdb\u884c\u91cd\u590d\u6027\u7684\u6d4b\u8bd5\uff0c\u8fd9\u6837\u505a\u6709\u5229\u4e8e\u6bd4\u8f83\u6bcf\u6b21\u7684\u6d4b\u8bd5\u7ed3\u679c\uff0c\u5f97\u5230\u6027\u80fd\u7ed3\u679c\u7684\u957f\u671f\u53d8\u5316\u8d8b\u52bf\uff0c\u4e3a\u7cfb\u7edf\u8c03\u4f18\u548c\u4e0a\u7ebf\u524d\u7684\u5bb9\u91cf\u89c4\u5212\u505a\u53c2\u8003\u3002"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u53ef\u89c2\u6d4b\u6027"),"\uff1a\u901a\u8fc7\u5168\u65b9\u4f4d\u7684\u76d1\u63a7\uff08\u5305\u62ec\u6d4b\u8bd5\u5f00\u59cb\u5230\u7ed3\u675f\uff0c\u6267\u884c\u673a\u3001\u670d\u52a1\u5668\u3001\u6570\u636e\u5e93\uff09\uff0c\u53ca\u65f6\u4e86\u89e3\u548c\u5206\u6790\u6d4b\u8bd5\u8fc7\u7a0b\u53d1\u751f\u4e86\u4ec0\u4e48\u3002"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u53ef\u5c55\u793a\u6027"),"\uff1a\u76f8\u5173\u4eba\u5458\u53ef\u4ee5\u76f4\u89c2\u660e\u4e86\u7684\u4e86\u89e3\u6d4b\u8bd5\u7ed3\u679c\uff08web \u754c\u9762\u3001\u4eea\u8868\u76d8\u3001\u6298\u7ebf\u56fe\u6811\u72b6\u56fe\u7b49\u5f62\u5f0f\uff09\u3002"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u771f\u5b9e\u6027"),"\uff1a\u6d4b\u8bd5\u7684\u7ed3\u679c\u53cd\u6620\u4e86\u5ba2\u6237\u4f53\u9a8c\u5230\u7684\u771f\u5b9e\u7684\u60c5\u51b5\uff08\u771f\u5b9e\u51c6\u786e\u7684\u4e1a\u52a1\u573a\u666f+\u4e0e\u751f\u4ea7\u4e00\u81f4\u7684\u914d\u7f6e+\u5408\u7406\u6b63\u786e\u7684\u6d4b\u8bd5\u65b9\u6cd5\uff09\u3002"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u53ef\u6267\u884c\u6027"),"\uff1a\u76f8\u5173\u4eba\u5458\u53ef\u4ee5\u5feb\u901f\u7684\u8fdb\u884c\u6d4b\u8bd5\u9a8c\u8bc1\u4fee\u6539\u8c03\u4f18\uff08\u53ef\u5b9a\u4f4d\u53ef\u5206\u6790\uff09\u3002")),(0,l.kt)("h3",{id:"36322-\u610f\u4e49"},"36.3.2.2 \u610f\u4e49"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u4e3a\u5bb9\u91cf\u89c4\u5212\u786e\u5b9a\u7cfb\u7edf\u548c\u5e94\u7528\u7a0b\u5e8f\u7684\u6781\u9650\uff1b"),(0,l.kt)("li",{parentName:"ul"},"\u4e3a\u914d\u7f6e\u6d4b\u8bd5\u7684\u53c2\u6570\u548c\u914d\u7f6e\u9009\u9879\u63d0\u4f9b\u53c2\u8003\u4f9d\u636e\uff1b"),(0,l.kt)("li",{parentName:"ul"},"\u4e3a\u9a8c\u6536\u6d4b\u8bd5\u786e\u5b9a\u7cfb\u7edf\u662f\u5426\u5177\u5907\u81ea\u5df1\u6240\u5ba3\u79f0\u7684\u80fd\u529b\uff1b"),(0,l.kt)("li",{parentName:"ul"},"\u4e3a\u6027\u80fd\u57fa\u7ebf\u7684\u5efa\u7acb\u63d0\u4f9b\u957f\u671f\u7684\u6570\u636e\u7edf\u8ba1\u6765\u6e90\u4ee5\u53ca\u6bd4\u8f83\u57fa\u51c6\uff1b")),(0,l.kt)("h2",{id:"3633-benchmarkdotnet"},"36.3.3 ",(0,l.kt)("inlineCode",{parentName:"h2"},"BenchmarkDotNet")),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"BenchmarkDotNet")," \u662f ",(0,l.kt)("inlineCode",{parentName:"p"},".NET")," \u5e73\u53f0\u63d0\u4f9b\u7684\u57fa\u51c6\u6d4b\u8bd5\u5de5\u5177\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"BenchmarkDotNet")," \u53ef\u5e2e\u52a9\u60a8\u5c06\u65b9\u6cd5\u8f6c\u6362\u4e3a\u57fa\u51c6\uff0c\u8ddf\u8e2a\u5176\u6027\u80fd\uff0c\u5e76\u5171\u4eab\u53ef\u91cd\u590d\u7684\u6d4b\u91cf\u5b9e\u9a8c\u3002",(0,l.kt)("inlineCode",{parentName:"p"},"BenchmarkDotNet")," \u53ef\u4fdd\u62a4\u60a8\u514d\u53d7\u6d41\u884c\u7684\u57fa\u51c6\u6d4b\u8bd5\u9519\u8bef\uff0c\u5e76\u5728\u57fa\u51c6\u8bbe\u8ba1\u6216\u83b7\u5f97\u7684\u6d4b\u91cf\u4e2d\u51fa\u73b0\u95ee\u9898\u65f6\u8b66\u544a\u60a8\u3002\u7ed3\u679c\u4ee5\u7528\u6237\u53cb\u597d\u7684\u5f62\u5f0f\u5448\u73b0\uff0c\u7a81\u51fa\u663e\u793a\u4e86\u6709\u5173\u5b9e\u9a8c\u7684\u6240\u6709\u91cd\u8981\u4e8b\u5b9e\u3002"),(0,l.kt)("h3",{id:"36331-\u5982\u4f55\u4f7f\u7528"},"36.3.3.1 \u5982\u4f55\u4f7f\u7528"),(0,l.kt)("p",null,"\u521b\u5efa\u4e00\u4e2a ",(0,l.kt)("inlineCode",{parentName:"p"},"\u63a7\u5236\u53f0")," \u5e94\u7528\u7a0b\u5e8f\uff0c\u5e76\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5b89\u88c5 ",(0,l.kt)("a",{parentName:"p",href:"https://www.nuget.org/packages/BenchmarkDotNet/"},"BenchmarkDotNet")," \u62d3\u5c55\u5305\u3002\u7f16\u5199\u6d4b\u8bd5\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-4,22,25,33}",showLineNumbers:!0,"":!0,"{3-4,22,25,33}":!0},"using System;\nusing System.Security.Cryptography;\nusing BenchmarkDotNet.Attributes;\nusing BenchmarkDotNet.Running;\n\nnamespace MyBenchmarks\n{\n public class Md5VsSha256\n {\n private const int N = 10000;\n private readonly byte[] data;\n\n private readonly SHA256 sha256 = SHA256.Create();\n private readonly MD5 md5 = MD5.Create();\n\n public Md5VsSha256()\n {\n data = new byte[N];\n new Random(42).NextBytes(data);\n }\n\n [Benchmark]\n public byte[] Sha256() => sha256.ComputeHash(data);\n\n [Benchmark]\n public byte[] Md5() => md5.ComputeHash(data);\n }\n\n public class Program\n {\n public static void Main(string[] args)\n {\n var summary = BenchmarkRunner.Run();\n }\n }\n}\n")),(0,l.kt)("h3",{id:"36332-\u67e5\u770b\u7ed3\u679c"},"36.3.3.2 \u67e5\u770b\u7ed3\u679c"),(0,l.kt)("p",null,"\u8fd0\u884c\u63a7\u5236\u5668\u7a0b\u5e8f\uff0c\u5c06\u5f97\u5230\u4ee5\u4e0b\u7ed3\u679c"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre"},"BenchmarkDotNet=v0.12.0, OS=Windows 10.0.17763.805 (1809/October2018Update/Redstone5)\nIntel Core i7-7700K CPU 4.20GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores\n [Host] : .NET Framework 4.7.2 (4.7.3468.0), X64 RyuJIT\n Net472 : .NET Framework 4.7.2 (4.7.3468.0), X64 RyuJIT\n NetCoreApp30 : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), X64 RyuJIT\n CoreRt30 : .NET CoreRT 1.0.28236.02 @Commit: 741d61493c560ba96e8151f9e56876d4d3828489, X64 AOT\n Mono : Mono 6.4.0 (Visual Studio), X64\n")),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Method"),(0,l.kt)("th",{parentName:"tr",align:null},"Runtime"),(0,l.kt)("th",{parentName:"tr",align:null},"N"),(0,l.kt)("th",{parentName:"tr",align:"right"},"Mean"),(0,l.kt)("th",{parentName:"tr",align:"right"},"Error"),(0,l.kt)("th",{parentName:"tr",align:"right"},"StdDev"),(0,l.kt)("th",{parentName:"tr",align:"right"},"Ratio"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},".NET 4.7.2"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"7.735 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.1913 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.4034 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.00")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},".NET Core 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"3.989 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0796 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0745 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.50")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},"CoreRt 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"4.091 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0811 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.1562 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.53")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},"Mono"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"13.117 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.2485 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.5019 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.70")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},".NET 4.7.2"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"2.872 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0552 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0737 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.00")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},".NET Core 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.848 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0348 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0326 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.64")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},"CoreRt 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.817 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0359 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0427 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.63")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},"Mono"),(0,l.kt)("td",{parentName:"tr",align:null},"1000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"3.574 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0678 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.0753 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.24")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},".NET 4.7.2"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"74.509 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.5787 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"4.6052 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.00")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},".NET Core 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"36.049 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.7151 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.0025 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.49")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},"CoreRt 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"36.253 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.7076 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.7571 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.49")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Sha256"),(0,l.kt)("td",{parentName:"tr",align:null},"Mono"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"116.350 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"2.2555 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"3.0110 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.58")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"}),(0,l.kt)("td",{parentName:"tr",align:"right"})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},".NET 4.7.2"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"17.308 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.3361 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.4250 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.00")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},".NET Core 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"15.726 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.2064 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.1930 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.90")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},"CoreRt 3.0"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"15.627 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.2631 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.2461 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.89")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Md5"),(0,l.kt)("td",{parentName:"tr",align:null},"Mono"),(0,l.kt)("td",{parentName:"tr",align:null},"10000"),(0,l.kt)("td",{parentName:"tr",align:"right"},"30.205 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.5868 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"0.6522 us"),(0,l.kt)("td",{parentName:"tr",align:"right"},"1.74")))),(0,l.kt)("h3",{id:"36333-\u5bfc\u51fa\u62a5\u8868"},"36.3.3.3 \u5bfc\u51fa\u62a5\u8868"),(0,l.kt)("p",null,"\u4e5f\u53ef\u4ee5\u5bfc\u51fa\u5404\u79cd\u56fe\u8868"),(0,l.kt)("img",{src:(0,i.Z)("img/bm1.png")}),(0,l.kt)("h2",{id:"3634-\u53cd\u9988\u4e0e\u5efa\u8bae"},"36.3.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,l.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,l.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,l.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,l.kt)("hr",null),(0,l.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,l.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,l.kt)("inlineCode",{parentName:"p"},"BenchmarkDotNet")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,l.kt)("a",{parentName:"p",href:"https://benchmarkdotnet.org/"},"BenchmarkDotNet \u5b98\u7f51"),"\u3002")))}N.isMDXComponent=!0},3905:function(t,e,a){a.d(e,{Zo:function(){return g},kt:function(){return o}});var n=a(7294);function r(t,e,a){return e in t?Object.defineProperty(t,e,{value:a,enumerable:!0,configurable:!0,writable:!0}):t[e]=a,t}function l(t,e){var a=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),a.push.apply(a,n)}return a}function i(t){for(var e=1;e=0||(r[a]=t[a]);return r}(t,e);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(t);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(t,a)&&(r[a]=t[a])}return r}var m=n.createContext({}),d=function(t){var e=n.useContext(m),a=e;return t&&(a="function"==typeof t?t(e):i(i({},e),t)),a},g=function(t){var e=d(t.components);return n.createElement(m.Provider,{value:e},t.children)},k={inlineCode:"code",wrapper:function(t){var e=t.children;return n.createElement(n.Fragment,{},e)}},u=n.forwardRef((function(t,e){var a=t.components,r=t.mdxType,l=t.originalType,m=t.parentName,g=p(t,["components","mdxType","originalType","parentName"]),u=d(a),o=r,N=u["".concat(m,".").concat(o)]||u[o]||k[o]||l;return a?n.createElement(N,i(i({ref:e},g),{},{components:a})):n.createElement(N,i({ref:e},g))}));function o(t,e){var a=arguments,r=e&&e.mdxType;if("string"==typeof t||r){var l=a.length,i=new Array(l);i[0]=u;var p={};for(var m in e)hasOwnProperty.call(e,m)&&(p[m]=e[m]);p.originalType=t,p.mdxType="string"==typeof t?t:r,i[1]=p;for(var d=2;d=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var u=n.createContext({}),s=function(e){var t=n.useContext(u),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},c=function(e){var t=s(e.components);return n.createElement(u.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,l=e.originalType,u=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),m=s(r),d=a,f=m["".concat(u,".").concat(d)]||m[d]||p[d]||l;return r?n.createElement(f,o(o({ref:t},c),{},{components:r})):n.createElement(f,o({ref:t},c))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=r.length,o=new Array(l);o[0]=m;var i={};for(var u in t)hasOwnProperty.call(t,u)&&(i[u]=t[u]);i.originalType=e,i.mdxType="string"==typeof e?e:a,o[1]=i;for(var s=2;sHello {0}", name];\n')),(0,l.kt)("h2",{id:"83-\u8bbe\u7f6e\u5f53\u524d\u8bed\u8a00"},"8.3 \u8bbe\u7f6e\u5f53\u524d\u8bed\u8a00"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'L.SetCulture("en-US");\n')),(0,l.kt)("h2",{id:"84-\u83b7\u53d6\u7cfb\u7edf\u8bed\u8a00\u5217\u8868"},"8.4 \u83b7\u53d6\u7cfb\u7edf\u8bed\u8a00\u5217\u8868"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var list = L.GetCultures();\n")),(0,l.kt)("h2",{id:"85-\u83b7\u53d6\u5f53\u524d\u9009\u4e2d\u8bed\u8a00"},"8.5 \u83b7\u53d6\u5f53\u524d\u9009\u4e2d\u8bed\u8a00"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var list = L.GetSelectCulture();\n")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/4c19669a.b0ff1dc3.js b/handbook/build/assets/js/4c19669a.b0ff1dc3.js deleted file mode 100644 index c9121c24d1..0000000000 --- a/handbook/build/assets/js/4c19669a.b0ff1dc3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[6078],{5760:function(e,t,r){r.r(t),r.d(t,{assets:function(){return c},contentTitle:function(){return u},default:function(){return d},frontMatter:function(){return i},metadata:function(){return s},toc:function(){return p}});var n=r(3117),a=r(102),l=(r(7294),r(3905)),o=["components"],i={id:"l",title:"8. L \u9759\u6001\u7c7b",sidebar_label:"8. L \u9759\u6001\u7c7b"},u=void 0,s={unversionedId:"global/l",id:"global/l",title:"8. L \u9759\u6001\u7c7b",description:"8.1 \u8f6c\u6362\u6587\u672c\u591a\u8bed\u8a00",source:"@site/docs/global/l.mdx",sourceDirName:"global",slug:"/global/l",permalink:"/furion/docs/global/l",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/global/l.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"l",title:"8. L \u9759\u6001\u7c7b",sidebar_label:"8. L \u9759\u6001\u7c7b"},sidebar:"global",previous:{title:"7. JsonSerializerUtility \u9759\u6001\u7c7b",permalink:"/furion/docs/global/jsonserializer"},next:{title:"9. MessageCenter \u9759\u6001\u7c7b",permalink:"/furion/docs/global/messagecenter"}},c={},p=[{value:"8.1 \u8f6c\u6362\u6587\u672c\u591a\u8bed\u8a00",id:"81-\u8f6c\u6362\u6587\u672c\u591a\u8bed\u8a00",level:2},{value:"8.2 \u8f6c\u6362 Html \u591a\u8bed\u8a00",id:"82-\u8f6c\u6362-html-\u591a\u8bed\u8a00",level:2},{value:"8.3 \u8bbe\u7f6e\u5f53\u524d\u8bed\u8a00",id:"83-\u8bbe\u7f6e\u5f53\u524d\u8bed\u8a00",level:2},{value:"8.4 \u83b7\u53d6\u7cfb\u7edf\u8bed\u8a00\u5217\u8868",id:"84-\u83b7\u53d6\u7cfb\u7edf\u8bed\u8a00\u5217\u8868",level:2},{value:"8.5 \u83b7\u53d6\u5f53\u524d\u9009\u4e2d\u8bed\u8a00",id:"85-\u83b7\u53d6\u5f53\u524d\u9009\u4e2d\u8bed\u8a00",level:2}],m={toc:p};function d(e){var t=e.components,r=(0,a.Z)(e,o);return(0,l.kt)("wrapper",(0,n.Z)({},m,r,{components:t,mdxType:"MDXLayout"}),(0,l.kt)("h2",{id:"81-\u8f6c\u6362\u6587\u672c\u591a\u8bed\u8a00"},"8.1 \u8f6c\u6362\u6587\u672c\u591a\u8bed\u8a00"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var apiInterface = L.Text["API \u63a5\u53e3"];\n')),(0,l.kt)("h2",{id:"82-\u8f6c\u6362-html-\u591a\u8bed\u8a00"},"8.2 \u8f6c\u6362 Html \u591a\u8bed\u8a00"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var name = L.Html["Hello {0}", name];\n')),(0,l.kt)("h2",{id:"83-\u8bbe\u7f6e\u5f53\u524d\u8bed\u8a00"},"8.3 \u8bbe\u7f6e\u5f53\u524d\u8bed\u8a00"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'L.SetCulture("en-US");\n')),(0,l.kt)("h2",{id:"84-\u83b7\u53d6\u7cfb\u7edf\u8bed\u8a00\u5217\u8868"},"8.4 \u83b7\u53d6\u7cfb\u7edf\u8bed\u8a00\u5217\u8868"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var list = L.GetCultures();\n")),(0,l.kt)("h2",{id:"85-\u83b7\u53d6\u5f53\u524d\u9009\u4e2d\u8bed\u8a00"},"8.5 \u83b7\u53d6\u5f53\u524d\u9009\u4e2d\u8bed\u8a00"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var list = L.GetSelectCulture();\n")))}d.isMDXComponent=!0},3905:function(e,t,r){r.d(t,{Zo:function(){return c},kt:function(){return d}});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var u=n.createContext({}),s=function(e){var t=n.useContext(u),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},c=function(e){var t=s(e.components);return n.createElement(u.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,l=e.originalType,u=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),m=s(r),d=a,f=m["".concat(u,".").concat(d)]||m[d]||p[d]||l;return r?n.createElement(f,o(o({ref:t},c),{},{components:r})):n.createElement(f,o({ref:t},c))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=r.length,o=new Array(l);o[0]=m;var i={};for(var u in t)hasOwnProperty.call(t,u)&&(i[u]=t[u]);i.originalType=e,i.mdxType="string"==typeof e?e:a,o[1]=i;for(var s=2;s());\n\npublic class XXXWebComponent : IWebComponent\n{\n public void Load(WebApplicationBuilder builder, ComponentContext componentContext)\n {\n // ....\n }\n}\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u7a0b\u5e8f\u96c6 ",(0,r.kt)("inlineCode",{parentName:"strong"},"PublicKeyToken")," \u5f3a\u7b7e\u540d")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/26b12c0fd64b153a71496eb62110567e05450f20"},"26b12c0")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},"\u4e8b\u4ef6\u603b\u7ebf ",(0,r.kt)("inlineCode",{parentName:"strong"},"IEventBusFactory")," \u4e8b\u4ef6\u5de5\u5382\u65b9\u6cd5 ",(0,r.kt)("inlineCode",{parentName:"strong"},"AddSubscriber -> Subscribe"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"strong"},"RemoveSubscriber -> Unsubscribe")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/commit/a29fc7cf63a3ea41b1617a6ad98a701a243e24f8"},"a29fc7c"))),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".AddInject()")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},".UseInject()")," \u914d\u7f6e\u9009\u9879\u540d\u79f0\uff0c\u79fb\u9664 ",(0,r.kt)("inlineCode",{parentName:"li"},"Configure")," \u540e\u7f00 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/b6953cd586936593e40ef626c3b8a1e770239e43"},"b6953cd")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},"\u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"strong"},"\u8bf7\u6c42\u62e6\u622a"),"\u3001",(0,r.kt)("inlineCode",{parentName:"strong"},"\u54cd\u5e94\u62e6\u622a")," \u548c ",(0,r.kt)("inlineCode",{parentName:"strong"},"\u5f02\u5e38\u62e6\u622a")," \u59d4\u6258\u7b7e\u540d\uff0c\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"strong"},"HttpClient")," \u53c2\u6570")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5OWBO"},"#I5OWBO"))))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,7,12}",showLineNumbers:!0,"{2,7,12}":!0},"[Interceptor(InterceptorTypes.Request)]\nstatic void OnRequest(HttpClient client, HttpRequestMessage req)\n{\n}\n\n[Interceptor(InterceptorTypes.Response)]\nstatic void OnResponsing(HttpClien client, HttpResponseMessage res)\n{\n}\n\n[Interceptor(InterceptorTypes.Exception)]\nstatic void OnException(HttpClient client, HttpResponseMessage res, string errors)\n{\n}\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u751f\u6210\u5305\u542b ",(0,r.kt)("inlineCode",{parentName:"li"},"\u4e2d\u6587")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT Token")," \u89e3\u5bc6\u540e\u51fa\u73b0\u4e71\u7801\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5O397"},"#I5O397")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," `HttpRequestMessage`` \u62d3\u5c55\u4e2d\u8ffd\u52a0\u67e5\u8be2\u53c2\u6570\u65f6\u7684\u7a7a\u5f15\u7528\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PENW"},"#I5PENW")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/547"},"!547")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u65e5\u5fd7\u6a21\u5757\u914d\u7f6e\u591a\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"IDatabaseLoggingWriter")," \u53ea\u6709\u4e00\u4e2a\u751f\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PFQ2"},"#I5PFQ2")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PFJ1"},"#I5PFJ1")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u9ed8\u8ba4\u8f93\u51fa\u6587\u4ef6\u65e5\u5fd7\u6a21\u677f\uff0c\u4f7f\u5176\u66f4\u52a0\u7f8e\u89c2 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/1518cf3be74524ed0d3f73360068a9a0ec6685d9"},"#1518cf3")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u9ed8\u8ba4\u89c4\u8303\u5316\u7ed3\u679c\u9a8c\u8bc1\u5904\u7406\u4e5f\u652f\u6301\u72b6\u6001\u7801\u8bbe\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/2eb939074a14d29fcd3e4726937c8a8430765f48"},"2eb9390")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugarCore")," \u62d3\u5c55\u5305\u548c\u811a\u624b\u67b6\u81f3 ",(0,r.kt)("inlineCode",{parentName:"li"},"5.1.2.6")," \u7248\u672c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PCXK"},"#I5PCXK")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON Schema")," \u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"li"},"LoggingMonitor")," \u66f4\u591a\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PFJ1"},"#I5PFJ1")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"RabbitMQ")," \u4e8b\u4ef6\u603b\u7ebf\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppSettings")," \u914d\u7f6e\u6587\u6863\u3001\u4e8b\u4ef6\u603b\u7ebf\u6587\u6863\u3001\u591a\u6570\u636e\u5e93\u914d\u7f6e\u6587\u6863\u3001\u65e5\u5fd7\u6587\u6863\u3001\u5b9a\u65f6\u4efb\u52a1\u6587\u6863\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"MessageCenter")," \u6587\u6863\u3001\u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863\u3001\u7ec4\u4ef6\u5316\u6587\u6863\u3001\u5165\u95e8\u6307\u5357\u3001\u591a\u8bed\u8a00\u6587\u6863\u3002")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v4213\u5df2\u53d1\u5e03"},"v4.2.13\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},"\u4e8b\u4ef6\u603b\u7ebf\u5de5\u5382\uff0c\u652f\u6301\u8fd0\u884c\u65f6\u52a8\u6001\u6dfb\u52a0\u8ba2\u9605\u7a0b\u5e8f\u548c\u79fb\u9664\u8ba2\u9605\u7a0b\u5e8f")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5NNQX"},"#I5NNQX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},"\u4e8b\u4ef6\u603b\u7ebf ",(0,r.kt)("inlineCode",{parentName:"strong"},"[EventSubscribe]")," \u4e8b\u4ef6 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Id")," \u652f\u6301\u6b63\u5219\u8868\u8fbe\u5f0f\u5339\u914d")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5NNQX"},"#I5NNQX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},"\u4e8b\u4ef6\u603b\u7ebf ",(0,r.kt)("inlineCode",{parentName:"strong"},"[EventSubscribe]")," \u652f\u6301\u5c40\u90e8\u5931\u8d25\u91cd\u8bd5\u914d\u7f6e")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5NNQX"},"#I5NNQX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Log")," \u5168\u5c40\u9759\u6001\u7c7b\uff0c\u65b9\u4fbf\u968f\u65f6\u968f\u5730\u8bb0\u5f55\u65e5\u5fd7")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/ba9b1f13a0b89b6670cf7078ac15abe0eed1f2c3"},"ba9b1f1")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4e8b\u4ef6\u603b\u7ebf ",(0,r.kt)("inlineCode",{parentName:"li"},"options.AddSubscriber(Type)")," \u91cd\u8f7d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/blob/424460780b630e1c71de4db84ad8fd14e33a09f5/framework/Furion.Pure/EventBus/Builders/EventBusOptionsBuilder.cs"},"42446078")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationMetadata")," \u7c7b\u578b ",(0,r.kt)("inlineCode",{parentName:"li"},"FirstErrorProperty")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"FirstErrorMessage")," \u5c5e\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MFJT"},"#I5MFJT")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u6a21\u5f0f ",(0,r.kt)("inlineCode",{parentName:"li"},"WithArgs(args)")," \u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MOJB"},"#I5MOJB")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[UnitOfWork]")," \u5206\u5e03\u5f0f\u4e8b\u52a1 ",(0,r.kt)("inlineCode",{parentName:"li"},"TransactionScope")," \u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MRTY"},"#I5MRTY")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," 16 \u4f4d ",(0,r.kt)("inlineCode",{parentName:"li"},"MD5")," \u52a0\u5bc6\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5N8RC"},"#I5N8RC")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u5f02\u6b65\u521b\u5efa\u4f5c\u7528\u57df\u65b9\u6cd5\u540d\u79f0\uff0c\u907f\u514d\u4e00\u4e9b\u60c5\u51b5\u4e0b\u65e0\u6cd5\u533a\u5206\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u540c\u6b65\u65b9\u6cd5\u4e0d\u53d8")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5N9XY"},"#I5N9XY"))))),(0,r.kt)("p",null,"\u7531\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-2}",showLineNumbers:!0,"{1-2}":!0},"// Scoped.CreateUow \u4e00\u6837\nawait Scoped.Create(async (f, s) => {});\n")),(0,r.kt)("p",null,"\u6539\u4e3a\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-2}",showLineNumbers:!0,"{1-2}":!0},"// Scoped.CreateUowAsync \u4e00\u6837\nawait Scoped.CreateAsync(async (f, s) => {});\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"[\u652f\u6301]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".NET 6.0.8")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},".NET 7 Preview 7")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/842d4f739c92366e05fb1d2c619c9b2c2c2c21b7"},"842d4f7")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u547d\u540d\u7a7a\u95f4\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"System"),"\uff0c\u56e0\u4e3a\u4f7f\u7528\u9891\u7387\u8d8a\u6765\u8d8a\u9ad8 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/b879861c9db5cf3cb0f4ae023d1e96b06fad3e46"},"b879861")),(0,r.kt)("li",{parentName:"ul"},"[\u6dfb\u52a0]"," ",(0,r.kt)("strong",{parentName:"li"},"\u5728\u975e ",(0,r.kt)("inlineCode",{parentName:"strong"},"Web")," \u73af\u5883\u4e2d\u4e0d\u6b63\u786e\u4f7f\u7528\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u6cd5\u68c0\u6d4b\u673a\u5236")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6389cbdd69f5ca826fad25749a45ede079db98ce"},"6389cbd")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},"\u6240\u6709 ",(0,r.kt)("inlineCode",{parentName:"strong"},".Default")," \u9759\u6001\u5c5e\u6027\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},".Default()")," \u65b9\u6cd5")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6389cbdd69f5ca826fad25749a45ede079db98ce"},"6389cbd")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},"\u5de5\u4f5c\u5355\u5143 ",(0,r.kt)("inlineCode",{parentName:"strong"},"IUnitOfWork")," \u6240\u6709\u65b9\u6cd5\u53c2\u6570\u7c7b\u578b\uff0c\u7531 ",(0,r.kt)("inlineCode",{parentName:"strong"},"ActionExecutingContext")," \u548c ",(0,r.kt)("inlineCode",{parentName:"strong"},"ActionExecutedContext")," \u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},"FilterContext"))," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MHX5"},"#I5MHX5"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5,7,9}",showLineNumbers:!0,"{3,5,7,9}":!0},"public interface IUnitOfWork\n{\n void BeginTransaction(FilterContext context, UnitOfWorkAttribute unitOfWork);\n\n void CommitTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork);\n\n void RollbackTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork);\n\n void OnCompleted(FilterContext context, FilterContext resultContext);\n}\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u65e5\u5fd7\u4e0a\u4e0b\u6587\u6570\u636e\u591a\u6b21\u5199\u5165\u88ab\u6e05\u7a7a\u95ee\u9898\u4ee5\u53ca\u6570\u636e\u5e93\u65e5\u5fd7\u51fa\u73b0\u5f02\u5e38\u540e\u505c\u6b62\u5199\u5165 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5LIWF"},"#I5LIWF")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e2a\u522b\u60c5\u51b5\u4e0b\u8de8\u57df\u9ed8\u8ba4\u914d\u7f6e\u7684\u54cd\u5e94\u7f13\u5b58\u5bfc\u81f4\u5d4c\u5165\u5f0f\u8d44\u6e90\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/7a57efe15a9a2d76475d758f2b64395f96d94077"},"7a57efe")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u4f20\u5165\u4e0d\u5408\u6cd5\u7684\u8bf7\u6c42\u62a5\u6587\u5934\u6570\u636e\u89e6\u53d1\u6821\u9a8c\u5931\u8d25\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5LPFE"},"#I5LPFE")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u7ebf\u7a0b\u4e2d\u4f7f\u7528\u9759\u6001\u65e5\u5fd7\u5199\u6570\u636e\u5e93\u65e5\u5fd7\u5bfc\u81f4\u8fde\u63a5\u6c60\u8017\u5149\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/8d5cdd6ca04d55e33322000ecc176e47195b6f4d"},"8d5cdd6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore 6.0")," \u4e4b\u540e ",(0,r.kt)("inlineCode",{parentName:"li"},"IModelCacheKeyFactory")," \u63a5\u53e3\u65b9\u6cd5\u6539\u53d8\u5bfc\u81f4\u5206\u8868\u5206\u5e93\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MCZ6"},"#I5MCZ6")," ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/dotnet/efcore/issues/25154#issuecomment-868804532"},"EFCore#25154")," ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/dotnet/EntityFramework.Docs/pull/3305"},"EFCore!3305")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationMetadata")," \u5bf9\u8c61 ",(0,r.kt)("inlineCode",{parentName:"li"},"Message")," \u5b57\u7b26\u4e32\u7c7b\u578b\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},'\\"\\"')," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MFJT"},"#I5MFJT")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[IfException]")," \u8986\u76d6 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Oh/Bah")," \u9519\u8bef\u6d88\u606f\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4bbd854c6779bf7eca26fd69b25c4979b8cec32d"},"4bbd854")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u65e5\u5fd7\u5199\u5165\u5faa\u73af\u5199\u5165\u548c\u9891\u7e41\u521b\u5efa\u6570\u636e\u5e93\u8fde\u63a5\u6c60\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/9ce214c9cf49eb1ff59f3c52dbecd789be4f45fd"},"9ce214c")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Razor Pages")," \u4e0d\u652f\u6301\u5168\u5c40\u5f02\u5e38\u62e6\u622a\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MHX5"},"#I5MHX5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Razor Pages")," \u4e0d\u652f\u6301\u5168\u5c40\u6570\u636e\u9a8c\u8bc1\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MHX5"},"#I5MHX5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Razor Pages")," \u4e0d\u652f\u6301\u5de5\u4f5c\u5355\u5143 ",(0,r.kt)("inlineCode",{parentName:"li"},"[UnitOfWork]")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MHX5"},"#I5MHX5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Razor Pages")," \u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u81ea\u52a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"SaveChanges")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MHX5"},"#I5MHX5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Blazor Server")," \u56e0 ",(0,r.kt)("inlineCode",{parentName:"li"},"v4.2.2")," \u7248\u672c\u66f4\u65b0\u5bfc\u81f4\u7684\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MNFN"},"#I5MNFN")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[IfException]")," \u4e0d\u652f\u6301\u591a\u8bed\u8a00\u914d\u7f6e\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MPN7"},"#I5MPN7")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddMvcFilter()")," \u65b9\u5f0f\u6ce8\u518c\u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/8d1477d8b44ae111bddb8e4780672bcaf4e0e467"},"8d1477d")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e8b\u4ef6\u603b\u7ebf\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Channel")," \u7ba1\u9053\u521d\u59cb\u5316\u65f6\u673a\u8fc7\u665a\u95ee\u9898\uff0c\u89e3\u51b3\u90e8\u5206\u7b2c\u4e09\u65b9\u4f9d\u8d56\u4f7f\u7528\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MM3O"},"#I5MM3O")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e3b\u673a\u505c\u6b62\u65f6\u5199\u5165\u65e5\u5fd7\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5N7S2"},"#I5N7S2")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u624b\u52a8\u91ca\u653e\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},"AutoSaveChange")," \u7279\u6027\u51fa\u73b0\u91ca\u653e\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5NFWC"},"#I5NFWC")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u5faa\u73af\u5f15\u7528\u5e8f\u5217\u5316\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5NRT9"},"#I5NRT9")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u4f20\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"null")," Body \u53c2\u6570\u629b\u51fa\u7a7a\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5NTUE"},"#I5NTUE")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e8b\u4ef6\u603b\u7ebf\u9ed8\u8ba4\u5f00\u542f\u6a21\u7cca\u5339\u914d\uff08\u6b63\u5219\u8868\u8fbe\u5f0f\uff09\u5bfc\u81f4\u4e0d\u5fc5\u8981\u7684\u8ba2\u9605 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5NVOP"},"#I5NVOP")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u4e8b\u4ef6\u603b\u7ebf\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Channel")," \u7ba1\u9053\u521d\u59cb\u5316\u65f6\u673a\uff0c\u89e3\u51b3\u90e8\u5206\u7b2c\u4e09\u65b9\u4f9d\u8d56\u4f7f\u7528\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MM3O"},"#I5MM3O")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u5e95\u5c42\u8fed\u4ee3\u6539\u8fdb\u4f18\u5316"),(0,r.kt)("li",{parentName:"ul"},"[\u516c\u5f00]"," \u89c4\u8303\u5316\u6587\u6863\u83b7\u53d6\u63a7\u5236\u5668\u3001\u65b9\u6cd5\u5206\u7ec4\u3001\u6807\u7b7e\u4fe1\u606f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/66d8d54b225b5294cd54aa76b548312f7c37903a"},"66d8d54")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u65e5\u5fd7\u9759\u6001\u7c7b ",(0,r.kt)("inlineCode",{parentName:"li"},"Log")," \u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/ba9b1f13a0b89b6670cf7078ac15abe0eed1f2c3"},"ba9b1f1")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Nuget")," \u672c\u5730\u6d4b\u8bd5\u5305\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u65e5\u5fd7\u6587\u6863\u3001\u9759\u6001\u7c7b\u6587\u6863\u3001\u6570\u636e\u6821\u9a8c\u6587\u6863\u3001Worker Service \u6587\u6863\u3001\u5de5\u4f5c\u5355\u5143\u6587\u6863\u3001\u4f9d\u8d56\u6ce8\u5165\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v4114\u5df2\u53d1\u5e03"},"v4.1.14\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Furion.Xunit")," \u62d3\u5c55\u5305\uff0c\u6b63\u5f0f\u5b9e\u73b0 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Xunit")," \u5355\u5143\u6d4b\u8bd5\u5b8c\u6574\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/commit/063a034edd089e88d501af4c09251611476fd238"},"063a034e"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddMonitorLogging()")," \u65e5\u5fd7\u76d1\u89c6\u5668\u670d\u52a1\uff0c\u652f\u6301\u975e\u5e38\u7075\u6d3b\u7684\u65e5\u5fd7\u64cd\u4f5c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/81df742b2784a18fbf4060fe30cc5151909c3cab"},"81df742")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Serve.Run(silence: true)")," \u7b49\u4e00\u7cfb\u5217\u5f3a\u5927\u7684\u9759\u9ed8\u542f\u52a8\u529f\u80fd ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I5JBSQ"},"#I5JBSQ")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I5J98T"},"#I5J98T")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/commit/7cced443ca1cdcb29226c71274e087ec2a6135ef"},"7cced4"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationDocumentBuilder.GetOpenApiGroups()")," \u65b9\u6cd5\u83b7\u53d6\u5e95\u5c42\u7684\u89c4\u8303\u5316\u63a5\u53e3\u5206\u7ec4\u4fe1\u606f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4ff03c5f8342c4d9b26fb1336cd78936ab189f5e"},"4ff03c5")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"logger.ScopeContext()")," \u914d\u7f6e\u65e5\u5fd7\u4e0a\u4e0b\u6587\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5JC0D"},"#I5JC0D")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8de8\u57df\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"CorsAccessorSettings.SignalRSupport")," \u914d\u7f6e\u9009\u9879\uff0c\u652f\u6301\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"SignalR")," \u8de8\u57df ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5JREM"},"#I5JREM")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4e8b\u4ef6\u603b\u7ebf ",(0,r.kt)("inlineCode",{parentName:"li"},"UseUtcTimestamp")," \u9009\u9879\u914d\u7f6e\uff0c\u53ef\u9009\u62e9\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTime.UtcNow")," \u8fd8\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTime.Now"),"\uff0c\u9ed8\u8ba4\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTime.Now")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5JSEU"},"#I5JSEU")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c4\u8303\u5316\u6587\u6863 ",(0,r.kt)("inlineCode",{parentName:"li"},"[OperationId]")," \u914d\u7f6e\uff0c\u89e3\u51b3\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger UI")," \u4e0d\u80fd\u6b63\u786e\u663e\u793a\u8def\u7531\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5K1IB"},"#I5K1IB")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"IHttpDispatchProxy")," \u65b9\u5f0f\u5168\u5c40\u62e6\u622a\u652f\u6301\u591a\u6001\uff08\u7ee7\u627f\uff09 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5K8FS"},"#I5K8FS")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Xunit")," \u62d3\u5c55\u5305\uff0c\u6b63\u5f0f\u5b9e\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Xunit")," \u5355\u5143\u6d4b\u8bd5\u5b8c\u6574\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/063a034edd089e88d501af4c09251611476fd238"},"063a034e")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.DatabaseAccessor.SqlSugar")," \u62d3\u5c55\u63d2\u4ef6\u4e2d\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"[SqlSugarUnitOfWork]")," \u5de5\u4f5c\u5355\u5143\u7279\u6027\uff0c\u5c06\u4f7f\u7528\u901a\u7528\u5de5\u4f5c\u5355\u5143\u66ff\u6362\uff0c",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("a",{parentName:"strong",href:"/furion/docs/tran#92631-%E8%87%AA%E5%8A%A8%E7%AE%A1%E7%90%86"},"\u67e5\u770b\u6700\u65b0\u5b9e\u73b0\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Inject.Create()")," \u65b9\u6cd5\uff0c\u518d\u4e5f\u4e0d\u9700\u8981\u4e86\uff0c\u6846\u67b6\u63d0\u4f9b\u4e86\u65e0\u654c\u5f3a\u5927\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u9759\u9ed8\u542f\u52a8\u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/200848eda8c2e419c0b5be83f7768a257f3c88bd"},"200848e")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ConfigureConfiguration")," \u65b9\u6cd5\u53c2\u6570\uff0c\u7531 ",(0,r.kt)("inlineCode",{parentName:"li"},"configuration => {}")," \u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"(environment, configuration) => {}")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/83c97bb5a19d6fc4e51cfe05f635675d26067d45"},"83c97bb"))))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6}",showLineNumbers:!0,"{2,6}":!0},"// \u7531\nServe.Run(RunOptions.Default.ConfigureConfiguration(configuration => {\n\n}));\n// \u6539\u4e3a\uff1a\nServe.Run(RunOptions.Default.ConfigureConfiguration((environment, configuration) => {\n\n}));\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u5f02\u5e38\u6d88\u606f\u65e5\u5fd7\u7ea7\u522b\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Information")," \u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/ab46cdf534433f45d39ce4d3ee7c71ca84707140"},"ab46cdf")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u65b0\u7248\u672c\u65e5\u5fd7\u7ec4\u4ef6\u9891\u7e41\u63d0\u793a\u6587\u4ef6\u5360\u7528\u95ee\u9898\uff0c\u5c06\u6587\u4ef6\u72ec\u5360\u9501\u6539\u4e3a\u5171\u4eab\u9501 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5J3S6"},"#I5J3S6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u914d\u7f6e\u6570\u636e\u5e93\u65e5\u5fd7\u8bfb\u5199\u5668\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u65f6\u63a7\u5236\u53f0\u51fa\u73b0\u65e0\u9650\u6253\u5370\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5J474"},"#I5J474")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u9488\u5bf9 ",(0,r.kt)("inlineCode",{parentName:"li"},"byte[]")," \u7c7b\u578b\u53c2\u6570\u8f93\u51fa\u8fc7\u5927\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/5380f3551de69f8607ca0fc33c950103c7ed8174"},"5380f35")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u53cb\u597d\u5f02\u5e38\u548c\u89c4\u8303\u5316\u7ed3\u679c\u4e22\u5931\u4e86\u539f\u59cb ",(0,r.kt)("inlineCode",{parentName:"li"},"ErrorCode")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5IX2R"},"#I5IX2R")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u65b0\u7248\u672c\u65e5\u5fd7\u7ec4\u4ef6\u81ea\u5b9a\u4e49\u6570\u636e\u5e93\u8bfb\u5199\u5668\u6ce8\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"IRepository")," \u4ed3\u50a8\u5bfc\u81f4\u6b7b\u5faa\u73af\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5IX2R"},"#I5IX2R")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mvc")," \u9ed8\u8ba4\u624b\u52a8\u9a8c\u8bc1\u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u5168\u5c40\u9a8c\u8bc1\u51b2\u7a81\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/2a06c39c1d0a032bbc317e25a22c646babce2a60"},"2a06c39")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u6a21\u5f0f\u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"SuperSocket")," \u7b2c\u4e09\u65b9\u5305\u95ee\u9898\uff0c\u539f\u751f\u662f\u652f\u6301\u7684\u3002",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/186ca0a35d696f58d9e696094848a560074cdf6f"},"186ca0a")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SignalR")," \u8de8\u57df\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5JREM"},"#I5JREM")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u5c06 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Oh")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Bah")," \u8bb0\u5f55\u5230\u4e86\u9519\u8bef\u65e5\u5fd7\u4e2d\uff0c\u9ed8\u8ba4\u5e94\u8be5\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"Information")," \u4e14\u63d0\u4f9b\u53ef\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5JZ1H"},"#I5JZ1H")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger UI")," \u4e4b\u540e\u4e2a\u522b ",(0,r.kt)("inlineCode",{parentName:"li"},"UI")," \u8981\u6c42\u5fc5\u987b\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"operationId"),"\uff0c\u5426\u5219\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"guid")," \u5e8f\u53f7 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5K1IB"},"#I5K1IB")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e3b\u52a8\u629b\u51fa ",(0,r.kt)("inlineCode",{parentName:"li"},"NotFoundResult")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"NotFoundObjectResult")," \u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5KALZ"},"#I5KALZ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u89e3\u6790\u65b9\u6cd5\u53c2\u6570\u4f46\u524d\u7aef\u672a\u4f20\u5165\u65f6\u51fa\u73b0\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5KC5P"},"#I5KC5P")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u65e0\u6cd5\u5e8f\u5217\u5316 ",(0,r.kt)("inlineCode",{parentName:"li"},"IQueryable")," \u8fd4\u56de\u503c\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5KJD1"},"#I5KJD1")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u4e0d\u80fd\u8bb0\u5f55\u5168\u5c40\u9a8c\u8bc1\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/b44087dcc7dbe9992b8f4518e0b0cf4ed61c56bb"},"b44087d")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u5b58\u5728\u6ce8\u518c\u987a\u5e8f\u5dee\u5f02\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/b44087dcc7dbe9992b8f4518e0b0cf4ed61c56bb"},"b44087d")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5f00\u653e]"," \u5e95\u5c42\u7684\u89c4\u8303\u5316\u6587\u6863 ",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationDocumentBuilder")," \u90e8\u5206\u65b9\u6cd5\uff0c\u63d0\u4f9b\u66f4\u52a0\u4fbf\u6377\u7684\u7b2c\u4e09\u65b9 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger UI")," \u96c6\u6210 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/10f0f01996586eedb138304c7b00c6f31282dfeb"},"10f0f01")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u5355\u5143\u6d4b\u8bd5\u6587\u6863\u3001\u5165\u95e8\u6307\u5357\u6587\u6863\u3001Worker Services \u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u5f7b\u5f7b\u5e95\u5e95\u652f\u6301\u5168\u5e73\u53f0\uff0c\u63d0\u4f9b\u975e\u5e38\u5f3a\u5927\u7684\u9759\u9ed8\u6a21\u5f0f")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u542f\u7528\u9759\u9ed8\u6a21\u5f0f\u53ef\u4ee5\u5b9e\u73b0\u65e0\u963b\u585e\u65b9\u5f0f\u6267\u884c\u7a0b\u5e8f\uff0c\u800c\u4e14\u8fd8\u80fd\u4f53\u9a8c\u5b8c\u6574\u7684 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u529f\u80fd\u3002")),(0,r.kt)("admonition",{title:"\u5927\u9769\u547d",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"\u6709\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"Serve.Run()")," \u9759\u9ed8\u6a21\u5f0f\u540e\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u5f7b\u5f7b\u5e95\u5e95\u652f\u6301\u5168\u5e73\u53f0\uff0c\u4e0d\u7ba1\u4f60\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"\u63a7\u5236\u53f0\u3001Web\u3001\u684c\u9762\u3001\u79fb\u52a8\u3001\u5355\u5143\u6d4b\u8bd5\uff0c\u96c6\u6210\u6d4b\u8bd5\uff0c\u57fa\u51c6\u6d4b\u8bd5\u7b49\u7b49\u5e94\u7528\u7a0b\u5e8f"),"\u3002")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3}",showLineNumbers:!0,"{1,3}":!0},'Serve.Run(silence: true);\n\n// \u4e0d\u4f1a\u963b\u585e\u6267\u884c\u54e6\uff0c\u800c\u4e14\u4ece\u8fd9\u91cc\u5f00\u59cb\u53ef\u4ee5\u4f7f\u7528 Furion \u4efb\u4f55\u529f\u80fd\uff0c\u6bd4\u5982 App.Configuration....\nConsole.WriteLine("Hello, World!");\nConsole.ReadKey();\n')),(0,r.kt)("p",null,"\u8fd8\u6709\u66f4\u591a\u9759\u9ed8\u6a21\u5f0f\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,8}",showLineNumbers:!0,"{2,5,8}":!0},"// RunOptions \u65b9\u5f0f\nServe.Run(RunOptions.DefaultSilence);\n\n// LegacyRunOptions \u65b9\u5f0f\nServe.Run(LegacyRunOptions.DefaultSilence);\n\n// GenericRunOptions \u65b9\u5f0f\nServe.Run(GenericRunOptions.DefaultSilence);\n")),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},"\u5f3a\u5927\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Xunit")," \u5355\u5143\u6d4b\u8bd5\u3001\u96c6\u6210\u6d4b\u8bd5")),(0,r.kt)("admonition",{title:"\u5927\u9769\u547d",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"\u5355\u5143\u6d4b\u8bd5\u548c\u96c6\u6210\u6d4b\u8bd5\u662f\u4fdd\u8bc1\u4e00\u4e2a\u7cfb\u7edf\u80fd\u591f\u6301\u7eed\u7ef4\u62a4\u548c\u7a33\u5b9a\u8fd0\u884c\u7684\u5fc5\u5907\u6280\u80fd\uff0c\u4f46\u662f\u76ee\u524d\u73b0\u6709\u7684\u5355\u5143\u6d4b\u8bd5\u7ec4\u4ef6\u65e0\u6cd5\u76f4\u63a5\u96c6\u6210 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u7684\u529f\u80fd\uff0c\u6700\u5e38\u7528\u7684\u5c31\u662f\u5982\u4f55\u5728\u5355\u5143\u6d4b\u8bd5\u4e2d\u8bfb\u53d6\u914d\u7f6e\uff0c\u4ee5\u53ca",(0,r.kt)("strong",{parentName:"p"},"\u5982\u4f55\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165"),"\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u5728\u8fc7\u53bb\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u53ea\u80fd\u4e0d\u65ad\u7684\u53bb\u8c03\u6574\uff0c\u4ee5\u81f3\u4e8e\u9002\u914d\u7b2c\u4e09\u65b9\u5355\u5143\u6d4b\u8bd5\u5199\u6cd5\uff0c\u641e\u5f97\u4e0d\u4f26\u4e0d\u7c7b\uff01"),(0,r.kt)("p",{parentName:"admonition"},"\u6240\u4ee5\uff0c\u8fd9\u4e00\u6b21\u4e0d\u518d\u59a5\u534f\uff0c",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u63a8\u51fa\u81ea\u5df1\u7684\u5355\u5143\u6d4b\u8bd5\u5de5\u5177\uff0c\u53ef\u4ee5\u8ba9\u73b0\u6709\u7684\u5355\u5143\u6d4b\u8bd5\u5982 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Xunit")," 100% \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u6240\u6709\u529f\u80fd\uff0c\u5168\u90e8\u4fdd\u8bc1\u4e00\u81f4\u7684\u5199\u6cd5\u3002"))),(0,r.kt)("p",null,"\u5355\u5143\u6d4b\u8bd5\u4e2d\u521d\u59cb\u5316 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,13,18}",showLineNumbers:!0,"{6,13,18}":!0},'using Furion.Xunit;\nusing Xunit.Abstractions;\nusing Xunit.Sdk;\n\n// \u914d\u7f6e\u542f\u52a8\u7c7b\u7c7b\u578b\uff0c\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f TestProgram \u7c7b\u5b8c\u6574\u9650\u5b9a\u540d\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f\u5f53\u524d\u9879\u76ee\u7a0b\u5e8f\u96c6\u540d\u79f0\n[assembly: TestFramework("TestProject1.TestProgram", "TestProject1")]\n\nnamespace TestProject1;\n\n/// \n/// \u5355\u5143\u6d4b\u8bd5\u542f\u52a8\u7c7b\n/// \npublic class TestProgram : TestStartup\n{\n public TestProgram(IMessageSink messageSink) : base(messageSink)\n {\n // \u521d\u59cb\u5316 Furion\n Serve.Run(silence: true);\n }\n}\n')),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u6d4b\u8bd5\u7c7b\u652f\u6301\u5b8c\u6574\u4f9d\u8d56\u6ce8\u5165")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,15}",showLineNumbers:!0,"{9,15}":!0},"using TestProject1.Services;\nusing Xunit;\n\nnamespace TestProject1;\n\npublic class UnitTest1\n{\n private readonly ICalcService _calcService;\n public UnitTest1(ICalcService calcService)\n {\n _calcService = calcService;\n }\n\n [Fact]\n public void \u6d4b\u8bd5\u4e24\u4e2a\u6570\u7684\u548c()\n {\n Assert.Equal(3, _calcService.Plus(1, 2));\n }\n}\n")),(0,r.kt)("img",{src:(0,l.Z)("img/ut9.png")}),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"/furion/docs/unittest"},"\u67e5\u770b\u65b0\u7248\u672c\u5355\u5143\u6d4b\u8bd5\u6587\u6863"))),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},"\u5f00\u653e\u5e95\u5c42\u89c4\u8303\u5316\u6587\u6863\u5206\u7ec4\u63a5\u53e3\uff0c\u4f7f\u5f97\u96c6\u6210\u7b2c\u4e09\u65b9 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger UI")," \u66f4\u52a0\u5bb9\u6613\uff0c\u5982\u96c6\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"IGeekFan.AspNetCore.Knife4jUI")," \u62d3\u5c55\uff1a")),(0,r.kt)("admonition",{title:"\u5b89\u88c5\u5305",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u53ea\u9700\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"YourPoject.Web.Core")," \u5c42\u5b89\u88c5 ",(0,r.kt)("inlineCode",{parentName:"p"},"IGeekFan.AspNetCore.Knife4jUI")," \u5373\u53ef\u3002")),(0,r.kt)("p",null,"3.1.1 ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"Knife4jUI")," \u72ec\u7acb\u7248\u672c\u914d\u7f6e")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,12}",showLineNumbers:!0,"{1,3,12}":!0},'var routePrefix = "api"; // \u5b9a\u4e49 swagger \u8def\u7531\u5730\u5740\uff0c\u5982\u679c\u662f\u8ddf\u76ee\u5f55\uff0c\u8bbe\u7f6e string.Empty \u5373\u53ef\n\napp.UseKnife4UI(options =>\n{\n options.RoutePrefix = routePrefix; // \u914d\u7f6e Knife4UI \u8def\u7531\u5730\u5740\n foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())\n {\n options.SwaggerEndpoint("/" + groupInfo.RouteTemplate, groupInfo.Title);\n }\n});\n\napp.UseInject(routePrefix); // \u914d\u7f6e Furion \u8def\u7531\u5730\u5740\n')),(0,r.kt)("p",null,"3.1.2 ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"Knife4jUI")," \u548c ",(0,r.kt)("inlineCode",{parentName:"strong"},"Swagger")," \u5171\u5b58\u7248\u672c\u914d\u7f6e")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,10}",showLineNumbers:!0,"{1,3,10}":!0},'app.UseKnife4UI(options =>\n{\n options.RoutePrefix = "newapi"; // \u914d\u7f6e Knife4UI \u8def\u7531\u5730\u5740\uff0c\u73b0\u5728\u662f /newapi\n foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())\n {\n options.SwaggerEndpoint("/" + groupInfo.RouteTemplate, groupInfo.Title);\n }\n});\n\napp.UseInject(); // Furion \u9ed8\u8ba4 api \u5730\u5740\u4e3a /api\n')),(0,r.kt)("img",{src:(0,l.Z)("img/sg20.png")}),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u5982\u9700\u5b9e\u73b0\u767b\u5f55\u4e4b\u540e\u81ea\u52a8\u5c06 ",(0,r.kt)("inlineCode",{parentName:"strong"},"token")," \u6dfb\u52a0\u5230\u5934\u90e8\u53ef\u5728\u767b\u5f55\u63a5\u53e3 ",(0,r.kt)("inlineCode",{parentName:"strong"},"AfterScript")," \u6267\u884c\u4ee5\u4e0b\u4ee3\u7801\uff1a")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},'ke.global.setAllHeader(\n "Authorization",\n "Bearer " + ke.response.headers["access-token"]\n);\n')),(0,r.kt)("img",{src:(0,l.Z)("img/kni.jpg")}),(0,r.kt)("ol",{start:4},(0,r.kt)("li",{parentName:"ol"},"\u63d0\u4f9b\u5f3a\u5927\u7684\u65e5\u5fd7\u4e0a\u4e0b\u6587\u529f\u80fd")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6,12}",showLineNumbers:!0,"{2,6,12}":!0},'// \u5199\u6cd5\u4e00\n_logger.ScopeContext(ctx => ctx.Set("Name", "Furion").Set("UserId", 10))\n .LogInformation("\u6211\u662f\u4e00\u4e2a\u65e5\u5fd7 {id}", 20);\n\n// \u5199\u6cd5\u4e8c\n_logger.ScopeContext(new Dictionary {\n { "Name", "Furion" },\n { "UserId", 10 }\n}).LogInformation("\u6211\u662f\u4e00\u4e2a\u65e5\u5fd7 {id}", 20);\n\n// \u5199\u6cd5\u4e09\n_logger.ScopeContext(new LogContext {\n // ....\n}).LogInformation("\u6211\u662f\u4e00\u4e2a\u65e5\u5fd7 {id}", 20)\n')),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v400\u91cd\u65b0\u8d77\u822a"},"v4.0.0\uff08\u91cd\u65b0\u8d77\u822a\uff09"),(0,r.kt)("admonition",{title:"\u4e0d\u5fd8\u521d\u5fc3\uff0c\u611f\u6069\u9047\u89c1\uff0c\u611f\u6069\u4fe1\u4efb",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"2020 \u5e74 09 \u6708 01 \u65e5\uff0c\u4e00\u4e2a\u53eb ",(0,r.kt)("inlineCode",{parentName:"p"},"Fur")," \u7684\u5f00\u6e90\u9879\u76ee\u6084\u7136\u8bde\u751f\uff0c\u5979\u7684\u51fa\u751f\u4eff\u4f5b\u5e26\u7740\u67d0\u79cd\u4f7f\u547d\uff0c\u6ca1\u6709\u5305\u88b1\uff0c\u65e0\u9650\u53ef\u80fd\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u5979\u7f13\u7f13\u7684\u5f20\u5f00\u53cc\u773c\uff0c\u5e72\u51c0\u96ea\u4eae\u7684\u773c\u775b\u4f3c\u4e4e\u5bf9\u8fd9\u4e2a\u4e16\u754c\u5145\u6ee1\u4e86\u597d\u5947\uff0c\u6bcf\u4e00\u6b21\u601d\u60f3\u78b0\u649e\u5728\u5979\u770b\u6765\u90fd\u662f\u975e\u5e38\u5b9d\u8d35\u7684\u8d22\u5bcc\uff0c\u5979\u8c8c\u4f3c\u6709\u7528\u4e0d\u5b8c\u7684\u7cbe\u529b\uff0c\u4e00\u8def\u6c72\u53d6\u77e5\u8bc6\uff0c\u5347\u7ea7\u6253\u602a\uff0c\u4e0d\u65ad\u5954\u8dd1\uff0c\u4e50\u6b64\u4e0d\u75b2\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u8bb0\u5f97 2020 \u5e74 11 \u6708 11 \u65e5\u7684\u5355\u8eab\u8282\uff0c\u5979\u8fce\u6765\u4e86\u201c\u4e00\u5c81\uff08v1.0.0\uff09\u201d\u751f\u65e5\uff0c\u81ea\u90a3\u4ee5\u540e\uff0cIT \u8fd9\u4e2a\u5927\u94f6\u5e55\u4e0a\u9891\u7e41\u51fa\u73b0\u5979\u7684\u8eab\u5f71\uff0c\u8d8a\u6765\u8d8a\u591a ",(0,r.kt)("inlineCode",{parentName:"p"},".NET5")," \u5f00\u53d1\u8005\u8f6c\u7c89\uff0c\u50cf\u662f\u544a\u8bc9\u8fd9\u4e2a\u4e16\u754c\uff0c\u5979\u5c31\u662f IT \u754c\u5927\u660e\u661f\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u6bcf\u4e00\u4e2a\u660e\u661f\u90fd\u6709\u4e00\u4e2a\u597d\u542c\u7684\u827a\u540d\uff0c\u5979\u5f53\u7136\u4e5f\u4e0d\u4f8b\u5916\uff0c2020 \u5e74 11 \u6708 20 \u65e5\uff0c\u7ecf\u7eaa\u4eba\u767e\u5c0f\u50e7\u4e3a\u5979\u8d77\u540d\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion"),"\u3002"),(0,r.kt)("p",{parentName:"admonition"},"2021 \u5e74 11 \u6708 09 \u65e5\uff0c\u5979\u8fdb\u5165\u4e86\u53db\u9006\u671f\uff0c\u629b\u5f03\u4e86\u66fe\u7ecf\u652f\u6301\u5979\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET5")," \u7c89\u4e1d\u4eec\uff0c\u62e5\u62b1\u4e86\u65b0\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET6")," \u62e5\u8db8\u8005\uff0c\u81ea\u4ece\u8fc7\u4e0a\u4e86\u5962\u9761\u5bcc\u8db3\u7684\u751f\u6d3b\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u4f46\u5979\u8fc7\u7684\u4e0d\u5f00\u5fc3\uff0c\u65f6\u5e38\u5728\u591c\u91cc\u60f3\u8d77 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET5")," \u7684\u7c89\u4e1d\u4eec\uff0c\u5185\u5fc3\u975e\u5e38\u81ea\u8d23\uff0c\u4f46\u5728\u53cc\u91cd\u5de5\u4f5c\u538b\u529b\u4e0b\u5979\u4f9d\u7136\u9009\u62e9\u4e86\u5ffd\u89c6\u4ed6\u4eec\u7684\u8bc9\u6c42\uff0c\u4eff\u4f5b\u4ed6\u4eec\u5c31\u662f\u7d2f\u8d58\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u65f6\u95f4\u771f\u7684\u662f\u597d\u4e1c\u897f\uff0c\u66fe\u7ecf\u8ba4\u4e3a\u662f\u5bf9\u7684\uff0c\u7ecf\u8fc7\u5c81\u6708\u7684\u8e49\u8dce\u5386\u78e8\uff0c\u6e10\u6e10\u7684\u660e\u767d\uff1a\u4e0d\u5fd8\u521d\u5fc3\uff0c\u65b9\u80fd\u59cb\u7ec8\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u8fd9\u4e00\u6b21\uff0c\u4e0d\u843d\u4e0b\u4e00\u4eba\uff08",(0,r.kt)("inlineCode",{parentName:"p"},".NET5"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},".NET6"),"\uff0c...\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},".NET N"),"\uff09\uff0c\u643a\u624b\u5171\u8fdb\uff0c\u91cd\u65b0\u8d77\u822a\uff0c\u611f\u6069\u9047\u89c1\uff0c\u611f\u6069\u4fe1\u4efb\u3002")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"v4.0.0")," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"strong"},".NET5"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"strong"},".NET6"),"\uff0c...\uff0c",(0,r.kt)("inlineCode",{parentName:"strong"},".NET N"),"\uff0c\u6240\u6709\u7684 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u9879\u76ee\u90fd\u80fd\u591f\u5347\u7ea7\u5230\u8be5\u7248\u672c\uff0c\u91cd\u65b0\u8d77\u822a\uff0c\u5b9e\u73b0\u5927\u7edf\u3002"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v392\u5df2\u53d1\u5e03"},"v3.9.2\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("admonition",{title:"\u5173\u4e8e\u65e5\u5fd7",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u65e5\u5fd7\u6a21\u5757\u662f\u4efb\u4f55\u5e94\u7528\u7cfb\u7edf\u90fd\u5fc5\u5907\u7684\u529f\u80fd\uff0c\u53ef\u4ee5\u8bf4\u662f\u6700\u91cd\u8981\u7684\u6a21\u5757\uff01\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET")," \u793e\u533a\u4e2d\u6709 ",(0,r.kt)("inlineCode",{parentName:"p"},"Log4NET"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"NLog"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Serilog")," \u7b49\u65e5\u5fd7\u7ec4\u4ef6\uff0c\u5b83\u4eec\u65e0\u4e00\u4e0d\u662f\u4f18\u79c0\u7684\u5f00\u6e90\u9879\u76ee\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u4f46\u7531\u4e8e\u8fd9\u4e9b\u65e5\u5fd7\u7ec4\u4ef6\u5386\u53f2\u60a0\u4e45\uff0c\u5185\u90e8\u517c\u5bb9\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET")," \u7248\u672c\u975e\u5e38\u591a\uff0c\u529f\u80fd\u968f\u7740\u65f6\u95f4\u63a8\u79fb\u53d8\u5f97\u6781\u5176\u5f3a\u5927\u590d\u6742\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u5728\u5b9e\u9645\u9879\u76ee\u4f7f\u7528\u4e2d\uff0c\u53d1\u73b0\u6bcf\u4e00\u4e2a\u65e5\u5fd7\u7ec4\u4ef6\u914d\u7f6e\u603b\u662f\u4e0d\u90a3\u4e48\u53cb\u597d\uff0c\u7279\u522b\u662f\u5728\u4f7f\u7528\u4e0a\u4e0d\u591f\u7b80\u5355"),"\u3002"),(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u4f5c\u4e3a\u5168\u6808\u5f00\u53d1\u6846\u67b6\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u5728\u8fc7\u53bb\u7248\u672c\u5e76\u6ca1\u6709\u63d0\u4f9b\u8db3\u4ee5\u6ee1\u8db3\u5f00\u53d1\u8005\u9700\u6c42\u7684\u65e5\u5fd7\u6a21\u5757"),"\uff0c\u8f6c\u800c\u63a8\u8350\u5927\u5bb6\u96c6\u6210\u7b2c\u4e09\u65b9\u7ec4\u4ef6\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"p"},"Serilog"),"\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u5bfc\u81f4\u540e\u7eed\u65e0\u6cd5\u5b9e\u73b0\u81ea\u5b9a\u4e49\u529f\u80fd\u548c\u4e5f\u589e\u52a0\u4e86\u4e0d\u5c11\u7ef4\u62a4\u6210\u672c\u3002")),(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("strong",{parentName:"p"},"\u8fd9\u4e00\u6b21\uff0c",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u4e0d\u518d\u59a5\u534f\uff0c\u5f7b\u5e95\u91cd\u6784\u4e86\u65e5\u5fd7\u6a21\u5757\uff0c\u5b9e\u73b0\u65e5\u5fd7\u529f\u80fd/\u9700\u6c42\u5b8c\u5168\u81ea\u4e3b\u53ef\u63a7\uff0c\u63d0\u4f9b\u7ed9\u5f00\u53d1\u8005\u51e0\u4e4e\u6240\u6709\u65e5\u5fd7\u529f\u80fd\u7684\u9700\u6c42\uff01")),(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u7684\u4f7f\u7528\u8005\u4eec\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u662f\u65f6\u5019\u201c\u66f4\u6362\u201d\u6389\u7b2c\u4e09\u65b9\u65e5\u5fd7\u7ec4\u4ef6\uff0c\u8ba9\u6211\u4eec\u4e00\u8d77\u8fed\u4ee3\u51fa\u66f4\u5f3a\u66f4\u597d\u7684\u65e5\u5fd7\u7ec4\u4ef6\u5427\uff01")," \ud83c\udf56")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u65e5\u5fd7\u6a21\u5757\uff0c\u5185\u7f6e\u5199\u5165\u63a7\u5236\u53f0\u3001\u6587\u4ef6\u3001\u6570\u636e\u5e93\u529f\u80fd\uff0c\u518d\u4e5f\u65e0\u9700\u5f15\u5165\u7b2c\u4e09\u65b9\u65e5\u5fd7\u4e86\uff01",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/tree/net6/framework/Furion/Logging"},"\u65e5\u5fd7\u6e90\u7801")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},"\u5f3a\u5927\u7684\u8c03\u8bd5\u65e5\u5fd7 ",(0,r.kt)("inlineCode",{parentName:"strong"},"[LoggingMonitor]")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/commit/32dfc11fd6b47551a81c09e676eb7f5d018ef737"},"32dfc1"))))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("strong",{parentName:"li"},"\u65e5\u5fd7\u6a21\u5757\uff0c\u5185\u7f6e\u5199\u5165\u63a7\u5236\u53f0\u3001\u6587\u4ef6\u3001\u6570\u636e\u5e93\u529f\u80fd\uff0c\u518d\u4e5f\u65e0\u9700\u5f15\u5165\u7b2c\u4e09\u65b9\u65e5\u5fd7\u4e86\uff01",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/tree/net6/framework/Furion/Logging"},"\u65e5\u5fd7\u6e90\u7801"))),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"TP.Wrapper")," \u89c4\u8303\u5316\u65e5\u5fd7\u6a21\u677f\u7b97\u6cd5\uff0c\u7531\u8fc7\u53bb\u7684 ",(0,r.kt)("inlineCode",{parentName:"strong"},"[\u5c5e\u6027]")," \u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},"##\u5c5e\u6027##"),"\uff0c\u89e3\u51b3 ",(0,r.kt)("inlineCode",{parentName:"strong"},"JSON")," \u5185\u5bb9\u51b2\u7a81\u95ee\u9898 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/commit/394ecec28629aee9945480155d502418d0b7a8f8"},"394ecec"))),(0,r.kt)("li",{parentName:"ul"},"[\u516c\u544a]"," ",(0,r.kt)("strong",{parentName:"li"},"\u672a\u6765 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion.Extras.Logging.Serilog")," \u62d3\u5c55\u5c06\u4e0d\u518d\u7ee7\u7eed\u7ef4\u62a4\uff0c\u56e0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u6709\u5f3a\u5927\u7684\u65e5\u5fd7\u7ec4\u4ef6\u4e86\uff01")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u8131\u654f\u6a21\u5757\u6a21\u578b\u7ed1\u5b9a\u4e2a\u522b\u60c5\u51b5\u4e0b\u7a7a\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5IM5C"},"#I5IM5C")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u65e5\u5fd7\u6587\u6863\u3001\u9759\u6001\u7c7b\u6587\u6863\u3001\u6570\u636e\u6821\u9a8c\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u6781\u6613\u4f7f\u7528\u4e14\u5f3a\u5927\u7684\u65e5\u5fd7\u6a21\u5757"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u5199\u5165\u6587\u4ef6\nservices.AddFileLogging("logs/application.log");\n\n// \u5199\u5165\u6570\u636e\u5e93\nservices.AddDatabaseLogging();\n')),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"/furion/docs/logging"},"\u67e5\u770b\u66f4\u591a\u65e5\u5fd7\u6587\u6863"))),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u5f3a\u5927\u7684 ",(0,r.kt)("inlineCode",{parentName:"strong"},"[LoggingMonitor]")," \u8c03\u8bd5\u65e5\u5fd7"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,7}",showLineNumbers:!0,"{1,7}":!0},"using Furion.Logging;\n\nnamespace Furion.Application;\n\npublic class TestLoggerServices : IDynamicApiController\n{\n [LoggingMonitor]\n public PersonDto GetPerson(int id)\n {\n return new PersonDto\n {\n Id = id\n };\n }\n}\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u652f\u6301\u63a7\u5236\u5668\u3001\u64cd\u4f5c\u6216\u5168\u5c40\u6ce8\u518c\u62e6\u622a"),"\u3002"),(0,r.kt)("p",null,"\u8f93\u51fa\u65e5\u5fd7\u4e3a\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},'\u250f\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Logging Monitor \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 Furion.Application.TestLoggerServices.GetPerson (Furion.Application)\n\u2523\n\u2523 \u63a7\u5236\u5668\u540d\u79f0\uff1a TestLoggerServices\n\u2523 \u64cd\u4f5c\u540d\u79f0\uff1a GetPerson\n\u2523 \u8def\u7531\u4fe1\u606f\uff1a [area]: ; [controller]: test-logger; [action]: person\n\u2523 \u8bf7\u6c42\u5730\u5740\uff1a https://localhost:44316/api/test-logger/person/11\n\u2523 \u6765\u6e90\u5730\u5740\uff1a https://localhost:44316/api/index.html\n\u2523 \u6d4f\u89c8\u5668\u6807\u8bc6\uff1a Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62\n\u2523 \u5ba2\u6237\u7aef IP \u5730\u5740\uff1a 0.0.0.1\n\u2523 \u670d\u52a1\u7aef IP \u5730\u5740\uff1a 0.0.0.1\n\u2523 \u670d\u52a1\u7aef\u8fd0\u884c\u73af\u5883\uff1a Development\n\u2523 \u6267\u884c\u8017\u65f6\uff1a 31ms\n\u2523 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 \u6388\u6743\u4fe1\u606f \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 JWT Token\uff1a Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjEsIkFjY291bnQiOiJhZG1pbiIsImlhdCI6MTY1ODcxNjc5NywibmJmIjoxNjU4NzE2Nzk3LCJleHAiOjE2NTg3MTc5OTcsImlzcyI6ImRvdG5ldGNoaW5hIiwiYXVkIjoicG93ZXJieSBGdXJpb24ifQ.VYZkwwqCwlUy3aJjuL-og62I0rkxNQ96kSjEm3VgXtg\n\u2523\n\u2523 UserId (integer)\uff1a 1\n\u2523 Account (string)\uff1a admin\n\u2523 iat (integer)\uff1a 1658716797\n\u2523 nbf (integer)\uff1a 1658716797\n\u2523 exp (integer)\uff1a 1658717997\n\u2523 iss (string)\uff1a dotnetchina\n\u2523 aud (string)\uff1a powerby Furion\n\u2523 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 \u53c2\u6570\u5217\u8868 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 Content-Type\uff1a\n\u2523\n\u2523 id (Int32)\uff1a 11\n\u2523 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 \u8fd4\u56de\u4fe1\u606f \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 \u7c7b\u578b\uff1a Furion.Application.Persons.PersonDto\n\u2523 \u8fd4\u56de\u503c\uff1a {"Id":11,"Name":null,"Age":0,"Address":null,"PhoneNumber":null,"QQ":null,"CreatedTime":"0001-01-01T00:00:00+00:00","Childrens":null,"Posts":null}\n\u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Logging Monitor \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n')),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v389\u5df2\u53d1\u5e03"},"v3.8.9\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c4\u8303\u5316\u7ed3\u679c ",(0,r.kt)("inlineCode",{parentName:"li"},"ExceptionMetadata")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationMetadata")," \u90fd\u53ef\u4ee5\u83b7\u53d6 ",(0,r.kt)("inlineCode",{parentName:"li"},"ErrorCode")," \u5c5e\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5GJ6D"},"#I5GJ6D")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationMetadata")," \u7c7b ",(0,r.kt)("inlineCode",{parentName:"li"},"StatusCode")," \u5c5e\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5HB5L"},"#I5HB5L")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u5bf9 ",(0,r.kt)("inlineCode",{parentName:"li"},"Url")," \u662f\u5426\u7f16\u7801\u8bbe\u7f6e\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"[Get(WithEncodeUrl = false)]")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"WithEncodeUrl(false)")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5GOBC"},"#I5GOBC")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u66f4\u5f3a\u5927\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWTEncryption.SecurityReadJwtToken('token')")," \u8bfb\u53d6\u89e3\u6790 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u9759\u6001\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/574eeb601294378e68c3d57ceaf6cb17f36636e3"},"574eeb6")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValiationTypes.Html")," \u9a8c\u8bc1 ",(0,r.kt)("inlineCode",{parentName:"li"},"Html")," \u6807\u7b7e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5HBKC"},"#I5HBKC")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("a",{parentName:"strong",href:"https://github.com/efcore/EFCore.NamingConventions"},"EFCore.NamingConventions")," \u652f\u6301\uff0c\u53ef\u81ea\u5b9a\u4e49\u751f\u6210\u8868\u540d\uff0c\u5b57\u6bb5\u540d\u98ce\u683c\uff0c\u6bd4\u5982\u5c0f\u9a7c\u5cf0\uff0c\u86c7\u5f62\u547d\u540d\u7b49 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I5HBEI"},"#I5HBEI"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"INamedServiceProvider")," \u547d\u540d\u670d\u52a1\u63d0\u4f9b\u5668\uff0c\u53ef\u89e3\u6790\u63a5\u53e3\u591a\u5b9e\u73b0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5HF98"},"#I5HF98")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8131\u654f\u5904\u7406\u6a21\u5757\u65b9\u6cd5\u53c2\u6570\u5355\u4e2a\u503c\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a22ec3cc3565582eea67052936e788ede8c633cb"},"a22ec3c")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8131\u654f\u8bcd\u5e93\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"|")," \u5206\u5272\u8bcd\u8bed ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/3106b1d78b27b24f4141f052bf804a201a268ff7"},"3106b1d")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," \u6240\u6709 ",(0,r.kt)("inlineCode",{parentName:"li"},".NET")," \u4f9d\u8d56\u5305\u81f3 ",(0,r.kt)("inlineCode",{parentName:"li"},"6.0.7")," \u7248\u672c"),(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serilog.AspNetCore")," \u5305\u81f3 ",(0,r.kt)("inlineCode",{parentName:"li"},"6.0.0")," \u7248\u672c"),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT")," ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u5237\u65b0\u903b\u8f91 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5GXML"},"#I5GXML")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/574eeb601294378e68c3d57ceaf6cb17f36636e3"},"574eeb6")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"ExceptionMetadata")," \u547d\u540d\u7a7a\u95f4\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion.FriendlyException"))," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/3105d168db10bfbe6e83fff2e435ba5d9ef62ed5"},"3105d16")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Retry.Invoke(Func...)")," \u4e3a\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Retry.InvokeAsync(Func...)")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/3b7899942bb37423c2c4ed313069fe361aabf682"},"3b78999")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u8131\u654f\u5904\u7406\u6a21\u5757\uff0c\u5927\u5927\u63d0\u9ad8\u6027\u80fd\u548c\u51c6\u786e\u7387\uff0c\u540c\u65f6\u652f\u6301\u65b9\u6cd5\u53c2\u6570\u5355\u4e2a\u503c\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a22ec3cc3565582eea67052936e788ede8c633cb"},"a22ec3c")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Rider")," \u5f00\u53d1\u5de5\u5177\u5bf9\u540c\u540d\u811a\u624b\u67b6 (",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar"),") \u53ea\u663e\u793a\u4e00\u4e2a\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/518"},"!518")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"UnitOfWork")," \u5de5\u4f5c\u5355\u5143\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u4e2d\u5931\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5H0T3"},"#I5H0T3")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT")," \u4e2d ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u5982\u679c\u5b58\u5728\u6570\u7ec4\u7c7b\u578b\u7684\u503c\u65f6\uff0c\u5237\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u540e\u4e22\u5931\u4e86\u5386\u53f2\u503c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5GXML"},"#I5GXML")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"WithEncodeUrl")," \u65e0\u6cd5\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"[HttpMethod]")," \u8bbe\u7f6e\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/574eeb601294378e68c3d57ceaf6cb17f36636e3"},"574eeb6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u6a21\u5f0f\u4e0b\u6dfb\u52a0\u81ea\u5b9a\u4e49\u914d\u7f6e\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u65e0\u6cd5\u83b7\u53d6\u81ea\u5b9a\u4e49\u914d\u7f6e\u6587\u4ef6\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5GZ0F"},"#I5GZ0F")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Bah")," \u8fdb\u5165\u5168\u5c40\u5f02\u5e38\u62e6\u622a\u5668\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5H47S"},"#I5H47S")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AddDbPool/AddDb")," \u6269\u5c55\u672a\u6839\u636e\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Key")," \u8def\u5f84\u8bfb\u53d6\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5H6S4"},"#I5H6S4")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/520"},"!520")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValiationTypes.Url")," \u6b63\u5219\u8868\u8fbe\u5f0f\u8986\u76d6\u4e0d\u5168\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5HBKC"},"#I5HBKC")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"v3.5.x")," \u7248\u672c\u5bfc\u81f4\u96c6\u6210 ",(0,r.kt)("a",{parentName:"strong",href:"https://github.com/efcore/EFCore.NamingConventions"},"EFCore.NamingConventions")," \u5931\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I5HBEI"},"#I5HBEI"))),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u957f\u8def\u7531\u4e0d\u652f\u6301\u95ee\u9898\u4ee5\u53ca ",(0,r.kt)("inlineCode",{parentName:"li"},"[Required]")," \u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"AllowEmptyStrings")," \u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/c0143300329b5a96a2fbd4d92de109f520674d33"},"c014330")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u4e0a\u4f20\u6587\u4ef6\u65f6\u8bf7\u6c42\u62a5\u6587 ",(0,r.kt)("inlineCode",{parentName:"li"},"boundary")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Content-Disposition")," \u8bbe\u7f6e\u4e0d\u6b63\u786e\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5HEF0"},"#I5HEF0")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8131\u654f\u6a21\u5757\u66ff\u6362\u654f\u611f\u8bcd\u6c47\u51fa\u73b0\u591a\u66ff\u6362\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a22ec3cc3565582eea67052936e788ede8c633cb"},"a22ec3c")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u591a\u8bed\u8a00\u9ed8\u8ba4\u5904\u7406\u903b\u8f91\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u5141\u8bb8\u4e0d\u914d\u7f6e\u4efb\u4f55\u8bed\u8a00"),"\uff0c\u8fc7\u53bb\u7248\u672c\u4f1a\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5GRD9"},"#I5GRD9")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/5077c5dab9ee94733817f55ff8224b853d0001a3"},"5077c5d")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u89c4\u8303\u5316\u6587\u6863 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u6027\u80fd"),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u8c03\u6574 ",(0,r.kt)("inlineCode",{parentName:"li"},"MongoDB")," \u4ed3\u50a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"TDocument")," \u6cdb\u578b\u7ea6\u675f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/3f49055b6b80ef7861f58b0c6feabf5c87a32010"},"3f49055")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863\uff0c\u65e5\u5fd7\u8bb0\u5f55\u6587\u6863\u3001\u591a\u6570\u636e\u5e93\u6587\u6863\u3001PM2 \u90e8\u7f72\u6587\u6863\u3001Visual Studio \u9ad8\u6548\u7387\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v3711\u5df2\u53d1\u5e03"},"v3.7.11\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Minimal API")," \u5e94\u7528\u652f\u6301\uff1a",(0,r.kt)("inlineCode",{parentName:"strong"},".AddInjectMini()")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I4KOQ5"},"#I4KOQ5"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8de8\u57df ",(0,r.kt)("inlineCode",{parentName:"li"},"WithExposedHeaders")," \u9ed8\u8ba4\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"access-token")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"x-access-token")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/42ebdfd33a01353a0b3a801528de052990d2e4c9"},"42ebdfd")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u811a\u624b\u67b6\u9ed8\u8ba4\u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"app.UseHttpLogging()")," ",(0,r.kt)("inlineCode",{parentName:"li"},"HTTP")," \u65e5\u5fd7 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/42ebdfd33a01353a0b3a801528de052990d2e4c9"},"42ebdfd")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u548c ",(0,r.kt)("inlineCode",{parentName:"strong"},"ASP.NET Core")," \u5b8c\u6574 ",(0,r.kt)("inlineCode",{parentName:"strong"},"json")," \u914d\u7f6e\u7684 ",(0,r.kt)("inlineCode",{parentName:"strong"},"JSON Schema")," \u67b6\u6784 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"},"JSON Schema"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u4ee3\u7406\u652f\u6301\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/1d7fb5b5330c5a30098056818a93a0879034fecd"},"1d7fb5b")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u4ee3\u7406\u652f\u6301\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"ValueTuple")," \u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/876a2f5f7e2d07fa3bbc3f5b99c0653893e0ada8"},"876a2f5")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7ec4\u4ef6\u5316\u8bbe\u8ba1\u6a21\u5757\uff0c\u652f\u6301\u6bd4 ",(0,r.kt)("inlineCode",{parentName:"li"},"AppStartup")," \u66f4\u7075\u6d3b\u4fbf\u6377\u7684\u8bbe\u8ba1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/tree/net6/framework/Furion/Components"},"#components")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u72ec\u7acb\u5de5\u4f5c\u5355\u5143\u6a21\u5757\uff0c\u652f\u6301\u4efb\u4f55\u7b2c\u4e09\u65b9 ",(0,r.kt)("inlineCode",{parentName:"li"},"ORM")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a02413d6887d258ad3a1ba972bb6a08d29291d0c"},"a02413d")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8de8\u57df ",(0,r.kt)("inlineCode",{parentName:"li"},"FixedClientToken")," \u914d\u7f6e\u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/bd016386681631a5539bcf215c068c2069bba15f"},"bd01638")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"throw Oops.Bah")," \u53ef\u4ee5\u624b\u52a8\u89e6\u53d1\u89c4\u8303\u5316\u9a8c\u8bc1\u5931\u8d25\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/83f0036a4ce10c6b1cfc4a258dc61e197af38879"},"83f0036")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"FriendlyExceptionSettings")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ThrowBah")," \u914d\u7f6e\uff0c\u53ef\u6807\u8bb0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Oh")," \u4e0d\u8fdb\u5165\u5f02\u5e38\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/76ffa7f18d3683ad36e37e5fc90cf54a4b04e520"},"76ffa7f")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Minimal API")," \u5e94\u7528\u652f\u6301\uff1a",(0,r.kt)("inlineCode",{parentName:"strong"},".AddInjectMini()")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I4KOQ5"},"#I4KOQ5"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u548c ",(0,r.kt)("inlineCode",{parentName:"strong"},"ASP.NET Core")," \u5b8c\u6574 ",(0,r.kt)("inlineCode",{parentName:"strong"},"json")," \u914d\u7f6e\u7684 ",(0,r.kt)("inlineCode",{parentName:"strong"},"JSON Schema")," \u67b6\u6784 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"},"JSON Schema"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7ec4\u4ef6\u5316\u8bbe\u8ba1\u6a21\u5757\uff0c\u652f\u6301\u6bd4 ",(0,r.kt)("inlineCode",{parentName:"li"},"AppStartup")," \u66f4\u7075\u6d3b\u4fbf\u6377\u7684\u8bbe\u8ba1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/tree/net6/framework/Furion/Components"},"#components")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u72ec\u7acb\u5de5\u4f5c\u5355\u5143\u5355\u5143\u6a21\u5757\uff0c\u652f\u6301\u4efb\u4f55\u7b2c\u4e09\u65b9 ",(0,r.kt)("inlineCode",{parentName:"li"},"ORM")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a02413d6887d258ad3a1ba972bb6a08d29291d0c"},"a02413d")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DataValidationFilter")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"FriendlyExceptionFilter"),"\uff0c\u89e3\u51b3\u4e0d\u652f\u6301\u624b\u52a8\u629b\u51fa\u4e1a\u52a1\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/83f0036a4ce10c6b1cfc4a258dc61e197af38879"},"83f0036")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},".AddDb<>")," \u548c ",(0,r.kt)("inlineCode",{parentName:"strong"},".AddDbPool<>")," \u81ea\u5b9a\u4e49\u59d4\u6258\u53c2\u6570\u7b7e\u540d\uff0c\u7531 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Action")," \u6539\u4e3a\uff1a",(0,r.kt)("inlineCode",{parentName:"strong"},"Action")))))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5}",showLineNumbers:!0,"{2,5}":!0},"// \u7531\uff1a\noptions.AddDbPool(DbProvider.MySql, opt => {\n});\n// \u6539\u4e3a\noptions.AddDbPool(DbProvider.MySql, (services, opt)=> {\n})\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea ",(0,r.kt)("inlineCode",{parentName:"li"},"v3.6.3")," \u7248\u672c\u4f9d\u8d56\uff0c\u6267\u884c\u539f\u751f ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u6dfb\u52a0\u4e86\u53c2\u6570\u6821\u9a8c\u5bfc\u81f4\u5b58\u50a8\u8fc7\u7a0b\u6267\u884c\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5ERMQ"},"#I5ERMQ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"tools/cli.ps1")," \u811a\u672c\u5de5\u5177\u51fa\u73b0\u6570\u636e\u5e93\u94fe\u63a5\u88ab\u5360\u7528\u95ee\u9898"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWTSettings")," \u7b97\u6cd5\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON Schema")," \u9519\u8bef\u95ee\u9898\uff0c\u611f\u8c22 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/gitwentao"},"@gitwentao")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5G27B"},"#I5G27B")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/516"},"!516")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u57fa\u4e8e\u7b56\u7565\u6388\u6743\u5728\u4e0d\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Policy")," \u7684\u60c5\u51b5\u4e0b\u51fa\u73b0\u7a7a\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5EVF2"},"#I5EVF2")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u542f\u7528\u6570\u636e\u5e93\u5b9e\u4f53\u8ddf\u8e2a\u65f6\u5bfc\u81f4\u65b0\u589e\u5b9e\u4f53\u591a\u6b21\u67e5\u8be2\u6570\u636e\u5e93\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4J2LZ"},"#I4J2LZ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e0d\u542f\u7528\u89c4\u8303\u5316\u7ed3\u679c\u5bfc\u81f4\u9a8c\u8bc1\u5931\u6548\uff0c\u5f02\u5e38\u5931\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/cdb3f570ab72cff0a5327a717f85c48e153211be"},"cdb3f57")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u9a8c\u8bc1\u5f02\u5e38\u548c\u53cb\u597d\u5f02\u5e38\u51b2\u7a81\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/83f0036a4ce10c6b1cfc4a258dc61e197af38879"},"83f0036")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"CentOS 7.9")," \u7cfb\u7edf\u90e8\u7f72\u65e0\u6cd5\u6307\u5b9a\u547d\u4ee4 ",(0,r.kt)("inlineCode",{parentName:"li"},"--urls")," \u53c2\u6570\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/8cc8eeff6b5b25de42367884b7c91d419557d054"},"8cc8ee")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u811a\u624b\u67b6\u6240\u6709 ",(0,r.kt)("inlineCode",{parentName:"li"},".json")," \u6587\u4ef6\uff0c\u9ed8\u8ba4\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON Schema")," \u652f\u6301"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7ec4\u4ef6\u5316\u542f\u52a8\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Vue/React/Angular")," \u8bf7\u6c42\u4ee3\u7406\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON Schema")," \u6587\u6863\uff0c\u652f\u6301\u914d\u7f6e\u667a\u80fd\u63d0\u793a\u548c\u9a8c\u8bc1"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u8de8\u57df\u6587\u6863\u3001\u89c4\u8303\u5316\u6587\u6863\u3001\u914d\u7f6e\u6587\u6863\u3001\u65e5\u5fd7\u6587\u6863\u3001IIS \u90e8\u7f72\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"strong"},"JSON Schema")," \u652f\u6301\uff0c\u6240\u6709 ",(0,r.kt)("inlineCode",{parentName:"strong"},".json")," \u6587\u4ef6\u652f\u6301\u667a\u80fd\u63d0\u793a\u548c\u9a8c\u8bc1"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},'{\n "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json",\n\n "Logging": {\n "LogLevel": {\n "Default": "Information",\n "Microsoft": "Warning",\n "Microsoft.Hosting.Lifetime": "Information",\n "Microsoft.EntityFrameworkCore": "Information"\n }\n },\n "AllowedHosts": "*"\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/js1.png")}),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"./jsonschema"},"\u67e5\u770b\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"a"},"JSON Schema")," \u6587\u6863"))),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u6839\u636e ",(0,r.kt)("inlineCode",{parentName:"strong"},"Swagger")," \u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Vue/React/Angular")," \u524d\u7aef\u8bf7\u6c42\u4ee3\u7801"))),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"./clientapi"},"\u67e5\u770b\u6587\u6863"))),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Sql")," \u4ee3\u7406\u652f\u6301\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7-9}",showLineNumbers:!0,"{7-9}":!0},'public interface ISql : ISqlDispatchProxy\n{\n // \u96c6\u5408\u7c7b\u578b\n [SqlExecute("select * from person")]\n List GetPersons();\n\n // \u81ea v3.7.3+ \u7248\u672c\u652f\u6301\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570\n [SqlExecute("select * from person where id=@id")]\n Person GetPerson(int id);\n}\n')),(0,r.kt)("ol",{start:4},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Sql")," \u4ee3\u7406\u652f\u6301\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"strong"},"ValueTuple")," \u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-6}",showLineNumbers:!0,"{3-6}":!0},'public interface ISql : ISqlDispatchProxy\n{\n [SqlExecute(@"\n select * from person where id =@id;\n select * from person")]\n (Person, List) GetData(int id); // \u6ce8\u610f\u8fd4\u56de\u503c\u662f `(Person, List)` \u7ec4\u5408\n}\n')),(0,r.kt)("ol",{start:5},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Minimal API")," \u5e94\u7528"))),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-6.0"},"\u4e86\u89e3 ",(0,r.kt)("inlineCode",{parentName:"a"},"Minimal API")," \u5e94\u7528"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3-4,10,12-15}",showLineNumbers:!0,"{1,3-4,10,12-15}":!0},'var builder = WebApplication.CreateBuilder(args).Inject();\n\n// \u6ce8\u518c Minimal \u670d\u52a1\nbuilder.Services.AddInjectMini();\n\nvar app = builder.Build();\n\napp.UseHttpsRedirection();\n\napp.UseInject(string.Empty);\n\napp.MapGet("/hello", () =>\n{\n return "Hello, Furion";\n});\n\napp.Run();\n')),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v369\u5df2\u53d1\u5e03"},"v3.6.9\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u6781\u7b80\u4e3b\u673a\u6a21\u5f0f\uff0c\u771f\u6b63\u5b9e\u73b0\u6781\u901f\u5165\u95e8\u3002",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/95cac5b391b70d73bfc94147ee40eef529b2eec6"},"95cac5b")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"TP.Wrapper(...)")," \u62d3\u5c55\u65b9\u6cd5\uff0c\u4e3b\u8981\u7528\u6765\u751f\u6210\u89c4\u8303\u5316\u7684\u65e5\u5fd7\u6a21\u677f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/427999aba4847522ea91c42df6164e5fe69c5bc0"},"427999a")),(0,r.kt)("li",{parentName:"ul"},"[\u652f\u6301]"," \u9879\u76ee\u7c7b\u578b\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},'')," \u7684\u63a7\u5236\u53f0\u9879\u76ee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/fb08a6548d49921aa143d01389a2592b92e94e31"},"fb08a65")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"BadPageResult")," \u9519\u8bef\u9875\u9762\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/494"},"!494")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[SchemaId]")," \u7279\u6027\uff0c\u89e3\u51b3\u4e0d\u540c\u7a0b\u5e8f\u96c6\u76f8\u540c\u7684\u7c7b\u540d\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"SchemaId")," \u51b2\u7a81\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5D3CU"},"#I5D3CU")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"options.ApproveAllCerts()")," \u5ffd\u7565\u6240\u6709\u5ba2\u6237\u7aef\u8bc1\u4e66\u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/eb7d18ac183894d604cec1d4c8527466ef9c648a"},"eb7d18a")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5224\u65ad\u662f\u5426\u662f\u5355\u6587\u4ef6\u73af\u5883\u90e8\u7f72\u9759\u6001\u5c5e\u6027 ",(0,r.kt)("inlineCode",{parentName:"li"},"App.SingleFileEnvironment")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/de556f0aaf87c41fe01cca2655f086890b2638a0"},"de556f0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"WebApplicationBuilder.UseSerilogDefault()")," \u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/e02524c8a15fd660b6359285ef07a697878e6678"},"e02524c")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u652f\u6301]"," \u9879\u76ee\u7c7b\u578b\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},'')," \u7684\u63a7\u5236\u53f0\u9879\u76ee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/fb08a6548d49921aa143d01389a2592b92e94e31"},"fb08a65")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u6781\u7b80\u4e3b\u673a\u6a21\u5f0f\uff0c\u771f\u6b63\u5b9e\u73b0\u6781\u901f\u5165\u95e8\u3002",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/95cac5b391b70d73bfc94147ee40eef529b2eec6"},"95cac5b")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u672a\u542f\u7528\u89c4\u8303\u5316\u7ed3\u679c\u65f6\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"MVC")," \u9a8c\u8bc1\u5931\u8d25\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"BadPageResult()")," \u9875\u9762\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/494"},"!494")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u9ed8\u8ba4\u6ce8\u518c\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddResponseCaching();")," \u670d\u52a1\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},".axd")," \u5185\u5d4c\u8d44\u6e90\u8bf7\u6c42\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/495"},"!495")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Oracle")," \u6570\u636e\u5e93\u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u5fc5\u987b\u8981\u6c42\u547d\u4ee4\u53c2\u6570\u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u8bed\u8a00\u53c2\u6570\u6570\u91cf\u4e00\u81f4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5D057"},"#I5D057")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IHostService")," \u7c7b\u578b\u4e0d\u80fd\u81ea\u52a8\u6ce8\u518c\u95ee\u9898\uff0c\u4e4b\u524d\u53ea\u626b\u63cf\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"BackgroundService")," \u6d3e\u751f\u7c7b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/968344aa07348f4c06f914abf7b6f46174633d81"},"968344")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u56fd\u4ea7\u82af\u7247\u4e3b\u673a\u4e0d\u80fd\u8bc6\u522b ",(0,r.kt)("inlineCode",{parentName:"li"},"dotnet run --urls")," \u53c2\u6570\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6d43983781e0c41228c4917a242141d011088bdb"},"6d4398")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u4e0a\u4f20\u6587\u4ef6\u4e0d\u652f\u6301\u7279\u5b9a\u6587\u4ef6\u540e\u7f00\u95ee\u9898\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"li"},".pem")," \u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/ba42198c1cd58612f2b383349c37068aac78cdd7"},"ba42198")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e00\u4e9b\u7a0b\u5e8f\u96c6\u5df2\u7834\u574f\u6216\u7a0b\u5e8f\u96c6\u4e0d\u5b8c\u6574\u5bfc\u81f4\u4e3b\u673a\u65e0\u6cd5\u542f\u52a8\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d2dc3e4d09e726699c38ebb8cb7b83de0e97f46f"},"d2dc3e4")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u4f20\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"headers")," \u65f6\u7c7b\u578b\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Dictionary")," \u5bfc\u81f4\u8f6c\u6362\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5DHL9"},"#I5DHL9")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serilog")," \u5355\u6587\u4ef6\u53d1\u5e03\u4e0d\u751f\u6210\u65e5\u5fd7\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5DQ2B"},"I5DQ2B")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u8fdc\u7a0b\u8bf7\u6c42\u9ed8\u8ba4\u5ba2\u6237\u7aef\u4e0d\u68c0\u67e5 ",(0,r.kt)("inlineCode",{parentName:"li"},"SSL")," \u8bc1\u4e66 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/eb7d18ac183894d604cec1d4c8527466ef9c648a"},"eb7d18a")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u5f00\u653e\u9a8c\u8bc1\u670d\u52a1\u9009\u9879 ",(0,r.kt)("inlineCode",{parentName:"li"},"SuppressModelStateInvalidFilter")," \u5c5e\u6027\u4e3a\u53ef\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/495"},"!494")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContext")," \u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"GlobalUsings")," \u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"TP")," \u5168\u5c40\u9759\u6001\u7c7b\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4e2d\u95f4\u4ef6\u6587\u6863\u3001\u7b5b\u9009\u5668\u6587\u6863\u3001\u5ba1\u8ba1\u65e5\u5fd7\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u8de8\u57df\u6587\u6863\u3001\u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7cbe\u5f69\u8d21\u732e")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/494"},"!494")," \u4f18\u79c0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Pull Request")," \u8fa9\u8bba\u5178\u8303"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u6781\u901f\u5165\u95e8"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="Program.cs" {3,6}',showLineNumbers:!0,title:'"Program.cs"',"{3,6}":!0},'Serve.Run();\n\n[DynamicApiController]\npublic class HelloService\n{\n public string Say()\n {\n return "Hello, Furion";\n }\n}\n')),(0,r.kt)("p",null,"\u542f\u52a8\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\uff0c\u60ca\u5446\u4e86\u5417\uff01"),(0,r.kt)("img",{src:(0,l.Z)("img/07.png")}),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u5185\u7f6e\u9519\u8bef\u9875"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers{1,7}","showLineNumbers{1,7}":!0},"using Furion.FriendlyException;\n\npublic IActionResult Add(Person person)\n{\n if(!ModelState.IsValid)\n {\n return new BadPageResult();\n }\n}\n")),(0,r.kt)("img",{src:(0,l.Z)("img/er1.png")}),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Swagger")," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Markdown")))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4-62}",showLineNumbers:!0,"{4-62}":!0},'/// \n/// \u6d4b\u8bd5 Markdown\n/// \n/// \n/// # \u6d4b\u8bd5 `Markdown` \u6ce8\u91ca\n///\n/// ![](https://localhost:44316/images/logo.png)\n///\n/// ```cs\n/// Serve.Run();\n///\n/// [DynamicApiController\n/// public class HelloService\n/// {\n/// public string Say()\n/// {\n/// return nameof(Furion);\n/// }\n/// }\n/// ```\n///\n/// \u529f\u80fd\u8fd8\u4e0d\u9519\uff01\uff01\uff01\n///\n/// | \u5546\u54c1 | \u4ef7\u683c | # \u5176\u4ed6 |\n/// |--------------|-----------|------------|\n/// | Juicy Apples | 1.99 | *7* |\n/// | Bananas | **1.89** | 5234 |\n/// | Bananas | **1.89** | 5234 |\n/// | Bananas | **1.89** | 5234 |\n///\n/// -----\n///\n/// # Furion \u63a2\u7d22\u7248\n///\n/// > \u5728\u8fc7\u53bb\u4e00\u5e74\uff0c\u5b9e\u73b0 `Furion` \u4ece\u65e0\u5230\u6709\uff0c\u7f16\u5199\u6587\u6863\u5df2\u903e\u767e\u4e07\u5b57\uff0c\u8fc7\u7a0b\u5fc3\u9178\u5f00\u6e90\u4eba\u81ea\u77e5\u3002\n/// >\n/// > \u8fd9\u4e00\u8def\u65e5\u591c\u517c\u7a0b\uff0c\u5632\u8bbd\u6279\u8bc4\u5e38\u4f34\u773c\u8033\uff0c\u5373\u4fbf\u8f9b\u82e6\u65e0\u5948\u3001\u60f3\u8fc7\u653e\u5f03\uff0c\u4f46\u4e3a\u4e86\u90a3\u5fae\u4e0d\u8db3\u9053\u7684\u5b58\u5728\u611f\u4f9d\u7136\u52aa\u529b\u7740\u3002\n/// >\n/// > \u5f53\u7136\uff0c\u4e5f\u6536\u83b7\u4e86\u4e0d\u5c11...\u8d8a\u6765\u8d8a\u591a\u62e5\u8db8\u8005\uff0c\u8d8a\u53d1\u7cbe\u6e5b\u6280\u672f\u80fd\u529b\uff0c\u66f4\u9ad8\u5c42\u6b21\u601d\u7ef4\u6a21\u5f0f\uff0c\u8fd8\u6709\u8bb8\u591a\u8de8\u754c\u8de8\u884c\u670b\u53cb\u3002\n/// >\n/// > \u5728 \u300a[\u5f00\u6e90\u6307\u5317] (https://gitee.com/opensource-guide/comments/)\u300b\u4e2d\uff0c\u6211\u66fe\u8bf4\u9053\uff1a\u201c\u5f00\u6e90\u5982\u540c\u4eba\u7684\u8138\uff0c\u597d\u574f\u4e00\u9762\u4fbf\u77e5\uff0c\u7f3a\u70b9\u53ef\u80fd\u4f1a\u53d7\u5230\u5632\u8bbd\u6279\u8bc4\uff0c\u4f18\u70b9\u4e5f\u4f1a\u6536\u83b7\u8d5e\u626c\u5c0a\u91cd\u3002\u522b\u62c5\u5fc3\uff0c\u4ed6\u4eec\u6b63\u5728\u5851\u9020\u66f4\u597d\u7684\u4f60\u3002\u201d\n/// >\n/// > \u6240\u4ee5\uff0c\u8fd9\u4e00\u6b21\u91cd\u65b0\u8d77\u822a\uff0c\u91cd\u5851 `Furion` \u91cd\u5851\u81ea\u5df1\u3002\u4e5f\u8bb8\u672a\u6765\u5728\u67d0\u4e2a IT \u5708\u4f46\u51e1\u6709\u4eba\u8c08\u8d77 `.NET` \u8fd8\u80fd\u779f\u5230 `Furion` \u7684\u8eab\u5f71\u3002\n///\n/// ---\n///\n/// \ud83c\udf89 \u63a2\u7d22 Furion \u672a\u6765\u66f4\u591a\u53ef\u80fd\u6027\uff0c\u5b9e\u73b0\u65e0\u7b2c\u4e09\u65b9\u4f9d\u8d56\u7684\u7248\u672c\uff0c\u6240\u6709\u6a21\u5757\u529f\u80fd\u6309\u9700\u5b89\u88c5\uff0c\u6309\u9700\u52a0\u8f7d\u3002\n///\n/// - \u4f5c\u8005\uff1a[\u767e\u5c0f\u50e7] (https://gitee.com/monksoul)\n/// - \u65e5\u671f\uff1a2021 \u5e74 08 \u6708 30 \u65e5\n///\n/// ## \u73af\u5883\n///\n/// - IDE \uff1a[Microsoft Visual Studio Enterprise 2022 Preview(64 \u4f4d) \u7248\u672c 17.0.0 Preview 3.1] (https://visualstudio.microsoft.com/zh-hans/vs/preview/)\n/// - SDK \uff1a[.NET SDK 6] (https://dotnet.microsoft.com/download/dotnet/6.0)\n/// - \u8bed\u8a00\uff1a[C# 10](https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-10)\n///\n/// ## \u5305\u8bf4\u660e\n///\n/// - `Furion.Core`\uff1a\u65e0\u7b2c\u4e09\u65b9\u4f9d\u8d56\uff0c\u53ef\u5728 `.NET 6` \u6240\u6709\u9879\u76ee\u7c7b\u578b\u4e2d\u8fd0\u884c\u3002\n/// - `Furion`\uff1a\u5185\u90e8\u4f9d\u8d56 `Furion.Core` \u4e14\u65e0\u7b2c\u4e09\u65b9\u4f9d\u8d56\uff0c**\u805a\u7126 `Web` \u5e94\u7528**\uff0c\u91c7\u7528\u5171\u4eab\u6846\u67b6 `` \u6a21\u5f0f\n/// \npublic void MarkdownTest()\n{\n // ....\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/mdx2.png")}),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v357\u5df2\u53d1\u5e03"},"v3.5.7\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Options")," \u9009\u9879\u5c5e\u6027\u652f\u6301\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},"Key")," \u540d\u79f0\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},'[MapSettings("key")]')," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5B2HN"},"#I5B2HN")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EventBus")," \u6a21\u5757\u4e8b\u4ef6 ",(0,r.kt)("inlineCode",{parentName:"li"},"Id")," \u652f\u6301\u679a\u4e3e\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/2f328aa8213c8efe7a8480116985573cc6b7fce6"},"2f328aa")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EventBus")," \u6a21\u5757\u53d1\u5e03\u8005 ",(0,r.kt)("inlineCode",{parentName:"li"},"PublishAsync")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"PublishDelayAsync")," \u91cd\u8f7d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/2f328aa8213c8efe7a8480116985573cc6b7fce6"},"2f328aa")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EventBus")," \u6a21\u5757\u62d3\u5c55\u65b9\u6cd5\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Enum.ParseToString()")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"String.ParseToEnum()")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/2f328aa8213c8efe7a8480116985573cc6b7fce6"},"2f328aa")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u548c ",(0,r.kt)("inlineCode",{parentName:"strong"},"SqlSugar")," \u811a\u624b\u67b6")," \ud83c\udd95\ud83c\udd95\ud83c\udd95 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/8d9293d1188670626f017ccea4ffb85ac315d2fc"},"8d9293d")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Dapper")," \u62d3\u5c55\u5168\u5c40\u914d\u7f6e\u59d4\u6258 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5AYFX"},"#I5AYFX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u8f6c\u5b9e\u4f53\u652f\u6301\u591a\u79cd\u547d\u540d\u7b56\u7565\uff08\u7eaf\u5927\u5199\uff0c\u7eaf\u5c0f\u5199\uff0c\u5e26\u4e0b\u5212\u7ebf\u5206\u5272\u7b49\u7b49\uff09\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oracle")," \u6570\u636e\u5e93 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a90e24516387e088b2c427e6b99d3dab937116c9"},"a90e245")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"FS.InitalContentTypeProvider()")," \u62d3\u5c55\u65b9\u6cd5\uff0c\u83b7\u53d6\u7cfb\u7edf\u5185\u6240\u6709\u652f\u6301\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Content-Type")," \u6587\u4ef6\u63d0\u4f9b\u5668 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6099900472d93dab7012f0b091b05c914be11c4a"},"6099900")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u89e3\u51b3]"," \u5f7b\u5e95\u89e3\u51b3\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u4e0d\u80fd\u5355\u6587\u4ef6\u53d1\u5e03\u7684\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/7e8e0b708bcdac670aa835dec5cd494d41ff3648"},"7e8e0b7")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6846\u67b6\u89c4\u8303\u5316\u6587\u6863 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Controller")," \u6d3e\u751f\u7c7b ",(0,r.kt)("inlineCode",{parentName:"li"},"api")," \u8def\u7531\u95ee\u9898\uff0c\u539f\u751f ",(0,r.kt)("inlineCode",{parentName:"li"},"ASP.NET")," \u662f\u652f\u6301\u7684 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/29e47bce3678767c4793ad254777704ab9dd7e03"},"29e47bc")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u57fa\u4e8e ",(0,r.kt)("inlineCode",{parentName:"li"},"Schema")," \u591a\u79df\u6237\u914d\u7f6e\u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6f820ce0f28dd27a6e265b969b5b4095de676106"},"6f820ce")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6307\u5b9a\u5b9e\u4f53 ",(0,r.kt)("inlineCode",{parentName:"li"},'[Table(schema:"dbo")]')," \u7279\u6027\u540e ",(0,r.kt)("inlineCode",{parentName:"li"},"Schema")," \u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6f820ce0f28dd27a6e265b969b5b4095de676106"},"6f820ce")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u89c6\u56fe\u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Schema")," \u914d\u7f6e\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6f820ce0f28dd27a6e265b969b5b4095de676106"},"6f820ce")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c4\u8303\u5316\u7ed3\u679c\u6781\u7aef\u60c5\u51b5\u4e0b\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"\u7a7a\u5f02\u5e38")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/c9b0ef09427418e2ccb88d3a4c02e7a29d9d510e"},"c9b0ef")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"axios-utils.ts")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"angular-utils.ts")," \uff0c\u65b0\u589e\u8bf7\u6c42\u62e6\u622a\u643a\u5e26\u5237\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u7684\u65f6\u673a\u5224\u65ad ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/82f89bd95573aefa7075676af7f00c55507cb03b"},"82f89bd")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u89c4\u8303\u5316\u6587\u6863 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u52a0\u8f7d\u7ee7\u627f\u6ce8\u91ca ",(0,r.kt)("inlineCode",{parentName:"li"},"")," \u6027\u80fd\u5c0f\u4f18\u5316 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/5f06880564ee8cd2e77caa5957ff18a0c489bdd2"},"5f06880")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u811a\u624b\u67b6\u6a21\u677f\uff0c\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"GlobalUsings.cs")," \u6a21\u5f0f"),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u5bf9\u8c61\u6620\u5c04\u9ed8\u8ba4\u652f\u6301\u5ffd\u7565\u5927\u5c0f\u5199 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/486"},"!486")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u5355\u6587\u4ef6\u53d1\u5e03\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion + SqlSugar")," \u811a\u624b\u67b6\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u4e8b\u4ef6\u603b\u7ebf\u6587\u6863\u3001\u9009\u9879\u6587\u6863\u3001\u5373\u65f6\u901a\u8baf\u6587\u6863\u3001",(0,r.kt)("inlineCode",{parentName:"li"},".NET5")," \u5347\u7ea7 ",(0,r.kt)("inlineCode",{parentName:"li"},".NET6")," \u6587\u6863\u3001\u4f9d\u8d56\u6ce8\u5165\u6587\u6863\u3001\u8de8\u57df\u6587\u6863\u3001\u6570\u636e\u52a0\u89e3\u5bc6\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u4e8b\u4ef6\u603b\u7ebf ",(0,r.kt)("inlineCode",{parentName:"strong"},"Id")," \u652f\u6301\u679a\u4e3e\u7c7b\u578b"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10}",showLineNumbers:!0,"{7,10}":!0},'EventSubscribe("TO:DO")] // \u5b57\u7b26\u4e32\u7c7b\u578b\npublic async Task EventHandler1(EventHandlerExecutingContext context)\n{\n // ....\n}\n\n[EventSubscribe(YourEnum.Some)] // \u679a\u4e3e\u7c7b\u578b\npublic async Task EventHandler2(EventHandlerExecutingContext context)\n{\n var eventEnum = context.Source.EventId.ParseToEnum(); // \u5c06\u4e8b\u4ef6 Id \u8f6c\u6362\u6210\u679a\u4e3e\u5bf9\u8c61\n // ....\n}\n')),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u4e8b\u4ef6\u603b\u7ebf\u53d1\u5e03\u652f\u6301\u66f4\u7b80\u5355\u8c03\u7528"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,6}",showLineNumbers:!0,"{5,6}":!0},'// \u65e7\u7248\u672c\nawait _eventPublisher.PublishAsync(new ChannelEventSource("ToDo:Create", name));\n\n// \u65b0\u7248\u672c\nawait _eventPublisher.PublishAsync("ToDo:Create", name);\nawait _eventPublisher.PublishAsync(YourEnum.Some); // \u4e5f\u652f\u6301\u679a\u4e3e\n')),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u9009\u9879\u652f\u6301\u5c5e\u6027\u81ea\u5b9a\u4e49\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"strong"},"Key")))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {4}",showLineNumbers:!0,"{4}":!0},'"AppInfo": {\n "Name": "Furion",\n "Version": "1.0.0",\n "Company_Name": "Baiqian" // \u53ef\u4ee5\u548c\u5c5e\u6027\u4e0d\u4e00\u6837\n}\n')),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,7}",showLineNumbers:!0,"{6,7}":!0},'public class AppInfoOptions : IConfigurableOptions\n{\n public string Name { get; set; }\n public string Version { get; set; }\n\n [MapSettings("Company_Name")] // \u652f\u6301\u81ea\u5b9a\u4e49\n public string Company { get; set; }\n}\n')),(0,r.kt)("ol",{start:4},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u65e5\u5fd7\u89c4\u8303\u5316\u6a21\u677f"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},'// \u751f\u6210\u6a21\u677f\u5b57\u7b26\u4e32\nvar template = TP.Wrapper("Furion \u6846\u67b6", "\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",\n "[\u4f5c\u8005] \u767e\u5c0f\u50e7",\n "[\u5f53\u524d\u7248\u672c] v3.5.3",\n "[\u6587\u6863\u5730\u5740] https://furion.icu",\n "[Copyright] \u767e\u5c0f\u50e7, Baiqian Co.,Ltd.");\nConsole.WriteLine(template);\n')),(0,r.kt)("p",null,"\u8f93\u51fa\u7ed3\u679c"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"\u250f\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Furion \u6846\u67b6 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 \u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002\n\u2523\n\u2523 \u4f5c\u8005\uff1a \u767e\u5c0f\u50e7\n\u2523 \u5f53\u524d\u7248\u672c\uff1a v3.5.3\n\u2523 \u6587\u6863\u5730\u5740\uff1a https://furion.icu\n\u2523 Copyright\uff1a \u767e\u5c0f\u50e7, Baiqian Co.,Ltd.\n\u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Furion \u6846\u67b6 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n")),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v342\u5df2\u53d1\u5e03"},"v3.4.2\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c4\u8303\u5316\u6587\u4ef6 ",(0,r.kt)("inlineCode",{parentName:"li"},"EnableAllGroups")," \u529f\u80fd\uff0c\u53ef\u4ee5\u5c06\u591a\u4e2a\u5206\u7ec4\u5408\u5e76\u5230\u4e00\u4e2a\u5206\u7ec4\u4e2d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/9277b982ce024bac8ab5117ba02c3bd96ad07972"},"9277b98")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"angular-utils")," \u5ba2\u6237\u7aef\u5de5\u5177\u5e93\uff0c\u4e13\u95e8\u5904\u7406 ",(0,r.kt)("inlineCode",{parentName:"li"},"angular")," \u9879\u76ee\u63a5\u53e3\u4ee3\u7406\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6c705848a77fbf7234070d0ef9f053a85cc8838a"},"6c70584")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u652f\u6301\u5355\u4e2a\u63a5\u53e3\u66f4\u591a\u63cf\u8ff0\u529f\u80fd\uff08\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"html"),"\uff09",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/e5e1db09710dab02966330063935bd5e5b7e4dc8"},"e5e1db0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u63a5\u53e3 ",(0,r.kt)("inlineCode",{parentName:"li"},"[Obsolete]")," \u8fc7\u65f6\u652f\u6301\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/e5e1db09710dab02966330063935bd5e5b7e4dc8"},"e5e1db0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001 ",(0,r.kt)("inlineCode",{parentName:"li"},"API")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"[ApiDescriptionSettings]")," \u7279\u6027 \u548c",(0,r.kt)("inlineCode",{parentName:"li"},"DynamicApiControllerSettings")," \u914d\u7f6e \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ForceWithRoutePrefix")," \u53c2\u6570\uff0c\u652f\u6301\u5f3a\u5236\u590d\u5199 ",(0,r.kt)("inlineCode",{parentName:"li"},"[Route]")," \u7279\u6027\u5e76\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"DefaultRoutePrefix")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I59B74"},"#I59B74")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5185\u7f6e]"," \u9ed8\u8ba4\u5185\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"GBK"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"Windows-1252"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"Shift-JIS"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"GB2312")," \u7b49\u7f16\u7801\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/c456ecb225b099e5d24add32024f16c359414532"},"c456ecb")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u811a\u624b\u67b6"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"")," \u4e0d\u80fd\u8de8\u7a0b\u5e8f\u96c6\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/3b9d39ce691f9505c5541a790103fbb0ba6d35af"},"3b9d39c")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"")," \u4e0d\u652f\u6301\u5e26\u53c2\u6570\uff0c\u4e0d\u652f\u6301\u9690\u5f0f\u5b9e\u73b0\u63a5\u53e3\u6ce8\u91ca\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I59A6W#note_10699021_link"},"#I59A6W#note_10699021")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"v3.3.1")," \u7248\u672c\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e0d\u80fd\u663e\u793a\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/676335264478d68b99db009d32b65de781702605"},"6763352")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"JSON"),"\u4ee5\u53ca ",(0,r.kt)("inlineCode",{parentName:"li"},"Web")," \u9875\u9762\u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"GBK"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"GB2312")," \u7b49\u56fd\u6807\u7f16\u7801\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/c456ecb225b099e5d24add32024f16c359414532"},"c456ecb")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u54cd\u5e94\u62a5\u6587\u8bbe\u7f6e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"Content-Type:charset=")," \u4e0d\u80fd\u81ea\u52a8\u8f6c\u6362\u7f16\u7801\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/c456ecb225b099e5d24add32024f16c359414532"},"c456ecb")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"axios-utils.ts")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"angular-utils.ts")," \u591a\u5ba2\u6237\u7aef\u652f\u6301"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"GlobalUsings")," \u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://dotnetchina.gitee.io/furion/blog/global-usings"},"\u6587\u6863\u5730\u5740")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8bf7\u6c42\u5927\u5c0f/\u4e0a\u4f20\u5927\u5c0f\u9650\u5236\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://dotnetchina.gitee.io/furion/docs/file-provider/#317-%E8%AF%B7%E6%B1%82%E5%A4%A7%E5%B0%8F%E6%8E%A7%E5%88%B6%E4%B8%8A%E4%BC%A0%E6%96%87%E4%BB%B6%E5%A4%A7%E5%B0%8F%E6%8E%A7%E5%88%B6"},"\u6587\u6863\u5730\u5740")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u89c4\u8303\u5316\u6587\u6863\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u6587\u6863\uff0c\u52a8\u6001 API \u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"strong"},"All Groups")," \u5206\u7ec4\u529f\u80fd"))),(0,r.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u4e3a\u4e86\u66f4\u597d\u7684\u5bf9\u63a5\u53e3\u8fdb\u884c\u5f52\u7c7b\uff0c\u914d\u7f6e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u591a\u4e2a\u5206\u7ec4\u7684\u529f\u80fd\uff0c\u4f46\u8fd9\u6837\u4e5f\u5bf9\u751f\u6210\u5ba2\u6237\u7aef\u8bf7\u6c42\u4ee3\u7801\u9020\u6210\u4e86\u56f0\u6270\uff0c\u6240\u4ee5\u6dfb\u52a0\u4e86\u65b0\u7684\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-3}",showLineNumbers:!0,"{2-3}":!0},'{\n "SpecificationDocumentSettings": {\n "EnableAllGroups": true\n }\n}\n')),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u63a5\u53e3\u8fc7\u65f6\u63a7\u5236"))),(0,r.kt)("p",null,"\u5f53\u6211\u4eec\u67d0\u4e2a\u63a5\u53e3\u5df2\u7ecf\u8fc7\u65f6\uff0c\u63d0\u793a\u5c3d\u65e9\u8c03\u7528\u6700\u65b0\u63a5\u53e3\uff0c\u53ea\u9700\u8981\u5728\u65b9\u6cd5\u4e0a\u9762\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[Obsolete]")," \u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,7}",showLineNumbers:!0,"{1,7}":!0},'[Obsolete("GetName() \u5df2\u7ecf\u8fc7\u65f6\uff0c\u8bf7\u8c03\u7528 GetFrameworkName() \u66ff\u4ee3")]\npublic string GetName()\n{\n return nameof(Furion);\n}\n\n[Obsolete]\npublic string Other()\n{\n // ...\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/swg2.png")}),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u5355\u4e00\u63a5\u53e3\u66f4\u591a\u63cf\u8ff0"))),(0,r.kt)("p",null,"\u5728\u8be5\u7248\u672c\u65b0\u589e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"[ApiDescriptionSettings]")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Description")," \u5c5e\u6027\uff0c\u652f\u6301\u5b9a\u4e49\u66f4\u591a\u63cf\u8ff0\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},'[ApiDescriptionSettings(Description = "\u6211\u662f\u4e00\u6bb5\u63cf\u8ff0\uff0c\u663e\u793a\u66f4\u591a\u5185\u5bb9 ")]\npublic string add()\n{\n //....\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/swg1.png")}),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v333\u5df2\u53d1\u5e03"},"v3.3.3\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u6587\u4ef6\u4e0a\u4f20\u81ea\u52a8\u8bc6\u522b ",(0,r.kt)("inlineCode",{parentName:"li"},"Content-Type")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Mime")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I57ZMN"},"#I57ZMN")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u65b9\u6cd5\u652f\u6301\u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Content-Type")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Encoding")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I57ZMN"},"#I57ZMN")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6839\u636e\u6587\u4ef6\u540d\u83b7\u53d6 ",(0,r.kt)("inlineCode",{parentName:"li"},"Content-Type")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Mime")," \u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/8f78184f8661830744592c054b65d503346c1b27"},"#8f78184")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c4\u8303\u5316\u6587\u6863\u652f\u6301\u6388\u6743\u8bbf\u95ee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/32aa3b6328d23a5885033837883c7b546e898d43"},"#32aa3b6")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4ee3\u7801\u6ce8\u91ca\uff0c\u89c4\u8303\u5316\u6587\u6863\u6ce8\u91ca ",(0,r.kt)("inlineCode",{parentName:"li"},"inheritdoc")," \u8bed\u6cd5\u652f\u6301 \u2764\ufe0f\ufe0f\ufe0f\ufe0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I59A6W"},"#159A6W")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"Vue2/3"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"React 16.8+"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"Angular 9+")," \u524d\u7aef\u8bf7\u6c42\u5de5\u5177\u5e93\uff0c\u5b9e\u73b0\u540e\u7aef API \u4ee3\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/tree/net6/clients/axios"},"axios-utils")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4ee3\u7801\u6ce8\u91ca\uff0c\u89c4\u8303\u5316\u6587\u6863\u6ce8\u91ca ",(0,r.kt)("inlineCode",{parentName:"li"},"inheritdoc")," \u8bed\u6cd5\u652f\u6301 \u2764\ufe0f\ufe0f\ufe0f\ufe0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I59A6W"},"#159A6W")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".NET")," \u6240\u6709\u4f9d\u8d56\u5305\u81f3 ",(0,r.kt)("inlineCode",{parentName:"li"},"v6.0.5")," \u7248\u672c"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u5b9a\u4e49\u5168\u5c40\u5f02\u5e38 ",(0,r.kt)("inlineCode",{parentName:"li"},"Exception")," \u540e\u5bfc\u81f4\u83b7\u53d6\u9519\u8bef\u884c\u53f7\uff0c\u6587\u4ef6\u7a7a\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I53EGM"},"#I53EGM")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4f20\u9012\u7a7a\u59d4\u6258\u5bfc\u81f4\u7a7a\u5f15\u7528\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I519AW"},"#I519AW")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b57\u7b26\u4e32\u6a21\u677f\u6a21\u677f ",(0,r.kt)("inlineCode",{parentName:"li"},"Render")," \u62d3\u5c55\u65b9\u6cd5\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"void")," \u95ee\u9898\uff0c\u5e94\u8be5\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"string")," ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/MonkSoul/Furion/issues/99#issuecomment-1073131906"},"Github-#99")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u6587\u4ef6\u4e0a\u4f20\u51fa\u73b0\u7a7a\u60c5\u51b5\u95ee\u9898\uff08\u539f\u56e0\u662f\u7f3a\u5931 ",(0,r.kt)("inlineCode",{parentName:"li"},"Content-Type")," \uff09",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I57ZMN"},"I57ZMN")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u6846\u67b6\u6e90\u7801\u5f15\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"GlobalUsings")," \u673a\u5236\uff0c\u51cf\u5c11\u4ee3\u7801\u4f53\u79ef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/7e9cc1c205750906cddd540ad08a4c02f14efa3a"},"#7e9cc1c")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u8de8\u57df\u8bf7\u6c42\u7684\u9884\u68c0\u8bbe\u7f6e\uff0c\u5982\u679c\u672a\u8bbe\u7f6e\uff0c\u5219\u9ed8\u8ba4\u4e3a 24 \u5c0f\u65f6\uff0c\u4e3b\u8981\u89e3\u51b3\u524d\u7aef\u591a\u6b21\u53d1\u9001 204 \u9884\u68c0\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4a11e7c9fa20b4419ac00f6ad21c078500d00791"},"4a11e7c")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u89c6\u56fe\u5f15\u64ce\u53cd\u5c04\u6027\u80fd"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7c98\u571f\u5bf9\u8c61\u5e8f\u5217\u5316 ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON")," \u914d\u7f6e\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u524d\u7aef\u89e3\u5bc6 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT")," \u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5c06 ",(0,r.kt)("inlineCode",{parentName:"li"},"byte[]")," \u8f6c ",(0,r.kt)("inlineCode",{parentName:"li"},"url")," \u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u4e8c\u7ea7\u865a\u62df\u76ee\u5f55\u90e8\u7f72\u6587\u6863\uff0c\u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863\uff0c\u6587\u4ef6\u4e0a\u4f20\u6587\u6863\uff0c\u5b89\u5168\u6388\u6743\u6587\u6863\u3001\u89c4\u8303\u5316\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"\u2764\ufe0f\ufe0f\ufe0f\ufe0f ",(0,r.kt)("strong",{parentName:"li"},"\u6839\u636e\u6587\u4ef6\u540d\u83b7\u53d6 ",(0,r.kt)("inlineCode",{parentName:"strong"},"MIME")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Content-Type")," \u7c7b\u578b"))))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var success = FS.TryGetContentType("image.png", out var contentType); // image/png\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u2764\ufe0f\ufe0f\ufe0f\ufe0f ",(0,r.kt)("strong",{parentName:"li"},"\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Swagger")," \u914d\u7f6e\u767b\u5f55\u540e\u624d\u80fd\u8bbf\u95ee"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-6}",showLineNumbers:!0,"{2-6}":!0},'{\n "SpecificationDocumentSettings": {\n "LoginInfo": {\n "Enabled": true,\n "CheckUrl": "\u68c0\u67e5\u767b\u5f55\u5730\u5740",\n "SubmitUrl": "\u63d0\u4ea4\u767b\u5f55\u5730\u5740"\n }\n }\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/swgdl.png")}),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"./specification-document#6529-%E5%B8%A6%E7%99%BB%E5%BD%95%E7%9A%84-swagger-%E6%96%87%E6%A1%A3"},"\u67e5\u770b\u8be6\u7ec6\u6587\u6863")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u2764\ufe0f\ufe0f\ufe0f\ufe0f ",(0,r.kt)("strong",{parentName:"li"},"\u652f\u6301\u4ee3\u7801\u6ce8\u91ca\u7ee7\u627f\uff0cSwagger \u6587\u6863\u6ce8\u91ca\u4e5f\u652f\u6301"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4,10}",showLineNumbers:!0,"{1,4,10}":!0},'/// \npublic class TestInheritdoc : ITestInheritdoc, IDynamicApiController\n{\n /// \n public string GetName()\n {\n return "Furion";\n }\n\n /// \n public string GetVersion()\n {\n return "3.3.3";\n }\n}\n\n/// \n/// \u6d4b\u8bd5\u6ce8\u91ca\u7ee7\u627f\n/// \npublic interface ITestInheritdoc\n{\n /// \n /// \u83b7\u53d6\u540d\u79f0\n /// \n /// \n string GetName();\n\n /// \n /// \u83b7\u53d6\u7248\u672c\n /// \n /// \n string GetVersion();\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/cdr22.png")}),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"./specification-document#6530-inheritdoc-%E5%AE%9E%E7%8E%B0%E6%B3%A8%E9%87%8A%E7%BB%A7%E6%89%BF"},"\u67e5\u770b\u8be6\u7ec6\u6587\u6863")),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v320\u5df2\u53d1\u5e03"},"v3.2.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IFormFile")," \u62d3\u5c55\u65b9\u6cd5 ",(0,r.kt)("inlineCode",{parentName:"li"},"ToByteArray()")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/da69640da2331e2c8582b88bbda965c5ad7ecbe0"},"da69640")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c4\u8303\u5316\u6587\u6863 ",(0,r.kt)("inlineCode",{parentName:"li"},"ServeDir")," \u865a\u62df\u76ee\u5f55\u914d\u7f6e\u529f\u80fd\uff0c\u652f\u6301\u4e00\u952e\u5c06\u4e00\u7ea7\u76ee\u5f55\u5207\u6362\u81f3\u4e8c\u7ea7\u76ee\u5f55\u90e8\u7f72\uff08IIS\uff09",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/87183921ac8b6f9856db01b4de679b858a58e753"},"8718392")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u6240\u6709\u4f9d\u8d56\u5305\u81f3\u6700\u65b0\u7248"),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u4f9d\u8d56\u6ce8\u5165\u6a21\u5757\u6838\u5fc3\u4ee3\u7801\uff0c\u79fb\u9664\u6ce8\u518c\u670d\u52a1\u91c7\u7528\u53cd\u5c04\u673a\u5236\uff0c\u51cf\u5c11\u53cd\u5c04\u6027\u80fd\u635f\u8017 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/acdb3157af92891610a1ba6d317b6af3f09e233f"},"acdb315")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"schema")," \u7c7b\u578b\u5982\u679c\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"C# Object")," \u7c7b\u578b\u65e0\u6cd5\u6b63\u786e\u751f\u6210\u524d\u7aef\u4ee3\u7801\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/swagger-api/swagger-codegen-generators/issues/692"},"Swagger \u5b98\u65b9 Issue")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/1a252747fd60fc87a8ed4425c8edf7803f96ce43"},"1a25274")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u53d1\u5e03\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"Windows Services")," \u65f6\u65e5\u5fd7\u7edd\u5bf9\u8def\u5f84\u95ee\u9898 \u611f\u8c22 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/jacoat"},"@jacoat")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/467"},"!467")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Nginx")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"IIS")," \u5bf9\u4e8c\u7ea7\u865a\u62df\u76ee\u5f55\u914d\u7f6e\u4e0d\u540c\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},"404")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/87183921ac8b6f9856db01b4de679b858a58e753"},"8718392")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u6a21\u5757\u672a\u521d\u59cb\u5316 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnRequestFailded")," \u5bfc\u81f4\u7a7a\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I54PK7"},"#I54PK7")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4f9d\u8d56\u6ce8\u5165\u53cd\u5c04\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Not found Method")," bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I546L1"},"#I546L1")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u5b9a\u65f6\u4efb\u52a1\u5931\u8d25\u540e\u5f02\u5e38\u5904\u7406\u903b\u8f91\uff0c\u611f\u8c22 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/cxs1992"},"@\u7a0b\u5c0f\u80dc")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/463"},"!463")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u5b9a\u65f6\u4efb\u52a1\u6587\u6863\uff0c\u65e5\u5fd7\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6587\u4ef6\u4e0a\u4f20/\u4e0b\u8f7d \u6587\u6863\uff0c\u5305\u542b\u5355\u6587\u4ef6/\u591a\u6587\u4ef6/Base64/Byte[]")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v310\u5df2\u53d1\u5e03"},"v3.1.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u6a21\u5757\u5f02\u5e38 ",(0,r.kt)("inlineCode",{parentName:"li"},"Http")," \u72b6\u6001\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/462"},"!462")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001 WebAPI \u652f\u6301\u5c0f\u9a7c\u5cf0\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4W1R4"},"#I4W1R4")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"SendAsByteArrayAsync")," \u7b49\u4e00\u7cfb\u5217\u65b9\u6cd5\uff0c\u652f\u6301\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"byte[]")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/452"},"!452")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"GZip")," \u538b\u7f29\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I506S5"},"#I506S5")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".NET6")," \u4f9d\u8d56\u5305\u5168\u90e8\u5347\u7ea7\u81f3 ",(0,r.kt)("inlineCode",{parentName:"li"},"Nuget")," \u6700\u65b0\u7248 ",(0,r.kt)("inlineCode",{parentName:"li"},"v6.0.3")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".NET6 WebApplication")," \u6a21\u5f0f\u4e8c\u7ea7\u865a\u62df\u76ee\u5f55\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4UZLM"},"#I4UZLM")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4PZ0C"},"#I4PZ0C")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u65e5\u671f\u9a8c\u8bc1\u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"2022-03-01 0:00:00"),"\uff08\u73b0\u5728\u652f\u6301\u5c0f\u65f6\u57df ",(0,r.kt)("inlineCode",{parentName:"li"},"0")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"00"),"\uff09 \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4Y3NT"},"#I4Y3NT")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u73af\u5883\u914d\u7f6e\u548c\u6587\u4ef6\u914d\u7f6e\u4f18\u5148\u7ea7\u95ee\u9898"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8131\u654f\u6a21\u5757\u66ff\u6362\u654f\u611f\u8bcd\u6c47\u53ea\u66ff\u6362\u6700\u540e\u4e00\u4e2a bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4YFA0"},"#I4YFA0")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u8fd4\u56de\u5b57\u7b26\u4e32\u4e2a\u522b\u60c5\u51b5\u51fa\u73b0\u4e2d\u6587\u4e71\u7801\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I50GBD"},"#I50GBD")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[DataValidate]")," \u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"AllowNullValue")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"AllowEmptyString")," \u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4ZZBE"},"#I4ZZBE")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8fc7\u65f6]"," \u6807\u8bb0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.Logging.Serilog")," \u62d3\u5c55\u5305 ",(0,r.kt)("inlineCode",{parentName:"li"},"IWebHost")," \u62d3\u5c55\u4e3a\u8fc7\u65f6\u72b6\u6001"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6587\u6863]"," \u4f18\u5316\u6587\u6863\u4f53\u9a8c\uff0c\u65b0\u589e\u9762\u5305\u5c51\u5bfc\u822a\uff0c\u91cd\u5199\u6587\u6863\u7f13\u5b58\uff0c\u63d0\u5347\u6587\u6863\u8bbf\u95ee\u901f\u5ea6"),(0,r.kt)("li",{parentName:"ul"},"[\u6587\u6863]"," \u66f4\u65b0\u52a8\u6001 API \u6587\u6863\u3001\u914d\u7f6e\u6587\u6863\u3001\u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u6587\u6863]"," \u66f4\u65b0\u4e8c\u7ea7\u865a\u62df\u76ee\u5f55\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"\u65b0\u589e\u52a8\u6001 ",(0,r.kt)("inlineCode",{parentName:"li"},"WebApi")," \u652f\u6301\u5c0f\u9a7c\u5cf0\u8def\u5f84\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"li"},"GetMyName")," -> ",(0,r.kt)("inlineCode",{parentName:"li"},"getMyName"),"\uff1a")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "DynamicApiControllerSettings": {\n "LowercaseRoute": false,\n "KeepName": true,\n "AsLowerCamelCase": true\n }\n}\n')),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},"\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},".NET6 WebApplication")," \u6a21\u5f0f\u4e8c\u7ea7\u865a\u62df\u76ee\u5f55\u914d\u7f6e\uff1a")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {title="Progame.cs"}',showLineNumbers:!0,"":!0,"{title":'"Progame.cs"}'},"app.UseVirtualPath(app =>\n{\n app.UseInject(String.Empty); // \u6ce8\u610f String.Empty \u53ea\u662f\u4f8b\u5b50\uff0c\u53ef\u4ee5\u4e0d\u586b\u6216\u586b\u5176\u4ed6\u7684\uff0c\u89c1\u4e00\u5206\u949f\u5165\u95e8\n app.MapRouteControllers();\n});\n")),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v300\u5df2\u53d1\u5e03"},"v3.0.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("admonition",{title:"v3+ \u7248\u672c\u8bf4\u660e",type:"warning"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("strong",{parentName:"p"},"Furion v3.x \u7248\u672c\u91c7\u7528 .NET6 \u6784\u5efa\u3002"))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"GET")," \u8bf7\u6c42\u81ea\u52a8\u8f6c\u6362 ",(0,r.kt)("inlineCode",{parentName:"li"},"\u7c7b\u7c7b\u578b")," \u7c7b\u578b\u5bf9\u8c61 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4HR5Q"},"#I4HR5Q")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," \u5168\u9762\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},".NET6")," \u7248\u672c"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5f00\u542f\u89c4\u8303\u5316\u7ed3\u679c\u5e76\u81ea\u5b9a\u4e49\u5168\u5c40\u5f02\u5e38\u5bfc\u81f4\u5f02\u5e38\u7ecf\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnSucceeded")," \u8fc7\u6ee4\u5668 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4DTVL"},"#I4DTVL")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".NET5.0.5+")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},".NET6")," \u5fae\u8f6f\u5e95\u5c42\u4fee\u6539\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"[ApiController]")," \u9a8c\u8bc1\u5931\u8d25\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"IActionResult")," \u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4ISOK"},"#I4ISOK")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore 6.0")," \u9002\u914d ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlServer 2005+")," \u51fa\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4ILA5"},"#I4ILA5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," .NET6 \u83b7\u53d6\u914d\u7f6e\u5bf9\u8c61\u5982\u679c\u4e0d\u5b58\u5728\u8fd4\u56de null \u95ee\u9898\uff0c.NET5 \u5219\u8fd4\u56de\u521d\u59cb\u5bf9\u8c61 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/94ae4d8c9b0fe7eb4d713a171f953c0d3c5a76ac"},"94ae4d")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u547d\u4ee4\u53c2\u6570\u4f20\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"Clay")," \u7c7b\u578b\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4D21Q"},"#I4D21Q")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Cron")," \u5b9a\u65f6\u4efb\u52a1\u7279\u6027\u65b9\u5f0f bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4OJQI"},"#I4OJQI")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ToPagedList")," \u6cdb\u578b\u7ea6\u675f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d0244dc33a0e5236158cdcdff21d086e00a42ee7"},"d0244d")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6587\u6863]"," \u67e5\u770b ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("a",{parentName:"strong",href:"https://dotnetchina.gitee.io/furion/docs/get-start-net6"},".NET6 \u4e00\u5206\u949f\u5165\u95e8"))),(0,r.kt)("li",{parentName:"ul"},"[\u6587\u6863]"," \u67e5\u770b ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("a",{parentName:"strong",href:"https://dotnetchina.gitee.io/furion/docs/net5-to-net6"},"Furion v2 \u5347\u7ea7 v3"))))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7279\u522b\u9e23\u8c22")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/KaneLeung"},"KaneLeung"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v220\u5df2\u53d1\u5e03"},"v2.20\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("admonition",{title:"v2.20+ \u7248\u672c\u8bf4\u660e",type:"warning"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("strong",{parentName:"p"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion v2.20+")," \u7248\u672c\u540e\u91c7\u7528 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Jaina"},"Jaina")," \u4e8b\u4ef6\u603b\u7ebf\u66ff\u6362\u539f\u6709\u7684 ",(0,r.kt)("inlineCode",{parentName:"strong"},"EventBus")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"GET")," \u8bf7\u6c42\u81ea\u52a8\u8f6c\u6362 ",(0,r.kt)("inlineCode",{parentName:"li"},"\u7c7b\u7c7b\u578b")," \u7c7b\u578b\u5bf9\u8c61 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4HR5Q"},"#I4HR5Q")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EventBus")," \u6a21\u5757\uff0c\u91c7\u7528 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Jaina"},"Jaina")," \u65b9\u5f0f"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5f00\u542f\u89c4\u8303\u5316\u7ed3\u679c\u5e76\u81ea\u5b9a\u4e49\u5168\u5c40\u5f02\u5e38\u5bfc\u81f4\u5f02\u5e38\u7ecf\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnSucceeded")," \u8fc7\u6ee4\u5668 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4DTVL"},"#I4DTVL")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".NET5.0.5+")," \u5fae\u8f6f\u5e95\u5c42\u4fee\u6539\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"[ApiController]")," \u9a8c\u8bc1\u5931\u8d25\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"IActionResult")," \u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4ISOK"},"#I4ISOK")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u4e0a\u4f20\u6587\u4ef6\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/0c0752c624799d7d3c7661a8f36a93983399bb59"},"0c0752")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6846\u67b6\u542f\u52a8\u4e0d\u652f\u6301\u73af\u5883\u53d8\u91cf ",(0,r.kt)("inlineCode",{parentName:"li"},"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES")," \u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/438"},"!438")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b9a\u65f6\u4efb\u52a1\u5185\u5b58\u548c CPU \u5360\u7528\u53ca\u7279\u6b8a\u60c5\u51b5\u4e0b\u7a7a\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/12c65debf552c57780679e6a567a9dd9fb077f46"},"12c65de")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u9ed8\u8ba4\u63a7\u5236\u5668\u542f\u7528\u89c4\u8303\u5316\u7ed3\u679c\u65e0\u6548 bug",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/c7a4a5ef8c3282d245cbe04124cf379d381d496f"},"c7a4a5e")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u6b63]"," \u4f9d\u8d56\u6ce8\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"InjectionAttribute")," \u7279\u6027\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ExceptInterfaces")," \u5355\u8bcd\u62fc\u5199\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/436"},"!436")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u547d\u4ee4\u53c2\u6570\u4f20\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"Clay")," \u7c7b\u578b\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4D21Q"},"#I4D21Q")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"InjectionAttribute")," \u4ee3\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/435"},"!435")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ToPagedList")," \u6cdb\u578b\u7ea6\u675f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d0244dc33a0e5236158cdcdff21d086e00a42ee7"},"d0244d")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4e8b\u4ef6\u603b\u7ebf\u65b0\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v219\u5df2\u53d1\u5e03"},"v2.19\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9a\u65f6\u4efb\u52a1\u76d1\u542c\u5668 ",(0,r.kt)("inlineCode",{parentName:"li"},"ISpareTimeListener")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I468Q1"},"#I468Q1")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"JsonElement")," \u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/61985d6a300485d553cbe8461b01f01bcd0936ef"},"61985d6")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u914d\u7f6e\u679a\u4e3e\u53ca\u6807\u7b7e\u6392\u5e8f\u8fc7\u6ee4\u5668 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I46LON"},"#I46LON")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/404"},"!404")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"application/octet-stream")," \u7c7b\u578b\u9ed8\u8ba4\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d9bad0320cc4a204e24bc3a070517ebce4cdc5d7"},"d9bad03")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u6a21\u5f0f\u8bf7\u6c42\u62a5\u6587\u5934\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"IDictionary")," \u7c7b\u578b\u3002",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/0204c0afe2de5c28ebbd44b29131e701b93ae8b8"},"0204c0a")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MongoDB")," \u62d3\u5c55\u7c7b\uff0c\u6dfb\u52a0\u66f4\u591a\u5e38\u7528\u64cd\u4f5c\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/423"},"!423")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTimeOffset?")," \u8f6c\u6362 ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTime")," \u62d3\u5c55\uff08\u5305\u542b\u4e92\u6362\uff09 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/432"},"!432")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped.Create")," \u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u8fdb\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"Add-Migration")," \u65f6\u5019\u62a5\u7a7a\u5f02\u5e38\u95ee\u9898\uff0c\u539f\u56e0\u662f\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"PM")," \u73af\u5883\u4e2d\u4e0d\u5b58\u5728\u6839\u670d\u52a1",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/0853e74de90718fce9c0892e2ee4da597f62a918"},"0853e74")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b9a\u65f6\u4efb\u52a1\u6267\u884c\u5f02\u5e38\u540e\u5f02\u5e38\u4e00\u76f4\u9a7b\u7559\u5185\u5b58\u95ee\u9898\uff0c\u4fee\u6b63\u4e3a\u6267\u884c\u6210\u529f\u81ea\u52a8\u6e05\u7a7a\u8fc7\u53bb\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/197a62bb4a7df34eb2c0dbda65121e9cf00d905c"},"197a62b")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Jwt")," \u62d3\u5c55\u5305\u4e0d\u6b63\u786e\u7684\u4ee3\u7801\u5bfc\u81f4 IOptions \u5931\u6548",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I46LUP"},"#I46LUP")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u679a\u4e3e ",(0,r.kt)("inlineCode",{parentName:"li"},"Schema")," \u8fc7\u6ee4\u5668\u4e0d\u8f93\u51fa\u503c\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I46LON"},"#I46LON")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/404"},"!404")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5904\u7406\u975e ",(0,r.kt)("inlineCode",{parentName:"li"},"int")," \u7c7b\u578b\u679a\u4e3e\u8f6c\u6362 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I46QJ9"},"#I46QJ9")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c6\u56fe\u5f15\u64ce\u7f16\u8bd1\u6a21\u677f\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"dll")," \u540e\u518d\u6b21\u52a0\u8f7d\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"IL")," \u683c\u5f0f\u5316\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/ff52d383718b4d34968619f17c9d54d8718b4f3f"},"ff52d38")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u7ba1\u9053 ",(0,r.kt)("inlineCode",{parentName:"li"},"Channel")," \u8bfb\u53d6\u5668\u65e0\u6cd5\u91ca\u653e ",(0,r.kt)("inlineCode",{parentName:"li"},"Handler")," \u5bf9\u8c61\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/10f4a900ee558a29f40ae21366a0eba83eceb3eb"},"10f4a90")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Services")," \u4e0b\u65e5\u5fd7\u4e0d\u8f93\u51fa\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/c48254822c09092906ef77f04d54497e27665a92"},"c482548")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"multipart/form-data")," \u7c7b\u578b\u5bf9\u63a5\u5fae\u4fe1\u5c0f\u7a0b\u5e8f\u4e0a\u4f20\u6587\u4ef6 \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d9bad0320cc4a204e24bc3a070517ebce4cdc5d7"},"d9bad03")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5de5\u4f5c\u5355\u5143\u4e0a\u4e0b\u6587\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\u5171\u4eab\u4e8b\u52a1\u5931\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/006d439de3357d4d58ea6d7d3f9d51771a7b604e"},"006d439")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u679a\u4e3e\u503c\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"GET")," \u8bf7\u6c42\u4e2d ",(0,r.kt)("inlineCode",{parentName:"li"},"Schema")," \u663e\u793a\u4e0d\u6b63\u786e\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/fb72fd7c98de5bf2246dd1bf08200152bd7ab7a0"},"fb72fd7")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"404")," \u4e0d\u8d70\u5f02\u5e38\u8fc7\u6ee4\u5668\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/423"},"!426")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u5b9a\u4e49\u4e8b\u4ef6\u603b\u7ebf\u5e76\u53d1\u60c5\u51b5\u4e0b\u8c03\u7528\u5b8c\u6210\u540e\u65e0\u6cd5\u6b63\u786e\u5904\u7406\u961f\u5217\u6570\u636e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/429"},"!429")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"v2.19+")," \u7248\u672c\u4e4b\u540e\u6a21\u5757\u5316\u5f00\u53d1\u52a0\u8f7d\u5916\u90e8\u7a0b\u5e8f\u96c6\u5931\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/433"},"!433")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b9a\u65f6\u4efb\u52a1 SpareTime \u9891\u7e41\u68c0\u67e5\u5bfc\u81f4 CPU \u589e\u9ad8\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/aa0a2eec95f6ed2b74c681877498900726267d82"},"aa0a2ee")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7279\u522b\u9e23\u8c22")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/YaChengMu"},"YaChengMu"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v218\u5df2\u53d1\u5e03"},"v2.18\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Tools.CommandLine")," \u62d3\u5c55\u5e93 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/tree/net6/tools/Furion.Tools/Furion.Tools.CommandLine"},"\u67e5\u770b\u6e90\u7801")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u57fa\u4e8e ",(0,r.kt)("inlineCode",{parentName:"li"},"AsyncLocal")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"CallContext")," \u5b9e\u73b0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/9057a212aab8057b668086bd14369fa68ce120df"},"9057a21")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u53ef\u914d\u7f6e\u8bf7\u6c42\u5f02\u5e38\u91cd\u8bd5\u7b56\u7565 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/656da87a667c2da7d82425cdcd47146e99602d65"},"656da87")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnRequestFailded")," \u4e8b\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4a3da4ba2c69380fe5f8c2fda80054544c0a3468"},"4a3da4b")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped")," \u6240\u6709\u5e26\u8fd4\u56de\u503c\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/656da87a667c2da7d82425cdcd47146e99602d65"},"656da87")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"strong"},"ConfigureService")," \u4e2d\u8c03\u7528 ",(0,r.kt)("inlineCode",{parentName:"strong"},"App.GetOptions<>()")," \u83b7\u53d6\u914d\u7f6e\u903b\u8f91")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/afa4ac347152ccac37bd1d0f9af1e8ffb665a662"},"afa4ac3"))))),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u5728\u8fc7\u53bb\uff0c\u5f88\u591a\u5f00\u53d1\u8005\u603b\u662f\u559c\u6b22\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u914d\u7f6e\u670d\u52a1\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"ConfigureService")," \u65b9\u6cd5\u4e2d\u89e3\u6790\u670d\u52a1\uff0c\u8fd9\u6837\u5bfc\u81f4\u5185\u5b58\u5b58\u5728\u6ea2\u51fa\u98ce\u9669\uff0cGC \u65e0\u6cd5\u56de\u6536\u3002\n\u6b63\u786e\u7684\u65b9\u5f0f\u662f\u5c3d\u53ef\u80fd\u7684\u907f\u514d ",(0,r.kt)("inlineCode",{parentName:"p"},"ConfigureService")," \u4e2d\u89e3\u6790\u670d\u52a1\u3002",(0,r.kt)("strong",{parentName:"p"},"\u5982\u679c\u9700\u8981\u5728\u3010\u542f\u52a8\u65f6\u3011\u83b7\u53d6 ",(0,r.kt)("inlineCode",{parentName:"strong"},"\u914d\u7f6e\u9009\u9879"),"\uff0c\u8bf7\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"strong"},"App.GetConfig(\u8def\u5f84, true)")," \u4ee3\u66ff ",(0,r.kt)("inlineCode",{parentName:"strong"},"App.GetOptions")),"\u3002")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," v2.16+ \u7248\u672c\u91cd\u6784 ",(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContextBuilder")," \u4e4b\u540e\u5199\u9519\u5b9e\u4f53\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I45E6M"},"#I45E6M")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u5355\u4e2a\u503c\u5e8f\u5217\u5316\u9519\u8bef\u5904\u7406\u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/3282eba2cecb505e339ef3f9c8e823f84dcb43f0"},"3282eba")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," v2.17.3+ \u5355\u5143\u6d4b\u8bd5\u521b\u5efa ",(0,r.kt)("inlineCode",{parentName:"li"},"TestServer")," bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I45JR3"},"#I45JR3")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Retry.Invoke")," \u6b63\u5e38\u65b9\u6cd5\u6b7b\u5faa\u73af bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/392"},"!392")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5237\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u751f\u6210\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u5b58\u5728\u6570\u7ec4/\u96c6\u5408\u7c7b\u578b\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Key")," \u91cd\u590d\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/aeea2b1b19434f3171bd1c77be057ca36ecf9be2"},"aeea2b1")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u5e8f\u5217\u5316\u5f15\u7528\u7c7b\u578b\u5bf9\u8c61\uff08\u4e0d\u542b ",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff09\u4e0d\u6b63\u786e\u7684\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/93cf63a023f3372b80edb5debc46271d2281318a"},"93cf63a")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u9ed8\u8ba4\u79df\u6237\u5c5e\u6027\u53d7\u5de5\u4f5c\u5355\u5143\u5f71\u54cd\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/e51557fdf37ae5646b2ea37c227c970eccdbed38"},"e51557f")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5305\u7ba1\u7406\u5de5\u5177\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u6a21\u677f\u5f15\u64ce\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587")," \u7b49\u7b49\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v217\u5df2\u53d1\u5e03"},"v2.17\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IPC\uff08Inter-Process Communication\uff0c\u8fdb\u7a0b\u95f4\u901a\u4fe1\uff09")," \u6a21\u5757\u529f\u80fd\uff0c\u76ee\u524d\u63d0\u4f9b\u8fdb\u7a0b\u5185\u901a\u4fe1\u548c\u5171\u4eab\u5185\u5b58\u8fdb\u7a0b\u5916\u901a\u8baf ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/tree/net6/framework/Furion/ProcessChannel"},"ProcessChannel")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"application/xml")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"text/xml")," \u9ed8\u8ba4\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4753a1aed527a6282fe6c05036de9d50bd3b3dd8"},"4753a1a")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u63a7\u5236\u53f0\u5168\u5c40\u5f02\u5e38\u62e6\u622a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4a4fe1f40e1856ea36a0c0d19ca625d3f7bf95b7"},"4a4fe1f")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},".json")," \u914d\u7f6e\u6587\u4ef6\u626b\u63cf\u76ee\u5f55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/3e2910a8b775fb6323e293b020bbe7cdfb4c6436"},"3e2910a")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301\u6570\u636e\u5e93\u5b9e\u4f53\u63a5\u53e3\u663e\u5f0f\u5b9e\u73b0\u63a5\u53e3\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/9610a0a481f4f78770bc2fc3ed4cabbef2a8f937"},"9610a0a")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u5168\u5c40\u62e6\u622a ",(0,r.kt)("inlineCode",{parentName:"li"},"[IfException]")," \u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4a4fe1f40e1856ea36a0c0d19ca625d3f7bf95b7"},"4a4fe1f")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4f9d\u8d56\u6ce8\u5165\u6a21\u5757\u63a5\u53e3\u53ef\u4ee5\u9650\u5236\u5b9e\u73b0\u7c7b\u751f\u5b58\u5468\u671f\uff0c\u5b9e\u73b0\u7c7b\u4e5f\u652f\u6301\u590d\u5199\u751f\u5b58\u5468\u671f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d2ce089130300cdd8b1bc6792f325c5d38ee9404"},"d2ce089")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u62bd\u79bb]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Retry()")," \u91cd\u8bd5\u7b56\u7565\u529f\u80fd\u81f3\u65b0\u7c7b\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Retry.Invoke()")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6a7bbd0b30a653b9a42d340a63520485aa6bbfa4"},"6a7bbd0")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IHttpContextAccessor.SigninToSwagger()")," \u62d3\u5c55\uff0c\u8bf7\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"IHttpContextAccessor.HttpContext.SigninToSwagger()"),"\uff0c\u9000\u51fa\u4e5f\u4e00\u6837"),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u5168\u5c40\u5904\u7406 ",(0,r.kt)("inlineCode",{parentName:"li"},"Request Body")," \u91cd\u590d\u8bfb\u5904\u7406 ",(0,r.kt)("inlineCode",{parentName:"li"},"Request.EnableBuffering()")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d92c24bdb43bfb01643007ebb6a4ee42a5c738e9"},"d92c24b")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c4\u8303\u5316\u72b6\u6001\u7801\u8fc7\u6ee4\u903b\u8f91\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I44JYS"},"#I44JYS")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u975e\u5173\u7cfb\u578b\u6570\u636e\u5e93\uff08\u5185\u5b58\u6570\u636e\u5e93\uff09\u6ce8\u518c\u53ca\u64cd\u4f5c\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/e1676512a54374427bedbde17cd8cb59d7852557"},"e167651")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u9ed8\u8ba4\u5e8f\u5217\u5316\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a55603bf7ed109296375dbeffc31591a6f8f8e49"},"a55603b")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b9a\u65f6\u4efb\u52a1\u96f6\u70b9/\u6574\u70b9\u63d0\u524d\u4e00\u79d2\u89e6\u53d1\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4321L"},"#I4321L")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u53cb\u597d\u5f02\u5e38\u5728\u5b50\u7c7b\u91cd\u5199\u62bd\u8c61\u7c7b\u65b9\u6cd5\u5185\u90e8\u629b\u5f02\u5e38\u65e0\u6cd5\u83b7\u53d6\u7684\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4a4fe1f40e1856ea36a0c0d19ca625d3f7bf95b7"},"4a4fe1f")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u975e Web \u9879\u76ee\u629b\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4a4fe1f40e1856ea36a0c0d19ca625d3f7bf95b7"},"4a4fe1f")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u5b9e\u4f53\u6a21\u578b\u8d34 ",(0,r.kt)("inlineCode",{parentName:"li"},"[NotMapper]")," \u7279\u6027\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I44MNO"},"#I44MNO")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," Swagger \u751f\u6210\u6cdb\u578b SchemaIds \u9ed8\u8ba4\u8fde\u63a5\u7b26\uff0c\u7531 ",(0,r.kt)("inlineCode",{parentName:"li"},"Of")," \u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"_")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/81946b64e81d9e290f80cd5bcebdb69c99001153"},"81946b6"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v216\u5df2\u53d1\u5e03"},"v2.16\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"MVC")," \u63a7\u5236\u5668\u652f\u6301\u89c4\u8303\u5316\u5904\u7406 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I427Z2"},"#I427Z2"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"throw Oops.Bah()")," \u629b\u51fa\u4e1a\u52a1\u5f02\u5e38\uff08\u72b6\u6001\u7801 ",(0,r.kt)("inlineCode",{parentName:"li"},"400"),"\uff09"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"UnifyResultSettings")," \u89c4\u8303\u5316 ",(0,r.kt)("inlineCode",{parentName:"li"},"json")," \u914d\u7f6e\u9009\u9879 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I42NY7"},"#I42NY7")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u591a\u8bed\u8a00\u81ea\u5b9a\u4e49\u914d\u7f6e\u8d44\u6e90\u6587\u4ef6\u540d\u53ca\u81ea\u5b9a\u4e49\u7a0b\u5e8f\u96c6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I434YJ"},"#I434YJ")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u89c4\u8303\u5316\u7ed3\u679c ",(0,r.kt)("inlineCode",{parentName:"li"},"IUnifyResultProvider")," \u53c2\u6570 ",(0,r.kt)("strong",{parentName:"li"},"\uff08\u7834\u574f\u6027\u66f4\u6539\uff09")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I427Z2"},"#I427Z2")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IJsonSerializerProvider")," \u63a5\u53e3\u53c2\u6570\uff0c\u53bb\u6389 ",(0,r.kt)("inlineCode",{parentName:"li"},"inherit")," \u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a55603bf7ed109296375dbeffc31591a6f8f8e49"},"a55603b"))))),(0,r.kt)("admonition",{title:"\u65b0\u7248\u672c\u81ea\u5b9a\u4e49\u89c4\u8303\u5316\u7ed3\u679c",type:"important"},(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {15-16}",showLineNumbers:!0,"":!0,"{15-16}":!0},'using Furion.DataValidation;\nusing Furion.DependencyInjection;\nusing Furion.UnifyResult.Internal;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.Filters;\nusing System;\nusing System.Threading.Tasks;\n\nnamespace Furion.UnifyResult\n{\n /// \n /// RESTful \u98ce\u683c\u8fd4\u56de\u503c\n /// \n [SuppressSniffer, UnifyModel(typeof(RESTfulResult<>))]\n public class RESTfulResultProvider : IUnifyResultProvider\n {\n /// \n /// \u5f02\u5e38\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata)\n {\n return new JsonResult(RESTfulResult(metadata.StatusCode, errors: metadata.Errors));\n }\n\n /// \n /// \u6210\u529f\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n public IActionResult OnSucceeded(ActionExecutedContext context, object data)\n {\n return new JsonResult(RESTfulResult(StatusCodes.Status200OK, true, data));\n }\n\n /// \n /// \u9a8c\u8bc1\u5931\u8d25\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n public IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata)\n {\n return new JsonResult(RESTfulResult(StatusCodes.Status400BadRequest, errors: metadata.ValidationResult));\n }\n\n /// \n /// \u7279\u5b9a\u72b6\u6001\u7801\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n /// \n public async Task OnResponseStatusCodes(HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings)\n {\n // \u8bbe\u7f6e\u54cd\u5e94\u72b6\u6001\u7801\n UnifyContext.SetResponseStatusCodes(context, statusCode, unifyResultSettings);\n\n switch (statusCode)\n {\n // \u5904\u7406 401 \u72b6\u6001\u7801\n case StatusCodes.Status401Unauthorized:\n await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "401 Unauthorized")\n , App.GetOptions()?.JsonSerializerOptions);\n break;\n // \u5904\u7406 403 \u72b6\u6001\u7801\n case StatusCodes.Status403Forbidden:\n await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "403 Forbidden")\n , App.GetOptions()?.JsonSerializerOptions);\n break;\n default: break;\n }\n }\n\n /// \n /// \u8fd4\u56de RESTful \u98ce\u683c\u7ed3\u679c\u96c6\n /// \n /// \n /// \n /// \n /// \n /// \n private static RESTfulResult RESTfulResult(int statusCode, bool succeeded = default, object data = default, object errors = default)\n {\n return new RESTfulResult\n {\n StatusCode = statusCode,\n Succeeded = succeeded,\n Data = data,\n Errors = errors,\n Extras = UnifyContext.Take(),\n Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()\n };\n }\n }\n}\n'))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MVC")," \u63a7\u5236\u5668\u542f\u7528\u89c4\u8303\u5316\u5904\u7406\u540e\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"new Json({})")," \u5bf9\u8c61\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"null")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4354S"},"#I4354S")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u591a\u8bed\u8a00\u5e95\u5c42\u8bbe\u8ba1\uff0c\u53d6\u6d88\u9700\u8981\u521b\u5efa ",(0,r.kt)("inlineCode",{parentName:"li"},"Lang.cs")," \u7a7a\u7c7b\u7684\u8981\u6c42 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I434YJ"},"#I434YJ")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MiniProfiler")," \u6027\u80fd\uff0c\u51cf\u5c11\u4e0d\u5fc5\u8981\u7684\u76d1\u542c")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v215\u5df2\u53d1\u5e03"},"v2.15\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetDbRepository<\u5b9a\u4f4d\u5668>()")," \u9759\u6001\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I41MZP"},"#I41MZP")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u7f3a\u7701\u5e8f\u5217\u5316\u914d\u7f6e\u9009\u9879 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I41PBW"},"#I41PBW")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u52a8\u626b\u63cf\u63a5\u53e3\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165\u83b7\u53d6\u9996\u4e2a\u63a5\u53e3\u9519\u8bef bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I41D1M"},"#I41D1M")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IRepository")," \u6ca1\u6709\u5b9e\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"IRepository")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I41MZP"},"#I41MZP")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u7f3a\u7701\u5e8f\u5217\u5316 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I41PBW"},"#I41PBW")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d ",(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext.Tenant")," \u591a\u79df\u6237\u7a7a\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I421DA"},"#I421DA")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u591a\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker")," \u5b9a\u65f6\u4efb\u52a1\u963b\u585e\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/82a79cce0a3d9b09f4090b7363c3b78327c76846"},"82a79cc")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Jwt")," \u81ea\u52a8\u5237\u65b0\u673a\u5236\u65f6\u533a\u5904\u7406\u95ee\u9898\uff0c\u4e3b\u8981\u9488\u5bf9\u56fd\u5916\u7528\u6237 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I41UB1"},"#I41UB1")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/82a79cce0a3d9b09f4090b7363c3b78327c76846"},"82a79cc")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("strong",{parentName:"li"},"\u7cfb\u7edf\u542f\u52a8\u6027\u80fd\uff0c\u4ece 106M \u51cf\u5c11\u5230 84M")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("strong",{parentName:"li"},"\u5927\u91cf\u5e95\u5c42\u4ee3\u7801\uff0c\u5305\u5927\u5c0f\u4ece 391Kb \u51cf\u5c11\u5230 350Kb\uff08\u4e0d\u5e26\u6ce8\u91ca\u7248\u672c\u4ec5 64Kb\uff09"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v213v214\u5df2\u53d1\u5e03"},"v2.13/v2.14\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7b80\u6613\u5b57\u7b26\u4e32\u6a21\u677f\u529f\u80fd\uff0c\u652f\u6301\u8fdc\u7a0b\u8bf7\u6c42\u3001\u6570\u636e\u5e93\u6a21\u5757\u3001\u65e5\u5fd7\u6a21\u5757\u3001\u4e8b\u4ef6\u603b\u7ebf\u6a21\u5757\u3001\u5b9a\u65f6\u4efb\u52a1\u6a21\u5757\u3001\u5f02\u5e38\u6a21\u5757\u3001\u6570\u636e\u6821\u9a8c\u6a21\u5757 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I402BL"},"#I402BL")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"404")," \u72b6\u6001\u7801\u89c4\u8303\u5316\u9ed8\u8ba4\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I408F5"},"#I408F5")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9a\u65f6\u4efb\u52a1 ",(0,r.kt)("inlineCode",{parentName:"li"},"ISpareTimeWorker")," \u58f0\u660e\u65b9\u5f0f\u652f\u6301\u5f02\u6b65\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I40KWR"},"#I40KWR")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u81ea\u52a8\u914d\u7f6e\u4e8c\u7ea7\u865a\u62df\u76ee\u5f55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/354"},"!354")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," ",(0,r.kt)("strong",{parentName:"li"},"\u6846\u67b6\u4f9d\u8d56 ",(0,r.kt)("inlineCode",{parentName:"strong"},"SDK")," \u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},".NET 5.0.8")," \u7248\u672c")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetNewDbContext()")," \u9759\u6001\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I400BK"},"#I400BK")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u6570\u636e\u5e93\u6a21\u5757\u65f6\u6001\u8868\u62d3\u5c55\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I405HI"},"#I405HI")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IJsonSerializerProvider")," \u63a5\u53e3\u53c2\u6570\uff0c\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"inherit")," \u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ZQU5"},"#I3ZQU5")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppSettings")," \u914d\u7f6e\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"LogEntityFrameworkCoreSqlExecuteCommand")," \u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"OutputOriginalSqlExecuteLog")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I40VVE"},"#I40VVE")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Services")," \u5b9a\u65f6\u4efb\u52a1\u8fb9\u754c\u503c\u95ee\u9898\u5bfc\u81f4\u8df3\u8fc7\u5355\u6b21\u4efb\u52a1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I405NI"},"#I405NI")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Services")," \u72ec\u7acb\u53d1\u5e03\u540e\u7a0b\u5e8f\u96c6\u626b\u63cf\u5931\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ZH3X"},"#I3ZH3X")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u5982\u679c\u914d\u7f6e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"Client")," \u5ba2\u6237\u7aef\u4f46\u4f20\u5165\u4e86\u7a7a ",(0,r.kt)("inlineCode",{parentName:"li"},"RequestUrl")," \u5730\u5740\u5bfc\u81f4\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I40BC6"},"#I40BC6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c4\u8303\u5316\u7ed3\u679c\u7be1\u6539\u975e\u77ed\u8def\u7aef\u72b6\u6001\u7801\u51fa\u73b0\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I408F5"},"#I408F5")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.GetServiceProvider(type)")," \u89e3\u6790\u670d\u52a1\u6027\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I40KXN"},"#I40KXN")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u89c6\u56fe\u5f15\u64ce\u4fdd\u5b58\u6210\u6587\u4ef6\u6d41\u9ed8\u8ba4\u7f13\u5b58\u533a\u5927\u5c0f\uff0c\u4ece ",(0,r.kt)("inlineCode",{parentName:"li"},"4096")," \u63d0\u5347\u81f3 ",(0,r.kt)("inlineCode",{parentName:"li"},"8192")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I40KH5"},"#I40KH5"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v210211212-\u5df2\u53d1\u5e03"},"v2.10/2.11/2.12 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u8be5\u7248\u672c\u6709\u591a\u4e2a\u7834\u574f\u6027\u66f4\u6539\uff0c\u66f4\u65b0\u65f6\u8bf7\u8ba4\u771f\u67e5\u770b\u3002")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.Configuration.Reload()")," \u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XYI8"},"#I3XYI8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ISubscribeHandler")," \u652f\u6301\u5f02\u6b65\u65b9\u6cd5\u5b9a\u4e49 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XYHJ"},"#I3XYHJ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"app.UseUnifyResultStatusCodes()")," \u53ef\u914d\u7f6e\u4fee\u6539\u8fd4\u56de\u72b6\u6001\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VZQH"},"#I3VZQH")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u6dfb\u52a0\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"User-Agent")," \u5934 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W17C"},"#I3W17C")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u9ad8\u7ea7\u4ee3\u7406\u5207\u6362\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XFP6"},"#I3XFP6")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XDCR"},"#I3XDCR")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9a\u65f6\u4efb\u52a1 ",(0,r.kt)("inlineCode",{parentName:"li"},"CronFormat")," \u81ea\u52a8\u8bc6\u522b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Y7GT"},"#I3Y7GT")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql \u9ad8\u7ea7\u4ee3\u7406")," \u62e6\u622a\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YHG4"},"#I3YHG4")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u62e6\u622a\u8fdc\u7a0b\u8bf7\u6c42\u6240\u6709\u5f02\u5e38\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YPDE"},"#I3YPDE")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Timeout")," \u8d85\u65f6\u65f6\u95f4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YPPK"},"#I3YPPK")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"RSA")," \u52a0\u5bc6\u7b97\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YZNU"},"#I3YZNU")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/345"},"!345")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DataTable")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"DataSet")," \u652f\u6301\u4e0d\u6307\u5b9a\u5f3a\u7c7b\u578b\u8fd4\u56de ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Z6RI"},"#I3Z6RI")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u6cd5\u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Timeout")," \u8d85\u65f6\u65f6\u95f4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ZKWF"},"#I3ZKWF")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u9ad8\u7ea7\u4ee3\u7406 ",(0,r.kt)("inlineCode",{parentName:"li"},"[Timeout]")," \u7279\u6027\uff0c\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ZKWF"},"#I3ZKWF")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"FakeDelete")," \u5047\u5220\u9664/\u8f6f\u5220\u9664\u6240\u6709\u529f\u80fd ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I3XKII"},"#I3XKII"))),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("strong",{parentName:"li"},"\u79fb\u9664 ",(0,r.kt)("inlineCode",{parentName:"strong"},"PBKDF2")," \u52a0\u5bc6\u7b97\u6cd5 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I3Z0IO"},"#I3Z0IO"))),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},"\u8fdc\u7a0b\u8bf7\u6c42\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4\u5355\u4f4d\u7531 ",(0,r.kt)("inlineCode",{parentName:"strong"},"\u5206\u949f")," \u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},"\u79d2")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I3YPPK"},"#I3YPPK"))),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"IJsonSerializerProvider")," \u63a5\u53e3\u53c2\u6570\uff0c\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"strong"},"inherit")," \u53c2\u6570 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I3ZQU5"},"#I3ZQU5"))),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[NonAutomatic]")," \u7279\u6027\u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"[Manual]")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XKKX"},"#I3XKKX")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[NotChangedListener]")," \u7279\u6027\u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"[SuppressChangedListener]")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XKLZ"},"#I3XKLZ")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[ManualSaveChanges]")," \u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"[ManualCommit]")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XKNP"},"#I3XKNP")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"DbContext.TenantIdQueryFilterExpression")," \u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},"DbContext.BuildTenantQueryFilter")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I3XKTB"},"#I3XKTB"))),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[SkipScan]")," \u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"[SuppressSniffer]")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XN5N"},"#I3XN5N")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[SkipProxy]")," \u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"[SuppressProxy]")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XN7O"},"#I3XN7O")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u6267\u884c\uff0c\u6027\u80fd\u63d0\u5347 20% ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W33U"},"#I3W33U")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u52a8\u6001 WebAPI \u626b\u63cf\u63a7\u5236\u5668\u6ca1\u6709\u5c4f\u853d\u6ca1\u6709\u6ce8\u518c\u7684\u7b2c\u4e09\u65b9\u63a7\u5236\u5668 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Y7TJ"},"#I3Y7TJ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"TablePrefix")," \u65e0\u6548\uff1a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Y57Q"},"#I3Y57Q")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u5b9a\u65f6\u4efb\u52a1\u4f7f\u7528\u5f02\u6b65\u59d4\u6258\u5bfc\u81f4\u7a0b\u5e8f\u7ec8\u6b62 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XVZ0"},"#I3XVZ0")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e8b\u4ef6\u603b\u7ebf\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"\u6d88\u606fid")," \u5bf9\u5e94\u591a\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"Handler")," \u53ea\u89e6\u53d1\u7b2c\u4e00\u4e2a",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XYP0"},"#I3XYP0")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".ToPagedList()")," \u5206\u9875\u65b9\u6cd5\u4f20\u5165\u5c0f\u4e8e\u6216\u7b49\u4e8e 0 \u7684\u9875\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XNAN"},"#I3XNAN")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON")," \u5e8f\u5217\u5316\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTimeOffset")," \u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XMOL"},"#I3XMOL")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"li"},"Serilog")," \u65e5\u5fd7\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u751f\u6210\u91cd\u590d\u65e5\u5fd7 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3WA0L"},"#I3WA0L")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/331"},"!331")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"\u7c98\u571f\u5bf9\u8c61")," \u52a8\u6001\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Clay")," \u7c7b\u578b bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W9LW"},"#I3W9LW")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationTypes.Numeric")," \u6821\u9a8c\u6570\u503c\u7c7b\u578b\u6b63\u5219\u8868\u8fbe\u5f0f\u9519\u8bef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3WADS"},"#I3WADS")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u547d\u4ee4\u53c2\u6570 ",(0,r.kt)("inlineCode",{parentName:"li"},"DbParameter")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Value")," \u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"object")," \u7c7b\u578b\u7684\u65f6\u5019\u4e14\u4e0d\u6307\u5b9a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YKM6"},"#I3YKM6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Oracle")," \u6570\u636e\u5e93\u5b58\u50a8\u8fc7\u7a0b ",(0,r.kt)("inlineCode",{parentName:"li"},"\u6e38\u6807\u53c2\u6570")," \u62a5\u9519\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ZBYE"},"#I3ZBYE")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Services")," \u91c7\u7528\u72ec\u7acb\u53d1\u5e03\u540e\u65e0\u6cd5\u6267\u884c\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ZH3X"},"#I3ZH3X")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u8fdc\u7a0b\u8bf7\u6c42\u5982\u679c\u65e0\u8fd4\u56de\u503c\u5e8f\u5217\u5316\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/348"},"!348")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u589e\u5f3a]"," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"appsettings.json")," \u7b49\u81ea\u5b9a\u4e49\u914d\u7f6e\u6587\u4ef6\u4e2d\u6587\u547d\u540d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YBFD"},"#I3YBFD")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u8fdc\u7a0b\u8bf7\u6c42\u914d\u7f6e\u547d\u540d\u5ba2\u6237\u7aef ",(0,r.kt)("inlineCode",{parentName:"li"},"BaseAddress")," \u5730\u5740\u517c\u5bb9\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YCRH"},"#I3YCRH")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u6846\u67b6\u65e0\u7528\u4ee3\u7801\u3001\u4f18\u5316\u4ee3\u7801"),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"\u975e Web")," \u73af\u5883\u4e0b\u6027\u80fd"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4f1a\u8bdd\u548c\u72b6\u6001\u7ba1\u7406 \u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YI3G"},"#I3YI3G")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u8fdc\u7a0b\u8bf7\u6c42\u3001\u65e5\u5fd7\u3001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3001\u8fdc\u7a0b\u8bf7\u6c42\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u9ad8\u7ea7\u4ee3\u7406\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u914d\u7f6e\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Y2EV"},"#I3Y2EV")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"dapper")," \u591a\u4e2a\u6570\u636e\u6e90\u5982\u4f55\u7ee7\u627f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3WUOI"},"#I3WUOI")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"li"},"SpareTime")," \u591a\u6b21\u6267\u884c\u95ee\u9898",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XEQU"},"#I3XEQU")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u9009\u9879\u66f4\u6539\u901a\u77e5\uff08\u70ed\u66f4\u65b0\uff09\uff1a\u6570\u636e\u5e93\u91cc\u7684\u6570\u636e\u66f4\u6539\u4e86\u5982\u4f55\u901a\u77e5\u9009\u9879\u8fdb\u884c\u6539\u53d8\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XYI8"},"#I3XYI8")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SaaS")," \u591a\u79df\u6237\u6dfb\u52a0\u65f6\u65e0\u6cd5\u83b7\u53d6\u79df\u6237",(0,r.kt)("inlineCode",{parentName:"li"},"Id")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Y5CF"},"#I3Y5CF")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u83b7\u53d6 ",(0,r.kt)("inlineCode",{parentName:"li"},"_httpContextAccessor.HttpContext")," \u4e3a\u7a7a",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Y6BI"},"#I3Y6BI")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Ubuntu")," \u4e2d\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"App.Configuration")," \u65b9\u6cd5\u8bfb\u53d6\u4e0d\u5230\u503c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Y74H"},"#I3Y74H")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4f5c\u7528\u57df\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YHXP"},"#I3YHXP")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"UnitofWork")," \u63d0\u4ea4\u4e8b\u52a1\uff0c\u53ef\u4ee5\u63d0\u4ea4\u6210\u529f\uff0c\u4f46\u662f\u7cfb\u7edf\u4f1a\u6709\u9519\u8bef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YIWU"},"#I3YIWU")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6570\u636e\u5e93\u8bfb\u5199\u5206\u79bb--\u975e\u9ed8\u8ba4\u4e3b\u5e93\u7684\u4ece\u5e93\u968f\u673a\u8be5\u5982\u4f55\u914d\u7f6e\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YVR7"},"#I3YVR7")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SpareTIme")," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"Dashboard")," \u63a7\u5236\u53f0\u770b\u677f\uff0c\u540c\u65f6\u53ef\u4ee5\u5bf9\u4efb\u52a1\u8fdb\u884c\u6682\u505c\u3001\u5220\u9664\u3001\u67e5\u770b",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XELY"},"#I3XELY"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v290-\u5df2\u53d1\u5e03"},"v2.9.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},"\u5e94\u7528\u5168\u5c40\u672a\u6258\u7ba1\u8d44\u6e90\u76d1\u542c\uff0c\u5e76\u5b9e\u73b0\u7279\u5b9a\u65f6\u673a\u91ca\u653e\u975e\u6258\u7ba1\u8d44\u6e90")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VXAU"},"#I3VXAU")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4e0d\u5305\u542b ",(0,r.kt)("inlineCode",{parentName:"li"},"EntityFramework.Core")," \u7248\u672c\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Pure")," \u5305",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VGW8"},"#I3VGW8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," swagger \u652f\u6301\u8bbe\u7f6e\u591a\u8bed\u8a00\u65b9\u5f0f\uff0c\u8bbe\u7f6e\u7684\u8bed\u8a00\u81ea\u52a8\u6dfb\u52a0\u5230 api \u5730\u5740\u540e\u9762 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VDTD"},"#I3VDTD")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001 WebAPI \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"[FromRoute]")," \u975e\u5fc5\u586b\uff08\u9009\u586b\uff09\u53c2\u6570\u8bbe\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VFIM"},"#I3VFIM")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001 WebAPI \u53c2\u6570\u652f\u6301\u914d\u7f6e\u8def\u7531\u7ea6\u675f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VFIR"},"#I3VFIR")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MD5")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"DESC")," \u52a0\u5bc6\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"\u5927\u5199")," \u8f93\u51fa ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/326"},"#326")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6240\u6709\u5305\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},".snupkg")," \u5305\uff0c\u652f\u6301\u5f00\u53d1\u9636\u6bb5\u76f4\u63a5\u8c03\u8bd5 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6240\u6709\u5305\u6e90\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VFIX"},"#I3VFIX")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"repository.BuildChange()")," \u65b9\u6cd5\u7684\u8fd4\u56de\u503c\uff0c\u591a\u8fd4\u56de\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"IServiceScope")," \u5bf9\u8c61 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VX3D"},"#I3VX3D")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT")," \u5237\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u65b9\u6cd5 ",(0,r.kt)("inlineCode",{parentName:"li"},"AutoRefreshToken")," \u53c2\u6570 ",(0,r.kt)("inlineCode",{parentName:"li"},"days")," \u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"minutes")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VXNB"},"#I3VXNB")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.GetOptionsSnapshot<>")," \u4ece\u6839\u670d\u52a1\u89e3\u6790\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VS2X"},"#I3VS2X")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u8fdc\u7a0b\u8bf7\u6c42\u5982\u679c\u51fa\u73b0\u5f02\u5e38\uff0c\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"Stream")," \u4e3a null \u5bfc\u81f4\u5f02\u5e38\u7684\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VSTU"},"#I3VSTU")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5982\u679c\u5b9e\u4f53\u88ab\u8ddf\u8e2a\u540e\uff0c\u65e0\u6cd5\u6267\u884c\u5220\u9664\u64cd\u4f5c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W08P"},"#I3W08P")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u8fd0\u884c\u65f6\u5185\u5b58\uff0c\u5b9e\u73b0\u8bf7\u6c42\u7ed3\u675f\u81ea\u52a8\u91ca\u653e\u672a\u6258\u7ba1\u8d44\u6e90 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VXAU"},"#I3VXAU")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App")," \u9759\u6001\u7c7b\u6587\u6863\u3001\u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863\u3001\u5206\u8868\u5206\u5e93\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u52a8\u6001 WebAPI\uff0c\u81ea\u5b9a\u4e49\u6839\u636e\u65b9\u6cd5\u540d\u751f\u6210 ","[HttpMethod]"," \u89c4\u5219\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VKQG"},"#I3VKQG")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"InsertAsync")," \u7684\u65f6\u5019\u63d0\u793a ",(0,r.kt)("inlineCode",{parentName:"li"},"ID")," \u4e3a\u7a7a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VS7E"},"#I3VS7E")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"FirstOrDefault")," \u81ea\u52a8\u8fc7\u6ee4\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"TanantId")," \u5b57\u6bb5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W0VH"},"#I3W0VH")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5bf9\u65b9\u63a5\u53e3\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpConnectionResponseContent")," \u8fdc\u7a0b\u8bf7\u6c42\u62ff\u4e0d\u5230\u8fd4\u56de\u503c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W17C"},"#I3W17C")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u67e5\u8be2\u65b9\u6cd5 ",(0,r.kt)("inlineCode",{parentName:"li"},"FindOrDefault")," \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W830"},"#I3W830")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlNonQuery")," \u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"UnitOfWork")," \u5faa\u73af\u6267\u884c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W8WW"},"#I3W8WW")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u56e0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u914d\u7f6e\u95ee\u9898\uff0c\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e2d\u4e0d\u80fd\u81ea\u52a8\u643a\u5e26 token \u6388\u6743\u7684\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W934"},"#I3W934")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"SetBody")," \u53c2\u6570\u8bc6\u522b\u4e0d\u4e86",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3WBM1"},"#I3WBM1")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped.Create")," \u91cc\u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"sql.SqlNonQuery()")," \u6216\u8005 ",(0,r.kt)("inlineCode",{parentName:"li"},"obj.insert()")," \u95ee\u9898",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3WB5O"},"#I3WB5O")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u8c03\u7528\u51fd\u6570\u6216\u5b58\u50a8\u8fc7\u7a0b\uff0c\u600e\u4e48\u51fa\u53c2\u6570\u636e\u81ea\u5b9a\u4e49\u5bf9\u8c61\uff1f\u5982 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oracle"),"\u6570\u636e\u5e93\u7684\u6570\u7ec4\u6216\u8bb0\u5f55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W71W"},"#I3W71W")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65e0\u6548]"," \u6570\u636e\u5e93\u5c0f\u5199\u4e0b\u5212\u7ebf\u5b57\u6bb5\uff0c\u65e0\u6cd5\u81ea\u52a8\u6620\u5c04\u6210\u5c0f\u9a7c\u5cf0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W021"},"#I3W021")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EfCore 5")," \u76f4\u63a5\u591a\u5bf9\u591a\u65f6\u8fdb\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"SeedData")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3WDRJ"},"#I3WDRJ"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v270280-\u5df2\u53d1\u5e03"},"v2.7.0/2.8.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},'throw Oops.On("\u5f02\u5e38\u6d88\u606f")')," \u5e94\u7528\u591a\u8bed\u8a00\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UYC2"},"#I3UYC2")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetMSRepository()")," \u83b7\u53d6\u4e3b\u4ece\u5e93\u4ed3\u50a8\u9759\u6001\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UBSJ"},"#I3UBSJ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5de5\u4f5c\u5355\u5143\u7279\u6027\uff0c\u652f\u6301\u9759\u6001\u7c7b\u5f3a\u5236\u6027\u5f00\u542f\u5171\u4eab\u4e8b\u52a1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3S9N8"},"#I3S9N8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u6a21\u5f0f\u6253\u5370\u65e5\u5fd7 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SE8X"},"#I3SE8X")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u652f\u6301\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpClient")," \u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SI17"},"#I3SI17")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"\u77ed ID")," \u751f\u6210\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3T7JP"},"#I3T7JP")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[SensitiveDetection]")," \u652f\u6301\u914d\u7f6e\u66ff\u6362\u654f\u611f\u8bcd\u6c47 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3THIA"},"#I3THIA")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationDocumentBuilder.DocumentGroups")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationDocumentBuilder.CheckApiDescriptionInCurrentGroup(currentGroup, apiDescription)")," \u516c\u5f00\u65b9\u6cd5",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UDSY"},"#I3UDSY")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u81ea\u52a8\u626b\u63cf ",(0,r.kt)("inlineCode",{parentName:"li"},".json")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},".xml")," \u6587\u4ef6\u5e76\u52a0\u8f7d\u5230\u914d\u7f6e\u4e2d\u7684\u4ee3\u7801\u548c\u89c4\u5219\uff0c\u540c\u65f6\u79fb\u9664\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},".xml")," \u6587\u4ef6\u52a0\u8f7d\uff0c\u53ea\u4fdd\u7559 ",(0,r.kt)("inlineCode",{parentName:"li"},".json")," \u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UJ3L"},"#I3UJ3L")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u5206\u5e03\u5f0f\u8fde\u7eed ",(0,r.kt)("inlineCode",{parentName:"li"},"GUID")," \u4ee3\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UBK0"},"#I3UBK0")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Scoped.CreateUnitOfWork")," \u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},"Scoped.CreateUow")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I3SJPU"},"#I3SJPU"))),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWTEncryption.Validate")," \u8fd4\u56de\u503c\uff0c\u652f\u6301\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"TokenValidationResult")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3S2ND"},"#I3S2ND")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[DataValidation]")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"[SensitiveDetection]")," \u591a\u8bed\u8a00\u5e94\u7528\u5931\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UH6U"},"#I3UH6U")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped")," \u7cfb\u5217\u65b9\u6cd5\u5f02\u6b65\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Task is cancel")," \u60c5\u51b5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SJF6"},"#I3SJF6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mysql")," \u6570\u636e\u5e93\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ToPagedList")," \u65b9\u6cd5\u8fd4\u56de\u7684\u7ed3\u679c\u8fdb\u884c\u904d\u5386\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"MySqlConnection is aleady use")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SJQ3"},"#I3SJQ3")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"tool/cli.psl")," \u6ca1\u6709\u5305\u542b\u9879\u76ee\u540d\u79f0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3S1T6"},"#I3S1T6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u505a\u4e0a\u4f20\u6587\u4ef6\u65f6\uff0c\u6ca1\u6709\u4f20\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"Body"),"\uff0c\u7a0b\u5e8f\u76f4\u63a5\u8df3\u8fc7 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TKFH"},"#I3TKFH")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"multipart/form-data")," \u5185\u5bb9\u5206\u5272\u7b26\u7f3a\u5931 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TNO9"},"#I3TNO9")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u62e6\u622a\u65b9\u5f0f\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpResponseMessage")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3V161"},"#I3V161")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"repository.Database.SetCommandTimeout(600)")," \u65e0\u6cd5\u751f\u6548",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VAQS"},"#I3VAQS")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u652f\u6301\u89c4\u8303\u5316\u7ed3\u679c\u4e2d\u95f4\u4ef6\u5224\u65ad\u662f\u5426\u8df3\u8fc7\u89c4\u8303\u5316\u7ed3\u679c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3T2AA"},"#I3T2AA")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u66f4\u65b0\u90e8\u5206\u5217 ",(0,r.kt)("inlineCode",{parentName:"li"},"UpdateIncludeNowAsync")," \u5177\u6709\u4e8c\u4e49\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RW9Q"},"#I3RW9Q")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("strong",{parentName:"li"},"\u6846\u67b6\u5e95\u5c42\u6027\u80fd\uff0c\u5927\u5927\u51cf\u5c11\u5185\u5b58\u5360\u7528\u548c\u6ea2\u51fa\u60c5\u51b5\uff0c\u542f\u52a8\u5185\u5b58\u4ece\u4e4b\u524d ",(0,r.kt)("inlineCode",{parentName:"strong"},"136M")," \u4e0b\u5c06\u5230 ",(0,r.kt)("inlineCode",{parentName:"strong"},"86M"))),(0,r.kt)("li",{parentName:"ul"},"[\u5176\u4ed6]"," \u5220\u9664\u65e0\u7528\u4ee3\u7801\uff0c\u4f18\u5316\u4e0d\u89c4\u8303\u547d\u540d\u7b49"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Inject")," \u8bf4\u660e\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TITA"},"#I3TITA")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," 4.2.9 \u7684\u793a\u4f8b\u4ee3\u7801\u6587\u6863\uff0c\u65b9\u6cd5\u6ca1\u6709\u653e\u5728 class \u4e2d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3S9T5"},"#I3S9T5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u6b63]"," \u89c4\u8303\u5316\u7ed3\u679c 6.5.6 \u591a\u5206\u7ec4\u6392\u5e8f\u56fe\u7247\u5f15\u7528\u9519\u8bef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UBOQ"},"#I3UBOQ")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u9759\u6001\u7c7b ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped")," \u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"MasterDbContextLocator")," \u4e0d\u968f\u81ea\u5b9a\u4e49\u7684\u53c2\u6570\u751f\u6210 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SDBB"},"#I3SDBB")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u4e8b\u4ef6\u603b\u7ebf\u4e2d\u8ba2\u9605\u5904\u7406\u7a0b\u5e8f\u7c7b\u83b7\u53d6\u4e0d\u5230\u7528\u6237\u4fe1\u606f\uff0c\u8fd9\u4e2a\u6b63\u5e38\u5417 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SS0U"},"#I3SS0U")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5728\u6709\u591a\u79df\u6237\u8fc7\u6ee4\u5668\u7684\u60c5\u51b5\u4e0b\uff0c\u662f\u5426\u6709\u4e00\u79cd\u65b9\u5f0f\u67e5\u8be2\u5168\u91cf\u7684\u6570\u636e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3T0VI"},"#I3T0VI")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," mysql \u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},'&"tools/cli.ps1"')," \u9875\u9762\u5316\u52a0\u8f7d\u8868\u7ed3\u6784\u5931\u8d25 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3T4F8"},"#I3T4F8")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5176\u4ed6 Web \u5c42\u7684 Startup \u4f18\u5148\u6267\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3T8IP"},"#I3T8IP")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u8f85\u52a9\u89d2\u8272\u670d\u52a1\u5b9e\u73b0\u5efa\u8bae ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3T906"},"#I3T906")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5f00\u542f ",(0,r.kt)("inlineCode",{parentName:"li"},"easy connection")," \u540e\u540c\u4e00\u5185\u7f51\u5730\u5740\u6d4f\u89c8\u5668\u53ef\u4ee5\u6b63\u5e38\u8bbf\u95ee\uff0c\u8fdc\u7a0b\u8bf7\u6c42\u5219\u65e0\u6cd5\u8bbf\u95ee",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TA2U"},"#I3TA2U")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"scope.ServiceProvider.GetService"),"\u4e0d\u5b58\u5728 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TQMV"},"#I3TQMV")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u80fd\u5426\u5728 WPF \u9879\u76ee\u4e2d\u4f7f\u7528\u5462\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TMCC"},"#I3TMCC")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Dapper")," \u591a\u4e2a\u6570\u636e\u6e90 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TM9B"},"#I3TM9B")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"L.GetSelectCulture()")," \u65b9\u6cd5\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TQS4"},"#I3TQS4")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5faa\u73af\u4e2d\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"IDGen.NextID()")," \u5f97\u5230\u7684\u7ed3\u679c\u5e76\u4e0d\u662f\u8fde\u7eed\u7684 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UAF6"},"#I3UAF6")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6a21\u5757\u5316\u52a8\u6001\u52a0\u8f7d\u63d2\u4ef6\u652f\u6301\u901a\u914d\u7b26\u5339\u914d.dll ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UDT8"},"#I3UDT8")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MVC")," \u6a21\u5f0f\uff0c\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Controller")," \u91cc\u5feb\u6377\u65b9\u5f0f\u521b\u5efa ",(0,r.kt)("inlineCode",{parentName:"li"},"View")," \u9875\u9762\u51fa\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UFGB"},"#I3UFGB")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6570\u636e\u5e93\u8fc1\u79fb\u6ca1\u6709\u79cd\u5b50\u6570\u636e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UI7G"},"#I3UI7G")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SpareTimeAttribute")," \u4e2d \u6839\u636e Cron \u8868\u8fbe\u5f0f \u81ea\u52a8\u5339\u914d Cron \u8868\u8fbe\u5f0f\u683c\u5f0f\u5316\u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UTKQ"},"#I3UTKQ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"workService")," \u96c6\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3V8HJ"},"#I3V8HJ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"sqlserver 2008")," \u5206\u9875\u62a5\u9519\u5982\u4f55\u89e3\u51b3\u5462 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VF96"},"#I3VF96")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u6dfb\u52a0\u4ee4\u724c\u6876\u9650\u6d41\u7b97\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SCDV"},"#I3SCDV")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5b9a\u65f6\u4efb\u52a1\u7acb\u5373\u6267\u884c\u9700\u6c42 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SF4A"},"#I3SF4A")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u6587\u6863\u5efa\u8bae \u5173\u4e8e reids \u548c es \u3001\u6d88\u606f\u961f\u5217\u7684 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3T90I"},"#I3T90I")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," IP \u9ad8\u9891\u7387\u8bf7\u6c42\u9650\u5236 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UHE1"},"#I3UHE1")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Url")," \u8f6c\u53d1\u5927\u6a21\u5757 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TZHO"},"#I3TZHO"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v250260-\u5df2\u53d1\u5e03"},"v2.5.0/2.6.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u865a\u62df\u6587\u4ef6\u670d\u52a1\uff0c\u652f\u6301\u7269\u7406\u6587\u4ef6\u548c\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RBR9"},"#I3RBR9")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236\u4ed3\u50a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"IMSRepository")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"IMSRepository")," \u4ed3\u50a8\uff0c\u53ef\u8fdb\u884c\u968f\u673a\u6216\u81ea\u5b9a\u4e49\u83b7\u53d6\u4ece\u5e93"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6570\u636e\u8131\u654f\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3R5ZF"},"#I3R5ZF")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"InsertOrUpdate")," \u4e00\u7cfb\u5217\u6570\u636e\u5e93\u64cd\u4f5c\u65b9\u6cd5")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RI9L"},"#I3RI9L")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u6240\u6709\u5305\u542b ",(0,r.kt)("inlineCode",{parentName:"li"},"Exists")," \u5355\u8bcd\u7684\u6570\u636e\u5e93\u64cd\u4f5c\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RJ0T"},"#I3RJ0T")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u5206\u5e03\u5f0f GUID ",(0,r.kt)("inlineCode",{parentName:"li"},"IDGenerater")," \u9759\u6001\u7c7b\u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"IDGen")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RGUA"},"#I3RGUA")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8c03\u7528\u65b9\u6cd5\u9519\u8bef\uff0c\u8bf7\u6c42\u62a5\u6587\u5934 ",(0,r.kt)("inlineCode",{parentName:"li"},"Headers")," \u4e0d\u80fd\u6dfb\u52a0\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"IHttpDispatchProxy")," \u7684\u5b50\u63a5\u53e3\u4e0a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RAF7"},"#I3RAF7")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u5e94\u7528\u542f\u52a8\u6027\u80fd\uff0c\u51cf\u5c11\u5185\u5b58\u5206\u914d"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8131\u654f\u5904\u7406\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3R6WZ"},"#I3R6WZ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6587\u4ef6\u7cfb\u7edf\u6587\u6863\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"FS")," \u9759\u6001\u7c7b\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RCC4"},"#I3RCC4")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236\u3001\u6570\u636e\u5e93\u4ed3\u50a8\u6587\u6863\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"Db")," \u9759\u6001\u7c7b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3R3B6"},"#I3R3B6")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u96c6\u7fa4\u90e8\u7f72 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3R3J4"},"#I3R3J4")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5347\u7ea7\u6700\u65b0\u6846\u67b6\u4ee5\u540e\uff0c \u6570\u636e\u5e93\u751f\u6210\u6a21\u578b\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3R7TP"},"#I3R7TP")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e8b\u52a1\u6267\u884c\u4e2d\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"SaveNow")," \u6267\u884c\u540e\u6709\u8b66\u544a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RAJI"},"#I3RAJI")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Hangfire")," \u4f7f\u7528\u4e8b\u52a1\u51fa\u73b0\u9519\u8bef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ROQ5"},"#I3ROQ5")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5982\u4f55\u5b9e\u73b0 cli \u4e0d\u6267\u884c\u67d0\u4e9b\u8868\u7684\u8fc1\u79fb\uff0cweb \u8bf7\u6c42\u53ef\u4ee5\u6b63\u5e38\u64cd\u4f5c\u5462\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ROU5"},"#I3ROU5")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5728\u4f7f\u7528\u5b9a\u65f6\u4efb\u52a1\u65f6\u5019\u51fa\u73b0\u7684\u95ee\u9898\uff1a\u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"li"},"ISpareTimeWorker")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RRZS"},"#I3RRZS")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MySql")," \u65f6\u95f4\u5dee 8 \u5c0f\u65f6\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RSCO"},"#I3RSCO")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetRepository<>")," \u65b9\u6cd5\u7ed3\u5408 ",(0,r.kt)("inlineCode",{parentName:"li"},"[UnitOfWork]")," \u540e\u4e0d\u53ef\u7528 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RUK5"},"#I3RUK5")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u4e8b\u52a1\u5f00\u542f\u5931\u8d25\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RYJY"},"#I3RYJY")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"DbProvider")," \u53ef\u52a8\u6001\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RYPE"},"#I3RYPE")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"WorkService")," \u4f9d\u8d56\u6ce8\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"ISingleton")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RZ1L"},"#I3RZ1L")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ISpareTimeWorker")," \u8fd0\u884c\u671f\u52a8\u6001\u4fee\u6539 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3S33Q"},"#I3S33Q")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u62d2\u7edd]"," \u6709\u5e8f ",(0,r.kt)("inlineCode",{parentName:"li"},"Guid")," \u7cbe\u5ea6\u662f\u56fa\u5b9a\u7684\u6beb\u79d2\u7ea7\uff1a1 \u6beb\u79d2\u5185\u751f\u6210\u7684\u591a\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"Guid")," \u662f\u65e0\u5e8f\u7684 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3R59J"},"#I3R59J")),(0,r.kt)("li",{parentName:"ul"},"[\u62d2\u7edd]"," \u5efa\u8bae:JWTEncryption.Validate \u65b9\u6cd5\u8fd4\u56de JWT \u7684\u68c0\u67e5\u5931\u8d25\u65f6\u7684\u539f\u56e0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3S1F2"},"#I3S1F2"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v240-\u5df2\u53d1\u5e03"},"v2.4.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301\u81ea\u52a8\u52a0\u8f7d\u6a21\u5757\u5316/\u63d2\u4ef6 ",(0,r.kt)("inlineCode",{parentName:"li"},".xml")," \u6ce8\u91ca\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Q7XY"},"#I3Q7XY")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext.FailedAutoRollback")," \u5c5e\u6027\uff0c\u53ef\u914d\u7f6e\u4e8b\u52a1\u662f\u5426\u81ea\u52a8\u56de\u6eda ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QOUS"},"#I3QOUS")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," ",(0,r.kt)("strong",{parentName:"li"},".NET 5 SDK \u4e3a 5.0.6 \u7248\u672c")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IJsonSerializerProvider.GetSerializerOptions()")," \u63a5\u53e3\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QIJN"},"#I3QIJN")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddInject()")," \u65b9\u5f0f\u6ce8\u518c\uff0c\u6a21\u5757\u5316/\u63d2\u4ef6\u4e0d\u52a0\u8f7d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Q7XH"},"#I3Q7XH")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u79cd\u5b50\u6570\u636e\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"null")," \u62a5\u7a7a\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QCM5"},"#I3QCM5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"Clay.Object")," \u521b\u5efa\u7c98\u571f\u5bf9\u8c61\u540e\u5c5e\u6027\u53d8\u5c0f\u5199\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QRV3"},"#I3QRV3")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6846\u67b6\u5e95\u5c42\u6027\u80fd\uff0c\u51cf\u5c11\u5185\u5b58\u5360\u7528\uff0c\u63d0\u9ad8\u5e94\u7528\u521d\u59cb\u5316\u901f\u5ea6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/92f8cc1"},"92f8cc1")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," JSON \u5e8f\u5217\u5316\u6587\u6863\u3001\u89c4\u8303\u5316\u7ed3\u679c\u6587\u6863\u3001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"InsertOrUpdateNowAsync")," \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QKO5"},"#I3QKO5")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5b9a\u65f6\u4efb\u52a1\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},"Failed")," \u4e8b\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QCM2"},"#I3QCM2")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u6a21\u5757\u5316\u52a8\u6001\u751f\u6210\u6570\u636e\u5e93\u8868 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QH3G"},"#I3QH3G")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae\u4e8b\u4ef6\u603b\u7ebf\u65b0\u589e MQ \u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QWZ4"},"#I3QWZ4")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u91cd\u6784\u89c4\u8303\u5316\u6574\u4e2a\u6a21\u5757\u4ee3\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NFT7"},"#I3NFT7"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v230-\u5df2\u53d1\u5e03"},"v2.3.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.DatabaseAccessor.MongoDB")," \u62d3\u5c55\u5305\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PKST"},"#I3PKST")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001\u7c98\u571f\u7c7b\u578b\u76f4\u63a5\u8f6c ",(0,r.kt)("inlineCode",{parentName:"li"},"object")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"li"},"dynamic")," \u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OY27"},"#I3OY27")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Retry")," \u65b9\u6cd5\uff0c\u652f\u6301\u8bbe\u7f6e\u65b9\u6cd5\u8c03\u7528\u5931\u8d25\u8fdb\u884c\u91cd\u8bd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PJKQ"},"#I3PJKQ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWTSettings")," \u914d\u7f6e\u8282\u70b9 ",(0,r.kt)("inlineCode",{parentName:"li"},"Algorithm"),"\uff0c\u7528\u4e8e\u914d\u7f6e\u52a0\u5bc6\u7b97\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PQGV"},"#I3PQGV")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"repository.EnsureTransaction()")," \u65b9\u6cd5\u786e\u4fdd\u5de5\u4f5c\u5355\u5143\u4e8b\u52a1\u6709\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PVF1"},"#I3PVF1")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u652f\u6301]"," \u652f\u6301 .NET 6.0.0 Preview 3 \u7248\u672c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3P2C7"},"#I3P2C7")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4f7f\u7528\u6570\u636e\u5e93\u751f\u6210\u6a21\u578b ",(0,r.kt)("inlineCode",{parentName:"li"},"tools/cli.ps1"),"\uff0c\u4ece\u6570\u636e\u5e93\u8868\u751f\u6210\u7684\u5b9e\u4f53\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PL18"},"#I3PL18")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8d34\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"[NonUntify]")," \u7279\u6027\u540e\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Example Value")," \u6ca1\u6709\u5339\u914d\u6b63\u786e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PK0L"},"#I3PK0L")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SpareTimer.Tally")," \u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Cron")," \u8868\u8fbe\u5f0f\u4e2d\u8ba1\u6570\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PWSE"},"#I3PWSE")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u6846\u67b6\u9ed8\u8ba4\u5e8f\u5217\u5316\u5e94\u8be5\u4ece\u914d\u7f6e\u4e2d\u8bfb\u53d6\uff0c\u800c\u975e\u624b\u52a8\u7f16\u5199 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3P1SJ"},"#I3P1SJ")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u62d3\u5c55\u5e93\uff0c\u652f\u6301\u975e\u6cdb\u578b\u4ed3\u50a8\u83b7\u53d6\u4e0a\u4e0b\u6587\u64cd\u4f5c\u5bf9\u8c61 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PK2N"},"#I3PK2N")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u652f\u6301\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58\u53ef\u914d\u7f6e\u5316 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3POKD"},"#I3POKD")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6587\u6863]"," \u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWTSettings")," \u914d\u7f6e\u72ec\u7acb\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PQGW"},"#I3PQGW")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u8f6f\u5220\u9664\u5982\u679c\u6570\u636e\u4e0d\u5b58\u5728\uff0c\u5219\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PTVB"},"#I3PTVB")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u591a\u4e2a\u7c7b\u96c6\u6210\u6d4b\u8bd5\u4f1a\u9020\u6210\u6570\u636e\u5e93\u5b9a\u4f4d\u5668\u591a\u6b21\u6ce8\u518c\uff0c\u65e0\u6cd5\u8fd0\u884c\u6240\u6709\u6d4b\u8bd5\uff0c\u53ea\u80fd\u4e00\u4e2a\u7c7b\u4e00\u4e2a\u7c7b\u7684\u8fd0\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PXGY"},"#I3PXGY")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," CAS \u652f\u6301",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PIET"},"#I3PIET"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v220-\u5df2\u53d1\u5e03"},"v2.2.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Clay")," \u7c98\u571f\u7c7b\u578b\uff0c\u652f\u6301\u8ba9 ",(0,r.kt)("inlineCode",{parentName:"li"},"C#")," \u521b\u5efa\u4e00\u4e2a\u5f31\u7c7b\u578b\u5bf9\u8c61\u5e76\u64cd\u4f5c\u5f31\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O2QQ"},"#I3O2QQ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped.Create")," \u5e26\u8fd4\u56de\u503c\u91cd\u8f7d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O47J"},"#I3O47J")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped.Create()")," \u4e00\u7cfb\u5217\u65b9\u6cd5\u652f\u6301\u4f20\u5165\u4f5c\u7528\u57df\u5de5\u5382 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OAP5"},"#I3OAP5")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301\u4e8b\u4ef6\u603b\u7ebf\u540c\u6b65\u6267\u884c\u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OAW2"},"#I3OAW2")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[DataValidation]")," \u8df3\u8fc7\u7a7a\u5b57\u7b26\u4e32\u548c\u7a7a\u503c\u9a8c\u8bc1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OGEN"},"#I3OGEN")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u53ef\u914d\u7f6e\u662f\u5426\u81ea\u52a8\u6ce8\u518c ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OLW4"},"#I3OLW4")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b9a\u65f6\u4efb\u52a1\u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"cancelInNoneNextTime: false")," \u4e00\u6b21\u4e5f\u4e0d\u6267\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O3N0"},"#I3O3N0")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," SpareTime \u81ea\u5b9a\u4e49\u4e0b\u6b21\u6267\u884c\u65f6\u95f4\u51fa\u73b0\u7a7a\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O46X"},"#I3O46X")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MiniProfiler")," \u8bbe\u7f6e\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"false")," \u65f6\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u63d0\u4ea4\u62e6\u622a\u5668\u672a\u6dfb\u52a0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OAWX"},"#I3OAWX")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},'[Consumes("application/x-www-form-urlencoded")]')," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"ModelQuery")," \u914d\u7f6e\u540c\u65f6\u914d\u7f6e\u5bfc\u81f4\u7a7a\u5f15\u7528\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ODUR"},"#I3ODUR")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5728 Grpc \u4e2d\u4f7f\u7528 jwt \u6388\u6743\u51fa\u73b0\u7a7a\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OW3I"},"#I3OW3I")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u652f\u6301\u53d1\u5e03\u540e\u4ee3\u7801\u7cbe\u7b80\u914d\u7f6e\uff0c\u51cf\u5c11\u4e0d\u5fc5\u8981\u7684\u6587\u4ef6\u5939\u8f93\u51fa ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OAPF"},"#I3OAPF")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u81ea\u52a8\u5237\u65b0 Token \u673a\u5236\uff0c\u65b0\u589e\u5bb9\u9519\u503c\u5904\u7406\uff0c\u89e3\u51b3\u5e76\u53d1 Token \u5237\u65b0\u5931\u8d25\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OGYF"},"#I3OGYF")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7c98\u571f\u5bf9\u8c61\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OG18"},"#I3OG18")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u52a8\u6001 WebAPI \u5982\u4f55\u83b7\u53d6\u63a5\u6536\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O29B"},"#I3O29B")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5b9a\u65f6\u4efb\u52a1\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Scope.CreateUow")," \u5f15\u53d1\u7684\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O2CD"},"#I3O2CD")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5355\u6587\u4ef6\u53d1\u5e03\u7a0b\u5e8f\u5de5\u4f5c\u4e0d\u6b63\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O4D8"},"#I3O4D8")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u540c\u65f6\u914d\u7f6e\u79df\u6237\u8fc7\u6ee4\u5668\u548c\u8f6f\u5220\u9664\u8fc7\u6ee4\u5668\uff0c\u6700\u7ec8\u7684 sql \u53ea\u751f\u6210\u4e86\u4e00\u79cd\u8fc7\u6ee4\u6761\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OB0A"},"#I3OB0A")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," HTTP \u91cd\u5b9a\u5411 HTTPS \u540e\u8de8\u57df\u5931\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OB8R"},"#I3OB8R")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5728 PostgreSql \u6570\u636e\u5e93\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"rep.FirstOrDefault(u => u.Id == UserId);")," \u5f15\u8d77\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O5OF"},"#I3O5OF")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5b9a\u65f6\u4efb\u52a1\u6709\u65f6\u80fd\u89e6\u53d1\u6709\u65f6\u4e0d\u80fd\u89e6\u53d1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ORBE"},"#I3ORBE")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f5c\u5e9f]"," \u6846\u67b6\u4e2d\u7684 swagger \u662f\u5426\u6709\u63d0\u4f9b\u5bfc\u51fa\u6587\u6863\u4e3a markdwon/word \u7684\u529f\u80fd\u8ba1\u5212\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OL8O"},"#I3OL8O")),(0,r.kt)("li",{parentName:"ul"},"[\u4f5c\u5e9f]"," \u6570\u636e\u5e93\u5b9e\u4f53\u7236\u5b50\u7ee7\u627f\uff0c\u5b50\u7c7b\u751f\u6210\u7684 SQL \u4e0d\u4e00\u6837 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NHU3"},"#I3NHU3")),(0,r.kt)("li",{parentName:"ul"},"[\u4f5c\u5e9f]"," \u652f\u6301\u7b2c\u4e09\u65b9\u6570\u636e\u5e93 ORM ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OXA3"},"#I3OXA3"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v210-\u5df2\u53d1\u5e03"},"v2.1.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e\u5b9a\u65f6\u4efb\u52a1 ",(0,r.kt)("inlineCode",{parentName:"li"},"ISpareTimeWorker")," \u65b9\u5f0f\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},'[SpareTime("{\u914d\u7f6e\u8def\u5f84}}]')," \u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NTUX"},"#I3NTUX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9a\u65f6\u4efb\u52a1\u652f\u6301\u5f02\u6b65\u59d4\u6258 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NP96"},"#I3NP96")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8f7b\u91cf\u7ea7\u5206\u5e03\u5f0f\u8fde\u7eed GUID \u751f\u6210\u5668 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NKLZ"},"#I3NKLZ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ClayObject")," \u6a21\u5757\uff0c\u5904\u7406 ",(0,r.kt)("inlineCode",{parentName:"li"},"ExpandoObject")," \u53ca ",(0,r.kt)("inlineCode",{parentName:"li"},"IDictionary")," \u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3N3J4"},"#I3N3J4")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped.CreateUow(handler)")," \u521b\u5efa\u4f5c\u7528\u57df\u5e76\u81ea\u52a8\u63d0\u4ea4\u6570\u636e\u5e93\u66f4\u6539\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NU3G"},"#I3NU3G")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u89c4\u8303\u5316\u7ed3\u679c\u63a5\u53e3 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnResponseStatusCodes")," \u65b9\u6cd5\uff0c\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"UnifyResultStatusCodesOptions")," \u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NDB9"},"#I3NDB9")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("strong",{parentName:"li"},"\u96ea\u82b1 ID \u5b9e\u73b0\u4ee3\u7801 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I3NKLZ"},"#I3NKLZ"))))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e0d\u80fd\u652f\u6301\u975e int \u7c7b\u578b\u7684\u679a\u4e3e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NQM8"},"#I3NQM8")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u7ebf\u7a0b\u6c60\u591a\u7ebf\u7a0b\u5e76\u53d1\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NR4L"},"#I3NR4L")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u5b9a\u4e49\u63a7\u5236\u5668\u8def\u7531\u540e\u4e14\u4e3a\u65b9\u6cd5\u53c2\u6570\u6307\u5b9a\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"[ApiSeat]")," \u540e\u751f\u6210\u8def\u7531\u91cd\u590d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NRF6"},"#I3NRF6")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u652f\u6301\u5e94\u7528\u542f\u52a8\u7684\u65f6\u5019\u8fc1\u79fb\u79cd\u5b50\u6570\u636e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NH3M"},"#I3NH3M")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5206\u5e03\u5f0f ID \u751f\u6210\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3B6CX"},"#I3B6CX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e\u6a21\u5757\u5316\u5f00\u53d1\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NSUS"},"#I3NSUS")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," 20.4 \u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u5f0f > \u9519\u8bef",(0,r.kt)("inlineCode",{parentName:"li"},"ToAESDecrypt")," \u5199\u6210\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"ToToAESDecrypt")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NNKV"},"#")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6709\u5173\u3010\u5b9a\u65f6\u4efb\u52a1/\u59d4\u6258\u3011\u7684\u7591\u95ee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3N3EW"},"#I3N3EW")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u7edf\u4e00\u8fd4\u56de\u683c\u5f0f\u652f\u6301\u81ea\u5b9a\u4e49 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NU1G"},"#I3NU1G")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f5c\u5e9f]"," \u671f\u5f85 IEnumerableExtensions \u6269\u5c55 OrderBy \u51fd\u6570\u6765\u652f\u6301\u5206\u9875\u6392\u5e8f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NOQ9"},"#I3NOQ9"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v200-\u5df2\u53d1\u5e03"},"v2.0.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u53ca Worker Services \u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3K4DG"},"#I3K4DG")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b8c\u6574\u4efb\u52a1\u8c03\u5ea6\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IRUX"},"#I3IRUX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Cron")," \u8868\u8fbe\u5f0f\u89e3\u6790 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IQ9Y"},"#I3IQ9Y")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u81ea\u5b9a\u4e49\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"swagger.json")," \u5730\u5740\u6a21\u677f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IHMX"},"#I3IHMX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301\u914d\u7f6e\u52a8\u6001 WebApi \u533a\u57df ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IJAZ"},"#I3IJAZ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u65b0\u589e\u652f\u6301\u4f20\u5165\u670d\u52a1\u63d0\u4f9b\u5668 ",(0,r.kt)("inlineCode",{parentName:"li"},"IServiceProvider")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IVBL"},"#I3IVBL")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u914d\u7f6e\u9009\u578b ",(0,r.kt)("inlineCode",{parentName:"li"},"SupportPackageNamePrefixs")," \u914d\u7f6e\uff0c\u652f\u6301\u914d\u7f6e\u5305\u524d\u7f00 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3K0SN"},"#I3K0SN")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5e94\u7528\u542f\u52a8\u65f6\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"referenceassembly")," \u7c7b\u578b\u7a0b\u5e8f\u96c6\u626b\u63cf ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3K0SN"},"#I3K0SN")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4f9d\u8d56\u6ce8\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"AOP")," \u62e6\u622a\u83b7\u53d6\u65b9\u6cd5\u771f\u5b9e\u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3LZBX"},"#I3LZBX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," EFCore \u624b\u52a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"SaveChanges()")," \u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3N01Y"},"#I3N01Y")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Cors")," \u8de8\u57df\u66f4\u591a\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3N2J0"},"#I3N2J0")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u5b8c\u6574\u4efb\u52a1\u8c03\u5ea6\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IRUX"},"#I3IRUX")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u65e5\u5fd7\u6a21\u5757\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J2K0"},"#I3J2K0")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u6a21\u677f\u5f15\u64ce\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J46E"},"#I3J46E")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u5e95\u5c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCoreRepository")," \u4ed3\u50a8 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J6W5"},"#I3J6W5")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," sql \u5b57\u7b26\u4e32\u62d3\u5c55\u5e95\u5c42\u4ee3\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IVCE"},"#I3IVCE")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u5e95\u5c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlRepository")," \u6240\u6709\u903b\u8f91\u4ee3\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J6V6"},"#I3J6V6")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u6570\u636e\u5e93\u5b9e\u4f53\u62d3\u5c55\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J609"},"#I3J609")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u4e8b\u4ef6\u4e8b\u4ef6\u603b\u7ebf\u540c\u6b65\u6267\u884c\u4e3a\u5f02\u6b65\u65b9\u5f0f\u6267\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J0WA"},"#I3J0WA")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u6846\u67b6\u5e95\u5c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContext.IsAjaxRequest()")," \u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IVAA"},"#I3IVAA")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationTypes.Required")," \u9a8c\u8bc1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3KR85"},"#I3KR85")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5173\u95ed ",(0,r.kt)("inlineCode",{parentName:"li"},"InjectMiniProfiler")," \u53c2\u6570\u540e\u5185\u5b58\u7f13\u5b58\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IHLR"},"#I3IHLR")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5728\u591a\u79df\u6237\u4e2d\u8c03\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Tenant")," \u5c5e\u6027\u51fa\u73b0\u5076\u7136\u6027\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u88ab\u91ca\u653e\u7684\u60c5\u51b5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IC70"},"#I3IC70")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," Sql \u4ee3\u7406\u4e2d\u5982\u679c\u8fd4\u56de\u57fa\u5143\u7c7b\u578b\u629b\u51fa\u4e0d\u80fd\u5c06 object \u8f6c\u6362\u6210\u5bf9\u5e94\u7c7b\u578b\u7684\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IC84"},"#I3IC84")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b58\u50a8\u8fc7\u7a0b\u591a\u8fd4\u56de\u503c\u7684\u65f6\u5019\uff0coutputvalues \u7684 name \u4e0d\u662f\u5b9a\u4e49\u7684 MSG \u7684 name\uff0c\u662f Msg \u7c7b\u578b\u3002 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IC7Y"},"#I3IC7Y")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," PhoneNumber \u624b\u673a\u53f7\u9a8c\u8bc1\u6b63\u5219\u8868\u8fbe\u5f0f\u9519\u8bef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ID10"},"#I3ID10")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4f9d\u8d56\u6ce8\u5165 AOP \u62e6\u622a\u65e0\u6cd5\u6355\u83b7\u5185\u90e8\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IGCC"},"#I3IGCC")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5168\u5c40\u62e6\u622a\u6807\u8bb0\u5f02\u5e38\u5df2\u88ab\u5904\u7406\u540e\u5f02\u5e38\u8fc7\u6ee4\u5668\u4f9d\u7136\u6267\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J463"},"#I3J463")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u5b9a\u4e49\u5168\u5c40\u5f02\u5e38\u62e6\u622a\u5668\u4e0d\u8d77\u4f5c\u7528 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3K1SJ"},"#I3K1SJ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5728 WorkerService \u6a21\u5f0f\u4e0b\uff0c\u8fd8\u662f\u4f7f\u7528 WebHostEnvironment \u6765\u5224\u65ad Host \u73af\u5883\uff0c\u4f1a\u5bfc\u81f4\u9519\u8bef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3LCQY"},"#I3LCQY")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b9a\u65f6\u4efb\u52a1 ",(0,r.kt)("inlineCode",{parentName:"li"},"DoOnce")," \u629b\u7a7a\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3M0ZT"},"#I3M0ZT")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u542f\u52a8\u65f6\u7a0b\u5e8f\u96c6\u626b\u63cf\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3K0SN"},"#I3K0SN")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," ",(0,r.kt)("inlineCode",{parentName:"li"},'App.GetConfig<>("key")')," \u4e0d\u652f\u6301\u83b7\u53d6\u5355\u4e2a\u503c\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ILF1"},"#I3ILF1")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," UrlEncode \u5e94\u8be5\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Uri.EscapeDataString()")," \u800c\u4e0d\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpUtility.UrlEncode")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ICTK"},"#I3ICTK")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9a\u4f4d\u4efb\u52a1\u3001\u540e\u53f0\u4efb\u52a1\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3JHHG"},"#I3JHHG")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8f85\u52a9\u89d2\u8272\u670d\u52a1\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3K5GN"},"#I3K5GN")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u52a8\u6001 WebAPI\u3001\u89c4\u8303\u5316\u6587\u6863\u3001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6570\u636e\u6821\u9a8c\uff0c\u81ea\u5b9a\u4e49 ErrorMessage \u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ICL3"},"#I3ICL3")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6700\u65b0 issue \u4e2d\u65b0\u589e\u7684\u201c\u65b0\u589e\u5e38\u7528\u7684 JSON \u5e8f\u5217\u5316\u65b9\u6cd5\u201d \u4f1a\u5bfc\u81f4 AOP \u62e6\u622a\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3I7VE"},"#I3I7VE")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Furion.DatabaseAccessor.PrivateEntityBase \u4e2d\u7684 TenantId \u6570\u636e\u7c7b\u578b\u8bbe\u7f6e\u4e3a object ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IQV6"},"#I3IQV6")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6709\u5173\u5f02\u5e38\u62e6\u622a\u548c\u5904\u7406\u7684\u7591\u95ee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IUFZ"},"#I3IUFZ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DataValidation")," \u5728\u7a7a\u503c\u7684\u60c5\u51b5\u4e0b\u88ab\u5ffd\u7565\u6389\u4e86",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IWSM"},"#I3IWSM")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u65e5\u5fd7\u6587\u6863\u6ca1\u6709\u66f4\u65b0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J1DX"},"#I3J1DX")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5bf9\u4e8e webapi \u7b80\u5355\u7c7b\u578b\u53c2\u6570\uff0c\u662f\u5426\u53ef\u4ee5\u4ee5 json \u65b9\u5f0f\u63d0\u4ea4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J18I"},"#I3J18I")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IUnifyResultProvider")," \u5b9e\u73b0\u4e2d\u5982\u679c ",(0,r.kt)("inlineCode",{parentName:"li"},"UnifyModel")," \u7684 type \u4e0d\u662f\u8303\u578b\u4f1a\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3JBXF"},"#I3JBXF")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5982\u4f55\u6a21\u5757\u5316\u5f00\u53d1\u65b0\u529f\u80fd\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J7ZZ"},"#I3J7ZZ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5efa\u8bae\u589e\u52a0\u5fae\u670d\u52a1\u4e2d\u95f4\u4ef6\u7684\u96c6\u6210 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3JTZQ"},"#I3JTZQ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u4e8c\u7ea7\u865a\u62df\u76ee\u5f55\u90e8\u7f72\u7684 swagger \u7684 MiniProfiler js \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IWLR"},"#I3IWLR")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f5c\u5e9f]"," \u5728\u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7\u4e2d\u5bf9\u8d34\u6709 DisableAuditing \u7279\u6027\u7684\u5b57\u6bb5\u81ea\u52a8\u8fc7\u6ee4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DHAN"},"#I3DHAN"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v1190-\u5df2\u53d1\u5e03"},"v1.19.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore 5.0")," \u652f\u6301 ",(0,r.kt)("strong",{parentName:"li"},"SqlServer 2005-2008")," \u6570\u636e\u5e93 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HZZ6"},"#I3HZZ6")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u9ad8\u7ea7\u4ee3\u7406\u652f\u6301\u6a21\u677f\u66ff\u6362\u4e86 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HHWU"},"#I3HHWU")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HH2T"},"#I3HH2T")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"PBKDF2")," \u52a0\u5bc6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HN7A"},"#I3HN7A")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5e38\u7528\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON")," \u64cd\u4f5c\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HUYO"},"#I3HUYO")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6240\u6709\u89e3\u6790\u670d\u52a1\u7684\u65b9\u6cd5\u90fd\u652f\u6301\u4f20\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"IServiceProvidier")," \u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HXEU"},"#I3HXEU")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," .NET 5 SDK \u81f3 5.0.5 \u7248\u672c"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"application/x-www-form-urlencoded")," \u81ea\u52a8\u88ab\u8f6c\u7801\u4e86 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HDPC"},"#I3HDPC")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ISqlDispatchProxy")," \u8c03\u7528\u5e26\u8fd4\u56de\u503c\u7684\u5b58\u50a8\u8fc7\u7a0b\u51fa\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HISS"},"#I3HISS")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u6570\u636e\u5e93\u5de5\u4f5c\u5355\u5143\u5f02\u5e38\u65e0\u6cd5\u56de\u6eda\u6570\u636e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3I2KN"},"#I3I2KN")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/zuohuaijun/Admin.NET/issues/I3HYN5"},"#I3HYN5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," Serilog \u65e5\u5fd7\u751f\u6210\u592a\u591a\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3I2PN"},"#I3I2PN")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"1.18.0")," \u7248\u672c\u6570\u636e\u5e93\u8fde\u63a5\u6c60\u5b58\u5728\u8fde\u63a5\u6cc4\u6f0f\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3I5KO"},"#I3I5KO")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," Sqlite \u63d0\u793a\u4e8b\u52a1\u5df2\u5b8c\u6210\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3I9F2"},"#I3I9F2")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u89c6\u56fe\u6a21\u677f\u529f\u80fd\uff0c\u9ed8\u8ba4\u652f\u6301\u53ef\u679a\u4e3e\u6cdb\u578b\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3GYEE"},"#I3GYEE")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u5f00\u53d1\u9636\u6bb5 MiniProfiler \u6253\u5370\u6570\u636e\u5e93\u76f8\u5173\u4fe1\u606f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3I8VQ"},"#I3I8VQ")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," EFCore 5.0 \u672a\u63d0\u4f9b Sqlite \u6570\u636e\u5e93 DataAdapter \u7684\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3I9FC"},"#I3I9FC")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3001\u591a\u79df\u6237\u3001\u4ed3\u50a8\u3001\u65e5\u5fd7\u3001\u5e8f\u5217\u5316\u7b49\u6587\u6863\u3002"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5efa\u8bae MVC \u6a21\u5f0f\u4e0b\u589e\u52a0 Furion \u7684\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3GY4R"},"#I3GY4R")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6570\u636e\u5e93\u5173\u8054\u64cd\u4f5c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3H5QP"},"#I3H5QP")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," 1.17.5 \u7248\u672c suagger \u65e0\u6cd5\u751f\u6210 swagger.json ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HGPZ"},"#I3HGPZ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Serilog \u6269\u5c55+dll \u542f\u52a8\u4e0e swagger \u7684 MiniProfiler \u51b2\u7a81 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HWJM"},"#I3HWJM")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Sql \u9ad8\u7ea7\u4ee3\u7406\u8fd4\u56de DataTable \u65f6\uff0c\u7ed3\u679c\u4e3a\u7a7a\u53d6\u4e0d\u5230\u8bb0\u5f55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HUWG"},"#I3HUWG")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Task.Run \u64cd\u4f5c\u6570\u636e\u5e93\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HZ9D"},"#I3HZ9D")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v1180-\u5df2\u53d1\u5e03"},"v1.18.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Oracle")," 11 \u7248\u672c\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EVL5"},"#I3EVL5")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mysql")," \u5b98\u65b9\u5305 ",(0,r.kt)("inlineCode",{parentName:"li"},"MySql.EntityFrameworkCore")," \u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3E6J1"},"#I3E6J1")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"WebApi")," \u53c2\u6570 ",(0,r.kt)("inlineCode",{parentName:"li"},"[FromQury]")," \u5316 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EFYJ"},"#I3EFYJ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u516c\u5f00\u6846\u67b6\u5e95\u5c42\u4f9d\u8d56\u6ce8\u5165\u626b\u63cf\u6ce8\u518c\u62d3\u5c55 ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddRisterTypes(types)")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EIV3"},"#I3EIV3")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," SqlSugar \u5de5\u4f5c\u5355\u5143\u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EJO5"},"#I3EJO5")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6c60\u4e00\u65e6\u6709\u4e0a\u4e0b\u6587\u64cd\u4f5c\u5931\u8d25\u8fd8\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u51fa\u73b0\u4e8c\u6b21\u63d0\u4ea4\u6570\u636e\u5e93\u7684\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EIJJ"},"#I3EIJJ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e0d\u540c\u6570\u636e\u5e93\u547d\u4ee4\u53c2\u6570\u524d\u7f00\u90fd\u6dfb\u52a0\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"@")," \u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EBJP"},"#I3EBJP")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5c1d\u8bd5\u4fee\u590d\u4e8b\u4ef6\u603b\u7ebf\u7ebf\u7a0b\u5b89\u5168\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EGSB"},"#I3EGSB")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/236"},"#PR236")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContextExtensions")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"SignoutToSwagger")," \u65b9\u6cd5\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EHNQ"},"#I3EHNQ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5982\u679c\u52a8\u6001 WebApi \u8d34\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"[ApiController]")," \u7279\u6027\u540e\uff0c\u5bfc\u81f4\u8def\u7531\u53c2\u6570\u91cd\u590d\u751f\u6210 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EOQQ"},"#I3EOQQ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5982\u679c\u6ca1\u6709\u4efb\u4f55 webapi \u63a7\u5236\u5668\u65f6\uff0c\u6587\u6863\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EVLB"},"#I3EVLB")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4f9d\u8d56\u6ce8\u5165\u6cdb\u578b\u7c7b\u578b\u6ce8\u518c\u5931\u8d25 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EX66"},"#I3EX66")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," SqlSugar \u62d3\u5c55\u5e93\u4ed3\u50a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"Context")," \u5c5e\u6027\u7c7b\u578b\u672a ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugarClient")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EHXA"},"#I3EHXA")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u5237\u65b0 Token \u9ed1\u540d\u5355 Redis \u4e2d\u5206\u7ec4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EQWO"},"#I3EQWO")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u8fdc\u7a0b\u8bf7\u6c42\u5728\u8bf7\u6c42\u62e6\u622a\u6b21\u53d1\u8d77\u4e8c\u6b21\u8bf7\u6c42\u5bfc\u81f4\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ER71"},"#I3ER71")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u591a\u79df\u6237\u9ed8\u8ba4\u7f13\u5b58\u6539\u4e3a\u5206\u5e03\u5f0f\u7f13\u5b58 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EXEU"},"#I3EXEU")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u6570\u636e\u5e93\u64cd\u4f5c\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3E84X"},"#I3E84X")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5982\u4f55\u65b9\u4fbf\u7684\u83b7\u53d6 ",(0,r.kt)("inlineCode",{parentName:"li"},"IDynamicApiController")," API \u4ea7\u751f\u7684 url \u548c \u8c13\u8bcd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ED17"},"#I3ED17")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Code First -\u6267\u884c\u547d\u4ee4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Add-Migration")," \u9047\u5230\u4e86\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EHD0"},"#I3EHD0")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," tools v1.16.0 \u65e0\u6cd5\u751f\u6210\u5b9e\u4f53\uff0c\u4e00\u76f4\u63d0\u793a Missing required argument ",(0,r.kt)("inlineCode",{parentName:"li"},""),". ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ENZ8"},"#I3ENZ8")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Authorize \u7684 Logout \u6309\u94ae\uff0c\u65e0\u6cd5\u5b9e\u65f6\u8bf7\u7a7a token",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EOF9"},"#I3EOF9")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v1170-\u5df2\u53d1\u5e03"},"v1.17.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001 WebAPI \u652f\u6301\u7ee7\u627f\u57fa\u7c7b\u914d\u7f6e\u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3D5PX"},"#I3D5PX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"multipart/form-data")," \u5185\u5bb9\u7c7b\u578b\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3D7KG"},"#I3D7KG")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b57\u7b26\u4e32\u52a0\u5bc6\u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DHBW"},"#I3DHBW")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e\u8fdc\u7a0b\u8bf7\u6c42\u53ef\u76f4\u63a5\u4e0b\u8f7d\u8fd4\u56de\u503c\u5185\u5bb9\u8f6c\u4e3a string \u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DIGR"},"#I3DIGR")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u5730\u5740\u652f\u6301\u6a21\u677f\u5f15\u64ce ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3D5Y8"},"#I3D5Y8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[DataValidation]")," \u9519\u8bef\u6d88\u606f\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"string.Format")," \u64cd\u4f5c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3E08W"},"#I3E08W")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpRequestMessage")," \u62d3\u5c55\u65b9\u6cd5 ",(0,r.kt)("inlineCode",{parentName:"li"},"AppendQueries()")," \u8ffd\u52a0\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"li"},"query")," \u53c2\u6570\u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3E3DI"},"#I3E3DI")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IRepository.AsAsyncEnumerable()")," \u8fd4\u56de\u503c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DIQ1"},"#I3DIQ1"),"\uff0c\u8c03\u6574\u4e3a\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"rep.AsQueryable().ToListAsync()")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u9a8c\u8bc1\u5931\u8d25\u540e\u4e5f\u6253\u5370\u4e86\u6210\u529f\u7684\u5b57\u6bb5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CVBS"},"#I3CVBS")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"contentType")," \u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"application/x-www-form-urlencoded")," \u65e0\u6548\u95ee\u9898",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CWBS"},"#I3CWBS")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u65e0\u6cd5\u6253\u5370\u5b8c\u6574\u7684\u8bf7\u6c42\u5730\u5740\uff0c\u6bd4\u5982\u914d\u7f6e\u4e86 HttpClient \u4e4b\u540e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CY42"},"#I3CY42")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u7a0b\u5e8f\u542f\u52a8\u65f6\u6392\u9664\u9ed8\u8ba4\u914d\u7f6e\u6587\u4ef6\u7b97\u6cd5\u4e0d\u5bf9\uff0c\u5e94\u8be5\u91c7\u7528\u6b63\u5219\u8868\u8fbe\u5f0f\u5339\u914d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3D9E7"},"#I3D9E7")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u6210\u529f\u8bf7\u6c42\u62e6\u622a\u4e0d\u751f\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DOE4"},"#I3DOE4")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Dapper")," \u62d3\u5c55\u6570\u636e\u5e93\u5207\u6362\u4e3a oracle \u65f6\uff0c\u7cfb\u7edf\u627e\u4e0d\u5230\u6307\u5b9a\u7684\u6587\u4ef6 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oracle.ManagedDataAccess.Core")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DYM3"},"#I3DYM3")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u83b7\u53d6 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT token")," \u4fe1\u606f\u652f\u6301\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u524d\u7f00\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"li"},"Bearer ")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DJIV"},"#I3DJIV")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u5237\u65b0 Token \u9ed1\u540d\u5355\u5b58\u50a8\u65b9\u5f0f\uff0c\u5c06\u5185\u5b58\u7f13\u5b58\u8c03\u6574\u4e3a\u5206\u5e03\u5f0f\u7f13\u5b58 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DPBR"},"#I3DPBR")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CPJO"},"#I3CPJO")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"LinqExpression.And")," \u6ca1\u6709 2 \u4e2a\u53c2\u6570\u7684\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CXKZ"},"#I3CXKZ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5f02\u5e38\u4fe1\u606f \u5982\u4f55\u8bb0\u5f55\u5230\u6570\u636e\u5e93\u4e2d:) ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DDGO"},"#I3DDGO")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u65e0\u952e\u5b9e\u4f53\u9009\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntityNotKey")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DWRF"},"#I3DWRF")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6839\u636e\u4e3b\u952e\u5220\u9664\u4e00\u6761\u8bb0\u5f55\u4e0d\u6210\u529f\uff0c\u65e0\u9519\u8bef\u4fe1\u606f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DWWF"},"#I3DWWF")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5982\u4f55\u81ea\u5b9a\u4e49\u63a5\u53e3\u8fd4\u56de\u683c\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DZN6"},"#I3DZN6")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," DynamicApiController \u5982\u4f55\u5728\u8fd0\u884c\u65f6\u51b3\u5b9a\u662f\u5426\u516c\u5f00\u4e00\u4e2a Action ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3D5UL"},"#I3D5UL")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.DatabaseAccessor.DbHelpers")," \u65b9\u6cd5\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"ConvertToDbParameters")," \u662f\u4e0d\u662f\u5e94\u8be5\u8fc7\u6ee4\u6389\u8d34 ",(0,r.kt)("inlineCode",{parentName:"li"},"NotMapped")," \u7684\u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3E2XS"},"#I3E2XS")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u6846\u67b6\u662f\u5426\u63d0\u4f9b ",(0,r.kt)("inlineCode",{parentName:"li"},"ISoftDelete")," \u7c7b\u4f3c\u63a5\u53e3 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CP93"},"#I3CP93"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v1160-\u5df2\u53d1\u5e03"},"v1.16.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IDGenerator")," \u96ea\u82b1 ID \u7b97\u6cd5\uff0c\u611f\u8c22 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/yitter/idgenerator"},"idgenerator")," \u4f5c\u8005\u63d0\u4ea4 PR ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/204"},"#PR204")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3B60S"},"#I3B60S")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DbContext")," \u5237\u65b0\u591a\u79df\u6237\u7f13\u5b58\u62d3\u5c55\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39N5U"},"#I39N5U")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u81ea\u5b9a\u4e49\u914d\u7f6e\u5355\u4e2a\u63a7\u5236\u5668\u540d\u79f0\u89c4\u8303\uff0c\u5982\u5c0f\u5199\u8def\u7531 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3A5XL"},"#I3A5XL")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u83b7\u53d6\u5f53\u524d\u9009\u62e9\u533a\u57df\u8bed\u8a00\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BSDH"},"#I3BSDH")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," .NET 5 SDK \u81f3 5.0.4 \u7248\u672c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ASTL"},"#I3ASTL")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u8fdc\u7a0b\u8bf7\u6c42\u6240\u6709\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2LB7M"},"#I2LB7M")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON")," \u5e8f\u5217\u5316\u529f\u80fd\uff0c\u63d0\u4f9b\u7edf\u4e00\u7684\u62bd\u8c61\u63a5\u53e3\uff0c\u65b9\u4fbf\u81ea\u7531\u66ff\u6362 ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON")," \u5e93 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39GT9"},"#I39GT9")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u9a8c\u8bc1\u5931\u8d25\u8fd4\u56de\u6d88\u606f\u6a21\u578b\u53ca\u89c4\u8303\u5316\u63a5\u53e3\u9a8c\u8bc1\u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AFQW"},"#I3AFQW")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u63d2\u4ef6\u5f0f\u5f00\u53d1\u70ed\u63d2\u62d4\u529f\u80fd\uff0c\u5b9e\u73b0\u52a8\u6001\u52a0\u8f7d\u5378\u8f7d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/200"},"#PR200"),", \u611f\u8c22 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/samwangcoder"},"@SamWangCoder")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u79fb\u9664 ",(0,r.kt)("inlineCode",{parentName:"li"},"JsonSerializerUtility")," \u9759\u6001\u7c7b\u53ca\u79fb\u9664\u5c5e\u6027\u5927\u5199\u5e8f\u5217\u5316\u62d3\u5c55\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AFRJ"},"#I3AFRJ")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MVC")," \u6a21\u5f0f\u4e0b\u4e0d\u652f\u6301\u9a8c\u8bc1\u81ea\u5b9a\u4e49\u9a8c\u8bc1\u903b\u8f91 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39LM5"},"#I39LM5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u9a8c\u8bc1\u6570\u503c\u7c7b\u578b\u6b63\u5219\u8868\u8fbe\u5f0f\u4e0d\u652f\u6301\u8d1f\u6570 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39YUV"},"#I39YUV")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6846\u67b6\u542f\u52a8\u65f6\u65e0\u6cd5\u52a0\u8f7d\u672a\u88ab\u5f15\u7528\u7684\u7a0b\u5e8f\u96c6 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3A3Z4"},"#I3A3Z4")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCoreRepository.IsAttached()")," \u65b9\u6cd5\u5224\u65ad\u9519\u8bef bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3A824"},"#I3A824")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"\u52a8\u6001API")," \u9a7c\u5cf0\u663e\u793a\u914d\u7f6e\u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AF32"},"#I3AF32")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"cli.ps1")," \u4e0d\u652f\u6301\u65b0\u7248\u672c ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3APO9"},"#I3APO9")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u5b9e\u4f53\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"[Table]")," \u7279\u6027\u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BAYH"},"#I3BAYH")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u52a8\u6001 WebAPI ",(0,r.kt)("inlineCode",{parentName:"li"},"CheckIsSplitCamelCase")," bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BLKX"},"#I3BLKX")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u52a8\u6001 WebAPI \u914d\u7f6e\u4fdd\u7559 Action \u7684 Async \u540e\u7f00\u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3C3DA"},"#I3C3DA")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT")," Token \u5237\u65b0\u540e\u65e7\u7684\u5237\u65b0 Token \u4f9d\u65e7\u53ef\u7528 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3C8ZH"},"#I3C8ZH")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u8bed\u8a00 ",(0,r.kt)("inlineCode",{parentName:"li"},"Razor")," \u89c6\u56fe\u53d8\u91cf\u591a\u8bed\u8a00\u4e71\u7801\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CBMU"},"#I3CBMU")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u9ed8\u8ba4\u5e8f\u5217\u5316\u63d0\u4f9b\u5668 ",(0,r.kt)("inlineCode",{parentName:"li"},"System.Text.Json")," \u53cd\u5e8f\u5217\u5316\u5b57\u7b26\u4e32\u65f6\u533a\u5206\u5927\u5c0f\u5199\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BSXV"},"#I3BSXV")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u4f18\u5316 ",(0,r.kt)("inlineCode",{parentName:"li"},"MessageCenter")," \u6027\u80fd\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39PRR"},"#I39PRR")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6c60\u5c0f\u6027\u80fd\u4f18\u5316"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Docker")," \u73af\u5883\u4e0b\u81ea\u52a8\u5316\u90e8\u7f72 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/209"},"#PR209")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON")," \u5e8f\u5217\u5316 \u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3B6D8"},"#I3B6D8")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u8de8\u57df\u3001\u5b89\u5168\u6388\u6743\u3001\u5373\u65f6\u901a\u4fe1\u6587\u6863\u3001\u591a\u8bed\u8a00\u3001\u89c4\u8303\u5316\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.DatabaseAccessor.SqlSugar")," \u914d\u7f6e\u591a\u4e2a\u6570\u636e\u5e93\u6253\u5370 SQL \u8bed\u53e5\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39PDC"},"#I39PDC")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ORACLE")," \u6570\u636e\u5e93\u591a\u79df\u6237\u6a21\u5f0f\u4e0b\u8fd4\u56de\u503c\u4e3a\u6307\u5b9a\u7c7b\u578b\u65f6\u7cfb\u7edf\u5361\u6b7b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39RNH"},"#I39RNH")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5047\u5220\u9664\u6307\u5411\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39XZA"},"#I39XZA")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u591a\u8bed\u8a00\u914d\u7f6e\u8282\u662f\u653e\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"AppSettings")," \u91cc\u9762\u8fd8\u662f\u5916\u9762\u5462\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3A4SB"},"#I3A4SB")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6ca1\u627e\u5230\u6570\u636e\u5e93\u4e0a\u4e0b\u6587 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3A5HS"},"#I3A5HS")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6709 ",(0,r.kt)("inlineCode",{parentName:"li"},"QQ")," \u4ea4\u6d41\u7fa4\u5417\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AAM7"},"#I3AAM7")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Vue3")," \u73af\u5883\u4e0b\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"SignalR")," \u8de8\u57df\u51fa\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ALQ7"},"#I3ALQ7")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u53c2\u6570\u975e\u5fc5\u586b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AT02"},"#I3AT02")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," EFCore \u8c03\u7528 Insert \u65f6\u62a5 ",(0,r.kt)("inlineCode",{parentName:"li"},"Unknown column 'Discriminator' in 'field list'")," \u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3B2LC"},"#I3B2LC")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u9006\u5411 ",(0,r.kt)("inlineCode",{parentName:"li"},"mysql")," \u6570\u636e\u5e93\u65f6 ",(0,r.kt)("inlineCode",{parentName:"li"},"cli")," \u51fa\u73b0\u9519\u8bef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3B64F"},"#I3B64F")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Sql \u9ad8\u7ea7\u4ee3\u7406\u4f7f\u7528\u8fc7\u7a0b\u4e2d DateTime \u7c7b\u578b\u7684\u53c2\u6570\u5e8f\u5217\u5316\u5931\u8d25 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AZXK"},"#I3AZXK")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u4f7f\u7528 Mysql \u6267\u884c Add-Migration \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3B8EW"},"#I3B8EW")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Saas \u591a\u79df\u6237\u6a21\u5f0f-\u72ec\u7acb Database \u6a21\u5f0f\u4e0b\u65e0\u6cd5\u83b7\u53d6 Tenant, \u5bfc\u81f4\u65e0\u6cd5\u81ea\u52a8\u5207\u6362\u7684\u95ee\u9898",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AVXU"},"#I3AVXU")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5982\u4f55\u81ea\u5b9a\u4e49 WebAPI \u7edf\u4e00\u7ed3\u679c\u6a21\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BBYW"},"#I3BBYW")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BBYV"},"#I3BBYV")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Web.Entry")," \u9879\u76ee\u65b0\u5efa\u4e86\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"Controller"),"\uff0c\u591a\u4e86\u672a\u77e5\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BKH5"},"#I3BKH5")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AOP")," \u62e6\u622a\u5982\u4f55\u89e3\u6790\u670d\u52a1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BUM3"},"#I3BUM3")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u52a8\u6001 WebAPI \u8fd4\u56de\u53c2\u6570\u88ab\u7701\u7565 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3C2XR"},"#I3C2XR")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5982\u4f55\u8bbe\u7f6e\u67d0\u4e00\u4e2a\u63a5\u53e3\u54cd\u5e94\u6570\u636e\u4e0d\u81ea\u52a8\u8f6c\u5c0f\u5199\uff0c\u6309\u539f\u59cb\u5b57\u6bb5\u540d\u8fd4\u56de ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38L9B"},"#I38L9B")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," code first \u5982\u4f55\u914d\u7f6e\u81ea\u52a8\u8fc1\u79fb ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CCR0"},"#I3CCR0")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," webapi \u6df7\u5408\u6388\u6743\u5982\u4f55\u533a\u5206\u4e0d\u540c\u7cfb\u7edf ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CJCY"},"#I3CJCY")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," EFCore \u4e0d\u652f\u6301\u9012\u5f52\u65e0\u9650\u7ea7\u904d\u5386\u5173\u7cfb ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CET9"},"#I3CET9")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u53ef\u914d\u7f6e\u5916\u952e\u5173\u7cfb\u5bfc\u822a\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3994X"},"#I3994X")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae\u5c06 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u5265\u79bb\u51fa\u6765\uff0c\u4f5c\u4e3a\u63d2\u4ef6\u7684\u5f62\u5f0f\u63d0\u4f9b\u3002\u8fd9\u6837\u53ef\u4ee5\u9009\u62e9\u81ea\u5df1\u559c\u6b22\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ORM")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ABNX"},"#I3ABNX")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u4e8b\u4ef6\u603b\u7ebf\u80fd\u5426\u63d0\u4f9b\u8fd4\u56de\u503c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AWL6"},"#I3AWL6")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," Sql \u6a21\u677f\u80fd\u4eff\u7167 Mybatis \u4e00\u6837\u52a0\u5404\u79cd\u6807\u7b7e\u5417\uff1f",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ASRS"},"#I3ASRS")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," EFCore \u66f4\u65b0\u6216\u6392\u9664\u66f4\u65b0\u6307\u5b9a\u5217\u652f\u6301\u4f20\u5165 DTO \u6a21\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AS5K"},"#I3AS5K")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"UnitOfWork")," \u4e8b\u52a1\u5b8c\u6210\u4e8b\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BRMI"},"#I3BRMI"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v1150-\u5df2\u53d1\u5e03"},"v1.15.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8df3\u8fc7\u7279\u5b9a\u5b9e\u4f53\u6570\u636e\u5e93\u64cd\u4f5c\u76d1\u542c\u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I386LB"},"#I386LB")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntityChangedListener")," \u589e\u52a0\u5bf9 ",(0,r.kt)("inlineCode",{parentName:"li"},"OldEntity")," \u7684\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I385X2"},"#I385X2")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9e\u65f6\u901a\u4fe1\u81ea\u52a8\u914d\u7f6e\u96c6\u7ebf\u5668\u62d3\u5c55\u53ca\u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I387QX"},"#I387QX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mapster")," \u62d3\u5c55\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"IMapper")," \u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38C7C"},"#I38C7C")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[AppDbContext]")," \u7279\u6027\u9ed8\u8ba4\u6784\u9020\u51fd\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38J97"},"#I38J97")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"UnifyContext.GetExceptionMetadata(context)")," \u8fd4\u56de\u9519\u8bef\u7801\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38ONX"},"#I38ONX")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u6b21\u5faa\u73af\u4e2d\u8c03\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetNewDbContext()")," \u8fd8\u662f\u83b7\u53d6\u5230\u540c\u4e00\u4e2a\u5bf9\u8c61 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38NNP"},"#I38NNP")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u8fc7\u6ee4\u6389 ",(0,r.kt)("inlineCode",{parentName:"li"},"object ")," \u7c7b\u578b\u5c5e\u6027\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38FHL"},"#I38FHL")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u540c\u4e00\u7c7b\u4e0d\u652f\u6301\u591a\u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntityChangedListener")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38UQJ"},"#I38UQJ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u5b9a\u4e49\u5e8f\u5217\u5316\u5c5e\u6027\u540d\u79f0\u5bfc\u81f4\u9a8c\u8bc1\u5931\u8d25\u5c5e\u6027\u4e0d\u5339\u914d\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38W8Z"},"#I38W8Z")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u4ee3\u7801\u4e0d\u89c4\u8303\u547d\u540d\u5bfc\u81f4\u5f00\u53d1\u8005\u9605\u8bfb\u4ee3\u7801\u65f6\u4ea7\u751f\u6b67\u4e49"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"FluentValidation")," \u96c6\u6210\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38IOT"},"#I38IOT")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6846\u67b6\u7248\u672c\u5411\u4e0b\u517c\u5bb9\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38WMZ"},"#I38WMZ")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u6dfb\u52a0\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38G4M"},"#I38G4M")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae ",(0,r.kt)("inlineCode",{parentName:"li"},"MessageCenter")," \u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Channel")," \u5b9e\u73b0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38BP8"},"#I38BP8")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae\u63a5\u53e3\u6587\u6863\u6574\u5408 Knife4jUI \u6216 Redoc ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38S70"},"#I38S70"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v1140\u5df2\u53d1\u5e03"},"v1.14.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," 5.0 \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oracle")," \u6570\u636e\u5e93\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37Z8E"},"#I37Z8E")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u63a7\u5236\u662f\u5426\u5728\u5f00\u53d1\u73af\u5883\u4e0b\u663e\u793a\u6570\u636e\u5e93\u8fde\u63a5\u4fe1\u606f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37YQ2"},"#I37YQ2")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[NonUnify]")," \u652f\u6301\u5728\u7c7b\u4e2d\u8d34\u6b64\u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I359Q6"},"#I359Q6")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"\u7f51\u7edc\u8bf7\u6c42")," \u5b57\u7b26\u4e32 ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpClient")," \u62e6\u622a\u5668 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I35F3E"},"#I35F3E")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContext")," \u53ca ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpRequest")," \u83b7\u53d6\u8fdc\u7a0b\u5730\u5740\u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3688Z"},"#I3688Z")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddMvcFilter<>")," \u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Mvc")," \u8fc7\u6ee4\u5668\u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I368BH"},"#I368BH")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," \u6846\u67b6\u4f9d\u8d56\u7684 .NET 5 SDK \u81f3\u6700\u65b0\u7248 5.0.3 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37YQQ"},"#I37YQQ")),(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swashbuckle.AspNetCore")," \u7ec4\u4ef6\u5305\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"6.0.x")," \u7248\u672c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37EZK"},"#I37EZK")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6846\u67b6 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT")," \u62d3\u5c55\u7c7b\uff0c\u53ea\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.Authentication.JwtBearer")," \u4e2d\u4fdd\u7559 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I35D59"},"#I35D59")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4f20\u5165\u9519\u8bef ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT Token")," \u5b57\u7b26\u4e32\u5bfc\u81f4\u81ea\u52a8\u5237\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u51fa\u73b0\u5b57\u7b26\u4e32\u8fb9\u754c\u503c\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34ZE5"},"#I34ZE5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u77ac\u65f6\u4f5c\u7528\u57df\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e5f\u4f1a\u81ea\u52a8\u52a0\u5165\u5de5\u4f5c\u5355\u5143\u5bfc\u81f4\u5199\u65e5\u5fd7\u65f6\u8fde\u9501\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37WTV"},"#I37WTV")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u83b7\u53d6\u7cfb\u7edf\u73af\u5883\u53c2\u6570\u7684\u6027\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36SR5"},"#I36SR5")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u5e95\u5c42\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Mvc")," \u8fc7\u6ee4\u5668\u4ee3\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36SKA"},"#I36SKA")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u6dfb\u52a0\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Json")," \u5e8f\u5217\u5316\u65f6\u95f4\u9ed8\u8ba4\u65f6\u95f4\u683c\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36SL0"},"#I36SL0")),(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," \u5347\u7ea7 ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u62d3\u5c55\u5305\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"5.0.2.6")," \u7248\u672c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36SIG"},"#I36SIG")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6570\u636e\u5e93\u5165\u95e8\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37Z8S"},"#I37Z8S")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u66f4\u65b0\u65e5\u5fd7\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36PI0"},"#I36PI0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7\u3001\u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u66f4\u65b0\u65e5\u5fd7\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36PIK"},"#I36PIK")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u524d\u7aef\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"axios")," \u8de8\u57df\u914d\u7f6e\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36PIT"},"#I36PIT")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App")," \u9759\u6001\u7c7b\u83b7\u53d6\u5e94\u7528\u3001\u73af\u5883\u66f4\u591a\u4fe1\u606f\u6570\u636e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36SOV"},"#I36SOV")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u82f1\u6587\u7248 ",(0,r.kt)("inlineCode",{parentName:"li"},"README.md")," \u4ecb\u7ecd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37QHP"},"#I37QHP")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u591a\u8bed\u8a00\u8d44\u6e90\u6587\u4ef6\u81ea\u52a8\u521b\u5efa ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I35AA4"},"#I35AA4")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae\u591a\u8bed\u8a00\u52a0\u4e0a\u7ef4\u543e\u5c14\u8bed\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37X1L"},"#I37X1L"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v1130\u5df2\u53d1\u5e03"},"v1.13.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u591a\u8bed\u8a00\u529f\u80fd\u53ca\u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DOCL"},"#I2DOCL")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4e8b\u4ef6\u603b\u7ebf\u529f\u80fd\u53ca\u6d88\u606f\u4e2d\u5fc3 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I23BKN"},"#I23BKN")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5206\u7ec4\u663e\u793a\u9690\u85cf\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AHH8"},"#I2AHH8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.Logging.Serilog")," \u62d3\u5c55\u63d2\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AAN8"},"#I2AAN8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"cli.ps")," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"-Namespace")," \u547d\u540d\u7a7a\u95f4\u6307\u5b9a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2A175"},"#I2A175")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u89c4\u8303\u5316\u5316\u6587\u6863\u6388\u6743\u5931\u6548\u540e\u81ea\u52a8\u53d6\u6d88\u6388\u6743\u9501 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AIWC"},"#I2AIWC")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Request.Body")," \u652f\u6301\u91cd\u590d\u8bfb\u529f\u80fd\uff0c\u4e3b\u8981\u89e3\u51b3\u5fae\u4fe1 SDK \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AMG0"},"#I2AMG0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7f51\u7edc\u8bf7\u6c42\u529f\u80fd\u53ca\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2APGJ"},"#I2APGJ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u62d3\u5c55\u5305\u652f\u6301\u6253\u5370 ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"MiniProfiler")," \u4e2d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2ASLS"},"#I2ASLS")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.DatabaseAccesssor.Dapper")," \u62d3\u5c55\u63d2\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2ASYA"},"#I2ASYA")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.DatabaseAccessor.PetaPoco")," \u62d3\u5c55\u63d2\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AUGA"},"#I2AUGA")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7f51\u7edc\u8bf7\u6c42\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CPQ0"},"#I2CPQ0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u62d3\u5c55\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"PagedList")," \u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CW99"},"#I2CW99")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u652f\u6301\u53c2\u6570\u7279\u6027\u9a8c\u8bc1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CX5L"},"#I2CX5L")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.User")," \u83b7\u53d6\u5f53\u524d\u6388\u6743\u7528\u6237\u4fe1\u606f\u4fbf\u6377\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CZLO"},"#I2CZLO")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c4\u8303\u5316\u6587\u6863\u53ef\u914d\u7f6e\u529f\u80fd\uff0c\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"appsettings.json")," \u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D1K9"},"#I2D1K9")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u62e6\u622a\u5668\u6dfb\u52a0\u65b9\u6cd5\u548c\u65b9\u6cd5\u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D2CM"},"#I2D2CM")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u51fa\u9519\u8fd4\u56de\u9ed8\u8ba4\u503c\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D44M"},"#I2D44M")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"body")," \u53c2\u6570\u5e8f\u5217\u5316\u652f\u6301\u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"PropertyNamingPolicy")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D685"},"#I2D685")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u670d\u52a1\u63a5\u53e3\u5ba2\u6237\u7aef\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D7PS"},"#I2D7PS")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AddInject")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"UseInject")," \u5141\u8bb8\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},"SecurityDefinitions")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"SwaggerUI")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DIMG"},"#I2DIMG")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[SecurityDefine]")," \u9ed8\u8ba4\u6784\u9020\u51fd\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DNXT"},"#I2DNXT")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AspectDispatchProxy")," \u52a8\u6001\u4ee3\u7406\u7c7b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DO6I"},"#I2DO6I")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[QueryParameters]")," \u7279\u6027\uff0c\u652f\u6301\u4e00\u952e\u5c06 ",(0,r.kt)("inlineCode",{parentName:"li"},"Action")," \u53c2\u6570\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"[FromQuery]")," \u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2G8TF"},"#I2G8TF")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001\u65e5\u5fd7\u914d\u7f6e\u53ca\u62d3\u5c55\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2GDGD"},"#I2GDGD")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"WebApi")," \u8bf7\u6c42\u8c13\u8bcd\u9ed8\u8ba4\u89c4\u5219\u914d\u7f6e\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2M70X"},"#I2M70X")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".NET 5")," SDK \u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},".NET 5.0.2")," \u7248\u672c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D0PZ"},"#I2D0PZ")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u6846\u67b6\u5185\u6240\u6709\u62d3\u5c55\u7c7b\u547d\u540d\u7a7a\u95f4\uff0c\u5168\u90e8\u8fc1\u79fb\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.\u6a21\u5757.Extensions")," \u4e0b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AH54"},"#I2AH54")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u8bb0\u4f4f\u6388\u6743\u5b58\u50a8\u65b9\u5f0f\uff0c\u66ff\u6362 ",(0,r.kt)("inlineCode",{parentName:"li"},"Session")," \u5b58\u50a8\u65b9\u5f0f\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"LocalStorage")," \u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AKUA"},"#I2AKUA")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6846\u67b6\u5305\u63cf\u8ff0\u6587\u4ef6\uff0c\u51cf\u5c11\u6846\u67b6\u4f53\u79ef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2APAU"},"#I2APAU")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.CanBeScanTypes")," \u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"App.EffectiveTypes")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2B0ZR"},"#I2B0ZR")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.ServiceProvider")," \u5c5e\u6027\u5e76\u79fb\u9664 ",(0,r.kt)("inlineCode",{parentName:"li"},"App.GetDuplicateXXX")," \u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CYZE"},"#I2CYZE")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetDuplicateDbContext")," \u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetNewDbContext")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CZ04"},"#I2CZ04")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetSqlDispatchProxy")," \u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetSqlProxy")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DO9T"},"#I2DO9T")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Aop")," \u670d\u52a1\u62e6\u622a\u5668\uff0c\u652f\u6301\u5f02\u6b65\u3001\u540c\u6b65\u4e24\u79cd\u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2B9HQ"},"#I2B9HQ")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u7f51\u7edc\u8bf7\u6c42\u6240\u6709\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BMR7"},"#I2BMR7")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u89c4\u8303\u5316\u5316\u7ed3\u679c\u4e0d\u4e00\u81f4 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2ACF3"},"#I2ACF3")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u65b0\u589e\u6216\u66f4\u65b0\u5ffd\u7565\u7a7a\u503c\u64cd\u4f5c\u65b9\u6cd5\u62a5\u7a7a\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AB6C"},"#I2AB6C")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Startup.cs")," Aop \u5168\u5c40\u62e6\u622a\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2A7T2"},"#I2A7T2")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u8fc7\u671f\u540e\u81ea\u52a8\u5237\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u65e0\u6cd5\u83b7\u53d6\u6700\u65b0\u7684\u7528\u6237\u4fe1\u606f bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AWQI"},"#I2AWQI")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},'[ApiDescriptionSettings(Tag="xx")]')," \u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},"swagger.json")," \u62a5\u9519 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2B47R"},"#I2B47R")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mysql")," sql \u6570\u636e\u5e93\u67e5\u8be2\u7ed3\u679c ",(0,r.kt)("inlineCode",{parentName:"li"},"tinyint")," \u7c7b\u578b\u8f6c\u6362\u51fa\u9519 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BEBM"},"#I2BEBM")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c4\u8303\u5316\u7ed3\u679c\u591a\u6b21\u5305\u88f9\u7c7b\u578b bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BHHZ"},"#I2BHHZ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u52a8\u6001 Api \u57fa\u5143\u7c7b\u578b\u6570\u7ec4\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BMS5"},"#I2BMS5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u67e5\u8be2\u679a\u4e3e\u7c7b\u578b\u8f6c\u6362\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BS2Y"},"#I2BS2Y")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"string.SqlQuerizeAsync()")," \u62d3\u5c55\u8fd4\u56de\u9519\u8bef bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BSTS"},"#I2BSTS")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u52a8\u6001 Api \u5b50\u7c7b\u91cd\u5199\u7236\u7c7b\u65b9\u6cd5\u5e76\u53d6\u522b\u540d\u540e ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2C9VP"},"#I2C9VP")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u7f51\u7edc\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"application/json")," \u5e8f\u5217\u5316\u5927\u5c0f\u5199\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CRJC"},"#I2CRJC")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u6570\u636e\u5e93\u5b9a\u4f4d\u5668\u5b9e\u4f53\u5d4c\u5957\u5173\u8054 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CVN0"},"#I2CVN0")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8de8\u57df\u54cd\u5e94\u5934\u8bbe\u7f6e\u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CW5T"},"#I2CW5T")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u7f51\u7edc\u8bf7\u6c42\u4ee3\u7406\u6253\u5370\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"MiniProfiler")," bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CZBC"},"#I2CZBC")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u54cd\u5e94\u62e6\u622a\u5668 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D4DG"},"#I2D4DG")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u6846\u67b6 ",(0,r.kt)("inlineCode",{parentName:"li"},"AsQueryable()")," \u4e00\u76f4\u8ffd\u52a0\u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DH1D"},"#I2DH1D")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u52a8\u5237\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u7a7a\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DO29"},"#I2DO29")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT Token")," \u4e0d\u4f20\u8fc7\u671f\u65f6\u95f4\u51fa\u73b0\u9a8c\u8bc1 401 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DO8L"},"#I2DO8L")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppStartup")," \u6392\u5e8f\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DVD2"},"#I2DVD2")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u672a\u542f\u7528\u591a\u8bed\u8a00\u670d\u52a1\u65f6\u53cb\u597d\u5f02\u5e38\u548c\u9a8c\u8bc1\u51fa\u73b0\u7a7a\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2ECUJ"},"#I2ECUJ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u6821\u9a8c\u5b57\u6bcd\u548c\u6570\u5b57\u7ec4\u5408\u65e0\u6cd5\u5339\u914d bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2EF2Q"},"#I2EF2Q")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u6821\u9a8c\u624b\u673a\u6216\u56fa\u8bdd\u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2M5IZ"},"#I2M5IZ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Dapper")," \u62d3\u5c55\u89e3\u6790 ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlConnection")," \u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2M5P2"},"#I2M5P2")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5f00\u542f\u591a\u8bed\u8a00\u540e\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"EF")," \u8fc1\u79fb\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2M7DT"},"#I2M7DT")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntityTypeBuilder")," \u4e0d\u652f\u6301\u591a\u91cd\u7ee7\u627f bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2PAOD"},"#I2PAOD")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JwtHandler")," \u8bbe\u7f6e\u81ea\u52a8\u5237\u65b0\u540e\uff0c\u533f\u540d\u8bbf\u95ee\u65e0\u6cd5\u901a\u8fc7 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2SDOX"},"#I2SDOX")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Dapper")," \u62d3\u5c55\u4e2d ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlServer")," \u6570\u636e\u5e93\u83b7\u53d6\u8fde\u63a5\u5bf9\u8c61\u7c7b\u578b bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/159"},"#PR159")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u79fb\u9664 ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u67e5\u8be2\u7ed3\u679c\u6620\u5c04\u68c0\u67e5 ",(0,r.kt)("inlineCode",{parentName:"li"},"[NotMapper]")," \u7279\u6027\u673a\u5236 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XD0"},"#I34XD0")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u4f9d\u8d56\u6ce8\u5165\u65f6\u6392\u9664 ",(0,r.kt)("inlineCode",{parentName:"li"},"IDynamicApiController")," \u63a5\u53e3 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2ECTG"},"#I2ECTG")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MD5")," \u52a0\u5bc6\u6027\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/158"},"#PR158")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u6587\u6863\u9996\u9875 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XBR"},"#I34XBR")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7f51\u7edc\u8bf7\u6c42\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2APGJ"},"#I2APGJ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u591a\u8bed\u8a00\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DOCL"},"#I2DOCL")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6587\u6863\u5168\u6587\u641c\u7d22\u5f15\u64ce ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XAW"},"#I34XAW")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u9759\u6001\u7c7b\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XB4"},"#I34XB4")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6846\u67b6\u53ef\u914d\u7f6e\u9009\u9879\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XB9"},"#I34XB9")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4e8b\u4ef6\u603b\u7ebf\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XBI"},"#I34XBI")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6570\u636e\u52a0\u89e3\u5bc6\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XC0"},"#I34XC0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8d21\u732e\u6307\u5357\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XC8"},"#I34XC8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContext")," \u53ca ",(0,r.kt)("inlineCode",{parentName:"li"},"\u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d")," \u535a\u5ba2\u6587\u7ae0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XCB"},"#I34XCB")),(0,r.kt)("li",{parentName:"ul"},"[\u5176\u4ed6]"," \u6587\u6863\u5c0f\u8c03\u6574\uff0c\u5c0f\u4f18\u5316"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u8de8\u57df\u8bbe\u7f6e\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2ASNJ"},"#I2ASNJ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MVC")," \u89c6\u56fe\u65e0\u6548\uff0c\u539f\u56e0\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},".cshtml")," \u6587\u4ef6\u6ca1\u6709\u8bbe\u7f6e\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"\u5185\u5bb9")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AXUU"},"#I2AXUU")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\u53ef\u4ee5\u5b9e\u73b0\u4e8b\u52a1\u5417\uff1f",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2B0NX"},"#I2B0NX")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IRepository")," \u64cd\u4f5c\u6570\u636e\u5e93\u4f1a\u6253\u5f00\u591a\u6b21\u6570\u636e\u5e93\u8fde\u63a5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BB7B"},"#I2BB7B")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5982\u4f55\u8fdb\u5165\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},"AppAuthorizeHandler")," \u65ad\u70b9 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BGXY"},"#I2BGXY")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u6ce8\u5165\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2C2AQ"},"#I2C2AQ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5efa\u8bae\u589e\u52a0 API \u7b7e\u540d\u9a8c\u8bc1\uff0c\u65f6\u6548\u9a8c\u8bc1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2C6ET"},"#I2C6ET")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u591a\u6570\u636e\u5e93\u591a\u79df\u6237\u540c\u65f6\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Add-Migration")," \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CEHS"},"#I2CEHS")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ISqlSugarRepository")," \u6ca1\u6709 ",(0,r.kt)("inlineCode",{parentName:"li"},"Getxxx")," \u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CJLZ"},"#I2CJLZ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"cli.ps1")," \u5982\u4f55\u5c06 ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u91cc\u7684\u8868\u5bfc\u51fa\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"model")," \u7c7b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CSUL"},"#I2CSUL")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u624b\u52a8\u4fee\u6539 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u7ec8\u7ed3\u70b9\u8def\u5f84\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D608"},"#I2D608")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DefaultDbContext")," \u4e0d\u80fd\u8bc6\u522b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DCZX"},"#I2DCZX")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5404\u5206\u5c42\u9879\u76ee ",(0,r.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Configuration")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DDUP"},"#I2DDUP")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Aop")," \u65e0\u6cd5\u62e6\u622a\uff0c\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DEY8"},"#I2DEY8")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"mysql")," \u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"Add-Migration")," \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DSB8"},"#I2DSB8"),"\\"),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Entity")," \u521b\u5efa\u65f6\u95f4\u548c\u662f\u5426\u5220\u9664\u6dfb\u52a0\u9ed8\u8ba4\u503c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2E04H"},"#I2E04H")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"swagger")," \u4e2d\u591a\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"servers")," \u8bbe\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2E0IF"},"#I2E0IF")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5168\u5c40\u7b5b\u9009\u5668 \u6ca1\u6709\u6267\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2E5R4"},"#I2E5R4")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u591a\u6570\u636e\u5e93\u5b9a\u4f4d\u5668\u7591\u95ee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2E77T"},"#I2E77T")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"cli.ps")," \u9006\u5411\u5de5\u7a0b ",(0,r.kt)("inlineCode",{parentName:"li"},"Mysql")," \u6570\u636e\u5e93\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2E7I5"},"#I2E7I5")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5f00\u53d1\u73af\u5883 ",(0,r.kt)("inlineCode",{parentName:"li"},"applicationsettings.json")," \u4e2d\u6587\u4e71\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2EAG1"},"#I2EAG1")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u589e\u52a0\u6307\u5b9a\u8def\u5f84\u7a0b\u5e8f\u96c6\u6620\u5c04 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2EEO2"},"#I2EEO2")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u52a8\u6001\u7f16\u8bd1 ",(0,r.kt)("inlineCode",{parentName:"li"},"cs")," \u811a\u672c\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2EH66"},"#I2EH66")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6\uff0c\u8fd4\u56de\u7684\u9519\u8bef\u6ca1\u6709\u89c4\u8303\u5316\u7ed3\u679c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2NV8S"},"#I2NV8S")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5faa\u73af\u5f15\u7528\u8bbe\u7f6e\u751f\u6210\u6587\u6863\u5c42\u7ea7\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2PLQQ"},"#I2PLQQ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u914d\u7f6e\u6587\u4ef6\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"yaml")," \u6587\u4ef6\u5417? ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2TJ3N"},"#I2TJ3N")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u4fee\u6539\u6570\u636e\u5e93\u672a ",(0,r.kt)("inlineCode",{parentName:"li"},"mysql")," \u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"Add-Migration")," \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2VR64"},"#I2VR64")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u591a\u6570\u636e\u5e93\u4f7f\u7528\u5b9a\u4f4d\u5668\u65f6\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2VR8F"},"#I2VR8F")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Migration To Oracle")," \u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2WBYQ"},"#I2WBYQ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5f00\u53d1\u65f6\u663e\u793a ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger"),"\uff0c\u4e0a\u7ebf\u65f6\u5173\u95ed ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger"),"\uff0c\u8fd9\u9700\u8981\u600e\u4e48\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2WOYV"},"#I2WOYV")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u517c\u5bb9 Mvc \u590d\u6742\u9a8c\u8bc1\u6ca1\u6709\u8bd5\u9a8c\u6210\u529f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2X3GV"},"#I2X3GV")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Aop")," \u80fd\u4e0d\u80fd\u652f\u6301\u65e0\u63a5\u53e3\u7684\u7c7b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2X8AS"},"#I2X8AS")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT Token")," \u81ea\u52a8\u5237\u65b0\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2YD4K"},"#I2YD4K")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u80fd\u5426\u589e\u52a0\u4e00\u4e2a\u62d3\u5c55\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Entity"),"\uff0c\u589e\u52a0\u4e00\u4e9b\u62d3\u5c55\u7684\u5c5e\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2YDKT"},"#I2YDKT")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u65e0\u6cd5\u8fd8\u539f\u5305\uff0c\u4f7f\u7528",(0,r.kt)("inlineCode",{parentName:"li"},"Nuget")," \u4e0b\u8f7d\u548c\u901a\u8fc7\u6700\u65b0\u7684\u7684\u811a\u624b\u67b6\u4e0b\u8f7d\u90fd\u63d0\u793a\u8fd9\u4e2a\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I30446"},"#I30446")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u590d\u6742\u6821\u9a8c\u4e0e\u7279\u6027\u9a8c\u8bc1\u4e0d\u80fd\u5e76\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3046U"},"#I3046U")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5f15\u5165 Webhook \u673a\u5236 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2A3I0"},"#I2A3I0")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u589e\u52a0 blog \u5b58\u50a8\u670d\u52a1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AMBP"},"#I2AMBP")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," Blazor Server \u73af\u5883\u4e0b EF \u7684 DbContext \u591a\u7ebf\u7a0b\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AMD2"},"#I2AMD2")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5e0c\u671b\u5b9e\u73b0\u5de5\u4f5c\u5355\u5143\u64cd\u4f5c\u63a5\u53e3\uff08IUnitOfWork\uff09",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AOR5"},"#I2AOR5")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"string.ToPagedListAsync()")," \u64cd\u4f5c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BZ3Z"},"#I2BZ3Z")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"GraphQL"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"OData")," \u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2C9EH"},"#I2C9EH")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u8feb\u5207\u671f\u671b\u652f\u6301 CAP \u5206\u5e03\u5f0f\u4e8b\u52a1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CBRF"},"#I2CBRF")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5982\u4f55\u8ba9\u67d0\u4e2a\u65b9\u6cd5\u6216\u5b9e\u4f53\u53d8\u5316\u540e\uff0c\u4e0d\u88ab ",(0,r.kt)("inlineCode",{parentName:"li"},"SavingChangesEvent")," \u7b49\u62e6\u622a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CEM9"},"#I2CEM9")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae\u65e5\u5fd7\u5c01\u88c5\u589e\u52a0\u66f4\u591a\u62d3\u5c55\uff0c\u6bd4\u5982\uff1a\u81ea\u5b9a\u4e49\u4fdd\u5b58\u65e5\u5fd7\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CW8V"},"#I2CW8V")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5bf9 ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u7684\u652f\u6301\uff0c\u589e\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Nuget")," \u811a\u624b\u67b6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D91U"},"#I2D91U")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Middleware")," \u5b9e\u73b0\u53cd\u5411\u4ee3\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DKM1"},"#I2DKM1")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u652f\u6301\u914d\u7f6e\u591a\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"Aop")," \u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2E6Z2"},"#I2E6Z2")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u662f\u5426\u8ba1\u5212\u5f00\u53d1\u7c7b\u4f3c\u7f51\u5173\u7684\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2PD1L"},"#I2PD1L")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"waring CS8002"),": \u5f15\u7528\u7a0b\u5e8f\u96c6 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6ca1\u6709\u5f3a\u540d\u79f0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2WDN2"},"#I2WDN2")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," Oracle \u6570\u636e\u5e93\u9a71\u52a8\u96c6\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"Devart.Data.Oracle.Entity.EFCore")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2XJIU"},"#I2XJIU"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v170\u5df2\u53d1\u5e03"},"v1.7.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.ObjectMapper.Mapster")," \u62d3\u5c55\u5305 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29LSJ"},"#I29LSJ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.Logging.Serilog")," \u62d3\u5c55\u5305 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AAN8"},"#I2AAN8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.Web.HttpContext")," \u62d3\u5c55\u5305 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29LSM"},"#I29LSM")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5185\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u5237\u65b0\u673a\u5236\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29K57"},"#I29K57")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u652f\u6301\u8fd0\u884c\u65f6\u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"OnModelCreating")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28UDT"},"#I28UDT")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301\u4f9d\u8d56\u6ce8\u5165\u6392\u9664\u6307\u5b9a\u63a5\u53e3 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29693"},"#I29693")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c4\u8303\u5316\u7ed3\u679c\u8fd4\u56de\u65f6\u95f4\u6233\u5b57\u6bb5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29697"},"#I29697")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u57fa\u7840 ",(0,r.kt)("inlineCode",{parentName:"li"},"CURD")," \u7236\u7c7b\u64cd\u4f5c\u4f8b\u5b50 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I296SR"},"#I296SR")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},'sql.Change("\u5b9a\u4f4d\u5668\u5b8c\u6574\u7c7b\u578b\u540d\u79f0")')," \u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29LAB"},"#I29LAB")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"UpdateInclude")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"UpdateExclude")," \u5ffd\u7565\u7a7a\u53c2\u6570\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29VUG"},"#I29VUG")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5185\u7f6e\u5047\u5220\u9664\u67e5\u8be2\u8fc7\u6ee4\u5668\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29Y2R"},"#I29Y2R")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5ffd\u7565\u7a7a\u503c\u6392\u9664\u9ed8\u8ba4\u65f6\u95f4\u683c\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29VUV"},"#I29VUV")),(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MiniProfiler")," \u7ec4\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I297R9"},"#I297R9")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppAuthorizeHandler")," \u6388\u6743\u7ba1\u9053\u4e3a\u5f02\u6b65\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29MD9"},"#I29MD9")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u9ed8\u8ba4\u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT")," \u6388\u6743\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29LI4"},"#I29LI4")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContextUtilities")," \u540d\u79f0\u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContextLocal")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29KQE"},"#I29KQE")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"UnifyResultContext")," \u540d\u79f0\u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"UnifyContext")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29LLZ"},"#I29LLZ")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u53ea\u6709\u6267\u884c\u8fc1\u79fb\u547d\u4ee4\u624d\u626b\u63cf\u79cd\u5b50\u6570\u636e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29E6P"},"#I29E6P")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u89c4\u8303\u5316\u7ed3\u679c ",(0,r.kt)("inlineCode",{parentName:"li"},"Successed")," \u5c5e\u6027\u540d\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Succeeded")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29NMV"},"#I29NMV")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mapster")," \u5bf9\u8c61\u7ec4\u4ef6\uff0c\u91c7\u7528\u63d0\u4f9b\u62d3\u5c55\u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29D2M"},"#I29D2M")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"CacheManager")," \u62d3\u5c55\u7c7b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29LU1"},"#I29LU1")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SaveChanges")," \u62e6\u622a\u5668 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I292LO"},"#I292LO")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u672a\u6ce8\u518c\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e5f\u88ab\u5f15\u7528\u5168\u5c40\u67e5\u8be2\u62e6\u622a\u5668 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29ZXJ"},"#I29ZXJ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u624b\u52a8\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"BadObjectResult")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationProblemDetails")," \u7ed3\u679c\u7c7b\u578b\u65f6\u89c4\u8303\u5316\u7ed3\u679c\u5931\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29ZU9"},"#I29ZU9")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u52a8\u6001 WebApi ",(0,r.kt)("inlineCode",{parentName:"li"},"KeepName"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"KeepVerb"),"\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"SplitCamelCase")," \u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29X90"},"#I29X90")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql\u4ee3\u7406")," \u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"\u5143\u7ec4")," \u7c7b\u578b\u51fa\u9519 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29SMV"},"#I29SMV")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"401\uff0c403")," \u72b6\u6001\u7801\u89c4\u8303\u5316\u8fd4\u56de\u503c\u5c5e\u6027\u53d8\u5927\u5199 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29M8Y"},"#I29M8Y")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContext")," \u7a7a\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29LU4"},"#I29LU4")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u63a5\u53e3\u65e0\u8fd4\u56de\u503c\u6ca1\u6709\u5e94\u7528\u89c4\u8303\u5316\u7ed3\u679c bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29GT7"},"#I29GT7")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u524d\u7aef ",(0,r.kt)("inlineCode",{parentName:"li"},"Less")," \u914d\u7f6e\u6587\u4ef6\u5bfc\u81f4\u4e3b\u673a\u542f\u52a8\u5931\u8d25 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29E7P"},"#I29E7P")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u7ed3\u679c\u8f6c\u6cdb\u578b\u540e\u5c5e\u6027\u91cd\u590d\u8d4b\u503c bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29BUO"},"#I29BUO")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5173\u95ed ",(0,r.kt)("inlineCode",{parentName:"li"},"MiniProfiler")," \u4e4b\u540e ",(0,r.kt)("inlineCode",{parentName:"li"},"\u7ec4\u4e2d\u7ec4")," \u5931\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29789"},"#I29789")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u672a\u542f\u7528\u89c4\u8303\u5316\u7ed3\u679c\u65f6\u5f02\u5e38\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"System.Object")," \u5b57\u7b26 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2969A"},"#I2969A")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6b63\u6570\u6570\u636e\u9a8c\u8bc1 0 \u4e5f\u9a8c\u8bc1\u901a\u8fc7 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2955T"},"#I2955T")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u975e\u6cdb\u578b\u7c7b\u96c6\u6210\u6cdb\u578b\u63a5\u53e3\u4f9d\u8d56\u6ce8\u5165 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I294YT"},"#I294YT")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"new")," \u8986\u76d6\u7236\u7c7b\u7684 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28Z1A"},"#I28Z1A")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JsonSerializerUtility")," \u6ca1\u6709\u516c\u5f00 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28WMI"},"#I28WMI")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u62d3\u5c55\u67e5\u8be2\u6cdb\u578b\u7c7b\u578b\u6ce8\u518c\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28VMT"},"#I28VMT")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion Tools")," \u4e0d\u652f\u6301\u751f\u6210\u4e0d\u540c\u547d\u540d\u7a7a\u95f4\u7684\u5b9e\u4f53 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2A175"},"#I2A175")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5168\u5c40\u62e6\u622a\u5668\u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2A7T2"},"#I2A7T2")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u65b0\u589e\u6216\u66f4\u65b0\u5ffd\u7565\u7a7a\u503c\u7a7a\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AB6C"},"#I2AB6C")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u751f\u6210\u52a0\u5bc6\u7b97\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29KIH"},"#I29KIH")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65e5\u5fd7\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28Y9D"},"#I28Y9D")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3001\u5b9e\u4f53\u62e6\u622a\u5668\u3001\u914d\u7f6e\u3001\u4e00\u5206\u949f\u5165\u95e8\u7b49\u7b49\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u95ee\u7b54]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5982\u4f55\u5b9e\u73b0\u6388\u6743\u8bbf\u95ee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I294F2"},"#I294F2")),(0,r.kt)("li",{parentName:"ul"},"[\u95ee\u7b54]"," \u5982\u4f55\u5b9e\u73b0\u591a\u4e2a\u6570\u636e\u5e93\u591a\u5bf9\u591a\u5b9e\u4f53\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29G6S"},"#I29G6S")),(0,r.kt)("li",{parentName:"ul"},"[\u95ee\u7b54]"," \u52a8\u6001 WebApi \u652f\u6301\u6587\u4ef6\u4e0a\u4f20\u5417 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29R5E"},"#I29R5E")),(0,r.kt)("li",{parentName:"ul"},"[\u7591\u95ee]"," \u591a\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u65e0\u6cd5\u751f\u6210\u8fc1\u79fb\u4ee3\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2A6II"},"#I2A6II")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5b9e\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"BuildChange")," \u4f20\u5165\u8868\u540d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I292SN"},"#I292SN")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u6267\u884c\u6570\u636e\u5e93\u64cd\u4f5c\u7ed3\u679c\u4e0d\u652f\u6301\u5c5e\u6027\u5ffd\u7565\u5927\u5c0f\u5199\u8d4b\u503c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29DRQ"},"#I29DRQ")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5f15\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"Webhook")," \u673a\u5236 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2A3I0"},"#I2A3I0"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v140\u5df2\u53d1\u5e03"},"v1.4.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u652f\u6301\u4e8c\u7ea7\u865a\u62df\u76ee\u5f55\u90e8\u7f72\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28B77"},"#I28B77")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Template.RazorWithWebApi")," \u811a\u624b\u67b6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28QGI"},"#I28QGI")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Template.BlazorWithWebApi")," \u811a\u624b\u67b6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27Z3O"},"#I27Z3O")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u65f6\u6001\u67e5\u8be2\u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28AJ6"},"#I28AJ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[AppDbContext(\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u6570\u636e\u5e93\u7c7b\u578b)]")," \u914d\u7f6e\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28QTB"},"#I28QTB")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTimeOffset")," \u8f6c ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTime")," \u62d3\u5c55\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27MQA"},"#I27MQA")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationTypes")," \u9a8c\u8bc1\u6b63\u5219\u8868\u8fbe\u5f0f\u667a\u80fd\u63d0\u793a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2801V"},"#I2801V")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValiationTypes.WordWithNumber")," \u9a8c\u8bc1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2805A"},"#I2805")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u83b7\u53d6\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u7aef IP \u5730\u5740 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28QV9"},"#I28QV9")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," .NET 5.0 \u7248\u672c\u81f3 .NET 5.0.1 \u7248\u672c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28QU1"},"#I28QU")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u89c6\u56fe\u5f15\u64ce\u529f\u80fd\uff0c\u4f18\u5316\u4e0d\u89c4\u8303\u547d\u540d\u548c\u65b0\u589e\u5b57\u7b26\u4e32\u6a21\u677f\u7f16\u8bd1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28G0S"},"#I28G0S")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u6570\u636e\u5e93\u5b9e\u4f53\u67e5\u627e\u7b97\u6cd5\uff0c\u5e76\u4f18\u5316\u6027\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28QUQ"},"#I28QUQ")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u5e94\u7528\u542f\u52a8\u521d\u59cb\u5316\u6027\u80fd\u548c\u6570\u636e\u5e93\u7b2c\u4e00\u6b21\u81ea\u52a8\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"DbSet")," \u6027\u80fd"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u914d\u7f6e\u5b9a\u4f4d\u5668\u540e\u5b9e\u4f53\u65e0\u6cd5\u6b63\u786e\u751f\u6210 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2888L"},"#I2888L")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9e\u4f53\u751f\u6210 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2891G"},"#I2891G")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5bf9\u8c61\u9a8c\u8bc1\u5931\u8d25\u63d0\u793a\u6d88\u606f\u6ca1\u6709\u5e94\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON")," \u5927\u5c0f\u5199\u914d\u7f6e bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27UTX"},"#I27UTX")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4ed3\u50a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"Insert")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"li"},"Update")," \u65b9\u6cd5\u6307\u5b9a ",(0,r.kt)("inlineCode",{parentName:"li"},"ignoreNullValues")," \u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27UN6"},"#I27UN6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Controller")," \u6d3e\u751f\u7c7b\u5982\u679c\u8d34\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"[Route]")," \u7279\u6027\u540e\u51fa\u73b0\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e2d bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27TN7"},"#I27TN7")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlScalar")," \u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"Nullable")," \u7c7b\u578b\u51fa\u73b0\u8f6c\u6362\u5931\u8d25 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27S2N"},"#I27S2N")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[UnitOfWork]")," \u7279\u6027\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27MLM"},"#I27MLM")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u9759\u6001\u6267\u884c\u65b9\u5f0f\u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u9ad8\u7ea7\u4ee3\u7406\u65e0\u6cd5\u76d1\u542c\u6570\u636e\u5e93\u8fde\u63a5\u72b6\u6001 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27M4F"},"#I27M4F")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u66f4\u6362 Json \u5e8f\u5217\u5316\u5e93\u65e0\u6548 bug\uff0c\u5982\u66ff\u6362\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Microsoft.AspNetCore.Mvc.NewtonsoftJson")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27M43"},"#I27M43")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion Tools")," \u5de5\u5177\u751f\u6210\u6a21\u578b bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27XI5"},"#I27XI5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8f6f\u5220\u9664\u6ca1\u6709\u751f\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2804I"},"#I2804I")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion Tools")," \u8bc6\u522b\u5e26\u591a\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"\\\\")," \u7684\u8fde\u63a5\u5b57\u7b26\u4e32\u8bc6\u522b bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I280TS"},"#I280TS"),"\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/91"},"#PR91")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion Tools")," \u65e0\u6cd5\u53d6\u6d88\u751f\u6210 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2816M"},"#I2816M")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTimeOffset")," \u8f6c\u672c\u5730\u65f6\u95f4\u5dee 8 \u5c0f\u65f6 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28BA9"},"#I28BA9")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"bundle js&css")," \u538b\u7f29\u540e\u542f\u52a8\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28KRP"},"#I28KR")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationTypes.Required")," \u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/98"},"#PR98")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c4\u8303\u5316\u7ed3\u679c",(0,r.kt)("inlineCode",{parentName:"li"},"OnValidateFailed")," \u53c2\u6570\u540d\u62fc\u5199\u9519\u8bef bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/93"},"#PR93"),"\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/92"},"#PR92")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6388\u6743\u7ba1\u9053\u9a8c\u8bc1\u5931\u8d25\u8fd8\u663e\u793a\u7ed3\u679c bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/89"},"#PR89")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," README.md \u53cb\u60c5\u8fde\u63a5\u5730\u5740 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/88"},"#PR88")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u6a21\u677f\u811a\u624b\u67b6\u6e90\u7801\uff0c\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore Tools")," \u5e93 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/87"},"#PR87")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," README.md Nuget \u56fe\u6807 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/85"},"#PR85")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5c06 ",(0,r.kt)("inlineCode",{parentName:"li"},"List")," \u8f6c ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTable")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/97"},"#PR97")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c6\u56fe\u5f15\u64ce\u6a21\u677f\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27ZVA"},"#I27ZVA")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u65f6\u6001\u67e5\u8be2\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28AJ6"},"#I28AJ"),", ",(0,r.kt)("a",{parentName:"li",href:"https://dotnetchina.gitee.io/furion/docs/dbcontext-hight-query/#91111-%E6%97%B6%E6%80%81%E6%9F%A5%E8%AF%A2"},"DOC")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u4ed3\u50a8\u6587\u6863\u4e66\u5199\u7eb0\u6f0f bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/90"},"#PR90")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u9009\u9879\u6587\u6863\u9519\u8bef bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/86"},"#PR86")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"\u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668")," \u6587\u6863\u4e66\u5199\u9519\u8bef bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/83/files"},"#PR83")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3001\u591a\u6570\u636e\u5e93\u3001\u811a\u624b\u67b6\u7b49\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5efa\u8bae]"," \u5e0c\u671b ",(0,r.kt)("inlineCode",{parentName:"li"},"api")," \u8fd4\u56de\u7684\u503c\u81ea\u52a8\u5c06 null \u8f6c\u4e3a '' \u6216 ","[][#I286IJ]","(",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I286IJ)%EF%BC%8C%E3%80%90%E5%B7%B2%E5%85%B3%E9%97%AD%E3%80%91"},"https://gitee.com/dotnetchina/Furion/issues/I286IJ)\uff0c\u3010\u5df2\u5173\u95ed\u3011")),(0,r.kt)("li",{parentName:"ul"},"[\u5efa\u8bae]"," \u6dfb\u52a0\u7f51\u5173\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27TP7"},"#I27TP7"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011"),(0,r.kt)("li",{parentName:"ul"},"[\u5efa\u8bae]"," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlQuery")," \u83b7\u53d6\u5355\u6761\u8bb0\u5f55\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28M1V"},"#I28M1V"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011"),(0,r.kt)("li",{parentName:"ul"},"[\u5efa\u8bae]"," \u5e0c\u671b\u53ef\u4ee5\u63d0\u4f9b\u96c6\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"Serilog")," \u4f8b\u5b50 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I282J4"},"#I282J4"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011"),(0,r.kt)("li",{parentName:"ul"},"[\u7591\u95ee]"," \u5982\u4f55\u901a\u8fc7\u7279\u6027\u914d\u7f6e\u552f\u4e00\u7ea6\u675f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2891L"},"#I2891L"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011"),(0,r.kt)("li",{parentName:"ul"},"[\u7591\u95ee]"," \u600e\u4e48\u8bfb\u53d6 ",(0,r.kt)("inlineCode",{parentName:"li"},"appsettings.json")," \u6570\u7ec4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27WUR"},"#I27WU"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011"),(0,r.kt)("li",{parentName:"ul"},"[\u7591\u95ee]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IRepository")," \u51fa\u73b0\u7a7a\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I281IE"},"#I281IE"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011"),(0,r.kt)("li",{parentName:"ul"},"[\u7591\u95ee]"," \u89c4\u8303\u5316\u63a5\u53e3\u95ee\u9898\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28NMZ"},"#I28NMZ"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011"),(0,r.kt)("li",{parentName:"ul"},"[\u7591\u95ee]"," \u7edf\u4e00\u8fd4\u56de\u503c\u6a21\u578b\u4e2d OnResponseStatusCodes \u672a\u6267\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28NNL"},"#I28NNL"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v120\u5df2\u53d1\u5e03"},"v1.2.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u96ea\u82b1\u7b97\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26OXG"},"#I26OXG"),", ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/78"},"#PR78")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[AppDbContext]")," \u914d\u7f6e\u6570\u636e\u5e93\u63d0\u4f9b\u5668\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27G3T"},"#I27G3T")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9e\u4f53\u8868\u6570\u636e\u66f4\u6539\u76d1\u542c\u63a5\u53e3 ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntityDataChangedListener")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I278DD"},"#I278DD"),", ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I278LQ"},"#I278LQ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u670d\u52a1\u63a5\u53e3 AOP \u62e6\u622a\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I278CP"},"#I278CP")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9a\u4f4d\u5668\u4ed3\u50a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"IDbRepository")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I276Q3"},"#I276Q3")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6570\u636e\u5e93\u64cd\u4f5c ",(0,r.kt)("inlineCode",{parentName:"li"},"InsertOrUpdate")," \u652f\u6301\u6392\u9664\u7a7a\u5b57\u7b26\u4e32\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I272OG"},"#I272OG")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6570\u636e\u5e93\u64cd\u4f5c ",(0,r.kt)("inlineCode",{parentName:"li"},"UpdateInclude")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"UpdateExclude")," \u533f\u540d\u5bf9\u8c61\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I271X0"},"#I271X0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6570\u636e\u9a8c\u8bc1\u4f20\u5165\u7a7a\u5bf9\u8c61\u8df3\u8fc7\u9a8c\u8bc1\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I273R4"},"#I273R4")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5e94\u7528\u542f\u52a8\u65f6\u652f\u6301\u6392\u9664\u7279\u5b9a\u914d\u7f6e\u6587\u4ef6\u81ea\u52a8\u52a0\u8f7d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26U0A"},"#I26U0A")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5355\u4e2a\u5b9e\u4f53\u8868\u540d\u524d\u7f00\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26LX0"},"#I26LX0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MySql")," \u6570\u636e\u5e93\u81ea\u52a8\u914d\u7f6e\u9ed8\u8ba4\u7248\u672c\u53f7 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26XQ6"},"#I26XQ6")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u6388\u6743\u5904\u7406\u7a0b\u5e8f\u4ee3\u7801"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9e\u4f53\u8868\u6570\u636e\u66f4\u6539\u76d1\u542c\u63a5\u53e3 ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntityDataChangedListener")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I278DD"},"#I278DD"),", ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I278LQ"},"#I278LQ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u670d\u52a1\u63a5\u53e3 AOP \u62e6\u622a\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I278CP"},"#I278CP")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u96ea\u82b1\u7b97\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26OXG"},"#I26OXG"),", ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/78"},"#PR78")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c6\u56fe\u5f15\u64ce\u52a0\u8f7d\u5916\u90e8\u7a0b\u5e8f\u96c6\u51fa\u9519 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4f9d\u8d56\u6ce8\u5165\u4ee3\u7406\u63a5\u53e3\u62a5\u7a7a\u5bf9\u8c61\u5f02\u5e38 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u53d6\u6d88\u9644\u52a0\u5b9e\u4f53\u51fa\u9519 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u4ed3\u50a8\u5728\u975e Web \u8bf7\u6c42\u4e0b\u51fa\u73b0\u7a7a\u5f02\u5e38 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u4e2a\u6388\u6743\u7b56\u7565\u5171\u5b58\u95ee\u9898\u51fa\u73b0\u65e0\u6548 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u53cb\u597d\u5f02\u5e38 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oop.Oh")," \u4e0d\u652f\u6301\u666e\u901a\u65b9\u6cd5 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u83b7\u53d6\u591a\u79df\u6237\u5bf9\u8c61\u65f6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u51fa\u73b0\u4f5c\u7528\u57df\u9a8c\u8bc1\u5931\u8d25 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5de5\u4f5c\u5355\u5143\u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql\u4ee3\u7406")," \u62e6\u622a bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27GST"},"#I27GST")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5173\u95ed][#I26O1F]","(",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26O1F"},"https://gitee.com/dotnetchina/Furion/issues/I26O1F"),"), ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27B2I"},"#I27B2I"),", ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27BJ6"},"#I27BJ6"),", ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27E5Z"},"#I27E5Z"),", ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27EL4"},"#I27EL4")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e][\u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668]","(",(0,r.kt)("a",{parentName:"li",href:"https://dotnetchina.gitee.io/furion/docs/dbcontext-entitytrigger"},"https://dotnetchina.gitee.io/furion/docs/dbcontext-entitytrigger"),") \u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u4e00\u5206\u949f\u5165\u95e8\u3001\u5e94\u7528\u542f\u52a8\u3001\u5b98\u65b9\u811a\u624b\u67b6\u3001\u6570\u636e\u5e93\u64cd\u4f5c\u6307\u5357\u3001\u5bf9\u8c61\u6620\u5c04\u3001\u89c4\u8303\u5316\u6587\u6863\u3001\u5f02\u5e38\u5904\u7406\u3001\u9274\u6743\u6388\u6743\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v110\u5df2\u53d1\u5e03"},"v1.1.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetDbContext()")," \u83b7\u53d6\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u65b9\u6cd5"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContextUtility.GetCurrentHttpContext()")," \u83b7\u53d6\u5168\u5c40 ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContext")," \u4e0a\u4e0b\u6587"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.GetRequiredService<>")," \u89e3\u6790\u670d\u52a1\u65b9\u6cd5"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"object.GetService<>")," \u5bf9\u8c61\u62d3\u5c55\u65b9\u6cd5"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7b56\u7565\u6388\u6743 ",(0,r.kt)("inlineCode",{parentName:"li"},"PolicyPipeline")," \u57fa\u7c7b\u65b9\u6cd5\uff0c\u652f\u6301\u591a\u91cd\u5224\u65ad\u6388\u6743"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWTEncryption.ValidateJwtBearerToken")," \u624b\u52a8\u9a8c\u8bc1\u9759\u6001\u65b9\u6cd5"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u6570\u636e\u5e93\u4e0a\u4e0b\u6587 ",(0,r.kt)("inlineCode",{parentName:"li"},"InsertOrUpdateIgnoreNullValues")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"EnabledEntityStateTracked")," \u5168\u5c40\u914d\u7f6e"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger Jwt\u6388\u6743")," \u5168\u5c40\u6388\u6743\u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26GLR"},"#I26GLR")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"InsertOrUpdate")," \u652f\u6301\u81ea\u5b9a\u4e49\u5224\u65ad\u6761\u4ef6\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I269Q1"},"#I269Q1")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b57\u7b26\u4e32\u5b57\u6bb5\u5c0f\u5199\u547d\u540d\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2695D"},"#I2695D")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b57\u7b26\u4e32\u6587\u672c\u5bf9\u6bd4\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I268LE"},"#I268LE")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u5f02\u5e38\u7279\u6027\u6d88\u606f\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2662O"},"#I2662O")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Insert")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"li"},"Update")," \u6570\u636e\u5e93\u5ffd\u7565\u7a7a\u503c\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I264Q4"},"#I264Q4")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Fur")," \u9879\u76ee\u540d\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetRequestDbContext<>()")," \u547d\u540d\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetDbContext<>()")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetDbContext<>()")," \u547d\u540d\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetDuplicateDbContext<>()")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.GetService<>")," \u89e3\u6790\u670d\u52a1\u7684\u5e95\u5c42\u903b\u8f91\uff0c\u5927\u5927\u63d0\u9ad8\u4e86\u89e3\u6790\u670d\u52a1\u7684\u6027\u80fd"),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u6388\u6743\u6838\u5fc3\u4ee3\u7801\uff0c\u4fdd\u6301\u548c\u5fae\u8f6f\u4e00\u81f4\u7684\u6388\u6743\u89c4\u8303 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26DCB"},"#I26DCB")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.GetRequestService<>")," \u65b9\u6cd5"),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidateJwtBearer")," Jwt \u6388\u6743\u65b9\u6cd5\uff0c\u65e0\u9700\u624b\u52a8\u5224\u65ad\u4e86"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," Furion \u5b98\u65b9\u811a\u624b\u67b6\u751f\u6210\u540e\u7f16\u8bd1\u5f02\u5e38 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Tenant")," \u5185\u7f6e\u5c5e\u6027\u4e0d\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"virtual")," \u4fee\u9970 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"dockerfile")," \u65b0\u547d\u540d\u6784\u5efa\u5931\u8d25 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u5b9a\u4e49\u89d2\u8272\u6388\u6743\u548c\u591a\u4e2a\u6388\u6743\u5171\u5b58\u51fa\u73b0 403 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26H1L"},"#I26H1L")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"httpContext.GetEndpoint()")," \u7a7a\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/73"},"#PR73")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Oh")," \u7a7a\u5f02\u5e38\u548c\u4e0d\u652f\u6301\u670d\u52a1\u629b\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26EFU"},"#I26EFU"),"\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26GM4"},"#I26GM4")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"cli.ps")," \u751f\u6210\u6587\u4ef6\u7f16\u7801\u4e71\u7801 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26DVT"},"#I26DVT")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u6587\u4ef6\u4e0a\u4f20\u6309\u94ae\u4e0d\u663e\u793a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26B6U"},"#I26B6U")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c4\u8303\u5316\u7ed3\u679c\u6388\u6743\u72b6\u6001\u7801\u5e8f\u5217\u5316\u5927\u5c0f\u5199\u4e0d\u4e00\u81f4\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26B26"},"#I26B26")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u672a\u542f\u7528\u89c4\u8303\u5316\u7ed3\u679c\u65f6\u4e2d\u6587\u4e71\u7801 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I268T5"},"#I268T5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MySql")," \u5f02\u6b65\u5f02\u5e38\u6355\u83b7\u4e0d\u5230 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I265SO"},"#I265SO")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"cli.ps1")," \u63d0\u793a\u627e\u4e0d\u5230\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2647U"},"#I2647U")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5176\u4ed6]"," \u4ee3\u7801\u6027\u80fd\u5c0f\u4f18\u5316\u548c\u5c0f\u8c03\u6574"),(0,r.kt)("li",{parentName:"ul"},"[\u5173\u95ed][#I265JV]","(",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I265JV)%EF%BC%8C%5B#I26ERA%5D(https://gitee.com/dotnetchina/Furion/issues/I26ERA)%EF%BC%8C"},"https://gitee.com/dotnetchina/Furion/issues/I265JV)\uff0c[#I26ERA](https://gitee.com/dotnetchina/Furion/issues/I26ERA)\uff0c")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26EVW"},"#I26EVW"),"\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26GHC"},"#I26GHC"),"\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26GJ1"},"#I26GJ1"),"\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26O1F"},"#I26O1F")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u4e00\u5206\u949f\u5165\u95e8\u3001\u5b89\u5168\u9274\u6743\u3001\u6570\u636e\u5e93\u7b49\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v103\u5df2\u53d1\u5e03"},"v1.0.3\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," Mvc \u6a21\u677f\u811a\u624b\u67b6\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Fur.Template.Mvc")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," WebApi \u6a21\u677f\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Fur.Template.Api")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," Mvc/WebApi \u6a21\u677f\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Fur.Template.App")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," Razar Pages \u6a21\u677f\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Fur.Template.Razor")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," Blazor \u6a21\u677f\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Fur.Template.Blazor")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"PagedList")," \u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"System.Collections.Generic")," \u547d\u540d\u7a7a\u95f4\u4e0b"),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u89e3\u6790\u670d\u52a1\u6027\u80fd\u95ee\u9898\uff0c\u5e95\u5c42\u4ee3\u7801\u5927\u91cf\u4f18\u5316"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ApiSears.ControllerEnd"),"\u4e0d\u8d77\u4f5c\u7528 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I25KH6"},"#I25KH6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"RemoteRequest")," \u8bf7\u6c42\u5b8c\u6210\u7ed3\u679c\u5e8f\u5217\u5316\u5c5e\u6027\u5927\u5c0f\u5199\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I25I8R"},"#I25I8R")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContext.GetEndpoinet()")," \u7a7a\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/73"},"#PR73")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"\u65e0"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u5165\u95e8\u6587\u6863\u3001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6587\u6863\u3001\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v102\u5df2\u53d1\u5e03"},"v1.0.2\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Pomelo.EntityFrameworkCore.MySql")," \u6700\u65b0 .NET 5 \u5305\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24ZQK"},"#I24ZQK")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".AddDateTimeJsonConverter(format)")," \u65f6\u95f4\u683c\u5f0f\u5e8f\u5217\u5316\u914d\u7f6e"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTime")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTimeOffset")," \u7c7b\u578b\u5e8f\u5217\u5316\u683c\u5f0f\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I253FI"},"#I253FI")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mapster")," \u5305\u81f3 ",(0,r.kt)("inlineCode",{parentName:"li"},"7.0.0")," \u7248"),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.Services")," \u540d\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"App.ServiceProvider")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.ApplicationServices")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"App.GetRequestService<>()")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u975e Web \u4e3b\u673a\u6ce8\u5165\u62d3\u5c55"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddFriendlyException()")," \u7f3a\u5c11\u914d\u7f6e\u6ce8\u5165 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6c60\u88ab\u91ca\u653e\u548c\u9ad8\u5e76\u53d1\u4e0b\u5185\u5b58\u6ea2\u51fa bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2524K"},"#I2524K"),"\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24UMN"},"#I24UMN")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql\u4ee3\u7406")," \u8fd4\u56de\u7a7a\u6570\u636e\u65f6\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24TCK"},"#I24TCK")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5de5\u4f5c\u5355\u5143 ",(0,r.kt)("inlineCode",{parentName:"li"},"[UnitOfWork]")," \u591a\u6570\u636e\u5e93\u88ab\u91ca\u653e bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24Q6W"},"#I24Q6W")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EntityBase")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Entity")," \u6240\u6709\u5c5e\u6027\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"vitural")," \u4fee\u9970"),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Jwt")," \u8bfb\u53d6\u548c\u89e3\u6790\u6027\u80fd"),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u4f18\u5316\u4ee3\u7801\u652f\u6301 C# 9.0 \u6700\u65b0\u8bed\u6cd5"),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MD5")," \u52a0\u5bc6\u6027\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/71"},"#PR71")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u65e0\u7528\u6216\u672a\u4f7f\u7528\u4ee3\u7801"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3001\u591a\u6570\u636e\u5e93\u3001\u4e00\u5206\u949f\u5165\u95e8\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v100\u5df2\u53d1\u5e03"},"v1.0.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7f51\u7edc\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"RemoteRequest")," \u7ec4\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I1YYWD"},"#I1YYWD")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".AddInjectBase()")," \u6ce8\u5165\uff0c\u53ea\u5305\u542b\u57fa\u7840\u670d\u52a1\u6ce8\u5165"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6240\u6709\u670d\u52a1\u90fd\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"IServiceCollection")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"IMvcBuilder")," \u6ce8\u5165"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u629b\u5f02\u5e38\u72b6\u6001\u7801\u8bbe\u7f6e\u529f\u80fd ",(0,r.kt)("inlineCode",{parentName:"li"},"StatusCode")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5e8f\u5217\u5316\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Pascal")," \u5c5e\u6027\u547d\u540d\u65b9\u5f0f"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("strong",{parentName:"li"},"\u6240\u6709\u7684\u5305\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},".NET 5")," \u6b63\u5f0f\u7248")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlProxy")," \u4ee3\u7406\u5f02\u6b65\u5904\u7406 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u7c7b\u578b ",(0,r.kt)("inlineCode",{parentName:"li"},"Datetime")," \u8f6c ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTimeOffset")," bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5c5e\u6027\u9996\u5b57\u6bcd\u5927\u5c0f\u5199\u5e8f\u5217\u5316\u4e0d\u5339\u914d\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"null")," bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5bf9\u8c61\u5e8f\u5217\u5316\u4e2d\u6587\u51fa\u73b0\u4e71\u7801 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u9ed8\u8ba4\u5e8f\u5217\u5316\u914d\u7f6e\u65e0\u6548 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u975e\u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f\u63d0\u4ea4\u65e0\u6548 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5e94\u7528\u7a0b\u5e8f\u6c60\u63d0\u4ea4\u6240\u6709 ",(0,r.kt)("inlineCode",{parentName:"li"},"DbContext")," \u7a7a\u5f02\u5e38 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Saas")," \u591a\u79df\u6237 ",(0,r.kt)("inlineCode",{parentName:"li"},"Tenant")," \u7c7b\u578b\u5b57\u7b26\u4e32\u5c5e\u6027\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"MySql")," \u6570\u636e\u5e93\u4e0b\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"longtext")," \u7c7b\u578b bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mvc")," \u81ea\u52a8\u9a8c\u8bc1\u5b57\u7b26\u4e32\u7a7a\u503c bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24M2T"},"#I24M2T")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u679a\u4e3e\u6ce8\u91ca\u88ab\u8986\u76d6 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24N6J"},"#I24N6J")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5ffd\u7565\u89c4\u8303\u5316\u7ed3\u679c\u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24B8P"},"#I24B8P")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"ContentType")," \u4e0d\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"applicaiton/json")," bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24F3U"},"#I24F3U")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5185\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"System.Text.Json")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Newtonsoft.Json")," \u51b2\u7a81 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24F3U"},"#I24F3U")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Fur")," \u6846\u67b6\u57df\u540d\u4e3a\uff1a",(0,r.kt)("a",{parentName:"li",href:"https://furion.icu"},"https://furion.icu")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u4ed3\u50a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"FromSqlRaw")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"FromSqlInterpolated")," \u63a5\u53e3\u4f4d\u7f6e"),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u6570\u636e\u52a0\u89e3\u5bc6\u6027\u80fd\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/70"},"#PR70")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," README.md\u3001\u6846\u67b6\u4ecb\u7ecd\u3001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3001\u914d\u7f6e\u9009\u9879\u3001\u591a\u79df\u6237\u3001\u8de8\u57df\u6587\u6863")))))}c.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return u}});var a=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var o=a.createContext({}),m=function(e){var t=a.useContext(o),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},s=function(e){var t=m(e.components);return a.createElement(o.Provider,{value:t},e.children)},N={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},k=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,r=e.originalType,o=e.parentName,s=p(e,["components","mdxType","originalType","parentName"]),k=m(n),u=i,c=k["".concat(o,".").concat(u)]||k[u]||N[u]||r;return n?a.createElement(c,l(l({ref:t},s),{},{components:n})):a.createElement(c,l({ref:t},s))}));function u(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=n.length,l=new Array(r);l[0]=k;var p={};for(var o in t)hasOwnProperty.call(t,o)&&(p[o]=t[o]);p.originalType=e,p.mdxType="string"==typeof e?e:i,l[1]=p;for(var m=2;m=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var o=a.createContext({}),m=function(e){var t=a.useContext(o),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},s=function(e){var t=m(e.components);return a.createElement(o.Provider,{value:t},e.children)},N={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},k=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,r=e.originalType,o=e.parentName,s=p(e,["components","mdxType","originalType","parentName"]),k=m(n),u=i,c=k["".concat(o,".").concat(u)]||k[u]||N[u]||r;return n?a.createElement(c,l(l({ref:t},s),{},{components:n})):a.createElement(c,l({ref:t},s))}));function u(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=n.length,l=new Array(r);l[0]=k;var p={};for(var o in t)hasOwnProperty.call(t,o)&&(p[o]=t[o]);p.originalType=e,p.mdxType="string"==typeof e?e:i,l[1]=p;for(var m=2;m PostXXXAsync(HttpFile file);\n\n // \u652f\u6301\u591a\u4e2a\u6587\u4ef6\n [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")]\n Task PostXXXAsync(HttpFile[] files);\n\n // \u652f\u6301\u591a\u4e2a\u6587\u4ef6\n [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")]\n Task PostXXXAsync(IList files);\n}\n')),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,7}",showLineNumbers:!0,"{3,7}":!0},'// bytes \u53ef\u4ee5\u901a\u8fc7 File.ReadAllBytes(\u6587\u4ef6\u8def\u5f84) \u83b7\u53d6\nvar res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")\n .SetFiles(HttpFile.Create("file", bytes, "image.png")).PostAsync();\n\n// \u652f\u6301\u591a\u4e2a\u6587\u4ef6\nvar res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")\n .SetFiles(HttpFile.CreateMultiple("files", (bytes, "image1.png"), (bytes, "image2.png"))).PostAsync();\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWTEncryption")," \u9759\u6001\u7c7b\uff0c\u652f\u6301\u65e0\u9700\u6ce8\u518c ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddJwt()")," \u4f7f\u7528 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PPKE"},"#I5PPKE")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5POLZ"},"#I5POLZ")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u53cb\u597d\u5f02\u5e38\u6587\u6863\u3001\u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v439\u5df2\u53d1\u5e03"},"v4.3.9\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("admonition",{title:"\u7248\u672c\u7ec6\u8282",type:"important"},(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"v4.3.9")," \u7248\u672c\u7ec6\u8282\uff1a",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PIWD"},"https://gitee.com/dotnetchina/Furion/issues/I5PIWD")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"v4.3.8")," \u7248\u672c\u7ec6\u8282\uff1a",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PCXK"},"https://gitee.com/dotnetchina/Furion/issues/I5PCXK")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppSettings")," \u914d\u7f6e\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ExcludeAssemblies")," \u5c5e\u6027\uff0c\u652f\u6301\u5ffd\u7565\u6307\u5b9a\u7a0b\u5e8f\u96c6\u626b\u63cf ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/7b7747f38c84acfe7df3469599bebf417e5ad843"},"7b7747f")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Oh")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Bah")," \u652f\u6301\u8bbe\u7f6e\u989d\u5916\u6570\u636e ",(0,r.kt)("inlineCode",{parentName:"li"},".WithData(data)")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5O38E"},"#I5O38E")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9a\u65f6\u4efb\u52a1 ",(0,r.kt)("inlineCode",{parentName:"li"},"Crontab.GetSleepMilliseconds(baseTime)")," \u83b7\u53d6\u4e0b\u4e00\u4e2a\u53d1\u751f\u65f6\u95f4\u7684\u65f6\u95f4\u5dee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d024fae670b7ce3fd4bfd26aee70ed318a4c0383"},"d024fae")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},"\u53cb\u597d\u5f02\u5e38\u9ed8\u8ba4\u6253\u5370\u5f02\u5e38\u65e5\u5fd7\uff0c\u907f\u514d\u751f\u4ea7\u73af\u5883\u6f0f\u6389\u91cd\u8981\u5f02\u5e38\u4fe1\u606f ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/commit/6e3a5bdd0fd22a7f9ae618b7495cd64081a7f2e8"},"6e3a5bd"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65e5\u5fd7\u9759\u6001\u7c7b ",(0,r.kt)("inlineCode",{parentName:"li"},"Log.CreateLoggerFactory()")," \u9759\u6001\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/75c672afc58b393313916c433cb9d92c779b9629"},"75c672a")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u591a\u8bed\u8a00 ",(0,r.kt)("inlineCode",{parentName:"li"},"SharedResource")," \u6a21\u5f0f\uff0c\u907f\u514d\u786c\u7f16\u7a0b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/18e80c7d7c2c2450c6ad429601716f546552e987"},"18e80c7")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},"\u4e8b\u4ef6\u603b\u7ebf ",(0,r.kt)("inlineCode",{parentName:"strong"},"MessageCenter")," \u9759\u6001\u7c7b\uff0c\u89e3\u51b3\u4ece ",(0,r.kt)("inlineCode",{parentName:"strong"},"Fur v1.x")," \u7248\u672c\u5347\u7ea7\u95ee\u9898 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/commit/a29fc7cf63a3ea41b1617a6ad98a701a243e24f8"},"a29fc7c"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7ec4\u4ef6\u5316 ",(0,r.kt)("inlineCode",{parentName:"li"},"IWebComponent")," \u6a21\u5f0f\uff0c\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},".NET5+")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/08a44c347a56c467527935a8caac8966585f5d1a"},"08a44c3")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u8bbe\u7f6e\u81ea\u5df1\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpClient")," \u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PBR3"},"#I5PBR3")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/544"},"!545")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"LoggingMonitor")," \u652f\u6301\u6dfb\u52a0\u66f4\u591a\u81ea\u5b9a\u4e49\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PEPA"},"#I5PEPA")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"LoggingMonitor")," \u53ef\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"WithReturnValue")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"ReturnValueThreshold")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PFJ1"},"#I5PFJ1")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PFOW"},"#I5PFOW")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"LoggingMonitor")," \u53ef\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"MethodsSettings")," \u66f4\u591a\u4fe1\u606f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PFJ1"},"#I5PFJ1")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PFOW"},"#I5PFOW"))))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,4,6}",showLineNumbers:!0,"{2,4,6}":!0},"Serve.Run(RunOptions.Default\n .AddWebComponent());\n\npublic class XXXWebComponent : IWebComponent\n{\n public void Load(WebApplicationBuilder builder, ComponentContext componentContext)\n {\n // ....\n }\n}\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u7a0b\u5e8f\u96c6 ",(0,r.kt)("inlineCode",{parentName:"strong"},"PublicKeyToken")," \u5f3a\u7b7e\u540d")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/26b12c0fd64b153a71496eb62110567e05450f20"},"26b12c0")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},"\u4e8b\u4ef6\u603b\u7ebf ",(0,r.kt)("inlineCode",{parentName:"strong"},"IEventBusFactory")," \u4e8b\u4ef6\u5de5\u5382\u65b9\u6cd5 ",(0,r.kt)("inlineCode",{parentName:"strong"},"AddSubscriber -> Subscribe"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"strong"},"RemoveSubscriber -> Unsubscribe")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/commit/a29fc7cf63a3ea41b1617a6ad98a701a243e24f8"},"a29fc7c"))),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".AddInject()")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},".UseInject()")," \u914d\u7f6e\u9009\u9879\u540d\u79f0\uff0c\u79fb\u9664 ",(0,r.kt)("inlineCode",{parentName:"li"},"Configure")," \u540e\u7f00 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/b6953cd586936593e40ef626c3b8a1e770239e43"},"b6953cd")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},"\u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"strong"},"\u8bf7\u6c42\u62e6\u622a"),"\u3001",(0,r.kt)("inlineCode",{parentName:"strong"},"\u54cd\u5e94\u62e6\u622a")," \u548c ",(0,r.kt)("inlineCode",{parentName:"strong"},"\u5f02\u5e38\u62e6\u622a")," \u59d4\u6258\u7b7e\u540d\uff0c\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"strong"},"HttpClient")," \u53c2\u6570")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5OWBO"},"#I5OWBO"))))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,7,12}",showLineNumbers:!0,"{2,7,12}":!0},"[Interceptor(InterceptorTypes.Request)]\nstatic void OnRequest(HttpClient client, HttpRequestMessage req)\n{\n}\n\n[Interceptor(InterceptorTypes.Response)]\nstatic void OnResponsing(HttpClien client, HttpResponseMessage res)\n{\n}\n\n[Interceptor(InterceptorTypes.Exception)]\nstatic void OnException(HttpClient client, HttpResponseMessage res, string errors)\n{\n}\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u751f\u6210\u5305\u542b ",(0,r.kt)("inlineCode",{parentName:"li"},"\u4e2d\u6587")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT Token")," \u89e3\u5bc6\u540e\u51fa\u73b0\u4e71\u7801\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5O397"},"#I5O397")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," `HttpRequestMessage`` \u62d3\u5c55\u4e2d\u8ffd\u52a0\u67e5\u8be2\u53c2\u6570\u65f6\u7684\u7a7a\u5f15\u7528\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PENW"},"#I5PENW")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/547"},"!547")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u65e5\u5fd7\u6a21\u5757\u914d\u7f6e\u591a\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"IDatabaseLoggingWriter")," \u53ea\u6709\u4e00\u4e2a\u751f\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PFQ2"},"#I5PFQ2")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PFJ1"},"#I5PFJ1")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u9ed8\u8ba4\u8f93\u51fa\u6587\u4ef6\u65e5\u5fd7\u6a21\u677f\uff0c\u4f7f\u5176\u66f4\u52a0\u7f8e\u89c2 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/1518cf3be74524ed0d3f73360068a9a0ec6685d9"},"#1518cf3")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u9ed8\u8ba4\u89c4\u8303\u5316\u7ed3\u679c\u9a8c\u8bc1\u5904\u7406\u4e5f\u652f\u6301\u72b6\u6001\u7801\u8bbe\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/2eb939074a14d29fcd3e4726937c8a8430765f48"},"2eb9390")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugarCore")," \u62d3\u5c55\u5305\u548c\u811a\u624b\u67b6\u81f3 ",(0,r.kt)("inlineCode",{parentName:"li"},"5.1.2.6")," \u7248\u672c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PCXK"},"#I5PCXK")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON Schema")," \u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"li"},"LoggingMonitor")," \u66f4\u591a\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5PFJ1"},"#I5PFJ1")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"RabbitMQ")," \u4e8b\u4ef6\u603b\u7ebf\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppSettings")," \u914d\u7f6e\u6587\u6863\u3001\u4e8b\u4ef6\u603b\u7ebf\u6587\u6863\u3001\u591a\u6570\u636e\u5e93\u914d\u7f6e\u6587\u6863\u3001\u65e5\u5fd7\u6587\u6863\u3001\u5b9a\u65f6\u4efb\u52a1\u6587\u6863\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"MessageCenter")," \u6587\u6863\u3001\u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863\u3001\u7ec4\u4ef6\u5316\u6587\u6863\u3001\u5165\u95e8\u6307\u5357\u3001\u591a\u8bed\u8a00\u6587\u6863\u3002")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v4213\u5df2\u53d1\u5e03"},"v4.2.13\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},"\u4e8b\u4ef6\u603b\u7ebf\u5de5\u5382\uff0c\u652f\u6301\u8fd0\u884c\u65f6\u52a8\u6001\u6dfb\u52a0\u8ba2\u9605\u7a0b\u5e8f\u548c\u79fb\u9664\u8ba2\u9605\u7a0b\u5e8f")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5NNQX"},"#I5NNQX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},"\u4e8b\u4ef6\u603b\u7ebf ",(0,r.kt)("inlineCode",{parentName:"strong"},"[EventSubscribe]")," \u4e8b\u4ef6 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Id")," \u652f\u6301\u6b63\u5219\u8868\u8fbe\u5f0f\u5339\u914d")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5NNQX"},"#I5NNQX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},"\u4e8b\u4ef6\u603b\u7ebf ",(0,r.kt)("inlineCode",{parentName:"strong"},"[EventSubscribe]")," \u652f\u6301\u5c40\u90e8\u5931\u8d25\u91cd\u8bd5\u914d\u7f6e")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5NNQX"},"#I5NNQX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Log")," \u5168\u5c40\u9759\u6001\u7c7b\uff0c\u65b9\u4fbf\u968f\u65f6\u968f\u5730\u8bb0\u5f55\u65e5\u5fd7")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/ba9b1f13a0b89b6670cf7078ac15abe0eed1f2c3"},"ba9b1f1")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4e8b\u4ef6\u603b\u7ebf ",(0,r.kt)("inlineCode",{parentName:"li"},"options.AddSubscriber(Type)")," \u91cd\u8f7d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/blob/424460780b630e1c71de4db84ad8fd14e33a09f5/framework/Furion.Pure/EventBus/Builders/EventBusOptionsBuilder.cs"},"42446078")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationMetadata")," \u7c7b\u578b ",(0,r.kt)("inlineCode",{parentName:"li"},"FirstErrorProperty")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"FirstErrorMessage")," \u5c5e\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MFJT"},"#I5MFJT")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u6a21\u5f0f ",(0,r.kt)("inlineCode",{parentName:"li"},"WithArgs(args)")," \u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MOJB"},"#I5MOJB")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[UnitOfWork]")," \u5206\u5e03\u5f0f\u4e8b\u52a1 ",(0,r.kt)("inlineCode",{parentName:"li"},"TransactionScope")," \u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MRTY"},"#I5MRTY")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," 16 \u4f4d ",(0,r.kt)("inlineCode",{parentName:"li"},"MD5")," \u52a0\u5bc6\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5N8RC"},"#I5N8RC")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u5f02\u6b65\u521b\u5efa\u4f5c\u7528\u57df\u65b9\u6cd5\u540d\u79f0\uff0c\u907f\u514d\u4e00\u4e9b\u60c5\u51b5\u4e0b\u65e0\u6cd5\u533a\u5206\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u540c\u6b65\u65b9\u6cd5\u4e0d\u53d8")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5N9XY"},"#I5N9XY"))))),(0,r.kt)("p",null,"\u7531\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-2}",showLineNumbers:!0,"{1-2}":!0},"// Scoped.CreateUow \u4e00\u6837\nawait Scoped.Create(async (f, s) => {});\n")),(0,r.kt)("p",null,"\u6539\u4e3a\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-2}",showLineNumbers:!0,"{1-2}":!0},"// Scoped.CreateUowAsync \u4e00\u6837\nawait Scoped.CreateAsync(async (f, s) => {});\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"[\u652f\u6301]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".NET 6.0.8")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},".NET 7 Preview 7")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/842d4f739c92366e05fb1d2c619c9b2c2c2c21b7"},"842d4f7")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u547d\u540d\u7a7a\u95f4\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"System"),"\uff0c\u56e0\u4e3a\u4f7f\u7528\u9891\u7387\u8d8a\u6765\u8d8a\u9ad8 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/b879861c9db5cf3cb0f4ae023d1e96b06fad3e46"},"b879861")),(0,r.kt)("li",{parentName:"ul"},"[\u6dfb\u52a0]"," ",(0,r.kt)("strong",{parentName:"li"},"\u5728\u975e ",(0,r.kt)("inlineCode",{parentName:"strong"},"Web")," \u73af\u5883\u4e2d\u4e0d\u6b63\u786e\u4f7f\u7528\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u6cd5\u68c0\u6d4b\u673a\u5236")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6389cbdd69f5ca826fad25749a45ede079db98ce"},"6389cbd")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},"\u6240\u6709 ",(0,r.kt)("inlineCode",{parentName:"strong"},".Default")," \u9759\u6001\u5c5e\u6027\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},".Default()")," \u65b9\u6cd5")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6389cbdd69f5ca826fad25749a45ede079db98ce"},"6389cbd")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},"\u5de5\u4f5c\u5355\u5143 ",(0,r.kt)("inlineCode",{parentName:"strong"},"IUnitOfWork")," \u6240\u6709\u65b9\u6cd5\u53c2\u6570\u7c7b\u578b\uff0c\u7531 ",(0,r.kt)("inlineCode",{parentName:"strong"},"ActionExecutingContext")," \u548c ",(0,r.kt)("inlineCode",{parentName:"strong"},"ActionExecutedContext")," \u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},"FilterContext"))," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MHX5"},"#I5MHX5"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5,7,9}",showLineNumbers:!0,"{3,5,7,9}":!0},"public interface IUnitOfWork\n{\n void BeginTransaction(FilterContext context, UnitOfWorkAttribute unitOfWork);\n\n void CommitTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork);\n\n void RollbackTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork);\n\n void OnCompleted(FilterContext context, FilterContext resultContext);\n}\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u65e5\u5fd7\u4e0a\u4e0b\u6587\u6570\u636e\u591a\u6b21\u5199\u5165\u88ab\u6e05\u7a7a\u95ee\u9898\u4ee5\u53ca\u6570\u636e\u5e93\u65e5\u5fd7\u51fa\u73b0\u5f02\u5e38\u540e\u505c\u6b62\u5199\u5165 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5LIWF"},"#I5LIWF")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e2a\u522b\u60c5\u51b5\u4e0b\u8de8\u57df\u9ed8\u8ba4\u914d\u7f6e\u7684\u54cd\u5e94\u7f13\u5b58\u5bfc\u81f4\u5d4c\u5165\u5f0f\u8d44\u6e90\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/7a57efe15a9a2d76475d758f2b64395f96d94077"},"7a57efe")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u4f20\u5165\u4e0d\u5408\u6cd5\u7684\u8bf7\u6c42\u62a5\u6587\u5934\u6570\u636e\u89e6\u53d1\u6821\u9a8c\u5931\u8d25\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5LPFE"},"#I5LPFE")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u7ebf\u7a0b\u4e2d\u4f7f\u7528\u9759\u6001\u65e5\u5fd7\u5199\u6570\u636e\u5e93\u65e5\u5fd7\u5bfc\u81f4\u8fde\u63a5\u6c60\u8017\u5149\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/8d5cdd6ca04d55e33322000ecc176e47195b6f4d"},"8d5cdd6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore 6.0")," \u4e4b\u540e ",(0,r.kt)("inlineCode",{parentName:"li"},"IModelCacheKeyFactory")," \u63a5\u53e3\u65b9\u6cd5\u6539\u53d8\u5bfc\u81f4\u5206\u8868\u5206\u5e93\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MCZ6"},"#I5MCZ6")," ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/dotnet/efcore/issues/25154#issuecomment-868804532"},"EFCore#25154")," ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/dotnet/EntityFramework.Docs/pull/3305"},"EFCore!3305")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationMetadata")," \u5bf9\u8c61 ",(0,r.kt)("inlineCode",{parentName:"li"},"Message")," \u5b57\u7b26\u4e32\u7c7b\u578b\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},'\\"\\"')," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MFJT"},"#I5MFJT")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[IfException]")," \u8986\u76d6 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Oh/Bah")," \u9519\u8bef\u6d88\u606f\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4bbd854c6779bf7eca26fd69b25c4979b8cec32d"},"4bbd854")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u65e5\u5fd7\u5199\u5165\u5faa\u73af\u5199\u5165\u548c\u9891\u7e41\u521b\u5efa\u6570\u636e\u5e93\u8fde\u63a5\u6c60\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/9ce214c9cf49eb1ff59f3c52dbecd789be4f45fd"},"9ce214c")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Razor Pages")," \u4e0d\u652f\u6301\u5168\u5c40\u5f02\u5e38\u62e6\u622a\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MHX5"},"#I5MHX5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Razor Pages")," \u4e0d\u652f\u6301\u5168\u5c40\u6570\u636e\u9a8c\u8bc1\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MHX5"},"#I5MHX5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Razor Pages")," \u4e0d\u652f\u6301\u5de5\u4f5c\u5355\u5143 ",(0,r.kt)("inlineCode",{parentName:"li"},"[UnitOfWork]")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MHX5"},"#I5MHX5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Razor Pages")," \u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u81ea\u52a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"SaveChanges")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MHX5"},"#I5MHX5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Blazor Server")," \u56e0 ",(0,r.kt)("inlineCode",{parentName:"li"},"v4.2.2")," \u7248\u672c\u66f4\u65b0\u5bfc\u81f4\u7684\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MNFN"},"#I5MNFN")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[IfException]")," \u4e0d\u652f\u6301\u591a\u8bed\u8a00\u914d\u7f6e\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MPN7"},"#I5MPN7")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddMvcFilter()")," \u65b9\u5f0f\u6ce8\u518c\u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/8d1477d8b44ae111bddb8e4780672bcaf4e0e467"},"8d1477d")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e8b\u4ef6\u603b\u7ebf\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Channel")," \u7ba1\u9053\u521d\u59cb\u5316\u65f6\u673a\u8fc7\u665a\u95ee\u9898\uff0c\u89e3\u51b3\u90e8\u5206\u7b2c\u4e09\u65b9\u4f9d\u8d56\u4f7f\u7528\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MM3O"},"#I5MM3O")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e3b\u673a\u505c\u6b62\u65f6\u5199\u5165\u65e5\u5fd7\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5N7S2"},"#I5N7S2")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u624b\u52a8\u91ca\u653e\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},"AutoSaveChange")," \u7279\u6027\u51fa\u73b0\u91ca\u653e\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5NFWC"},"#I5NFWC")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u5faa\u73af\u5f15\u7528\u5e8f\u5217\u5316\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5NRT9"},"#I5NRT9")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u4f20\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"null")," Body \u53c2\u6570\u629b\u51fa\u7a7a\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5NTUE"},"#I5NTUE")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e8b\u4ef6\u603b\u7ebf\u9ed8\u8ba4\u5f00\u542f\u6a21\u7cca\u5339\u914d\uff08\u6b63\u5219\u8868\u8fbe\u5f0f\uff09\u5bfc\u81f4\u4e0d\u5fc5\u8981\u7684\u8ba2\u9605 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5NVOP"},"#I5NVOP")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u4e8b\u4ef6\u603b\u7ebf\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Channel")," \u7ba1\u9053\u521d\u59cb\u5316\u65f6\u673a\uff0c\u89e3\u51b3\u90e8\u5206\u7b2c\u4e09\u65b9\u4f9d\u8d56\u4f7f\u7528\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5MM3O"},"#I5MM3O")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u5e95\u5c42\u8fed\u4ee3\u6539\u8fdb\u4f18\u5316"),(0,r.kt)("li",{parentName:"ul"},"[\u516c\u5f00]"," \u89c4\u8303\u5316\u6587\u6863\u83b7\u53d6\u63a7\u5236\u5668\u3001\u65b9\u6cd5\u5206\u7ec4\u3001\u6807\u7b7e\u4fe1\u606f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/66d8d54b225b5294cd54aa76b548312f7c37903a"},"66d8d54")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u65e5\u5fd7\u9759\u6001\u7c7b ",(0,r.kt)("inlineCode",{parentName:"li"},"Log")," \u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/ba9b1f13a0b89b6670cf7078ac15abe0eed1f2c3"},"ba9b1f1")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Nuget")," \u672c\u5730\u6d4b\u8bd5\u5305\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u65e5\u5fd7\u6587\u6863\u3001\u9759\u6001\u7c7b\u6587\u6863\u3001\u6570\u636e\u6821\u9a8c\u6587\u6863\u3001Worker Service \u6587\u6863\u3001\u5de5\u4f5c\u5355\u5143\u6587\u6863\u3001\u4f9d\u8d56\u6ce8\u5165\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v4114\u5df2\u53d1\u5e03"},"v4.1.14\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Furion.Xunit")," \u62d3\u5c55\u5305\uff0c\u6b63\u5f0f\u5b9e\u73b0 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Xunit")," \u5355\u5143\u6d4b\u8bd5\u5b8c\u6574\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/commit/063a034edd089e88d501af4c09251611476fd238"},"063a034e"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddMonitorLogging()")," \u65e5\u5fd7\u76d1\u89c6\u5668\u670d\u52a1\uff0c\u652f\u6301\u975e\u5e38\u7075\u6d3b\u7684\u65e5\u5fd7\u64cd\u4f5c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/81df742b2784a18fbf4060fe30cc5151909c3cab"},"81df742")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Serve.Run(silence: true)")," \u7b49\u4e00\u7cfb\u5217\u5f3a\u5927\u7684\u9759\u9ed8\u542f\u52a8\u529f\u80fd ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I5JBSQ"},"#I5JBSQ")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I5J98T"},"#I5J98T")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/commit/7cced443ca1cdcb29226c71274e087ec2a6135ef"},"7cced4"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationDocumentBuilder.GetOpenApiGroups()")," \u65b9\u6cd5\u83b7\u53d6\u5e95\u5c42\u7684\u89c4\u8303\u5316\u63a5\u53e3\u5206\u7ec4\u4fe1\u606f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4ff03c5f8342c4d9b26fb1336cd78936ab189f5e"},"4ff03c5")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"logger.ScopeContext()")," \u914d\u7f6e\u65e5\u5fd7\u4e0a\u4e0b\u6587\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5JC0D"},"#I5JC0D")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8de8\u57df\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"CorsAccessorSettings.SignalRSupport")," \u914d\u7f6e\u9009\u9879\uff0c\u652f\u6301\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"SignalR")," \u8de8\u57df ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5JREM"},"#I5JREM")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4e8b\u4ef6\u603b\u7ebf ",(0,r.kt)("inlineCode",{parentName:"li"},"UseUtcTimestamp")," \u9009\u9879\u914d\u7f6e\uff0c\u53ef\u9009\u62e9\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTime.UtcNow")," \u8fd8\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTime.Now"),"\uff0c\u9ed8\u8ba4\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTime.Now")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5JSEU"},"#I5JSEU")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c4\u8303\u5316\u6587\u6863 ",(0,r.kt)("inlineCode",{parentName:"li"},"[OperationId]")," \u914d\u7f6e\uff0c\u89e3\u51b3\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger UI")," \u4e0d\u80fd\u6b63\u786e\u663e\u793a\u8def\u7531\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5K1IB"},"#I5K1IB")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"IHttpDispatchProxy")," \u65b9\u5f0f\u5168\u5c40\u62e6\u622a\u652f\u6301\u591a\u6001\uff08\u7ee7\u627f\uff09 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5K8FS"},"#I5K8FS")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Xunit")," \u62d3\u5c55\u5305\uff0c\u6b63\u5f0f\u5b9e\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Xunit")," \u5355\u5143\u6d4b\u8bd5\u5b8c\u6574\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/063a034edd089e88d501af4c09251611476fd238"},"063a034e")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.DatabaseAccessor.SqlSugar")," \u62d3\u5c55\u63d2\u4ef6\u4e2d\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"[SqlSugarUnitOfWork]")," \u5de5\u4f5c\u5355\u5143\u7279\u6027\uff0c\u5c06\u4f7f\u7528\u901a\u7528\u5de5\u4f5c\u5355\u5143\u66ff\u6362\uff0c",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("a",{parentName:"strong",href:"/furion/docs/tran#92631-%E8%87%AA%E5%8A%A8%E7%AE%A1%E7%90%86"},"\u67e5\u770b\u6700\u65b0\u5b9e\u73b0\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Inject.Create()")," \u65b9\u6cd5\uff0c\u518d\u4e5f\u4e0d\u9700\u8981\u4e86\uff0c\u6846\u67b6\u63d0\u4f9b\u4e86\u65e0\u654c\u5f3a\u5927\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u9759\u9ed8\u542f\u52a8\u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/200848eda8c2e419c0b5be83f7768a257f3c88bd"},"200848e")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ConfigureConfiguration")," \u65b9\u6cd5\u53c2\u6570\uff0c\u7531 ",(0,r.kt)("inlineCode",{parentName:"li"},"configuration => {}")," \u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"(environment, configuration) => {}")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/83c97bb5a19d6fc4e51cfe05f635675d26067d45"},"83c97bb"))))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6}",showLineNumbers:!0,"{2,6}":!0},"// \u7531\nServe.Run(RunOptions.Default.ConfigureConfiguration(configuration => {\n\n}));\n// \u6539\u4e3a\uff1a\nServe.Run(RunOptions.Default.ConfigureConfiguration((environment, configuration) => {\n\n}));\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u5f02\u5e38\u6d88\u606f\u65e5\u5fd7\u7ea7\u522b\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Information")," \u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/ab46cdf534433f45d39ce4d3ee7c71ca84707140"},"ab46cdf")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u65b0\u7248\u672c\u65e5\u5fd7\u7ec4\u4ef6\u9891\u7e41\u63d0\u793a\u6587\u4ef6\u5360\u7528\u95ee\u9898\uff0c\u5c06\u6587\u4ef6\u72ec\u5360\u9501\u6539\u4e3a\u5171\u4eab\u9501 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5J3S6"},"#I5J3S6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u914d\u7f6e\u6570\u636e\u5e93\u65e5\u5fd7\u8bfb\u5199\u5668\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u65f6\u63a7\u5236\u53f0\u51fa\u73b0\u65e0\u9650\u6253\u5370\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5J474"},"#I5J474")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u9488\u5bf9 ",(0,r.kt)("inlineCode",{parentName:"li"},"byte[]")," \u7c7b\u578b\u53c2\u6570\u8f93\u51fa\u8fc7\u5927\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/5380f3551de69f8607ca0fc33c950103c7ed8174"},"5380f35")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u53cb\u597d\u5f02\u5e38\u548c\u89c4\u8303\u5316\u7ed3\u679c\u4e22\u5931\u4e86\u539f\u59cb ",(0,r.kt)("inlineCode",{parentName:"li"},"ErrorCode")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5IX2R"},"#I5IX2R")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u65b0\u7248\u672c\u65e5\u5fd7\u7ec4\u4ef6\u81ea\u5b9a\u4e49\u6570\u636e\u5e93\u8bfb\u5199\u5668\u6ce8\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"IRepository")," \u4ed3\u50a8\u5bfc\u81f4\u6b7b\u5faa\u73af\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5IX2R"},"#I5IX2R")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mvc")," \u9ed8\u8ba4\u624b\u52a8\u9a8c\u8bc1\u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u5168\u5c40\u9a8c\u8bc1\u51b2\u7a81\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/2a06c39c1d0a032bbc317e25a22c646babce2a60"},"2a06c39")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u6a21\u5f0f\u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"SuperSocket")," \u7b2c\u4e09\u65b9\u5305\u95ee\u9898\uff0c\u539f\u751f\u662f\u652f\u6301\u7684\u3002",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/186ca0a35d696f58d9e696094848a560074cdf6f"},"186ca0a")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SignalR")," \u8de8\u57df\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5JREM"},"#I5JREM")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u5c06 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Oh")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Bah")," \u8bb0\u5f55\u5230\u4e86\u9519\u8bef\u65e5\u5fd7\u4e2d\uff0c\u9ed8\u8ba4\u5e94\u8be5\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"Information")," \u4e14\u63d0\u4f9b\u53ef\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5JZ1H"},"#I5JZ1H")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger UI")," \u4e4b\u540e\u4e2a\u522b ",(0,r.kt)("inlineCode",{parentName:"li"},"UI")," \u8981\u6c42\u5fc5\u987b\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"operationId"),"\uff0c\u5426\u5219\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"guid")," \u5e8f\u53f7 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5K1IB"},"#I5K1IB")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e3b\u52a8\u629b\u51fa ",(0,r.kt)("inlineCode",{parentName:"li"},"NotFoundResult")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"NotFoundObjectResult")," \u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5KALZ"},"#I5KALZ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u89e3\u6790\u65b9\u6cd5\u53c2\u6570\u4f46\u524d\u7aef\u672a\u4f20\u5165\u65f6\u51fa\u73b0\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5KC5P"},"#I5KC5P")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u65e0\u6cd5\u5e8f\u5217\u5316 ",(0,r.kt)("inlineCode",{parentName:"li"},"IQueryable")," \u8fd4\u56de\u503c\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5KJD1"},"#I5KJD1")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u4e0d\u80fd\u8bb0\u5f55\u5168\u5c40\u9a8c\u8bc1\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/b44087dcc7dbe9992b8f4518e0b0cf4ed61c56bb"},"b44087d")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u5b58\u5728\u6ce8\u518c\u987a\u5e8f\u5dee\u5f02\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/b44087dcc7dbe9992b8f4518e0b0cf4ed61c56bb"},"b44087d")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5f00\u653e]"," \u5e95\u5c42\u7684\u89c4\u8303\u5316\u6587\u6863 ",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationDocumentBuilder")," \u90e8\u5206\u65b9\u6cd5\uff0c\u63d0\u4f9b\u66f4\u52a0\u4fbf\u6377\u7684\u7b2c\u4e09\u65b9 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger UI")," \u96c6\u6210 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/10f0f01996586eedb138304c7b00c6f31282dfeb"},"10f0f01")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u5355\u5143\u6d4b\u8bd5\u6587\u6863\u3001\u5165\u95e8\u6307\u5357\u6587\u6863\u3001Worker Services \u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u5f7b\u5f7b\u5e95\u5e95\u652f\u6301\u5168\u5e73\u53f0\uff0c\u63d0\u4f9b\u975e\u5e38\u5f3a\u5927\u7684\u9759\u9ed8\u6a21\u5f0f")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u542f\u7528\u9759\u9ed8\u6a21\u5f0f\u53ef\u4ee5\u5b9e\u73b0\u65e0\u963b\u585e\u65b9\u5f0f\u6267\u884c\u7a0b\u5e8f\uff0c\u800c\u4e14\u8fd8\u80fd\u4f53\u9a8c\u5b8c\u6574\u7684 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u529f\u80fd\u3002")),(0,r.kt)("admonition",{title:"\u5927\u9769\u547d",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"\u6709\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"Serve.Run()")," \u9759\u9ed8\u6a21\u5f0f\u540e\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u5f7b\u5f7b\u5e95\u5e95\u652f\u6301\u5168\u5e73\u53f0\uff0c\u4e0d\u7ba1\u4f60\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"\u63a7\u5236\u53f0\u3001Web\u3001\u684c\u9762\u3001\u79fb\u52a8\u3001\u5355\u5143\u6d4b\u8bd5\uff0c\u96c6\u6210\u6d4b\u8bd5\uff0c\u57fa\u51c6\u6d4b\u8bd5\u7b49\u7b49\u5e94\u7528\u7a0b\u5e8f"),"\u3002")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3}",showLineNumbers:!0,"{1,3}":!0},'Serve.Run(silence: true);\n\n// \u4e0d\u4f1a\u963b\u585e\u6267\u884c\u54e6\uff0c\u800c\u4e14\u4ece\u8fd9\u91cc\u5f00\u59cb\u53ef\u4ee5\u4f7f\u7528 Furion \u4efb\u4f55\u529f\u80fd\uff0c\u6bd4\u5982 App.Configuration....\nConsole.WriteLine("Hello, World!");\nConsole.ReadKey();\n')),(0,r.kt)("p",null,"\u8fd8\u6709\u66f4\u591a\u9759\u9ed8\u6a21\u5f0f\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,8}",showLineNumbers:!0,"{2,5,8}":!0},"// RunOptions \u65b9\u5f0f\nServe.Run(RunOptions.DefaultSilence);\n\n// LegacyRunOptions \u65b9\u5f0f\nServe.Run(LegacyRunOptions.DefaultSilence);\n\n// GenericRunOptions \u65b9\u5f0f\nServe.Run(GenericRunOptions.DefaultSilence);\n")),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},"\u5f3a\u5927\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Xunit")," \u5355\u5143\u6d4b\u8bd5\u3001\u96c6\u6210\u6d4b\u8bd5")),(0,r.kt)("admonition",{title:"\u5927\u9769\u547d",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"\u5355\u5143\u6d4b\u8bd5\u548c\u96c6\u6210\u6d4b\u8bd5\u662f\u4fdd\u8bc1\u4e00\u4e2a\u7cfb\u7edf\u80fd\u591f\u6301\u7eed\u7ef4\u62a4\u548c\u7a33\u5b9a\u8fd0\u884c\u7684\u5fc5\u5907\u6280\u80fd\uff0c\u4f46\u662f\u76ee\u524d\u73b0\u6709\u7684\u5355\u5143\u6d4b\u8bd5\u7ec4\u4ef6\u65e0\u6cd5\u76f4\u63a5\u96c6\u6210 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u7684\u529f\u80fd\uff0c\u6700\u5e38\u7528\u7684\u5c31\u662f\u5982\u4f55\u5728\u5355\u5143\u6d4b\u8bd5\u4e2d\u8bfb\u53d6\u914d\u7f6e\uff0c\u4ee5\u53ca",(0,r.kt)("strong",{parentName:"p"},"\u5982\u4f55\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165"),"\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u5728\u8fc7\u53bb\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u53ea\u80fd\u4e0d\u65ad\u7684\u53bb\u8c03\u6574\uff0c\u4ee5\u81f3\u4e8e\u9002\u914d\u7b2c\u4e09\u65b9\u5355\u5143\u6d4b\u8bd5\u5199\u6cd5\uff0c\u641e\u5f97\u4e0d\u4f26\u4e0d\u7c7b\uff01"),(0,r.kt)("p",{parentName:"admonition"},"\u6240\u4ee5\uff0c\u8fd9\u4e00\u6b21\u4e0d\u518d\u59a5\u534f\uff0c",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u63a8\u51fa\u81ea\u5df1\u7684\u5355\u5143\u6d4b\u8bd5\u5de5\u5177\uff0c\u53ef\u4ee5\u8ba9\u73b0\u6709\u7684\u5355\u5143\u6d4b\u8bd5\u5982 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Xunit")," 100% \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u6240\u6709\u529f\u80fd\uff0c\u5168\u90e8\u4fdd\u8bc1\u4e00\u81f4\u7684\u5199\u6cd5\u3002"))),(0,r.kt)("p",null,"\u5355\u5143\u6d4b\u8bd5\u4e2d\u521d\u59cb\u5316 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,13,18}",showLineNumbers:!0,"{6,13,18}":!0},'using Furion.Xunit;\nusing Xunit.Abstractions;\nusing Xunit.Sdk;\n\n// \u914d\u7f6e\u542f\u52a8\u7c7b\u7c7b\u578b\uff0c\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f TestProgram \u7c7b\u5b8c\u6574\u9650\u5b9a\u540d\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f\u5f53\u524d\u9879\u76ee\u7a0b\u5e8f\u96c6\u540d\u79f0\n[assembly: TestFramework("TestProject1.TestProgram", "TestProject1")]\n\nnamespace TestProject1;\n\n/// \n/// \u5355\u5143\u6d4b\u8bd5\u542f\u52a8\u7c7b\n/// \npublic class TestProgram : TestStartup\n{\n public TestProgram(IMessageSink messageSink) : base(messageSink)\n {\n // \u521d\u59cb\u5316 Furion\n Serve.Run(silence: true);\n }\n}\n')),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u6d4b\u8bd5\u7c7b\u652f\u6301\u5b8c\u6574\u4f9d\u8d56\u6ce8\u5165")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,15}",showLineNumbers:!0,"{9,15}":!0},"using TestProject1.Services;\nusing Xunit;\n\nnamespace TestProject1;\n\npublic class UnitTest1\n{\n private readonly ICalcService _calcService;\n public UnitTest1(ICalcService calcService)\n {\n _calcService = calcService;\n }\n\n [Fact]\n public void \u6d4b\u8bd5\u4e24\u4e2a\u6570\u7684\u548c()\n {\n Assert.Equal(3, _calcService.Plus(1, 2));\n }\n}\n")),(0,r.kt)("img",{src:(0,l.Z)("img/ut9.png")}),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"/furion/docs/unittest"},"\u67e5\u770b\u65b0\u7248\u672c\u5355\u5143\u6d4b\u8bd5\u6587\u6863"))),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},"\u5f00\u653e\u5e95\u5c42\u89c4\u8303\u5316\u6587\u6863\u5206\u7ec4\u63a5\u53e3\uff0c\u4f7f\u5f97\u96c6\u6210\u7b2c\u4e09\u65b9 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger UI")," \u66f4\u52a0\u5bb9\u6613\uff0c\u5982\u96c6\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"IGeekFan.AspNetCore.Knife4jUI")," \u62d3\u5c55\uff1a")),(0,r.kt)("admonition",{title:"\u5b89\u88c5\u5305",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u53ea\u9700\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"YourPoject.Web.Core")," \u5c42\u5b89\u88c5 ",(0,r.kt)("inlineCode",{parentName:"p"},"IGeekFan.AspNetCore.Knife4jUI")," \u5373\u53ef\u3002")),(0,r.kt)("p",null,"3.1.1 ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"Knife4jUI")," \u72ec\u7acb\u7248\u672c\u914d\u7f6e")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,12}",showLineNumbers:!0,"{1,3,12}":!0},'var routePrefix = "api"; // \u5b9a\u4e49 swagger \u8def\u7531\u5730\u5740\uff0c\u5982\u679c\u662f\u8ddf\u76ee\u5f55\uff0c\u8bbe\u7f6e string.Empty \u5373\u53ef\n\napp.UseKnife4UI(options =>\n{\n options.RoutePrefix = routePrefix; // \u914d\u7f6e Knife4UI \u8def\u7531\u5730\u5740\n foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())\n {\n options.SwaggerEndpoint("/" + groupInfo.RouteTemplate, groupInfo.Title);\n }\n});\n\napp.UseInject(routePrefix); // \u914d\u7f6e Furion \u8def\u7531\u5730\u5740\n')),(0,r.kt)("p",null,"3.1.2 ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"Knife4jUI")," \u548c ",(0,r.kt)("inlineCode",{parentName:"strong"},"Swagger")," \u5171\u5b58\u7248\u672c\u914d\u7f6e")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,10}",showLineNumbers:!0,"{1,3,10}":!0},'app.UseKnife4UI(options =>\n{\n options.RoutePrefix = "newapi"; // \u914d\u7f6e Knife4UI \u8def\u7531\u5730\u5740\uff0c\u73b0\u5728\u662f /newapi\n foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())\n {\n options.SwaggerEndpoint("/" + groupInfo.RouteTemplate, groupInfo.Title);\n }\n});\n\napp.UseInject(); // Furion \u9ed8\u8ba4 api \u5730\u5740\u4e3a /api\n')),(0,r.kt)("img",{src:(0,l.Z)("img/sg20.png")}),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u5982\u9700\u5b9e\u73b0\u767b\u5f55\u4e4b\u540e\u81ea\u52a8\u5c06 ",(0,r.kt)("inlineCode",{parentName:"strong"},"token")," \u6dfb\u52a0\u5230\u5934\u90e8\u53ef\u5728\u767b\u5f55\u63a5\u53e3 ",(0,r.kt)("inlineCode",{parentName:"strong"},"AfterScript")," \u6267\u884c\u4ee5\u4e0b\u4ee3\u7801\uff1a")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},'ke.global.setAllHeader(\n "Authorization",\n "Bearer " + ke.response.headers["access-token"]\n);\n')),(0,r.kt)("img",{src:(0,l.Z)("img/kni.jpg")}),(0,r.kt)("ol",{start:4},(0,r.kt)("li",{parentName:"ol"},"\u63d0\u4f9b\u5f3a\u5927\u7684\u65e5\u5fd7\u4e0a\u4e0b\u6587\u529f\u80fd")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6,12}",showLineNumbers:!0,"{2,6,12}":!0},'// \u5199\u6cd5\u4e00\n_logger.ScopeContext(ctx => ctx.Set("Name", "Furion").Set("UserId", 10))\n .LogInformation("\u6211\u662f\u4e00\u4e2a\u65e5\u5fd7 {id}", 20);\n\n// \u5199\u6cd5\u4e8c\n_logger.ScopeContext(new Dictionary {\n { "Name", "Furion" },\n { "UserId", 10 }\n}).LogInformation("\u6211\u662f\u4e00\u4e2a\u65e5\u5fd7 {id}", 20);\n\n// \u5199\u6cd5\u4e09\n_logger.ScopeContext(new LogContext {\n // ....\n}).LogInformation("\u6211\u662f\u4e00\u4e2a\u65e5\u5fd7 {id}", 20)\n')),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v400\u91cd\u65b0\u8d77\u822a"},"v4.0.0\uff08\u91cd\u65b0\u8d77\u822a\uff09"),(0,r.kt)("admonition",{title:"\u4e0d\u5fd8\u521d\u5fc3\uff0c\u611f\u6069\u9047\u89c1\uff0c\u611f\u6069\u4fe1\u4efb",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"2020 \u5e74 09 \u6708 01 \u65e5\uff0c\u4e00\u4e2a\u53eb ",(0,r.kt)("inlineCode",{parentName:"p"},"Fur")," \u7684\u5f00\u6e90\u9879\u76ee\u6084\u7136\u8bde\u751f\uff0c\u5979\u7684\u51fa\u751f\u4eff\u4f5b\u5e26\u7740\u67d0\u79cd\u4f7f\u547d\uff0c\u6ca1\u6709\u5305\u88b1\uff0c\u65e0\u9650\u53ef\u80fd\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u5979\u7f13\u7f13\u7684\u5f20\u5f00\u53cc\u773c\uff0c\u5e72\u51c0\u96ea\u4eae\u7684\u773c\u775b\u4f3c\u4e4e\u5bf9\u8fd9\u4e2a\u4e16\u754c\u5145\u6ee1\u4e86\u597d\u5947\uff0c\u6bcf\u4e00\u6b21\u601d\u60f3\u78b0\u649e\u5728\u5979\u770b\u6765\u90fd\u662f\u975e\u5e38\u5b9d\u8d35\u7684\u8d22\u5bcc\uff0c\u5979\u8c8c\u4f3c\u6709\u7528\u4e0d\u5b8c\u7684\u7cbe\u529b\uff0c\u4e00\u8def\u6c72\u53d6\u77e5\u8bc6\uff0c\u5347\u7ea7\u6253\u602a\uff0c\u4e0d\u65ad\u5954\u8dd1\uff0c\u4e50\u6b64\u4e0d\u75b2\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u8bb0\u5f97 2020 \u5e74 11 \u6708 11 \u65e5\u7684\u5355\u8eab\u8282\uff0c\u5979\u8fce\u6765\u4e86\u201c\u4e00\u5c81\uff08v1.0.0\uff09\u201d\u751f\u65e5\uff0c\u81ea\u90a3\u4ee5\u540e\uff0cIT \u8fd9\u4e2a\u5927\u94f6\u5e55\u4e0a\u9891\u7e41\u51fa\u73b0\u5979\u7684\u8eab\u5f71\uff0c\u8d8a\u6765\u8d8a\u591a ",(0,r.kt)("inlineCode",{parentName:"p"},".NET5")," \u5f00\u53d1\u8005\u8f6c\u7c89\uff0c\u50cf\u662f\u544a\u8bc9\u8fd9\u4e2a\u4e16\u754c\uff0c\u5979\u5c31\u662f IT \u754c\u5927\u660e\u661f\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u6bcf\u4e00\u4e2a\u660e\u661f\u90fd\u6709\u4e00\u4e2a\u597d\u542c\u7684\u827a\u540d\uff0c\u5979\u5f53\u7136\u4e5f\u4e0d\u4f8b\u5916\uff0c2020 \u5e74 11 \u6708 20 \u65e5\uff0c\u7ecf\u7eaa\u4eba\u767e\u5c0f\u50e7\u4e3a\u5979\u8d77\u540d\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion"),"\u3002"),(0,r.kt)("p",{parentName:"admonition"},"2021 \u5e74 11 \u6708 09 \u65e5\uff0c\u5979\u8fdb\u5165\u4e86\u53db\u9006\u671f\uff0c\u629b\u5f03\u4e86\u66fe\u7ecf\u652f\u6301\u5979\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET5")," \u7c89\u4e1d\u4eec\uff0c\u62e5\u62b1\u4e86\u65b0\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET6")," \u62e5\u8db8\u8005\uff0c\u81ea\u4ece\u8fc7\u4e0a\u4e86\u5962\u9761\u5bcc\u8db3\u7684\u751f\u6d3b\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u4f46\u5979\u8fc7\u7684\u4e0d\u5f00\u5fc3\uff0c\u65f6\u5e38\u5728\u591c\u91cc\u60f3\u8d77 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET5")," \u7684\u7c89\u4e1d\u4eec\uff0c\u5185\u5fc3\u975e\u5e38\u81ea\u8d23\uff0c\u4f46\u5728\u53cc\u91cd\u5de5\u4f5c\u538b\u529b\u4e0b\u5979\u4f9d\u7136\u9009\u62e9\u4e86\u5ffd\u89c6\u4ed6\u4eec\u7684\u8bc9\u6c42\uff0c\u4eff\u4f5b\u4ed6\u4eec\u5c31\u662f\u7d2f\u8d58\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u65f6\u95f4\u771f\u7684\u662f\u597d\u4e1c\u897f\uff0c\u66fe\u7ecf\u8ba4\u4e3a\u662f\u5bf9\u7684\uff0c\u7ecf\u8fc7\u5c81\u6708\u7684\u8e49\u8dce\u5386\u78e8\uff0c\u6e10\u6e10\u7684\u660e\u767d\uff1a\u4e0d\u5fd8\u521d\u5fc3\uff0c\u65b9\u80fd\u59cb\u7ec8\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u8fd9\u4e00\u6b21\uff0c\u4e0d\u843d\u4e0b\u4e00\u4eba\uff08",(0,r.kt)("inlineCode",{parentName:"p"},".NET5"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},".NET6"),"\uff0c...\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},".NET N"),"\uff09\uff0c\u643a\u624b\u5171\u8fdb\uff0c\u91cd\u65b0\u8d77\u822a\uff0c\u611f\u6069\u9047\u89c1\uff0c\u611f\u6069\u4fe1\u4efb\u3002")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"v4.0.0")," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"strong"},".NET5"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"strong"},".NET6"),"\uff0c...\uff0c",(0,r.kt)("inlineCode",{parentName:"strong"},".NET N"),"\uff0c\u6240\u6709\u7684 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u9879\u76ee\u90fd\u80fd\u591f\u5347\u7ea7\u5230\u8be5\u7248\u672c\uff0c\u91cd\u65b0\u8d77\u822a\uff0c\u5b9e\u73b0\u5927\u7edf\u3002"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v392\u5df2\u53d1\u5e03"},"v3.9.2\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("admonition",{title:"\u5173\u4e8e\u65e5\u5fd7",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u65e5\u5fd7\u6a21\u5757\u662f\u4efb\u4f55\u5e94\u7528\u7cfb\u7edf\u90fd\u5fc5\u5907\u7684\u529f\u80fd\uff0c\u53ef\u4ee5\u8bf4\u662f\u6700\u91cd\u8981\u7684\u6a21\u5757\uff01\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET")," \u793e\u533a\u4e2d\u6709 ",(0,r.kt)("inlineCode",{parentName:"p"},"Log4NET"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"NLog"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Serilog")," \u7b49\u65e5\u5fd7\u7ec4\u4ef6\uff0c\u5b83\u4eec\u65e0\u4e00\u4e0d\u662f\u4f18\u79c0\u7684\u5f00\u6e90\u9879\u76ee\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u4f46\u7531\u4e8e\u8fd9\u4e9b\u65e5\u5fd7\u7ec4\u4ef6\u5386\u53f2\u60a0\u4e45\uff0c\u5185\u90e8\u517c\u5bb9\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET")," \u7248\u672c\u975e\u5e38\u591a\uff0c\u529f\u80fd\u968f\u7740\u65f6\u95f4\u63a8\u79fb\u53d8\u5f97\u6781\u5176\u5f3a\u5927\u590d\u6742\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u5728\u5b9e\u9645\u9879\u76ee\u4f7f\u7528\u4e2d\uff0c\u53d1\u73b0\u6bcf\u4e00\u4e2a\u65e5\u5fd7\u7ec4\u4ef6\u914d\u7f6e\u603b\u662f\u4e0d\u90a3\u4e48\u53cb\u597d\uff0c\u7279\u522b\u662f\u5728\u4f7f\u7528\u4e0a\u4e0d\u591f\u7b80\u5355"),"\u3002"),(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u4f5c\u4e3a\u5168\u6808\u5f00\u53d1\u6846\u67b6\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u5728\u8fc7\u53bb\u7248\u672c\u5e76\u6ca1\u6709\u63d0\u4f9b\u8db3\u4ee5\u6ee1\u8db3\u5f00\u53d1\u8005\u9700\u6c42\u7684\u65e5\u5fd7\u6a21\u5757"),"\uff0c\u8f6c\u800c\u63a8\u8350\u5927\u5bb6\u96c6\u6210\u7b2c\u4e09\u65b9\u7ec4\u4ef6\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"p"},"Serilog"),"\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u5bfc\u81f4\u540e\u7eed\u65e0\u6cd5\u5b9e\u73b0\u81ea\u5b9a\u4e49\u529f\u80fd\u548c\u4e5f\u589e\u52a0\u4e86\u4e0d\u5c11\u7ef4\u62a4\u6210\u672c\u3002")),(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("strong",{parentName:"p"},"\u8fd9\u4e00\u6b21\uff0c",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u4e0d\u518d\u59a5\u534f\uff0c\u5f7b\u5e95\u91cd\u6784\u4e86\u65e5\u5fd7\u6a21\u5757\uff0c\u5b9e\u73b0\u65e5\u5fd7\u529f\u80fd/\u9700\u6c42\u5b8c\u5168\u81ea\u4e3b\u53ef\u63a7\uff0c\u63d0\u4f9b\u7ed9\u5f00\u53d1\u8005\u51e0\u4e4e\u6240\u6709\u65e5\u5fd7\u529f\u80fd\u7684\u9700\u6c42\uff01")),(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u7684\u4f7f\u7528\u8005\u4eec\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u662f\u65f6\u5019\u201c\u66f4\u6362\u201d\u6389\u7b2c\u4e09\u65b9\u65e5\u5fd7\u7ec4\u4ef6\uff0c\u8ba9\u6211\u4eec\u4e00\u8d77\u8fed\u4ee3\u51fa\u66f4\u5f3a\u66f4\u597d\u7684\u65e5\u5fd7\u7ec4\u4ef6\u5427\uff01")," \ud83c\udf56")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u65e5\u5fd7\u6a21\u5757\uff0c\u5185\u7f6e\u5199\u5165\u63a7\u5236\u53f0\u3001\u6587\u4ef6\u3001\u6570\u636e\u5e93\u529f\u80fd\uff0c\u518d\u4e5f\u65e0\u9700\u5f15\u5165\u7b2c\u4e09\u65b9\u65e5\u5fd7\u4e86\uff01",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/tree/net6/framework/Furion/Logging"},"\u65e5\u5fd7\u6e90\u7801")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},"\u5f3a\u5927\u7684\u8c03\u8bd5\u65e5\u5fd7 ",(0,r.kt)("inlineCode",{parentName:"strong"},"[LoggingMonitor]")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/commit/32dfc11fd6b47551a81c09e676eb7f5d018ef737"},"32dfc1"))))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("strong",{parentName:"li"},"\u65e5\u5fd7\u6a21\u5757\uff0c\u5185\u7f6e\u5199\u5165\u63a7\u5236\u53f0\u3001\u6587\u4ef6\u3001\u6570\u636e\u5e93\u529f\u80fd\uff0c\u518d\u4e5f\u65e0\u9700\u5f15\u5165\u7b2c\u4e09\u65b9\u65e5\u5fd7\u4e86\uff01",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/tree/net6/framework/Furion/Logging"},"\u65e5\u5fd7\u6e90\u7801"))),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"TP.Wrapper")," \u89c4\u8303\u5316\u65e5\u5fd7\u6a21\u677f\u7b97\u6cd5\uff0c\u7531\u8fc7\u53bb\u7684 ",(0,r.kt)("inlineCode",{parentName:"strong"},"[\u5c5e\u6027]")," \u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},"##\u5c5e\u6027##"),"\uff0c\u89e3\u51b3 ",(0,r.kt)("inlineCode",{parentName:"strong"},"JSON")," \u5185\u5bb9\u51b2\u7a81\u95ee\u9898 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/commit/394ecec28629aee9945480155d502418d0b7a8f8"},"394ecec"))),(0,r.kt)("li",{parentName:"ul"},"[\u516c\u544a]"," ",(0,r.kt)("strong",{parentName:"li"},"\u672a\u6765 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion.Extras.Logging.Serilog")," \u62d3\u5c55\u5c06\u4e0d\u518d\u7ee7\u7eed\u7ef4\u62a4\uff0c\u56e0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u6709\u5f3a\u5927\u7684\u65e5\u5fd7\u7ec4\u4ef6\u4e86\uff01")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u8131\u654f\u6a21\u5757\u6a21\u578b\u7ed1\u5b9a\u4e2a\u522b\u60c5\u51b5\u4e0b\u7a7a\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5IM5C"},"#I5IM5C")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u65e5\u5fd7\u6587\u6863\u3001\u9759\u6001\u7c7b\u6587\u6863\u3001\u6570\u636e\u6821\u9a8c\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u6781\u6613\u4f7f\u7528\u4e14\u5f3a\u5927\u7684\u65e5\u5fd7\u6a21\u5757"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u5199\u5165\u6587\u4ef6\nservices.AddFileLogging("logs/application.log");\n\n// \u5199\u5165\u6570\u636e\u5e93\nservices.AddDatabaseLogging();\n')),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"/furion/docs/logging"},"\u67e5\u770b\u66f4\u591a\u65e5\u5fd7\u6587\u6863"))),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u5f3a\u5927\u7684 ",(0,r.kt)("inlineCode",{parentName:"strong"},"[LoggingMonitor]")," \u8c03\u8bd5\u65e5\u5fd7"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,7}",showLineNumbers:!0,"{1,7}":!0},"using Furion.Logging;\n\nnamespace Furion.Application;\n\npublic class TestLoggerServices : IDynamicApiController\n{\n [LoggingMonitor]\n public PersonDto GetPerson(int id)\n {\n return new PersonDto\n {\n Id = id\n };\n }\n}\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u652f\u6301\u63a7\u5236\u5668\u3001\u64cd\u4f5c\u6216\u5168\u5c40\u6ce8\u518c\u62e6\u622a"),"\u3002"),(0,r.kt)("p",null,"\u8f93\u51fa\u65e5\u5fd7\u4e3a\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},'\u250f\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Logging Monitor \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 Furion.Application.TestLoggerServices.GetPerson (Furion.Application)\n\u2523\n\u2523 \u63a7\u5236\u5668\u540d\u79f0\uff1a TestLoggerServices\n\u2523 \u64cd\u4f5c\u540d\u79f0\uff1a GetPerson\n\u2523 \u8def\u7531\u4fe1\u606f\uff1a [area]: ; [controller]: test-logger; [action]: person\n\u2523 \u8bf7\u6c42\u5730\u5740\uff1a https://localhost:44316/api/test-logger/person/11\n\u2523 \u6765\u6e90\u5730\u5740\uff1a https://localhost:44316/api/index.html\n\u2523 \u6d4f\u89c8\u5668\u6807\u8bc6\uff1a Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62\n\u2523 \u5ba2\u6237\u7aef IP \u5730\u5740\uff1a 0.0.0.1\n\u2523 \u670d\u52a1\u7aef IP \u5730\u5740\uff1a 0.0.0.1\n\u2523 \u670d\u52a1\u7aef\u8fd0\u884c\u73af\u5883\uff1a Development\n\u2523 \u6267\u884c\u8017\u65f6\uff1a 31ms\n\u2523 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 \u6388\u6743\u4fe1\u606f \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 JWT Token\uff1a Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjEsIkFjY291bnQiOiJhZG1pbiIsImlhdCI6MTY1ODcxNjc5NywibmJmIjoxNjU4NzE2Nzk3LCJleHAiOjE2NTg3MTc5OTcsImlzcyI6ImRvdG5ldGNoaW5hIiwiYXVkIjoicG93ZXJieSBGdXJpb24ifQ.VYZkwwqCwlUy3aJjuL-og62I0rkxNQ96kSjEm3VgXtg\n\u2523\n\u2523 UserId (integer)\uff1a 1\n\u2523 Account (string)\uff1a admin\n\u2523 iat (integer)\uff1a 1658716797\n\u2523 nbf (integer)\uff1a 1658716797\n\u2523 exp (integer)\uff1a 1658717997\n\u2523 iss (string)\uff1a dotnetchina\n\u2523 aud (string)\uff1a powerby Furion\n\u2523 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 \u53c2\u6570\u5217\u8868 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 Content-Type\uff1a\n\u2523\n\u2523 id (Int32)\uff1a 11\n\u2523 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 \u8fd4\u56de\u4fe1\u606f \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 \u7c7b\u578b\uff1a Furion.Application.Persons.PersonDto\n\u2523 \u8fd4\u56de\u503c\uff1a {"Id":11,"Name":null,"Age":0,"Address":null,"PhoneNumber":null,"QQ":null,"CreatedTime":"0001-01-01T00:00:00+00:00","Childrens":null,"Posts":null}\n\u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Logging Monitor \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n')),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v389\u5df2\u53d1\u5e03"},"v3.8.9\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c4\u8303\u5316\u7ed3\u679c ",(0,r.kt)("inlineCode",{parentName:"li"},"ExceptionMetadata")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationMetadata")," \u90fd\u53ef\u4ee5\u83b7\u53d6 ",(0,r.kt)("inlineCode",{parentName:"li"},"ErrorCode")," \u5c5e\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5GJ6D"},"#I5GJ6D")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationMetadata")," \u7c7b ",(0,r.kt)("inlineCode",{parentName:"li"},"StatusCode")," \u5c5e\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5HB5L"},"#I5HB5L")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u5bf9 ",(0,r.kt)("inlineCode",{parentName:"li"},"Url")," \u662f\u5426\u7f16\u7801\u8bbe\u7f6e\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"[Get(WithEncodeUrl = false)]")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"WithEncodeUrl(false)")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5GOBC"},"#I5GOBC")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u66f4\u5f3a\u5927\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWTEncryption.SecurityReadJwtToken('token')")," \u8bfb\u53d6\u89e3\u6790 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u9759\u6001\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/574eeb601294378e68c3d57ceaf6cb17f36636e3"},"574eeb6")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValiationTypes.Html")," \u9a8c\u8bc1 ",(0,r.kt)("inlineCode",{parentName:"li"},"Html")," \u6807\u7b7e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5HBKC"},"#I5HBKC")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("a",{parentName:"strong",href:"https://github.com/efcore/EFCore.NamingConventions"},"EFCore.NamingConventions")," \u652f\u6301\uff0c\u53ef\u81ea\u5b9a\u4e49\u751f\u6210\u8868\u540d\uff0c\u5b57\u6bb5\u540d\u98ce\u683c\uff0c\u6bd4\u5982\u5c0f\u9a7c\u5cf0\uff0c\u86c7\u5f62\u547d\u540d\u7b49 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I5HBEI"},"#I5HBEI"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"INamedServiceProvider")," \u547d\u540d\u670d\u52a1\u63d0\u4f9b\u5668\uff0c\u53ef\u89e3\u6790\u63a5\u53e3\u591a\u5b9e\u73b0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5HF98"},"#I5HF98")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8131\u654f\u5904\u7406\u6a21\u5757\u65b9\u6cd5\u53c2\u6570\u5355\u4e2a\u503c\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a22ec3cc3565582eea67052936e788ede8c633cb"},"a22ec3c")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8131\u654f\u8bcd\u5e93\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"|")," \u5206\u5272\u8bcd\u8bed ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/3106b1d78b27b24f4141f052bf804a201a268ff7"},"3106b1d")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," \u6240\u6709 ",(0,r.kt)("inlineCode",{parentName:"li"},".NET")," \u4f9d\u8d56\u5305\u81f3 ",(0,r.kt)("inlineCode",{parentName:"li"},"6.0.7")," \u7248\u672c"),(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serilog.AspNetCore")," \u5305\u81f3 ",(0,r.kt)("inlineCode",{parentName:"li"},"6.0.0")," \u7248\u672c"),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT")," ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u5237\u65b0\u903b\u8f91 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5GXML"},"#I5GXML")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/574eeb601294378e68c3d57ceaf6cb17f36636e3"},"574eeb6")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"ExceptionMetadata")," \u547d\u540d\u7a7a\u95f4\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion.FriendlyException"))," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/3105d168db10bfbe6e83fff2e435ba5d9ef62ed5"},"3105d16")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Retry.Invoke(Func...)")," \u4e3a\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Retry.InvokeAsync(Func...)")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/3b7899942bb37423c2c4ed313069fe361aabf682"},"3b78999")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u8131\u654f\u5904\u7406\u6a21\u5757\uff0c\u5927\u5927\u63d0\u9ad8\u6027\u80fd\u548c\u51c6\u786e\u7387\uff0c\u540c\u65f6\u652f\u6301\u65b9\u6cd5\u53c2\u6570\u5355\u4e2a\u503c\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a22ec3cc3565582eea67052936e788ede8c633cb"},"a22ec3c")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Rider")," \u5f00\u53d1\u5de5\u5177\u5bf9\u540c\u540d\u811a\u624b\u67b6 (",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar"),") \u53ea\u663e\u793a\u4e00\u4e2a\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/518"},"!518")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"UnitOfWork")," \u5de5\u4f5c\u5355\u5143\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u4e2d\u5931\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5H0T3"},"#I5H0T3")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT")," \u4e2d ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u5982\u679c\u5b58\u5728\u6570\u7ec4\u7c7b\u578b\u7684\u503c\u65f6\uff0c\u5237\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u540e\u4e22\u5931\u4e86\u5386\u53f2\u503c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5GXML"},"#I5GXML")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"WithEncodeUrl")," \u65e0\u6cd5\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"[HttpMethod]")," \u8bbe\u7f6e\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/574eeb601294378e68c3d57ceaf6cb17f36636e3"},"574eeb6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u6a21\u5f0f\u4e0b\u6dfb\u52a0\u81ea\u5b9a\u4e49\u914d\u7f6e\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u65e0\u6cd5\u83b7\u53d6\u81ea\u5b9a\u4e49\u914d\u7f6e\u6587\u4ef6\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5GZ0F"},"#I5GZ0F")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Bah")," \u8fdb\u5165\u5168\u5c40\u5f02\u5e38\u62e6\u622a\u5668\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5H47S"},"#I5H47S")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AddDbPool/AddDb")," \u6269\u5c55\u672a\u6839\u636e\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Key")," \u8def\u5f84\u8bfb\u53d6\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5H6S4"},"#I5H6S4")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/520"},"!520")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValiationTypes.Url")," \u6b63\u5219\u8868\u8fbe\u5f0f\u8986\u76d6\u4e0d\u5168\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5HBKC"},"#I5HBKC")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"v3.5.x")," \u7248\u672c\u5bfc\u81f4\u96c6\u6210 ",(0,r.kt)("a",{parentName:"strong",href:"https://github.com/efcore/EFCore.NamingConventions"},"EFCore.NamingConventions")," \u5931\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I5HBEI"},"#I5HBEI"))),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u957f\u8def\u7531\u4e0d\u652f\u6301\u95ee\u9898\u4ee5\u53ca ",(0,r.kt)("inlineCode",{parentName:"li"},"[Required]")," \u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"AllowEmptyStrings")," \u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/c0143300329b5a96a2fbd4d92de109f520674d33"},"c014330")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u4e0a\u4f20\u6587\u4ef6\u65f6\u8bf7\u6c42\u62a5\u6587 ",(0,r.kt)("inlineCode",{parentName:"li"},"boundary")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Content-Disposition")," \u8bbe\u7f6e\u4e0d\u6b63\u786e\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5HEF0"},"#I5HEF0")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8131\u654f\u6a21\u5757\u66ff\u6362\u654f\u611f\u8bcd\u6c47\u51fa\u73b0\u591a\u66ff\u6362\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a22ec3cc3565582eea67052936e788ede8c633cb"},"a22ec3c")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u591a\u8bed\u8a00\u9ed8\u8ba4\u5904\u7406\u903b\u8f91\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u5141\u8bb8\u4e0d\u914d\u7f6e\u4efb\u4f55\u8bed\u8a00"),"\uff0c\u8fc7\u53bb\u7248\u672c\u4f1a\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5GRD9"},"#I5GRD9")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/5077c5dab9ee94733817f55ff8224b853d0001a3"},"5077c5d")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u89c4\u8303\u5316\u6587\u6863 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u6027\u80fd"),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u8c03\u6574 ",(0,r.kt)("inlineCode",{parentName:"li"},"MongoDB")," \u4ed3\u50a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"TDocument")," \u6cdb\u578b\u7ea6\u675f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/3f49055b6b80ef7861f58b0c6feabf5c87a32010"},"3f49055")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863\uff0c\u65e5\u5fd7\u8bb0\u5f55\u6587\u6863\u3001\u591a\u6570\u636e\u5e93\u6587\u6863\u3001PM2 \u90e8\u7f72\u6587\u6863\u3001Visual Studio \u9ad8\u6548\u7387\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v3711\u5df2\u53d1\u5e03"},"v3.7.11\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Minimal API")," \u5e94\u7528\u652f\u6301\uff1a",(0,r.kt)("inlineCode",{parentName:"strong"},".AddInjectMini()")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I4KOQ5"},"#I4KOQ5"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8de8\u57df ",(0,r.kt)("inlineCode",{parentName:"li"},"WithExposedHeaders")," \u9ed8\u8ba4\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"access-token")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"x-access-token")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/42ebdfd33a01353a0b3a801528de052990d2e4c9"},"42ebdfd")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u811a\u624b\u67b6\u9ed8\u8ba4\u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"app.UseHttpLogging()")," ",(0,r.kt)("inlineCode",{parentName:"li"},"HTTP")," \u65e5\u5fd7 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/42ebdfd33a01353a0b3a801528de052990d2e4c9"},"42ebdfd")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u548c ",(0,r.kt)("inlineCode",{parentName:"strong"},"ASP.NET Core")," \u5b8c\u6574 ",(0,r.kt)("inlineCode",{parentName:"strong"},"json")," \u914d\u7f6e\u7684 ",(0,r.kt)("inlineCode",{parentName:"strong"},"JSON Schema")," \u67b6\u6784 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"},"JSON Schema"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u4ee3\u7406\u652f\u6301\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/1d7fb5b5330c5a30098056818a93a0879034fecd"},"1d7fb5b")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u4ee3\u7406\u652f\u6301\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"ValueTuple")," \u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/876a2f5f7e2d07fa3bbc3f5b99c0653893e0ada8"},"876a2f5")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7ec4\u4ef6\u5316\u8bbe\u8ba1\u6a21\u5757\uff0c\u652f\u6301\u6bd4 ",(0,r.kt)("inlineCode",{parentName:"li"},"AppStartup")," \u66f4\u7075\u6d3b\u4fbf\u6377\u7684\u8bbe\u8ba1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/tree/net6/framework/Furion/Components"},"#components")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u72ec\u7acb\u5de5\u4f5c\u5355\u5143\u6a21\u5757\uff0c\u652f\u6301\u4efb\u4f55\u7b2c\u4e09\u65b9 ",(0,r.kt)("inlineCode",{parentName:"li"},"ORM")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a02413d6887d258ad3a1ba972bb6a08d29291d0c"},"a02413d")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8de8\u57df ",(0,r.kt)("inlineCode",{parentName:"li"},"FixedClientToken")," \u914d\u7f6e\u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/bd016386681631a5539bcf215c068c2069bba15f"},"bd01638")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"throw Oops.Bah")," \u53ef\u4ee5\u624b\u52a8\u89e6\u53d1\u89c4\u8303\u5316\u9a8c\u8bc1\u5931\u8d25\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/83f0036a4ce10c6b1cfc4a258dc61e197af38879"},"83f0036")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"FriendlyExceptionSettings")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ThrowBah")," \u914d\u7f6e\uff0c\u53ef\u6807\u8bb0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Oh")," \u4e0d\u8fdb\u5165\u5f02\u5e38\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/76ffa7f18d3683ad36e37e5fc90cf54a4b04e520"},"76ffa7f")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Minimal API")," \u5e94\u7528\u652f\u6301\uff1a",(0,r.kt)("inlineCode",{parentName:"strong"},".AddInjectMini()")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I4KOQ5"},"#I4KOQ5"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u548c ",(0,r.kt)("inlineCode",{parentName:"strong"},"ASP.NET Core")," \u5b8c\u6574 ",(0,r.kt)("inlineCode",{parentName:"strong"},"json")," \u914d\u7f6e\u7684 ",(0,r.kt)("inlineCode",{parentName:"strong"},"JSON Schema")," \u67b6\u6784 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"},"JSON Schema"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7ec4\u4ef6\u5316\u8bbe\u8ba1\u6a21\u5757\uff0c\u652f\u6301\u6bd4 ",(0,r.kt)("inlineCode",{parentName:"li"},"AppStartup")," \u66f4\u7075\u6d3b\u4fbf\u6377\u7684\u8bbe\u8ba1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/tree/net6/framework/Furion/Components"},"#components")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u72ec\u7acb\u5de5\u4f5c\u5355\u5143\u5355\u5143\u6a21\u5757\uff0c\u652f\u6301\u4efb\u4f55\u7b2c\u4e09\u65b9 ",(0,r.kt)("inlineCode",{parentName:"li"},"ORM")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a02413d6887d258ad3a1ba972bb6a08d29291d0c"},"a02413d")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DataValidationFilter")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"FriendlyExceptionFilter"),"\uff0c\u89e3\u51b3\u4e0d\u652f\u6301\u624b\u52a8\u629b\u51fa\u4e1a\u52a1\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/83f0036a4ce10c6b1cfc4a258dc61e197af38879"},"83f0036")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},".AddDb<>")," \u548c ",(0,r.kt)("inlineCode",{parentName:"strong"},".AddDbPool<>")," \u81ea\u5b9a\u4e49\u59d4\u6258\u53c2\u6570\u7b7e\u540d\uff0c\u7531 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Action")," \u6539\u4e3a\uff1a",(0,r.kt)("inlineCode",{parentName:"strong"},"Action")))))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5}",showLineNumbers:!0,"{2,5}":!0},"// \u7531\uff1a\noptions.AddDbPool(DbProvider.MySql, opt => {\n});\n// \u6539\u4e3a\noptions.AddDbPool(DbProvider.MySql, (services, opt)=> {\n})\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea ",(0,r.kt)("inlineCode",{parentName:"li"},"v3.6.3")," \u7248\u672c\u4f9d\u8d56\uff0c\u6267\u884c\u539f\u751f ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u6dfb\u52a0\u4e86\u53c2\u6570\u6821\u9a8c\u5bfc\u81f4\u5b58\u50a8\u8fc7\u7a0b\u6267\u884c\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5ERMQ"},"#I5ERMQ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"tools/cli.ps1")," \u811a\u672c\u5de5\u5177\u51fa\u73b0\u6570\u636e\u5e93\u94fe\u63a5\u88ab\u5360\u7528\u95ee\u9898"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWTSettings")," \u7b97\u6cd5\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON Schema")," \u9519\u8bef\u95ee\u9898\uff0c\u611f\u8c22 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/gitwentao"},"@gitwentao")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5G27B"},"#I5G27B")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/516"},"!516")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u57fa\u4e8e\u7b56\u7565\u6388\u6743\u5728\u4e0d\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Policy")," \u7684\u60c5\u51b5\u4e0b\u51fa\u73b0\u7a7a\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5EVF2"},"#I5EVF2")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u542f\u7528\u6570\u636e\u5e93\u5b9e\u4f53\u8ddf\u8e2a\u65f6\u5bfc\u81f4\u65b0\u589e\u5b9e\u4f53\u591a\u6b21\u67e5\u8be2\u6570\u636e\u5e93\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4J2LZ"},"#I4J2LZ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e0d\u542f\u7528\u89c4\u8303\u5316\u7ed3\u679c\u5bfc\u81f4\u9a8c\u8bc1\u5931\u6548\uff0c\u5f02\u5e38\u5931\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/cdb3f570ab72cff0a5327a717f85c48e153211be"},"cdb3f57")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u9a8c\u8bc1\u5f02\u5e38\u548c\u53cb\u597d\u5f02\u5e38\u51b2\u7a81\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/83f0036a4ce10c6b1cfc4a258dc61e197af38879"},"83f0036")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"CentOS 7.9")," \u7cfb\u7edf\u90e8\u7f72\u65e0\u6cd5\u6307\u5b9a\u547d\u4ee4 ",(0,r.kt)("inlineCode",{parentName:"li"},"--urls")," \u53c2\u6570\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/8cc8eeff6b5b25de42367884b7c91d419557d054"},"8cc8ee")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u811a\u624b\u67b6\u6240\u6709 ",(0,r.kt)("inlineCode",{parentName:"li"},".json")," \u6587\u4ef6\uff0c\u9ed8\u8ba4\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON Schema")," \u652f\u6301"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7ec4\u4ef6\u5316\u542f\u52a8\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Vue/React/Angular")," \u8bf7\u6c42\u4ee3\u7406\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON Schema")," \u6587\u6863\uff0c\u652f\u6301\u914d\u7f6e\u667a\u80fd\u63d0\u793a\u548c\u9a8c\u8bc1"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u8de8\u57df\u6587\u6863\u3001\u89c4\u8303\u5316\u6587\u6863\u3001\u914d\u7f6e\u6587\u6863\u3001\u65e5\u5fd7\u6587\u6863\u3001IIS \u90e8\u7f72\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"strong"},"JSON Schema")," \u652f\u6301\uff0c\u6240\u6709 ",(0,r.kt)("inlineCode",{parentName:"strong"},".json")," \u6587\u4ef6\u652f\u6301\u667a\u80fd\u63d0\u793a\u548c\u9a8c\u8bc1"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},'{\n "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json",\n\n "Logging": {\n "LogLevel": {\n "Default": "Information",\n "Microsoft": "Warning",\n "Microsoft.Hosting.Lifetime": "Information",\n "Microsoft.EntityFrameworkCore": "Information"\n }\n },\n "AllowedHosts": "*"\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/js1.png")}),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"./jsonschema"},"\u67e5\u770b\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"a"},"JSON Schema")," \u6587\u6863"))),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u6839\u636e ",(0,r.kt)("inlineCode",{parentName:"strong"},"Swagger")," \u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Vue/React/Angular")," \u524d\u7aef\u8bf7\u6c42\u4ee3\u7801"))),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"./clientapi"},"\u67e5\u770b\u6587\u6863"))),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Sql")," \u4ee3\u7406\u652f\u6301\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7-9}",showLineNumbers:!0,"{7-9}":!0},'public interface ISql : ISqlDispatchProxy\n{\n // \u96c6\u5408\u7c7b\u578b\n [SqlExecute("select * from person")]\n List GetPersons();\n\n // \u81ea v3.7.3+ \u7248\u672c\u652f\u6301\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570\n [SqlExecute("select * from person where id=@id")]\n Person GetPerson(int id);\n}\n')),(0,r.kt)("ol",{start:4},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Sql")," \u4ee3\u7406\u652f\u6301\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"strong"},"ValueTuple")," \u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-6}",showLineNumbers:!0,"{3-6}":!0},'public interface ISql : ISqlDispatchProxy\n{\n [SqlExecute(@"\n select * from person where id =@id;\n select * from person")]\n (Person, List) GetData(int id); // \u6ce8\u610f\u8fd4\u56de\u503c\u662f `(Person, List)` \u7ec4\u5408\n}\n')),(0,r.kt)("ol",{start:5},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Minimal API")," \u5e94\u7528"))),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-6.0"},"\u4e86\u89e3 ",(0,r.kt)("inlineCode",{parentName:"a"},"Minimal API")," \u5e94\u7528"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3-4,10,12-15}",showLineNumbers:!0,"{1,3-4,10,12-15}":!0},'var builder = WebApplication.CreateBuilder(args).Inject();\n\n// \u6ce8\u518c Minimal \u670d\u52a1\nbuilder.Services.AddInjectMini();\n\nvar app = builder.Build();\n\napp.UseHttpsRedirection();\n\napp.UseInject(string.Empty);\n\napp.MapGet("/hello", () =>\n{\n return "Hello, Furion";\n});\n\napp.Run();\n')),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v369\u5df2\u53d1\u5e03"},"v3.6.9\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u6781\u7b80\u4e3b\u673a\u6a21\u5f0f\uff0c\u771f\u6b63\u5b9e\u73b0\u6781\u901f\u5165\u95e8\u3002",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/95cac5b391b70d73bfc94147ee40eef529b2eec6"},"95cac5b")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"TP.Wrapper(...)")," \u62d3\u5c55\u65b9\u6cd5\uff0c\u4e3b\u8981\u7528\u6765\u751f\u6210\u89c4\u8303\u5316\u7684\u65e5\u5fd7\u6a21\u677f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/427999aba4847522ea91c42df6164e5fe69c5bc0"},"427999a")),(0,r.kt)("li",{parentName:"ul"},"[\u652f\u6301]"," \u9879\u76ee\u7c7b\u578b\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},'')," \u7684\u63a7\u5236\u53f0\u9879\u76ee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/fb08a6548d49921aa143d01389a2592b92e94e31"},"fb08a65")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"BadPageResult")," \u9519\u8bef\u9875\u9762\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/494"},"!494")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[SchemaId]")," \u7279\u6027\uff0c\u89e3\u51b3\u4e0d\u540c\u7a0b\u5e8f\u96c6\u76f8\u540c\u7684\u7c7b\u540d\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"SchemaId")," \u51b2\u7a81\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5D3CU"},"#I5D3CU")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"options.ApproveAllCerts()")," \u5ffd\u7565\u6240\u6709\u5ba2\u6237\u7aef\u8bc1\u4e66\u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/eb7d18ac183894d604cec1d4c8527466ef9c648a"},"eb7d18a")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5224\u65ad\u662f\u5426\u662f\u5355\u6587\u4ef6\u73af\u5883\u90e8\u7f72\u9759\u6001\u5c5e\u6027 ",(0,r.kt)("inlineCode",{parentName:"li"},"App.SingleFileEnvironment")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/de556f0aaf87c41fe01cca2655f086890b2638a0"},"de556f0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"WebApplicationBuilder.UseSerilogDefault()")," \u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/e02524c8a15fd660b6359285ef07a697878e6678"},"e02524c")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u652f\u6301]"," \u9879\u76ee\u7c7b\u578b\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},'')," \u7684\u63a7\u5236\u53f0\u9879\u76ee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/fb08a6548d49921aa143d01389a2592b92e94e31"},"fb08a65")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u6781\u7b80\u4e3b\u673a\u6a21\u5f0f\uff0c\u771f\u6b63\u5b9e\u73b0\u6781\u901f\u5165\u95e8\u3002",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/95cac5b391b70d73bfc94147ee40eef529b2eec6"},"95cac5b")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u672a\u542f\u7528\u89c4\u8303\u5316\u7ed3\u679c\u65f6\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"MVC")," \u9a8c\u8bc1\u5931\u8d25\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"BadPageResult()")," \u9875\u9762\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/494"},"!494")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u9ed8\u8ba4\u6ce8\u518c\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddResponseCaching();")," \u670d\u52a1\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},".axd")," \u5185\u5d4c\u8d44\u6e90\u8bf7\u6c42\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/495"},"!495")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Oracle")," \u6570\u636e\u5e93\u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u5fc5\u987b\u8981\u6c42\u547d\u4ee4\u53c2\u6570\u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u8bed\u8a00\u53c2\u6570\u6570\u91cf\u4e00\u81f4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5D057"},"#I5D057")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IHostService")," \u7c7b\u578b\u4e0d\u80fd\u81ea\u52a8\u6ce8\u518c\u95ee\u9898\uff0c\u4e4b\u524d\u53ea\u626b\u63cf\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"BackgroundService")," \u6d3e\u751f\u7c7b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/968344aa07348f4c06f914abf7b6f46174633d81"},"968344")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u56fd\u4ea7\u82af\u7247\u4e3b\u673a\u4e0d\u80fd\u8bc6\u522b ",(0,r.kt)("inlineCode",{parentName:"li"},"dotnet run --urls")," \u53c2\u6570\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6d43983781e0c41228c4917a242141d011088bdb"},"6d4398")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u4e0a\u4f20\u6587\u4ef6\u4e0d\u652f\u6301\u7279\u5b9a\u6587\u4ef6\u540e\u7f00\u95ee\u9898\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"li"},".pem")," \u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/ba42198c1cd58612f2b383349c37068aac78cdd7"},"ba42198")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e00\u4e9b\u7a0b\u5e8f\u96c6\u5df2\u7834\u574f\u6216\u7a0b\u5e8f\u96c6\u4e0d\u5b8c\u6574\u5bfc\u81f4\u4e3b\u673a\u65e0\u6cd5\u542f\u52a8\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d2dc3e4d09e726699c38ebb8cb7b83de0e97f46f"},"d2dc3e4")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u4f20\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"headers")," \u65f6\u7c7b\u578b\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Dictionary")," \u5bfc\u81f4\u8f6c\u6362\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5DHL9"},"#I5DHL9")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serilog")," \u5355\u6587\u4ef6\u53d1\u5e03\u4e0d\u751f\u6210\u65e5\u5fd7\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5DQ2B"},"I5DQ2B")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u8fdc\u7a0b\u8bf7\u6c42\u9ed8\u8ba4\u5ba2\u6237\u7aef\u4e0d\u68c0\u67e5 ",(0,r.kt)("inlineCode",{parentName:"li"},"SSL")," \u8bc1\u4e66 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/eb7d18ac183894d604cec1d4c8527466ef9c648a"},"eb7d18a")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u5f00\u653e\u9a8c\u8bc1\u670d\u52a1\u9009\u9879 ",(0,r.kt)("inlineCode",{parentName:"li"},"SuppressModelStateInvalidFilter")," \u5c5e\u6027\u4e3a\u53ef\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/495"},"!494")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Serve.Run()")," \u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContext")," \u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"GlobalUsings")," \u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"TP")," \u5168\u5c40\u9759\u6001\u7c7b\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4e2d\u95f4\u4ef6\u6587\u6863\u3001\u7b5b\u9009\u5668\u6587\u6863\u3001\u5ba1\u8ba1\u65e5\u5fd7\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u8de8\u57df\u6587\u6863\u3001\u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7cbe\u5f69\u8d21\u732e")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/494"},"!494")," \u4f18\u79c0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Pull Request")," \u8fa9\u8bba\u5178\u8303"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u6781\u901f\u5165\u95e8"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="Program.cs" {3,6}',showLineNumbers:!0,title:'"Program.cs"',"{3,6}":!0},'Serve.Run();\n\n[DynamicApiController]\npublic class HelloService\n{\n public string Say()\n {\n return "Hello, Furion";\n }\n}\n')),(0,r.kt)("p",null,"\u542f\u52a8\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\uff0c\u60ca\u5446\u4e86\u5417\uff01"),(0,r.kt)("img",{src:(0,l.Z)("img/07.png")}),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u5185\u7f6e\u9519\u8bef\u9875"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers{1,7}","showLineNumbers{1,7}":!0},"using Furion.FriendlyException;\n\npublic IActionResult Add(Person person)\n{\n if(!ModelState.IsValid)\n {\n return new BadPageResult();\n }\n}\n")),(0,r.kt)("img",{src:(0,l.Z)("img/er1.png")}),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Swagger")," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Markdown")))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4-62}",showLineNumbers:!0,"{4-62}":!0},'/// \n/// \u6d4b\u8bd5 Markdown\n/// \n/// \n/// # \u6d4b\u8bd5 `Markdown` \u6ce8\u91ca\n///\n/// ![](https://localhost:44316/images/logo.png)\n///\n/// ```cs\n/// Serve.Run();\n///\n/// [DynamicApiController\n/// public class HelloService\n/// {\n/// public string Say()\n/// {\n/// return nameof(Furion);\n/// }\n/// }\n/// ```\n///\n/// \u529f\u80fd\u8fd8\u4e0d\u9519\uff01\uff01\uff01\n///\n/// | \u5546\u54c1 | \u4ef7\u683c | # \u5176\u4ed6 |\n/// |--------------|-----------|------------|\n/// | Juicy Apples | 1.99 | *7* |\n/// | Bananas | **1.89** | 5234 |\n/// | Bananas | **1.89** | 5234 |\n/// | Bananas | **1.89** | 5234 |\n///\n/// -----\n///\n/// # Furion \u63a2\u7d22\u7248\n///\n/// > \u5728\u8fc7\u53bb\u4e00\u5e74\uff0c\u5b9e\u73b0 `Furion` \u4ece\u65e0\u5230\u6709\uff0c\u7f16\u5199\u6587\u6863\u5df2\u903e\u767e\u4e07\u5b57\uff0c\u8fc7\u7a0b\u5fc3\u9178\u5f00\u6e90\u4eba\u81ea\u77e5\u3002\n/// >\n/// > \u8fd9\u4e00\u8def\u65e5\u591c\u517c\u7a0b\uff0c\u5632\u8bbd\u6279\u8bc4\u5e38\u4f34\u773c\u8033\uff0c\u5373\u4fbf\u8f9b\u82e6\u65e0\u5948\u3001\u60f3\u8fc7\u653e\u5f03\uff0c\u4f46\u4e3a\u4e86\u90a3\u5fae\u4e0d\u8db3\u9053\u7684\u5b58\u5728\u611f\u4f9d\u7136\u52aa\u529b\u7740\u3002\n/// >\n/// > \u5f53\u7136\uff0c\u4e5f\u6536\u83b7\u4e86\u4e0d\u5c11...\u8d8a\u6765\u8d8a\u591a\u62e5\u8db8\u8005\uff0c\u8d8a\u53d1\u7cbe\u6e5b\u6280\u672f\u80fd\u529b\uff0c\u66f4\u9ad8\u5c42\u6b21\u601d\u7ef4\u6a21\u5f0f\uff0c\u8fd8\u6709\u8bb8\u591a\u8de8\u754c\u8de8\u884c\u670b\u53cb\u3002\n/// >\n/// > \u5728 \u300a[\u5f00\u6e90\u6307\u5317] (https://gitee.com/opensource-guide/comments/)\u300b\u4e2d\uff0c\u6211\u66fe\u8bf4\u9053\uff1a\u201c\u5f00\u6e90\u5982\u540c\u4eba\u7684\u8138\uff0c\u597d\u574f\u4e00\u9762\u4fbf\u77e5\uff0c\u7f3a\u70b9\u53ef\u80fd\u4f1a\u53d7\u5230\u5632\u8bbd\u6279\u8bc4\uff0c\u4f18\u70b9\u4e5f\u4f1a\u6536\u83b7\u8d5e\u626c\u5c0a\u91cd\u3002\u522b\u62c5\u5fc3\uff0c\u4ed6\u4eec\u6b63\u5728\u5851\u9020\u66f4\u597d\u7684\u4f60\u3002\u201d\n/// >\n/// > \u6240\u4ee5\uff0c\u8fd9\u4e00\u6b21\u91cd\u65b0\u8d77\u822a\uff0c\u91cd\u5851 `Furion` \u91cd\u5851\u81ea\u5df1\u3002\u4e5f\u8bb8\u672a\u6765\u5728\u67d0\u4e2a IT \u5708\u4f46\u51e1\u6709\u4eba\u8c08\u8d77 `.NET` \u8fd8\u80fd\u779f\u5230 `Furion` \u7684\u8eab\u5f71\u3002\n///\n/// ---\n///\n/// \ud83c\udf89 \u63a2\u7d22 Furion \u672a\u6765\u66f4\u591a\u53ef\u80fd\u6027\uff0c\u5b9e\u73b0\u65e0\u7b2c\u4e09\u65b9\u4f9d\u8d56\u7684\u7248\u672c\uff0c\u6240\u6709\u6a21\u5757\u529f\u80fd\u6309\u9700\u5b89\u88c5\uff0c\u6309\u9700\u52a0\u8f7d\u3002\n///\n/// - \u4f5c\u8005\uff1a[\u767e\u5c0f\u50e7] (https://gitee.com/monksoul)\n/// - \u65e5\u671f\uff1a2021 \u5e74 08 \u6708 30 \u65e5\n///\n/// ## \u73af\u5883\n///\n/// - IDE \uff1a[Microsoft Visual Studio Enterprise 2022 Preview(64 \u4f4d) \u7248\u672c 17.0.0 Preview 3.1] (https://visualstudio.microsoft.com/zh-hans/vs/preview/)\n/// - SDK \uff1a[.NET SDK 6] (https://dotnet.microsoft.com/download/dotnet/6.0)\n/// - \u8bed\u8a00\uff1a[C# 10](https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-10)\n///\n/// ## \u5305\u8bf4\u660e\n///\n/// - `Furion.Core`\uff1a\u65e0\u7b2c\u4e09\u65b9\u4f9d\u8d56\uff0c\u53ef\u5728 `.NET 6` \u6240\u6709\u9879\u76ee\u7c7b\u578b\u4e2d\u8fd0\u884c\u3002\n/// - `Furion`\uff1a\u5185\u90e8\u4f9d\u8d56 `Furion.Core` \u4e14\u65e0\u7b2c\u4e09\u65b9\u4f9d\u8d56\uff0c**\u805a\u7126 `Web` \u5e94\u7528**\uff0c\u91c7\u7528\u5171\u4eab\u6846\u67b6 `` \u6a21\u5f0f\n/// \npublic void MarkdownTest()\n{\n // ....\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/mdx2.png")}),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v357\u5df2\u53d1\u5e03"},"v3.5.7\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Options")," \u9009\u9879\u5c5e\u6027\u652f\u6301\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},"Key")," \u540d\u79f0\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},'[MapSettings("key")]')," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5B2HN"},"#I5B2HN")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EventBus")," \u6a21\u5757\u4e8b\u4ef6 ",(0,r.kt)("inlineCode",{parentName:"li"},"Id")," \u652f\u6301\u679a\u4e3e\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/2f328aa8213c8efe7a8480116985573cc6b7fce6"},"2f328aa")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EventBus")," \u6a21\u5757\u53d1\u5e03\u8005 ",(0,r.kt)("inlineCode",{parentName:"li"},"PublishAsync")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"PublishDelayAsync")," \u91cd\u8f7d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/2f328aa8213c8efe7a8480116985573cc6b7fce6"},"2f328aa")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EventBus")," \u6a21\u5757\u62d3\u5c55\u65b9\u6cd5\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Enum.ParseToString()")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"String.ParseToEnum()")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/2f328aa8213c8efe7a8480116985573cc6b7fce6"},"2f328aa")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u548c ",(0,r.kt)("inlineCode",{parentName:"strong"},"SqlSugar")," \u811a\u624b\u67b6")," \ud83c\udd95\ud83c\udd95\ud83c\udd95 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/8d9293d1188670626f017ccea4ffb85ac315d2fc"},"8d9293d")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Dapper")," \u62d3\u5c55\u5168\u5c40\u914d\u7f6e\u59d4\u6258 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I5AYFX"},"#I5AYFX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u8f6c\u5b9e\u4f53\u652f\u6301\u591a\u79cd\u547d\u540d\u7b56\u7565\uff08\u7eaf\u5927\u5199\uff0c\u7eaf\u5c0f\u5199\uff0c\u5e26\u4e0b\u5212\u7ebf\u5206\u5272\u7b49\u7b49\uff09\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oracle")," \u6570\u636e\u5e93 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a90e24516387e088b2c427e6b99d3dab937116c9"},"a90e245")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"FS.InitalContentTypeProvider()")," \u62d3\u5c55\u65b9\u6cd5\uff0c\u83b7\u53d6\u7cfb\u7edf\u5185\u6240\u6709\u652f\u6301\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Content-Type")," \u6587\u4ef6\u63d0\u4f9b\u5668 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6099900472d93dab7012f0b091b05c914be11c4a"},"6099900")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u89e3\u51b3]"," \u5f7b\u5e95\u89e3\u51b3\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u4e0d\u80fd\u5355\u6587\u4ef6\u53d1\u5e03\u7684\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/7e8e0b708bcdac670aa835dec5cd494d41ff3648"},"7e8e0b7")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6846\u67b6\u89c4\u8303\u5316\u6587\u6863 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Controller")," \u6d3e\u751f\u7c7b ",(0,r.kt)("inlineCode",{parentName:"li"},"api")," \u8def\u7531\u95ee\u9898\uff0c\u539f\u751f ",(0,r.kt)("inlineCode",{parentName:"li"},"ASP.NET")," \u662f\u652f\u6301\u7684 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/29e47bce3678767c4793ad254777704ab9dd7e03"},"29e47bc")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u57fa\u4e8e ",(0,r.kt)("inlineCode",{parentName:"li"},"Schema")," \u591a\u79df\u6237\u914d\u7f6e\u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6f820ce0f28dd27a6e265b969b5b4095de676106"},"6f820ce")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6307\u5b9a\u5b9e\u4f53 ",(0,r.kt)("inlineCode",{parentName:"li"},'[Table(schema:"dbo")]')," \u7279\u6027\u540e ",(0,r.kt)("inlineCode",{parentName:"li"},"Schema")," \u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6f820ce0f28dd27a6e265b969b5b4095de676106"},"6f820ce")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u89c6\u56fe\u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Schema")," \u914d\u7f6e\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6f820ce0f28dd27a6e265b969b5b4095de676106"},"6f820ce")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c4\u8303\u5316\u7ed3\u679c\u6781\u7aef\u60c5\u51b5\u4e0b\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"\u7a7a\u5f02\u5e38")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/c9b0ef09427418e2ccb88d3a4c02e7a29d9d510e"},"c9b0ef")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"axios-utils.ts")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"angular-utils.ts")," \uff0c\u65b0\u589e\u8bf7\u6c42\u62e6\u622a\u643a\u5e26\u5237\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u7684\u65f6\u673a\u5224\u65ad ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/82f89bd95573aefa7075676af7f00c55507cb03b"},"82f89bd")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u89c4\u8303\u5316\u6587\u6863 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u52a0\u8f7d\u7ee7\u627f\u6ce8\u91ca ",(0,r.kt)("inlineCode",{parentName:"li"},"")," \u6027\u80fd\u5c0f\u4f18\u5316 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/5f06880564ee8cd2e77caa5957ff18a0c489bdd2"},"5f06880")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u811a\u624b\u67b6\u6a21\u677f\uff0c\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"GlobalUsings.cs")," \u6a21\u5f0f"),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u5bf9\u8c61\u6620\u5c04\u9ed8\u8ba4\u652f\u6301\u5ffd\u7565\u5927\u5c0f\u5199 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/486"},"!486")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u5355\u6587\u4ef6\u53d1\u5e03\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion + SqlSugar")," \u811a\u624b\u67b6\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u4e8b\u4ef6\u603b\u7ebf\u6587\u6863\u3001\u9009\u9879\u6587\u6863\u3001\u5373\u65f6\u901a\u8baf\u6587\u6863\u3001",(0,r.kt)("inlineCode",{parentName:"li"},".NET5")," \u5347\u7ea7 ",(0,r.kt)("inlineCode",{parentName:"li"},".NET6")," \u6587\u6863\u3001\u4f9d\u8d56\u6ce8\u5165\u6587\u6863\u3001\u8de8\u57df\u6587\u6863\u3001\u6570\u636e\u52a0\u89e3\u5bc6\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u4e8b\u4ef6\u603b\u7ebf ",(0,r.kt)("inlineCode",{parentName:"strong"},"Id")," \u652f\u6301\u679a\u4e3e\u7c7b\u578b"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10}",showLineNumbers:!0,"{7,10}":!0},'EventSubscribe("TO:DO")] // \u5b57\u7b26\u4e32\u7c7b\u578b\npublic async Task EventHandler1(EventHandlerExecutingContext context)\n{\n // ....\n}\n\n[EventSubscribe(YourEnum.Some)] // \u679a\u4e3e\u7c7b\u578b\npublic async Task EventHandler2(EventHandlerExecutingContext context)\n{\n var eventEnum = context.Source.EventId.ParseToEnum(); // \u5c06\u4e8b\u4ef6 Id \u8f6c\u6362\u6210\u679a\u4e3e\u5bf9\u8c61\n // ....\n}\n')),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u4e8b\u4ef6\u603b\u7ebf\u53d1\u5e03\u652f\u6301\u66f4\u7b80\u5355\u8c03\u7528"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,6}",showLineNumbers:!0,"{5,6}":!0},'// \u65e7\u7248\u672c\nawait _eventPublisher.PublishAsync(new ChannelEventSource("ToDo:Create", name));\n\n// \u65b0\u7248\u672c\nawait _eventPublisher.PublishAsync("ToDo:Create", name);\nawait _eventPublisher.PublishAsync(YourEnum.Some); // \u4e5f\u652f\u6301\u679a\u4e3e\n')),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u9009\u9879\u652f\u6301\u5c5e\u6027\u81ea\u5b9a\u4e49\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"strong"},"Key")))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {4}",showLineNumbers:!0,"{4}":!0},'"AppInfo": {\n "Name": "Furion",\n "Version": "1.0.0",\n "Company_Name": "Baiqian" // \u53ef\u4ee5\u548c\u5c5e\u6027\u4e0d\u4e00\u6837\n}\n')),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,7}",showLineNumbers:!0,"{6,7}":!0},'public class AppInfoOptions : IConfigurableOptions\n{\n public string Name { get; set; }\n public string Version { get; set; }\n\n [MapSettings("Company_Name")] // \u652f\u6301\u81ea\u5b9a\u4e49\n public string Company { get; set; }\n}\n')),(0,r.kt)("ol",{start:4},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u65e5\u5fd7\u89c4\u8303\u5316\u6a21\u677f"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},'// \u751f\u6210\u6a21\u677f\u5b57\u7b26\u4e32\nvar template = TP.Wrapper("Furion \u6846\u67b6", "\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",\n "[\u4f5c\u8005] \u767e\u5c0f\u50e7",\n "[\u5f53\u524d\u7248\u672c] v3.5.3",\n "[\u6587\u6863\u5730\u5740] https://furion.icu",\n "[Copyright] \u767e\u5c0f\u50e7, Baiqian Co.,Ltd.");\nConsole.WriteLine(template);\n')),(0,r.kt)("p",null,"\u8f93\u51fa\u7ed3\u679c"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"\u250f\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Furion \u6846\u67b6 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 \u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002\n\u2523\n\u2523 \u4f5c\u8005\uff1a \u767e\u5c0f\u50e7\n\u2523 \u5f53\u524d\u7248\u672c\uff1a v3.5.3\n\u2523 \u6587\u6863\u5730\u5740\uff1a https://furion.icu\n\u2523 Copyright\uff1a \u767e\u5c0f\u50e7, Baiqian Co.,Ltd.\n\u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Furion \u6846\u67b6 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n")),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v342\u5df2\u53d1\u5e03"},"v3.4.2\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c4\u8303\u5316\u6587\u4ef6 ",(0,r.kt)("inlineCode",{parentName:"li"},"EnableAllGroups")," \u529f\u80fd\uff0c\u53ef\u4ee5\u5c06\u591a\u4e2a\u5206\u7ec4\u5408\u5e76\u5230\u4e00\u4e2a\u5206\u7ec4\u4e2d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/9277b982ce024bac8ab5117ba02c3bd96ad07972"},"9277b98")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"angular-utils")," \u5ba2\u6237\u7aef\u5de5\u5177\u5e93\uff0c\u4e13\u95e8\u5904\u7406 ",(0,r.kt)("inlineCode",{parentName:"li"},"angular")," \u9879\u76ee\u63a5\u53e3\u4ee3\u7406\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6c705848a77fbf7234070d0ef9f053a85cc8838a"},"6c70584")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u652f\u6301\u5355\u4e2a\u63a5\u53e3\u66f4\u591a\u63cf\u8ff0\u529f\u80fd\uff08\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"html"),"\uff09",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/e5e1db09710dab02966330063935bd5e5b7e4dc8"},"e5e1db0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u63a5\u53e3 ",(0,r.kt)("inlineCode",{parentName:"li"},"[Obsolete]")," \u8fc7\u65f6\u652f\u6301\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/e5e1db09710dab02966330063935bd5e5b7e4dc8"},"e5e1db0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001 ",(0,r.kt)("inlineCode",{parentName:"li"},"API")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"[ApiDescriptionSettings]")," \u7279\u6027 \u548c",(0,r.kt)("inlineCode",{parentName:"li"},"DynamicApiControllerSettings")," \u914d\u7f6e \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ForceWithRoutePrefix")," \u53c2\u6570\uff0c\u652f\u6301\u5f3a\u5236\u590d\u5199 ",(0,r.kt)("inlineCode",{parentName:"li"},"[Route]")," \u7279\u6027\u5e76\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"DefaultRoutePrefix")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I59B74"},"#I59B74")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5185\u7f6e]"," \u9ed8\u8ba4\u5185\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"GBK"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"Windows-1252"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"Shift-JIS"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"GB2312")," \u7b49\u7f16\u7801\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/c456ecb225b099e5d24add32024f16c359414532"},"c456ecb")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u811a\u624b\u67b6"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"")," \u4e0d\u80fd\u8de8\u7a0b\u5e8f\u96c6\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/3b9d39ce691f9505c5541a790103fbb0ba6d35af"},"3b9d39c")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"")," \u4e0d\u652f\u6301\u5e26\u53c2\u6570\uff0c\u4e0d\u652f\u6301\u9690\u5f0f\u5b9e\u73b0\u63a5\u53e3\u6ce8\u91ca\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I59A6W#note_10699021_link"},"#I59A6W#note_10699021")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"v3.3.1")," \u7248\u672c\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e0d\u80fd\u663e\u793a\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/676335264478d68b99db009d32b65de781702605"},"6763352")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"JSON"),"\u4ee5\u53ca ",(0,r.kt)("inlineCode",{parentName:"li"},"Web")," \u9875\u9762\u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"GBK"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"GB2312")," \u7b49\u56fd\u6807\u7f16\u7801\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/c456ecb225b099e5d24add32024f16c359414532"},"c456ecb")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u54cd\u5e94\u62a5\u6587\u8bbe\u7f6e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"Content-Type:charset=")," \u4e0d\u80fd\u81ea\u52a8\u8f6c\u6362\u7f16\u7801\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/c456ecb225b099e5d24add32024f16c359414532"},"c456ecb")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"axios-utils.ts")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"angular-utils.ts")," \u591a\u5ba2\u6237\u7aef\u652f\u6301"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"GlobalUsings")," \u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://dotnetchina.gitee.io/furion/blog/global-usings"},"\u6587\u6863\u5730\u5740")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8bf7\u6c42\u5927\u5c0f/\u4e0a\u4f20\u5927\u5c0f\u9650\u5236\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://dotnetchina.gitee.io/furion/docs/file-provider/#317-%E8%AF%B7%E6%B1%82%E5%A4%A7%E5%B0%8F%E6%8E%A7%E5%88%B6%E4%B8%8A%E4%BC%A0%E6%96%87%E4%BB%B6%E5%A4%A7%E5%B0%8F%E6%8E%A7%E5%88%B6"},"\u6587\u6863\u5730\u5740")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u89c4\u8303\u5316\u6587\u6863\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u6587\u6863\uff0c\u52a8\u6001 API \u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"strong"},"All Groups")," \u5206\u7ec4\u529f\u80fd"))),(0,r.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u4e3a\u4e86\u66f4\u597d\u7684\u5bf9\u63a5\u53e3\u8fdb\u884c\u5f52\u7c7b\uff0c\u914d\u7f6e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u591a\u4e2a\u5206\u7ec4\u7684\u529f\u80fd\uff0c\u4f46\u8fd9\u6837\u4e5f\u5bf9\u751f\u6210\u5ba2\u6237\u7aef\u8bf7\u6c42\u4ee3\u7801\u9020\u6210\u4e86\u56f0\u6270\uff0c\u6240\u4ee5\u6dfb\u52a0\u4e86\u65b0\u7684\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-3}",showLineNumbers:!0,"{2-3}":!0},'{\n "SpecificationDocumentSettings": {\n "EnableAllGroups": true\n }\n}\n')),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u63a5\u53e3\u8fc7\u65f6\u63a7\u5236"))),(0,r.kt)("p",null,"\u5f53\u6211\u4eec\u67d0\u4e2a\u63a5\u53e3\u5df2\u7ecf\u8fc7\u65f6\uff0c\u63d0\u793a\u5c3d\u65e9\u8c03\u7528\u6700\u65b0\u63a5\u53e3\uff0c\u53ea\u9700\u8981\u5728\u65b9\u6cd5\u4e0a\u9762\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[Obsolete]")," \u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,7}",showLineNumbers:!0,"{1,7}":!0},'[Obsolete("GetName() \u5df2\u7ecf\u8fc7\u65f6\uff0c\u8bf7\u8c03\u7528 GetFrameworkName() \u66ff\u4ee3")]\npublic string GetName()\n{\n return nameof(Furion);\n}\n\n[Obsolete]\npublic string Other()\n{\n // ...\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/swg2.png")}),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"\u5355\u4e00\u63a5\u53e3\u66f4\u591a\u63cf\u8ff0"))),(0,r.kt)("p",null,"\u5728\u8be5\u7248\u672c\u65b0\u589e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"[ApiDescriptionSettings]")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Description")," \u5c5e\u6027\uff0c\u652f\u6301\u5b9a\u4e49\u66f4\u591a\u63cf\u8ff0\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},'[ApiDescriptionSettings(Description = "\u6211\u662f\u4e00\u6bb5\u63cf\u8ff0\uff0c\u663e\u793a\u66f4\u591a\u5185\u5bb9 ")]\npublic string add()\n{\n //....\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/swg1.png")}),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v333\u5df2\u53d1\u5e03"},"v3.3.3\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u6587\u4ef6\u4e0a\u4f20\u81ea\u52a8\u8bc6\u522b ",(0,r.kt)("inlineCode",{parentName:"li"},"Content-Type")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Mime")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I57ZMN"},"#I57ZMN")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u65b9\u6cd5\u652f\u6301\u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Content-Type")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Encoding")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I57ZMN"},"#I57ZMN")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6839\u636e\u6587\u4ef6\u540d\u83b7\u53d6 ",(0,r.kt)("inlineCode",{parentName:"li"},"Content-Type")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Mime")," \u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/8f78184f8661830744592c054b65d503346c1b27"},"#8f78184")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c4\u8303\u5316\u6587\u6863\u652f\u6301\u6388\u6743\u8bbf\u95ee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/32aa3b6328d23a5885033837883c7b546e898d43"},"#32aa3b6")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4ee3\u7801\u6ce8\u91ca\uff0c\u89c4\u8303\u5316\u6587\u6863\u6ce8\u91ca ",(0,r.kt)("inlineCode",{parentName:"li"},"inheritdoc")," \u8bed\u6cd5\u652f\u6301 \u2764\ufe0f\ufe0f\ufe0f\ufe0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I59A6W"},"#159A6W")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"Vue2/3"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"React 16.8+"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"Angular 9+")," \u524d\u7aef\u8bf7\u6c42\u5de5\u5177\u5e93\uff0c\u5b9e\u73b0\u540e\u7aef API \u4ee3\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/tree/net6/clients/axios"},"axios-utils")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4ee3\u7801\u6ce8\u91ca\uff0c\u89c4\u8303\u5316\u6587\u6863\u6ce8\u91ca ",(0,r.kt)("inlineCode",{parentName:"li"},"inheritdoc")," \u8bed\u6cd5\u652f\u6301 \u2764\ufe0f\ufe0f\ufe0f\ufe0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I59A6W"},"#159A6W")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".NET")," \u6240\u6709\u4f9d\u8d56\u5305\u81f3 ",(0,r.kt)("inlineCode",{parentName:"li"},"v6.0.5")," \u7248\u672c"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u5b9a\u4e49\u5168\u5c40\u5f02\u5e38 ",(0,r.kt)("inlineCode",{parentName:"li"},"Exception")," \u540e\u5bfc\u81f4\u83b7\u53d6\u9519\u8bef\u884c\u53f7\uff0c\u6587\u4ef6\u7a7a\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I53EGM"},"#I53EGM")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4f20\u9012\u7a7a\u59d4\u6258\u5bfc\u81f4\u7a7a\u5f15\u7528\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I519AW"},"#I519AW")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b57\u7b26\u4e32\u6a21\u677f\u6a21\u677f ",(0,r.kt)("inlineCode",{parentName:"li"},"Render")," \u62d3\u5c55\u65b9\u6cd5\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"void")," \u95ee\u9898\uff0c\u5e94\u8be5\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"string")," ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/MonkSoul/Furion/issues/99#issuecomment-1073131906"},"Github-#99")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u6587\u4ef6\u4e0a\u4f20\u51fa\u73b0\u7a7a\u60c5\u51b5\u95ee\u9898\uff08\u539f\u56e0\u662f\u7f3a\u5931 ",(0,r.kt)("inlineCode",{parentName:"li"},"Content-Type")," \uff09",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I57ZMN"},"I57ZMN")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u6846\u67b6\u6e90\u7801\u5f15\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"GlobalUsings")," \u673a\u5236\uff0c\u51cf\u5c11\u4ee3\u7801\u4f53\u79ef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/7e9cc1c205750906cddd540ad08a4c02f14efa3a"},"#7e9cc1c")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u8de8\u57df\u8bf7\u6c42\u7684\u9884\u68c0\u8bbe\u7f6e\uff0c\u5982\u679c\u672a\u8bbe\u7f6e\uff0c\u5219\u9ed8\u8ba4\u4e3a 24 \u5c0f\u65f6\uff0c\u4e3b\u8981\u89e3\u51b3\u524d\u7aef\u591a\u6b21\u53d1\u9001 204 \u9884\u68c0\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4a11e7c9fa20b4419ac00f6ad21c078500d00791"},"4a11e7c")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u89c6\u56fe\u5f15\u64ce\u53cd\u5c04\u6027\u80fd"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7c98\u571f\u5bf9\u8c61\u5e8f\u5217\u5316 ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON")," \u914d\u7f6e\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u524d\u7aef\u89e3\u5bc6 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT")," \u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5c06 ",(0,r.kt)("inlineCode",{parentName:"li"},"byte[]")," \u8f6c ",(0,r.kt)("inlineCode",{parentName:"li"},"url")," \u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u4e8c\u7ea7\u865a\u62df\u76ee\u5f55\u90e8\u7f72\u6587\u6863\uff0c\u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863\uff0c\u6587\u4ef6\u4e0a\u4f20\u6587\u6863\uff0c\u5b89\u5168\u6388\u6743\u6587\u6863\u3001\u89c4\u8303\u5316\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"\u2764\ufe0f\ufe0f\ufe0f\ufe0f ",(0,r.kt)("strong",{parentName:"li"},"\u6839\u636e\u6587\u4ef6\u540d\u83b7\u53d6 ",(0,r.kt)("inlineCode",{parentName:"strong"},"MIME")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Content-Type")," \u7c7b\u578b"))))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var success = FS.TryGetContentType("image.png", out var contentType); // image/png\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u2764\ufe0f\ufe0f\ufe0f\ufe0f ",(0,r.kt)("strong",{parentName:"li"},"\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Swagger")," \u914d\u7f6e\u767b\u5f55\u540e\u624d\u80fd\u8bbf\u95ee"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-6}",showLineNumbers:!0,"{2-6}":!0},'{\n "SpecificationDocumentSettings": {\n "LoginInfo": {\n "Enabled": true,\n "CheckUrl": "\u68c0\u67e5\u767b\u5f55\u5730\u5740",\n "SubmitUrl": "\u63d0\u4ea4\u767b\u5f55\u5730\u5740"\n }\n }\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/swgdl.png")}),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"./specification-document#6529-%E5%B8%A6%E7%99%BB%E5%BD%95%E7%9A%84-swagger-%E6%96%87%E6%A1%A3"},"\u67e5\u770b\u8be6\u7ec6\u6587\u6863")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u2764\ufe0f\ufe0f\ufe0f\ufe0f ",(0,r.kt)("strong",{parentName:"li"},"\u652f\u6301\u4ee3\u7801\u6ce8\u91ca\u7ee7\u627f\uff0cSwagger \u6587\u6863\u6ce8\u91ca\u4e5f\u652f\u6301"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4,10}",showLineNumbers:!0,"{1,4,10}":!0},'/// \npublic class TestInheritdoc : ITestInheritdoc, IDynamicApiController\n{\n /// \n public string GetName()\n {\n return "Furion";\n }\n\n /// \n public string GetVersion()\n {\n return "3.3.3";\n }\n}\n\n/// \n/// \u6d4b\u8bd5\u6ce8\u91ca\u7ee7\u627f\n/// \npublic interface ITestInheritdoc\n{\n /// \n /// \u83b7\u53d6\u540d\u79f0\n /// \n /// \n string GetName();\n\n /// \n /// \u83b7\u53d6\u7248\u672c\n /// \n /// \n string GetVersion();\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/cdr22.png")}),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"./specification-document#6530-inheritdoc-%E5%AE%9E%E7%8E%B0%E6%B3%A8%E9%87%8A%E7%BB%A7%E6%89%BF"},"\u67e5\u770b\u8be6\u7ec6\u6587\u6863")),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v320\u5df2\u53d1\u5e03"},"v3.2.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IFormFile")," \u62d3\u5c55\u65b9\u6cd5 ",(0,r.kt)("inlineCode",{parentName:"li"},"ToByteArray()")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/da69640da2331e2c8582b88bbda965c5ad7ecbe0"},"da69640")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c4\u8303\u5316\u6587\u6863 ",(0,r.kt)("inlineCode",{parentName:"li"},"ServeDir")," \u865a\u62df\u76ee\u5f55\u914d\u7f6e\u529f\u80fd\uff0c\u652f\u6301\u4e00\u952e\u5c06\u4e00\u7ea7\u76ee\u5f55\u5207\u6362\u81f3\u4e8c\u7ea7\u76ee\u5f55\u90e8\u7f72\uff08IIS\uff09",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/87183921ac8b6f9856db01b4de679b858a58e753"},"8718392")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u6240\u6709\u4f9d\u8d56\u5305\u81f3\u6700\u65b0\u7248"),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u4f9d\u8d56\u6ce8\u5165\u6a21\u5757\u6838\u5fc3\u4ee3\u7801\uff0c\u79fb\u9664\u6ce8\u518c\u670d\u52a1\u91c7\u7528\u53cd\u5c04\u673a\u5236\uff0c\u51cf\u5c11\u53cd\u5c04\u6027\u80fd\u635f\u8017 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/acdb3157af92891610a1ba6d317b6af3f09e233f"},"acdb315")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"schema")," \u7c7b\u578b\u5982\u679c\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"C# Object")," \u7c7b\u578b\u65e0\u6cd5\u6b63\u786e\u751f\u6210\u524d\u7aef\u4ee3\u7801\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/swagger-api/swagger-codegen-generators/issues/692"},"Swagger \u5b98\u65b9 Issue")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/1a252747fd60fc87a8ed4425c8edf7803f96ce43"},"1a25274")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u53d1\u5e03\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"Windows Services")," \u65f6\u65e5\u5fd7\u7edd\u5bf9\u8def\u5f84\u95ee\u9898 \u611f\u8c22 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/jacoat"},"@jacoat")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/467"},"!467")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Nginx")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"IIS")," \u5bf9\u4e8c\u7ea7\u865a\u62df\u76ee\u5f55\u914d\u7f6e\u4e0d\u540c\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},"404")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/87183921ac8b6f9856db01b4de679b858a58e753"},"8718392")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u6a21\u5757\u672a\u521d\u59cb\u5316 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnRequestFailded")," \u5bfc\u81f4\u7a7a\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I54PK7"},"#I54PK7")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4f9d\u8d56\u6ce8\u5165\u53cd\u5c04\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Not found Method")," bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I546L1"},"#I546L1")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u5b9a\u65f6\u4efb\u52a1\u5931\u8d25\u540e\u5f02\u5e38\u5904\u7406\u903b\u8f91\uff0c\u611f\u8c22 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/cxs1992"},"@\u7a0b\u5c0f\u80dc")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/463"},"!463")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u5b9a\u65f6\u4efb\u52a1\u6587\u6863\uff0c\u65e5\u5fd7\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6587\u4ef6\u4e0a\u4f20/\u4e0b\u8f7d \u6587\u6863\uff0c\u5305\u542b\u5355\u6587\u4ef6/\u591a\u6587\u4ef6/Base64/Byte[]")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v310\u5df2\u53d1\u5e03"},"v3.1.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u6a21\u5757\u5f02\u5e38 ",(0,r.kt)("inlineCode",{parentName:"li"},"Http")," \u72b6\u6001\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/462"},"!462")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001 WebAPI \u652f\u6301\u5c0f\u9a7c\u5cf0\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4W1R4"},"#I4W1R4")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"SendAsByteArrayAsync")," \u7b49\u4e00\u7cfb\u5217\u65b9\u6cd5\uff0c\u652f\u6301\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"byte[]")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/452"},"!452")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"GZip")," \u538b\u7f29\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I506S5"},"#I506S5")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".NET6")," \u4f9d\u8d56\u5305\u5168\u90e8\u5347\u7ea7\u81f3 ",(0,r.kt)("inlineCode",{parentName:"li"},"Nuget")," \u6700\u65b0\u7248 ",(0,r.kt)("inlineCode",{parentName:"li"},"v6.0.3")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".NET6 WebApplication")," \u6a21\u5f0f\u4e8c\u7ea7\u865a\u62df\u76ee\u5f55\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4UZLM"},"#I4UZLM")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4PZ0C"},"#I4PZ0C")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u65e5\u671f\u9a8c\u8bc1\u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"2022-03-01 0:00:00"),"\uff08\u73b0\u5728\u652f\u6301\u5c0f\u65f6\u57df ",(0,r.kt)("inlineCode",{parentName:"li"},"0")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"00"),"\uff09 \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4Y3NT"},"#I4Y3NT")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u73af\u5883\u914d\u7f6e\u548c\u6587\u4ef6\u914d\u7f6e\u4f18\u5148\u7ea7\u95ee\u9898"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8131\u654f\u6a21\u5757\u66ff\u6362\u654f\u611f\u8bcd\u6c47\u53ea\u66ff\u6362\u6700\u540e\u4e00\u4e2a bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4YFA0"},"#I4YFA0")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u8fd4\u56de\u5b57\u7b26\u4e32\u4e2a\u522b\u60c5\u51b5\u51fa\u73b0\u4e2d\u6587\u4e71\u7801\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I50GBD"},"#I50GBD")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[DataValidate]")," \u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"AllowNullValue")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"AllowEmptyString")," \u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4ZZBE"},"#I4ZZBE")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8fc7\u65f6]"," \u6807\u8bb0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.Logging.Serilog")," \u62d3\u5c55\u5305 ",(0,r.kt)("inlineCode",{parentName:"li"},"IWebHost")," \u62d3\u5c55\u4e3a\u8fc7\u65f6\u72b6\u6001"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6587\u6863]"," \u4f18\u5316\u6587\u6863\u4f53\u9a8c\uff0c\u65b0\u589e\u9762\u5305\u5c51\u5bfc\u822a\uff0c\u91cd\u5199\u6587\u6863\u7f13\u5b58\uff0c\u63d0\u5347\u6587\u6863\u8bbf\u95ee\u901f\u5ea6"),(0,r.kt)("li",{parentName:"ul"},"[\u6587\u6863]"," \u66f4\u65b0\u52a8\u6001 API \u6587\u6863\u3001\u914d\u7f6e\u6587\u6863\u3001\u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u6587\u6863]"," \u66f4\u65b0\u4e8c\u7ea7\u865a\u62df\u76ee\u5f55\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u672c\u671f\u4eae\u70b9")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"\u65b0\u589e\u52a8\u6001 ",(0,r.kt)("inlineCode",{parentName:"li"},"WebApi")," \u652f\u6301\u5c0f\u9a7c\u5cf0\u8def\u5f84\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"li"},"GetMyName")," -> ",(0,r.kt)("inlineCode",{parentName:"li"},"getMyName"),"\uff1a")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "DynamicApiControllerSettings": {\n "LowercaseRoute": false,\n "KeepName": true,\n "AsLowerCamelCase": true\n }\n}\n')),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},"\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},".NET6 WebApplication")," \u6a21\u5f0f\u4e8c\u7ea7\u865a\u62df\u76ee\u5f55\u914d\u7f6e\uff1a")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {title="Progame.cs"}',showLineNumbers:!0,"":!0,"{title":'"Progame.cs"}'},"app.UseVirtualPath(app =>\n{\n app.UseInject(String.Empty); // \u6ce8\u610f String.Empty \u53ea\u662f\u4f8b\u5b50\uff0c\u53ef\u4ee5\u4e0d\u586b\u6216\u586b\u5176\u4ed6\u7684\uff0c\u89c1\u4e00\u5206\u949f\u5165\u95e8\n app.MapRouteControllers();\n});\n")),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v300\u5df2\u53d1\u5e03"},"v3.0.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("admonition",{title:"v3+ \u7248\u672c\u8bf4\u660e",type:"warning"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("strong",{parentName:"p"},"Furion v3.x \u7248\u672c\u91c7\u7528 .NET6 \u6784\u5efa\u3002"))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"GET")," \u8bf7\u6c42\u81ea\u52a8\u8f6c\u6362 ",(0,r.kt)("inlineCode",{parentName:"li"},"\u7c7b\u7c7b\u578b")," \u7c7b\u578b\u5bf9\u8c61 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4HR5Q"},"#I4HR5Q")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," \u5168\u9762\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},".NET6")," \u7248\u672c"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5f00\u542f\u89c4\u8303\u5316\u7ed3\u679c\u5e76\u81ea\u5b9a\u4e49\u5168\u5c40\u5f02\u5e38\u5bfc\u81f4\u5f02\u5e38\u7ecf\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnSucceeded")," \u8fc7\u6ee4\u5668 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4DTVL"},"#I4DTVL")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".NET5.0.5+")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},".NET6")," \u5fae\u8f6f\u5e95\u5c42\u4fee\u6539\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"[ApiController]")," \u9a8c\u8bc1\u5931\u8d25\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"IActionResult")," \u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4ISOK"},"#I4ISOK")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore 6.0")," \u9002\u914d ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlServer 2005+")," \u51fa\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4ILA5"},"#I4ILA5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," .NET6 \u83b7\u53d6\u914d\u7f6e\u5bf9\u8c61\u5982\u679c\u4e0d\u5b58\u5728\u8fd4\u56de null \u95ee\u9898\uff0c.NET5 \u5219\u8fd4\u56de\u521d\u59cb\u5bf9\u8c61 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/94ae4d8c9b0fe7eb4d713a171f953c0d3c5a76ac"},"94ae4d")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u547d\u4ee4\u53c2\u6570\u4f20\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"Clay")," \u7c7b\u578b\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4D21Q"},"#I4D21Q")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Cron")," \u5b9a\u65f6\u4efb\u52a1\u7279\u6027\u65b9\u5f0f bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4OJQI"},"#I4OJQI")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ToPagedList")," \u6cdb\u578b\u7ea6\u675f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d0244dc33a0e5236158cdcdff21d086e00a42ee7"},"d0244d")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6587\u6863]"," \u67e5\u770b ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("a",{parentName:"strong",href:"https://dotnetchina.gitee.io/furion/docs/get-start-net6"},".NET6 \u4e00\u5206\u949f\u5165\u95e8"))),(0,r.kt)("li",{parentName:"ul"},"[\u6587\u6863]"," \u67e5\u770b ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("a",{parentName:"strong",href:"https://dotnetchina.gitee.io/furion/docs/net5-to-net6"},"Furion v2 \u5347\u7ea7 v3"))))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7279\u522b\u9e23\u8c22")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/KaneLeung"},"KaneLeung"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v220\u5df2\u53d1\u5e03"},"v2.20\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("admonition",{title:"v2.20+ \u7248\u672c\u8bf4\u660e",type:"warning"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("strong",{parentName:"p"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion v2.20+")," \u7248\u672c\u540e\u91c7\u7528 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Jaina"},"Jaina")," \u4e8b\u4ef6\u603b\u7ebf\u66ff\u6362\u539f\u6709\u7684 ",(0,r.kt)("inlineCode",{parentName:"strong"},"EventBus")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"GET")," \u8bf7\u6c42\u81ea\u52a8\u8f6c\u6362 ",(0,r.kt)("inlineCode",{parentName:"li"},"\u7c7b\u7c7b\u578b")," \u7c7b\u578b\u5bf9\u8c61 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4HR5Q"},"#I4HR5Q")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EventBus")," \u6a21\u5757\uff0c\u91c7\u7528 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Jaina"},"Jaina")," \u65b9\u5f0f"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5f00\u542f\u89c4\u8303\u5316\u7ed3\u679c\u5e76\u81ea\u5b9a\u4e49\u5168\u5c40\u5f02\u5e38\u5bfc\u81f4\u5f02\u5e38\u7ecf\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnSucceeded")," \u8fc7\u6ee4\u5668 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4DTVL"},"#I4DTVL")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".NET5.0.5+")," \u5fae\u8f6f\u5e95\u5c42\u4fee\u6539\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"[ApiController]")," \u9a8c\u8bc1\u5931\u8d25\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"IActionResult")," \u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4ISOK"},"#I4ISOK")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u4e0a\u4f20\u6587\u4ef6\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/0c0752c624799d7d3c7661a8f36a93983399bb59"},"0c0752")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6846\u67b6\u542f\u52a8\u4e0d\u652f\u6301\u73af\u5883\u53d8\u91cf ",(0,r.kt)("inlineCode",{parentName:"li"},"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES")," \u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/438"},"!438")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b9a\u65f6\u4efb\u52a1\u5185\u5b58\u548c CPU \u5360\u7528\u53ca\u7279\u6b8a\u60c5\u51b5\u4e0b\u7a7a\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/12c65debf552c57780679e6a567a9dd9fb077f46"},"12c65de")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u9ed8\u8ba4\u63a7\u5236\u5668\u542f\u7528\u89c4\u8303\u5316\u7ed3\u679c\u65e0\u6548 bug",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/c7a4a5ef8c3282d245cbe04124cf379d381d496f"},"c7a4a5e")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u6b63]"," \u4f9d\u8d56\u6ce8\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"InjectionAttribute")," \u7279\u6027\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ExceptInterfaces")," \u5355\u8bcd\u62fc\u5199\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/436"},"!436")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u547d\u4ee4\u53c2\u6570\u4f20\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"Clay")," \u7c7b\u578b\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4D21Q"},"#I4D21Q")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"InjectionAttribute")," \u4ee3\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/435"},"!435")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ToPagedList")," \u6cdb\u578b\u7ea6\u675f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d0244dc33a0e5236158cdcdff21d086e00a42ee7"},"d0244d")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4e8b\u4ef6\u603b\u7ebf\u65b0\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v219\u5df2\u53d1\u5e03"},"v2.19\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9a\u65f6\u4efb\u52a1\u76d1\u542c\u5668 ",(0,r.kt)("inlineCode",{parentName:"li"},"ISpareTimeListener")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I468Q1"},"#I468Q1")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"JsonElement")," \u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/61985d6a300485d553cbe8461b01f01bcd0936ef"},"61985d6")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u914d\u7f6e\u679a\u4e3e\u53ca\u6807\u7b7e\u6392\u5e8f\u8fc7\u6ee4\u5668 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I46LON"},"#I46LON")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/404"},"!404")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"application/octet-stream")," \u7c7b\u578b\u9ed8\u8ba4\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d9bad0320cc4a204e24bc3a070517ebce4cdc5d7"},"d9bad03")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u6a21\u5f0f\u8bf7\u6c42\u62a5\u6587\u5934\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"IDictionary")," \u7c7b\u578b\u3002",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/0204c0afe2de5c28ebbd44b29131e701b93ae8b8"},"0204c0a")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MongoDB")," \u62d3\u5c55\u7c7b\uff0c\u6dfb\u52a0\u66f4\u591a\u5e38\u7528\u64cd\u4f5c\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/423"},"!423")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTimeOffset?")," \u8f6c\u6362 ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTime")," \u62d3\u5c55\uff08\u5305\u542b\u4e92\u6362\uff09 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/432"},"!432")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped.Create")," \u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u8fdb\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"Add-Migration")," \u65f6\u5019\u62a5\u7a7a\u5f02\u5e38\u95ee\u9898\uff0c\u539f\u56e0\u662f\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"PM")," \u73af\u5883\u4e2d\u4e0d\u5b58\u5728\u6839\u670d\u52a1",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/0853e74de90718fce9c0892e2ee4da597f62a918"},"0853e74")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b9a\u65f6\u4efb\u52a1\u6267\u884c\u5f02\u5e38\u540e\u5f02\u5e38\u4e00\u76f4\u9a7b\u7559\u5185\u5b58\u95ee\u9898\uff0c\u4fee\u6b63\u4e3a\u6267\u884c\u6210\u529f\u81ea\u52a8\u6e05\u7a7a\u8fc7\u53bb\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/197a62bb4a7df34eb2c0dbda65121e9cf00d905c"},"197a62b")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Jwt")," \u62d3\u5c55\u5305\u4e0d\u6b63\u786e\u7684\u4ee3\u7801\u5bfc\u81f4 IOptions \u5931\u6548",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I46LUP"},"#I46LUP")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u679a\u4e3e ",(0,r.kt)("inlineCode",{parentName:"li"},"Schema")," \u8fc7\u6ee4\u5668\u4e0d\u8f93\u51fa\u503c\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I46LON"},"#I46LON")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/404"},"!404")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5904\u7406\u975e ",(0,r.kt)("inlineCode",{parentName:"li"},"int")," \u7c7b\u578b\u679a\u4e3e\u8f6c\u6362 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I46QJ9"},"#I46QJ9")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c6\u56fe\u5f15\u64ce\u7f16\u8bd1\u6a21\u677f\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"dll")," \u540e\u518d\u6b21\u52a0\u8f7d\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"IL")," \u683c\u5f0f\u5316\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/ff52d383718b4d34968619f17c9d54d8718b4f3f"},"ff52d38")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u7ba1\u9053 ",(0,r.kt)("inlineCode",{parentName:"li"},"Channel")," \u8bfb\u53d6\u5668\u65e0\u6cd5\u91ca\u653e ",(0,r.kt)("inlineCode",{parentName:"li"},"Handler")," \u5bf9\u8c61\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/10f4a900ee558a29f40ae21366a0eba83eceb3eb"},"10f4a90")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Services")," \u4e0b\u65e5\u5fd7\u4e0d\u8f93\u51fa\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/c48254822c09092906ef77f04d54497e27665a92"},"c482548")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"multipart/form-data")," \u7c7b\u578b\u5bf9\u63a5\u5fae\u4fe1\u5c0f\u7a0b\u5e8f\u4e0a\u4f20\u6587\u4ef6 \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d9bad0320cc4a204e24bc3a070517ebce4cdc5d7"},"d9bad03")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5de5\u4f5c\u5355\u5143\u4e0a\u4e0b\u6587\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\u5171\u4eab\u4e8b\u52a1\u5931\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/006d439de3357d4d58ea6d7d3f9d51771a7b604e"},"006d439")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u679a\u4e3e\u503c\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"GET")," \u8bf7\u6c42\u4e2d ",(0,r.kt)("inlineCode",{parentName:"li"},"Schema")," \u663e\u793a\u4e0d\u6b63\u786e\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/fb72fd7c98de5bf2246dd1bf08200152bd7ab7a0"},"fb72fd7")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"404")," \u4e0d\u8d70\u5f02\u5e38\u8fc7\u6ee4\u5668\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/423"},"!426")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u5b9a\u4e49\u4e8b\u4ef6\u603b\u7ebf\u5e76\u53d1\u60c5\u51b5\u4e0b\u8c03\u7528\u5b8c\u6210\u540e\u65e0\u6cd5\u6b63\u786e\u5904\u7406\u961f\u5217\u6570\u636e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/429"},"!429")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"v2.19+")," \u7248\u672c\u4e4b\u540e\u6a21\u5757\u5316\u5f00\u53d1\u52a0\u8f7d\u5916\u90e8\u7a0b\u5e8f\u96c6\u5931\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/433"},"!433")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b9a\u65f6\u4efb\u52a1 SpareTime \u9891\u7e41\u68c0\u67e5\u5bfc\u81f4 CPU \u589e\u9ad8\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/aa0a2eec95f6ed2b74c681877498900726267d82"},"aa0a2ee")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7279\u522b\u9e23\u8c22")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/YaChengMu"},"YaChengMu"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v218\u5df2\u53d1\u5e03"},"v2.18\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Tools.CommandLine")," \u62d3\u5c55\u5e93 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/tree/net6/tools/Furion.Tools/Furion.Tools.CommandLine"},"\u67e5\u770b\u6e90\u7801")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u57fa\u4e8e ",(0,r.kt)("inlineCode",{parentName:"li"},"AsyncLocal")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"CallContext")," \u5b9e\u73b0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/9057a212aab8057b668086bd14369fa68ce120df"},"9057a21")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u53ef\u914d\u7f6e\u8bf7\u6c42\u5f02\u5e38\u91cd\u8bd5\u7b56\u7565 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/656da87a667c2da7d82425cdcd47146e99602d65"},"656da87")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnRequestFailded")," \u4e8b\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4a3da4ba2c69380fe5f8c2fda80054544c0a3468"},"4a3da4b")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped")," \u6240\u6709\u5e26\u8fd4\u56de\u503c\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/656da87a667c2da7d82425cdcd47146e99602d65"},"656da87")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"strong"},"ConfigureService")," \u4e2d\u8c03\u7528 ",(0,r.kt)("inlineCode",{parentName:"strong"},"App.GetOptions<>()")," \u83b7\u53d6\u914d\u7f6e\u903b\u8f91")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/afa4ac347152ccac37bd1d0f9af1e8ffb665a662"},"afa4ac3"))))),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u5728\u8fc7\u53bb\uff0c\u5f88\u591a\u5f00\u53d1\u8005\u603b\u662f\u559c\u6b22\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u914d\u7f6e\u670d\u52a1\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"ConfigureService")," \u65b9\u6cd5\u4e2d\u89e3\u6790\u670d\u52a1\uff0c\u8fd9\u6837\u5bfc\u81f4\u5185\u5b58\u5b58\u5728\u6ea2\u51fa\u98ce\u9669\uff0cGC \u65e0\u6cd5\u56de\u6536\u3002\n\u6b63\u786e\u7684\u65b9\u5f0f\u662f\u5c3d\u53ef\u80fd\u7684\u907f\u514d ",(0,r.kt)("inlineCode",{parentName:"p"},"ConfigureService")," \u4e2d\u89e3\u6790\u670d\u52a1\u3002",(0,r.kt)("strong",{parentName:"p"},"\u5982\u679c\u9700\u8981\u5728\u3010\u542f\u52a8\u65f6\u3011\u83b7\u53d6 ",(0,r.kt)("inlineCode",{parentName:"strong"},"\u914d\u7f6e\u9009\u9879"),"\uff0c\u8bf7\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"strong"},"App.GetConfig(\u8def\u5f84, true)")," \u4ee3\u66ff ",(0,r.kt)("inlineCode",{parentName:"strong"},"App.GetOptions")),"\u3002")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," v2.16+ \u7248\u672c\u91cd\u6784 ",(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContextBuilder")," \u4e4b\u540e\u5199\u9519\u5b9e\u4f53\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I45E6M"},"#I45E6M")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u5355\u4e2a\u503c\u5e8f\u5217\u5316\u9519\u8bef\u5904\u7406\u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/3282eba2cecb505e339ef3f9c8e823f84dcb43f0"},"3282eba")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," v2.17.3+ \u5355\u5143\u6d4b\u8bd5\u521b\u5efa ",(0,r.kt)("inlineCode",{parentName:"li"},"TestServer")," bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I45JR3"},"#I45JR3")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Retry.Invoke")," \u6b63\u5e38\u65b9\u6cd5\u6b7b\u5faa\u73af bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/392"},"!392")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5237\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u751f\u6210\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u5b58\u5728\u6570\u7ec4/\u96c6\u5408\u7c7b\u578b\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Key")," \u91cd\u590d\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/aeea2b1b19434f3171bd1c77be057ca36ecf9be2"},"aeea2b1")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u5e8f\u5217\u5316\u5f15\u7528\u7c7b\u578b\u5bf9\u8c61\uff08\u4e0d\u542b ",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff09\u4e0d\u6b63\u786e\u7684\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/93cf63a023f3372b80edb5debc46271d2281318a"},"93cf63a")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u9ed8\u8ba4\u79df\u6237\u5c5e\u6027\u53d7\u5de5\u4f5c\u5355\u5143\u5f71\u54cd\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/e51557fdf37ae5646b2ea37c227c970eccdbed38"},"e51557f")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5305\u7ba1\u7406\u5de5\u5177\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u6a21\u677f\u5f15\u64ce\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587")," \u7b49\u7b49\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v217\u5df2\u53d1\u5e03"},"v2.17\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IPC\uff08Inter-Process Communication\uff0c\u8fdb\u7a0b\u95f4\u901a\u4fe1\uff09")," \u6a21\u5757\u529f\u80fd\uff0c\u76ee\u524d\u63d0\u4f9b\u8fdb\u7a0b\u5185\u901a\u4fe1\u548c\u5171\u4eab\u5185\u5b58\u8fdb\u7a0b\u5916\u901a\u8baf ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/tree/net6/framework/Furion/ProcessChannel"},"ProcessChannel")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"application/xml")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"text/xml")," \u9ed8\u8ba4\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4753a1aed527a6282fe6c05036de9d50bd3b3dd8"},"4753a1a")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u63a7\u5236\u53f0\u5168\u5c40\u5f02\u5e38\u62e6\u622a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4a4fe1f40e1856ea36a0c0d19ca625d3f7bf95b7"},"4a4fe1f")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},".json")," \u914d\u7f6e\u6587\u4ef6\u626b\u63cf\u76ee\u5f55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/3e2910a8b775fb6323e293b020bbe7cdfb4c6436"},"3e2910a")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301\u6570\u636e\u5e93\u5b9e\u4f53\u63a5\u53e3\u663e\u5f0f\u5b9e\u73b0\u63a5\u53e3\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/9610a0a481f4f78770bc2fc3ed4cabbef2a8f937"},"9610a0a")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u5168\u5c40\u62e6\u622a ",(0,r.kt)("inlineCode",{parentName:"li"},"[IfException]")," \u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4a4fe1f40e1856ea36a0c0d19ca625d3f7bf95b7"},"4a4fe1f")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4f9d\u8d56\u6ce8\u5165\u6a21\u5757\u63a5\u53e3\u53ef\u4ee5\u9650\u5236\u5b9e\u73b0\u7c7b\u751f\u5b58\u5468\u671f\uff0c\u5b9e\u73b0\u7c7b\u4e5f\u652f\u6301\u590d\u5199\u751f\u5b58\u5468\u671f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d2ce089130300cdd8b1bc6792f325c5d38ee9404"},"d2ce089")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u62bd\u79bb]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Retry()")," \u91cd\u8bd5\u7b56\u7565\u529f\u80fd\u81f3\u65b0\u7c7b\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Retry.Invoke()")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/6a7bbd0b30a653b9a42d340a63520485aa6bbfa4"},"6a7bbd0")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IHttpContextAccessor.SigninToSwagger()")," \u62d3\u5c55\uff0c\u8bf7\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"IHttpContextAccessor.HttpContext.SigninToSwagger()"),"\uff0c\u9000\u51fa\u4e5f\u4e00\u6837"),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u5168\u5c40\u5904\u7406 ",(0,r.kt)("inlineCode",{parentName:"li"},"Request Body")," \u91cd\u590d\u8bfb\u5904\u7406 ",(0,r.kt)("inlineCode",{parentName:"li"},"Request.EnableBuffering()")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/d92c24bdb43bfb01643007ebb6a4ee42a5c738e9"},"d92c24b")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c4\u8303\u5316\u72b6\u6001\u7801\u8fc7\u6ee4\u903b\u8f91\u9519\u8bef\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I44JYS"},"#I44JYS")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u975e\u5173\u7cfb\u578b\u6570\u636e\u5e93\uff08\u5185\u5b58\u6570\u636e\u5e93\uff09\u6ce8\u518c\u53ca\u64cd\u4f5c\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/e1676512a54374427bedbde17cd8cb59d7852557"},"e167651")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u9ed8\u8ba4\u5e8f\u5217\u5316\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a55603bf7ed109296375dbeffc31591a6f8f8e49"},"a55603b")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b9a\u65f6\u4efb\u52a1\u96f6\u70b9/\u6574\u70b9\u63d0\u524d\u4e00\u79d2\u89e6\u53d1\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4321L"},"#I4321L")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u53cb\u597d\u5f02\u5e38\u5728\u5b50\u7c7b\u91cd\u5199\u62bd\u8c61\u7c7b\u65b9\u6cd5\u5185\u90e8\u629b\u5f02\u5e38\u65e0\u6cd5\u83b7\u53d6\u7684\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4a4fe1f40e1856ea36a0c0d19ca625d3f7bf95b7"},"4a4fe1f")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u975e Web \u9879\u76ee\u629b\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/4a4fe1f40e1856ea36a0c0d19ca625d3f7bf95b7"},"4a4fe1f")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u5b9e\u4f53\u6a21\u578b\u8d34 ",(0,r.kt)("inlineCode",{parentName:"li"},"[NotMapper]")," \u7279\u6027\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I44MNO"},"#I44MNO")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," Swagger \u751f\u6210\u6cdb\u578b SchemaIds \u9ed8\u8ba4\u8fde\u63a5\u7b26\uff0c\u7531 ",(0,r.kt)("inlineCode",{parentName:"li"},"Of")," \u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"_")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/81946b64e81d9e290f80cd5bcebdb69c99001153"},"81946b6"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v216\u5df2\u53d1\u5e03"},"v2.16\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"MVC")," \u63a7\u5236\u5668\u652f\u6301\u89c4\u8303\u5316\u5904\u7406 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I427Z2"},"#I427Z2"))),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"throw Oops.Bah()")," \u629b\u51fa\u4e1a\u52a1\u5f02\u5e38\uff08\u72b6\u6001\u7801 ",(0,r.kt)("inlineCode",{parentName:"li"},"400"),"\uff09"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"UnifyResultSettings")," \u89c4\u8303\u5316 ",(0,r.kt)("inlineCode",{parentName:"li"},"json")," \u914d\u7f6e\u9009\u9879 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I42NY7"},"#I42NY7")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u591a\u8bed\u8a00\u81ea\u5b9a\u4e49\u914d\u7f6e\u8d44\u6e90\u6587\u4ef6\u540d\u53ca\u81ea\u5b9a\u4e49\u7a0b\u5e8f\u96c6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I434YJ"},"#I434YJ")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u89c4\u8303\u5316\u7ed3\u679c ",(0,r.kt)("inlineCode",{parentName:"li"},"IUnifyResultProvider")," \u53c2\u6570 ",(0,r.kt)("strong",{parentName:"li"},"\uff08\u7834\u574f\u6027\u66f4\u6539\uff09")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I427Z2"},"#I427Z2")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IJsonSerializerProvider")," \u63a5\u53e3\u53c2\u6570\uff0c\u53bb\u6389 ",(0,r.kt)("inlineCode",{parentName:"li"},"inherit")," \u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/a55603bf7ed109296375dbeffc31591a6f8f8e49"},"a55603b"))))),(0,r.kt)("admonition",{title:"\u65b0\u7248\u672c\u81ea\u5b9a\u4e49\u89c4\u8303\u5316\u7ed3\u679c",type:"important"},(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {15-16}",showLineNumbers:!0,"":!0,"{15-16}":!0},'using Furion.DataValidation;\nusing Furion.DependencyInjection;\nusing Furion.UnifyResult.Internal;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.Filters;\nusing System;\nusing System.Threading.Tasks;\n\nnamespace Furion.UnifyResult\n{\n /// \n /// RESTful \u98ce\u683c\u8fd4\u56de\u503c\n /// \n [SuppressSniffer, UnifyModel(typeof(RESTfulResult<>))]\n public class RESTfulResultProvider : IUnifyResultProvider\n {\n /// \n /// \u5f02\u5e38\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata)\n {\n return new JsonResult(RESTfulResult(metadata.StatusCode, errors: metadata.Errors));\n }\n\n /// \n /// \u6210\u529f\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n public IActionResult OnSucceeded(ActionExecutedContext context, object data)\n {\n return new JsonResult(RESTfulResult(StatusCodes.Status200OK, true, data));\n }\n\n /// \n /// \u9a8c\u8bc1\u5931\u8d25\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n public IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata)\n {\n return new JsonResult(RESTfulResult(StatusCodes.Status400BadRequest, errors: metadata.ValidationResult));\n }\n\n /// \n /// \u7279\u5b9a\u72b6\u6001\u7801\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n /// \n public async Task OnResponseStatusCodes(HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings)\n {\n // \u8bbe\u7f6e\u54cd\u5e94\u72b6\u6001\u7801\n UnifyContext.SetResponseStatusCodes(context, statusCode, unifyResultSettings);\n\n switch (statusCode)\n {\n // \u5904\u7406 401 \u72b6\u6001\u7801\n case StatusCodes.Status401Unauthorized:\n await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "401 Unauthorized")\n , App.GetOptions()?.JsonSerializerOptions);\n break;\n // \u5904\u7406 403 \u72b6\u6001\u7801\n case StatusCodes.Status403Forbidden:\n await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "403 Forbidden")\n , App.GetOptions()?.JsonSerializerOptions);\n break;\n default: break;\n }\n }\n\n /// \n /// \u8fd4\u56de RESTful \u98ce\u683c\u7ed3\u679c\u96c6\n /// \n /// \n /// \n /// \n /// \n /// \n private static RESTfulResult RESTfulResult(int statusCode, bool succeeded = default, object data = default, object errors = default)\n {\n return new RESTfulResult\n {\n StatusCode = statusCode,\n Succeeded = succeeded,\n Data = data,\n Errors = errors,\n Extras = UnifyContext.Take(),\n Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()\n };\n }\n }\n}\n'))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MVC")," \u63a7\u5236\u5668\u542f\u7528\u89c4\u8303\u5316\u5904\u7406\u540e\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"new Json({})")," \u5bf9\u8c61\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"null")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I4354S"},"#I4354S")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u591a\u8bed\u8a00\u5e95\u5c42\u8bbe\u8ba1\uff0c\u53d6\u6d88\u9700\u8981\u521b\u5efa ",(0,r.kt)("inlineCode",{parentName:"li"},"Lang.cs")," \u7a7a\u7c7b\u7684\u8981\u6c42 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I434YJ"},"#I434YJ")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MiniProfiler")," \u6027\u80fd\uff0c\u51cf\u5c11\u4e0d\u5fc5\u8981\u7684\u76d1\u542c")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v215\u5df2\u53d1\u5e03"},"v2.15\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetDbRepository<\u5b9a\u4f4d\u5668>()")," \u9759\u6001\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I41MZP"},"#I41MZP")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u7f3a\u7701\u5e8f\u5217\u5316\u914d\u7f6e\u9009\u9879 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I41PBW"},"#I41PBW")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u52a8\u626b\u63cf\u63a5\u53e3\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165\u83b7\u53d6\u9996\u4e2a\u63a5\u53e3\u9519\u8bef bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I41D1M"},"#I41D1M")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IRepository")," \u6ca1\u6709\u5b9e\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"IRepository")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I41MZP"},"#I41MZP")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u7f3a\u7701\u5e8f\u5217\u5316 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I41PBW"},"#I41PBW")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d ",(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext.Tenant")," \u591a\u79df\u6237\u7a7a\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I421DA"},"#I421DA")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u591a\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker")," \u5b9a\u65f6\u4efb\u52a1\u963b\u585e\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/82a79cce0a3d9b09f4090b7363c3b78327c76846"},"82a79cc")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Jwt")," \u81ea\u52a8\u5237\u65b0\u673a\u5236\u65f6\u533a\u5904\u7406\u95ee\u9898\uff0c\u4e3b\u8981\u9488\u5bf9\u56fd\u5916\u7528\u6237 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I41UB1"},"#I41UB1")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/82a79cce0a3d9b09f4090b7363c3b78327c76846"},"82a79cc")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("strong",{parentName:"li"},"\u7cfb\u7edf\u542f\u52a8\u6027\u80fd\uff0c\u4ece 106M \u51cf\u5c11\u5230 84M")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("strong",{parentName:"li"},"\u5927\u91cf\u5e95\u5c42\u4ee3\u7801\uff0c\u5305\u5927\u5c0f\u4ece 391Kb \u51cf\u5c11\u5230 350Kb\uff08\u4e0d\u5e26\u6ce8\u91ca\u7248\u672c\u4ec5 64Kb\uff09"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v213v214\u5df2\u53d1\u5e03"},"v2.13/v2.14\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7b80\u6613\u5b57\u7b26\u4e32\u6a21\u677f\u529f\u80fd\uff0c\u652f\u6301\u8fdc\u7a0b\u8bf7\u6c42\u3001\u6570\u636e\u5e93\u6a21\u5757\u3001\u65e5\u5fd7\u6a21\u5757\u3001\u4e8b\u4ef6\u603b\u7ebf\u6a21\u5757\u3001\u5b9a\u65f6\u4efb\u52a1\u6a21\u5757\u3001\u5f02\u5e38\u6a21\u5757\u3001\u6570\u636e\u6821\u9a8c\u6a21\u5757 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I402BL"},"#I402BL")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"404")," \u72b6\u6001\u7801\u89c4\u8303\u5316\u9ed8\u8ba4\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I408F5"},"#I408F5")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9a\u65f6\u4efb\u52a1 ",(0,r.kt)("inlineCode",{parentName:"li"},"ISpareTimeWorker")," \u58f0\u660e\u65b9\u5f0f\u652f\u6301\u5f02\u6b65\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I40KWR"},"#I40KWR")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u81ea\u52a8\u914d\u7f6e\u4e8c\u7ea7\u865a\u62df\u76ee\u5f55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/354"},"!354")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," ",(0,r.kt)("strong",{parentName:"li"},"\u6846\u67b6\u4f9d\u8d56 ",(0,r.kt)("inlineCode",{parentName:"strong"},"SDK")," \u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},".NET 5.0.8")," \u7248\u672c")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetNewDbContext()")," \u9759\u6001\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I400BK"},"#I400BK")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u6570\u636e\u5e93\u6a21\u5757\u65f6\u6001\u8868\u62d3\u5c55\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I405HI"},"#I405HI")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IJsonSerializerProvider")," \u63a5\u53e3\u53c2\u6570\uff0c\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"inherit")," \u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ZQU5"},"#I3ZQU5")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppSettings")," \u914d\u7f6e\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"LogEntityFrameworkCoreSqlExecuteCommand")," \u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"OutputOriginalSqlExecuteLog")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I40VVE"},"#I40VVE")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Services")," \u5b9a\u65f6\u4efb\u52a1\u8fb9\u754c\u503c\u95ee\u9898\u5bfc\u81f4\u8df3\u8fc7\u5355\u6b21\u4efb\u52a1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I405NI"},"#I405NI")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Services")," \u72ec\u7acb\u53d1\u5e03\u540e\u7a0b\u5e8f\u96c6\u626b\u63cf\u5931\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ZH3X"},"#I3ZH3X")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u5982\u679c\u914d\u7f6e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"Client")," \u5ba2\u6237\u7aef\u4f46\u4f20\u5165\u4e86\u7a7a ",(0,r.kt)("inlineCode",{parentName:"li"},"RequestUrl")," \u5730\u5740\u5bfc\u81f4\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I40BC6"},"#I40BC6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c4\u8303\u5316\u7ed3\u679c\u7be1\u6539\u975e\u77ed\u8def\u7aef\u72b6\u6001\u7801\u51fa\u73b0\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I408F5"},"#I408F5")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.GetServiceProvider(type)")," \u89e3\u6790\u670d\u52a1\u6027\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I40KXN"},"#I40KXN")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u89c6\u56fe\u5f15\u64ce\u4fdd\u5b58\u6210\u6587\u4ef6\u6d41\u9ed8\u8ba4\u7f13\u5b58\u533a\u5927\u5c0f\uff0c\u4ece ",(0,r.kt)("inlineCode",{parentName:"li"},"4096")," \u63d0\u5347\u81f3 ",(0,r.kt)("inlineCode",{parentName:"li"},"8192")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I40KH5"},"#I40KH5"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v210211212-\u5df2\u53d1\u5e03"},"v2.10/2.11/2.12 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u8be5\u7248\u672c\u6709\u591a\u4e2a\u7834\u574f\u6027\u66f4\u6539\uff0c\u66f4\u65b0\u65f6\u8bf7\u8ba4\u771f\u67e5\u770b\u3002")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.Configuration.Reload()")," \u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XYI8"},"#I3XYI8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ISubscribeHandler")," \u652f\u6301\u5f02\u6b65\u65b9\u6cd5\u5b9a\u4e49 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XYHJ"},"#I3XYHJ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"app.UseUnifyResultStatusCodes()")," \u53ef\u914d\u7f6e\u4fee\u6539\u8fd4\u56de\u72b6\u6001\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VZQH"},"#I3VZQH")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u6dfb\u52a0\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"User-Agent")," \u5934 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W17C"},"#I3W17C")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u9ad8\u7ea7\u4ee3\u7406\u5207\u6362\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XFP6"},"#I3XFP6")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XDCR"},"#I3XDCR")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9a\u65f6\u4efb\u52a1 ",(0,r.kt)("inlineCode",{parentName:"li"},"CronFormat")," \u81ea\u52a8\u8bc6\u522b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Y7GT"},"#I3Y7GT")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql \u9ad8\u7ea7\u4ee3\u7406")," \u62e6\u622a\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YHG4"},"#I3YHG4")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u62e6\u622a\u8fdc\u7a0b\u8bf7\u6c42\u6240\u6709\u5f02\u5e38\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YPDE"},"#I3YPDE")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Timeout")," \u8d85\u65f6\u65f6\u95f4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YPPK"},"#I3YPPK")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"RSA")," \u52a0\u5bc6\u7b97\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YZNU"},"#I3YZNU")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/345"},"!345")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DataTable")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"DataSet")," \u652f\u6301\u4e0d\u6307\u5b9a\u5f3a\u7c7b\u578b\u8fd4\u56de ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Z6RI"},"#I3Z6RI")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u6cd5\u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Timeout")," \u8d85\u65f6\u65f6\u95f4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ZKWF"},"#I3ZKWF")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u9ad8\u7ea7\u4ee3\u7406 ",(0,r.kt)("inlineCode",{parentName:"li"},"[Timeout]")," \u7279\u6027\uff0c\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ZKWF"},"#I3ZKWF")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"FakeDelete")," \u5047\u5220\u9664/\u8f6f\u5220\u9664\u6240\u6709\u529f\u80fd ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I3XKII"},"#I3XKII"))),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("strong",{parentName:"li"},"\u79fb\u9664 ",(0,r.kt)("inlineCode",{parentName:"strong"},"PBKDF2")," \u52a0\u5bc6\u7b97\u6cd5 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I3Z0IO"},"#I3Z0IO"))),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},"\u8fdc\u7a0b\u8bf7\u6c42\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4\u5355\u4f4d\u7531 ",(0,r.kt)("inlineCode",{parentName:"strong"},"\u5206\u949f")," \u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},"\u79d2")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I3YPPK"},"#I3YPPK"))),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"IJsonSerializerProvider")," \u63a5\u53e3\u53c2\u6570\uff0c\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"strong"},"inherit")," \u53c2\u6570 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I3ZQU5"},"#I3ZQU5"))),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[NonAutomatic]")," \u7279\u6027\u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"[Manual]")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XKKX"},"#I3XKKX")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[NotChangedListener]")," \u7279\u6027\u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"[SuppressChangedListener]")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XKLZ"},"#I3XKLZ")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[ManualSaveChanges]")," \u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"[ManualCommit]")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XKNP"},"#I3XKNP")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"DbContext.TenantIdQueryFilterExpression")," \u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},"DbContext.BuildTenantQueryFilter")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I3XKTB"},"#I3XKTB"))),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[SkipScan]")," \u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"[SuppressSniffer]")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XN5N"},"#I3XN5N")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[SkipProxy]")," \u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"[SuppressProxy]")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XN7O"},"#I3XN7O")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u6267\u884c\uff0c\u6027\u80fd\u63d0\u5347 20% ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W33U"},"#I3W33U")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u52a8\u6001 WebAPI \u626b\u63cf\u63a7\u5236\u5668\u6ca1\u6709\u5c4f\u853d\u6ca1\u6709\u6ce8\u518c\u7684\u7b2c\u4e09\u65b9\u63a7\u5236\u5668 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Y7TJ"},"#I3Y7TJ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"TablePrefix")," \u65e0\u6548\uff1a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Y57Q"},"#I3Y57Q")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u5b9a\u65f6\u4efb\u52a1\u4f7f\u7528\u5f02\u6b65\u59d4\u6258\u5bfc\u81f4\u7a0b\u5e8f\u7ec8\u6b62 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XVZ0"},"#I3XVZ0")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e8b\u4ef6\u603b\u7ebf\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"\u6d88\u606fid")," \u5bf9\u5e94\u591a\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"Handler")," \u53ea\u89e6\u53d1\u7b2c\u4e00\u4e2a",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XYP0"},"#I3XYP0")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".ToPagedList()")," \u5206\u9875\u65b9\u6cd5\u4f20\u5165\u5c0f\u4e8e\u6216\u7b49\u4e8e 0 \u7684\u9875\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XNAN"},"#I3XNAN")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON")," \u5e8f\u5217\u5316\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTimeOffset")," \u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XMOL"},"#I3XMOL")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"li"},"Serilog")," \u65e5\u5fd7\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u751f\u6210\u91cd\u590d\u65e5\u5fd7 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3WA0L"},"#I3WA0L")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/331"},"!331")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"\u7c98\u571f\u5bf9\u8c61")," \u52a8\u6001\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Clay")," \u7c7b\u578b bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W9LW"},"#I3W9LW")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationTypes.Numeric")," \u6821\u9a8c\u6570\u503c\u7c7b\u578b\u6b63\u5219\u8868\u8fbe\u5f0f\u9519\u8bef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3WADS"},"#I3WADS")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u547d\u4ee4\u53c2\u6570 ",(0,r.kt)("inlineCode",{parentName:"li"},"DbParameter")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Value")," \u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"object")," \u7c7b\u578b\u7684\u65f6\u5019\u4e14\u4e0d\u6307\u5b9a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YKM6"},"#I3YKM6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Oracle")," \u6570\u636e\u5e93\u5b58\u50a8\u8fc7\u7a0b ",(0,r.kt)("inlineCode",{parentName:"li"},"\u6e38\u6807\u53c2\u6570")," \u62a5\u9519\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ZBYE"},"#I3ZBYE")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Services")," \u91c7\u7528\u72ec\u7acb\u53d1\u5e03\u540e\u65e0\u6cd5\u6267\u884c\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ZH3X"},"#I3ZH3X")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u8fdc\u7a0b\u8bf7\u6c42\u5982\u679c\u65e0\u8fd4\u56de\u503c\u5e8f\u5217\u5316\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/348"},"!348")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u589e\u5f3a]"," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"appsettings.json")," \u7b49\u81ea\u5b9a\u4e49\u914d\u7f6e\u6587\u4ef6\u4e2d\u6587\u547d\u540d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YBFD"},"#I3YBFD")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u8fdc\u7a0b\u8bf7\u6c42\u914d\u7f6e\u547d\u540d\u5ba2\u6237\u7aef ",(0,r.kt)("inlineCode",{parentName:"li"},"BaseAddress")," \u5730\u5740\u517c\u5bb9\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YCRH"},"#I3YCRH")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u6846\u67b6\u65e0\u7528\u4ee3\u7801\u3001\u4f18\u5316\u4ee3\u7801"),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"\u975e Web")," \u73af\u5883\u4e0b\u6027\u80fd"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4f1a\u8bdd\u548c\u72b6\u6001\u7ba1\u7406 \u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YI3G"},"#I3YI3G")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u8fdc\u7a0b\u8bf7\u6c42\u3001\u65e5\u5fd7\u3001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3001\u8fdc\u7a0b\u8bf7\u6c42\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u9ad8\u7ea7\u4ee3\u7406\u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u914d\u7f6e\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Y2EV"},"#I3Y2EV")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"dapper")," \u591a\u4e2a\u6570\u636e\u6e90\u5982\u4f55\u7ee7\u627f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3WUOI"},"#I3WUOI")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"li"},"SpareTime")," \u591a\u6b21\u6267\u884c\u95ee\u9898",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XEQU"},"#I3XEQU")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u9009\u9879\u66f4\u6539\u901a\u77e5\uff08\u70ed\u66f4\u65b0\uff09\uff1a\u6570\u636e\u5e93\u91cc\u7684\u6570\u636e\u66f4\u6539\u4e86\u5982\u4f55\u901a\u77e5\u9009\u9879\u8fdb\u884c\u6539\u53d8\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XYI8"},"#I3XYI8")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SaaS")," \u591a\u79df\u6237\u6dfb\u52a0\u65f6\u65e0\u6cd5\u83b7\u53d6\u79df\u6237",(0,r.kt)("inlineCode",{parentName:"li"},"Id")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Y5CF"},"#I3Y5CF")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u83b7\u53d6 ",(0,r.kt)("inlineCode",{parentName:"li"},"_httpContextAccessor.HttpContext")," \u4e3a\u7a7a",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Y6BI"},"#I3Y6BI")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Ubuntu")," \u4e2d\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"App.Configuration")," \u65b9\u6cd5\u8bfb\u53d6\u4e0d\u5230\u503c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Y74H"},"#I3Y74H")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4f5c\u7528\u57df\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YHXP"},"#I3YHXP")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"UnitofWork")," \u63d0\u4ea4\u4e8b\u52a1\uff0c\u53ef\u4ee5\u63d0\u4ea4\u6210\u529f\uff0c\u4f46\u662f\u7cfb\u7edf\u4f1a\u6709\u9519\u8bef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YIWU"},"#I3YIWU")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6570\u636e\u5e93\u8bfb\u5199\u5206\u79bb--\u975e\u9ed8\u8ba4\u4e3b\u5e93\u7684\u4ece\u5e93\u968f\u673a\u8be5\u5982\u4f55\u914d\u7f6e\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3YVR7"},"#I3YVR7")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SpareTIme")," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"Dashboard")," \u63a7\u5236\u53f0\u770b\u677f\uff0c\u540c\u65f6\u53ef\u4ee5\u5bf9\u4efb\u52a1\u8fdb\u884c\u6682\u505c\u3001\u5220\u9664\u3001\u67e5\u770b",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3XELY"},"#I3XELY"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v290-\u5df2\u53d1\u5e03"},"v2.9.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("strong",{parentName:"li"},"\u5e94\u7528\u5168\u5c40\u672a\u6258\u7ba1\u8d44\u6e90\u76d1\u542c\uff0c\u5e76\u5b9e\u73b0\u7279\u5b9a\u65f6\u673a\u91ca\u653e\u975e\u6258\u7ba1\u8d44\u6e90")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VXAU"},"#I3VXAU")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4e0d\u5305\u542b ",(0,r.kt)("inlineCode",{parentName:"li"},"EntityFramework.Core")," \u7248\u672c\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Pure")," \u5305",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VGW8"},"#I3VGW8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," swagger \u652f\u6301\u8bbe\u7f6e\u591a\u8bed\u8a00\u65b9\u5f0f\uff0c\u8bbe\u7f6e\u7684\u8bed\u8a00\u81ea\u52a8\u6dfb\u52a0\u5230 api \u5730\u5740\u540e\u9762 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VDTD"},"#I3VDTD")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001 WebAPI \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"[FromRoute]")," \u975e\u5fc5\u586b\uff08\u9009\u586b\uff09\u53c2\u6570\u8bbe\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VFIM"},"#I3VFIM")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001 WebAPI \u53c2\u6570\u652f\u6301\u914d\u7f6e\u8def\u7531\u7ea6\u675f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VFIR"},"#I3VFIR")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MD5")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"DESC")," \u52a0\u5bc6\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"\u5927\u5199")," \u8f93\u51fa ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/326"},"#326")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6240\u6709\u5305\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},".snupkg")," \u5305\uff0c\u652f\u6301\u5f00\u53d1\u9636\u6bb5\u76f4\u63a5\u8c03\u8bd5 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6240\u6709\u5305\u6e90\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VFIX"},"#I3VFIX")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"repository.BuildChange()")," \u65b9\u6cd5\u7684\u8fd4\u56de\u503c\uff0c\u591a\u8fd4\u56de\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"IServiceScope")," \u5bf9\u8c61 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VX3D"},"#I3VX3D")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT")," \u5237\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u65b9\u6cd5 ",(0,r.kt)("inlineCode",{parentName:"li"},"AutoRefreshToken")," \u53c2\u6570 ",(0,r.kt)("inlineCode",{parentName:"li"},"days")," \u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"minutes")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VXNB"},"#I3VXNB")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.GetOptionsSnapshot<>")," \u4ece\u6839\u670d\u52a1\u89e3\u6790\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VS2X"},"#I3VS2X")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u8fdc\u7a0b\u8bf7\u6c42\u5982\u679c\u51fa\u73b0\u5f02\u5e38\uff0c\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"Stream")," \u4e3a null \u5bfc\u81f4\u5f02\u5e38\u7684\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VSTU"},"#I3VSTU")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5982\u679c\u5b9e\u4f53\u88ab\u8ddf\u8e2a\u540e\uff0c\u65e0\u6cd5\u6267\u884c\u5220\u9664\u64cd\u4f5c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W08P"},"#I3W08P")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u8fd0\u884c\u65f6\u5185\u5b58\uff0c\u5b9e\u73b0\u8bf7\u6c42\u7ed3\u675f\u81ea\u52a8\u91ca\u653e\u672a\u6258\u7ba1\u8d44\u6e90 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VXAU"},"#I3VXAU")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App")," \u9759\u6001\u7c7b\u6587\u6863\u3001\u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863\u3001\u5206\u8868\u5206\u5e93\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u52a8\u6001 WebAPI\uff0c\u81ea\u5b9a\u4e49\u6839\u636e\u65b9\u6cd5\u540d\u751f\u6210 ","[HttpMethod]"," \u89c4\u5219\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VKQG"},"#I3VKQG")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"InsertAsync")," \u7684\u65f6\u5019\u63d0\u793a ",(0,r.kt)("inlineCode",{parentName:"li"},"ID")," \u4e3a\u7a7a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VS7E"},"#I3VS7E")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"FirstOrDefault")," \u81ea\u52a8\u8fc7\u6ee4\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"TanantId")," \u5b57\u6bb5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W0VH"},"#I3W0VH")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5bf9\u65b9\u63a5\u53e3\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpConnectionResponseContent")," \u8fdc\u7a0b\u8bf7\u6c42\u62ff\u4e0d\u5230\u8fd4\u56de\u503c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W17C"},"#I3W17C")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u67e5\u8be2\u65b9\u6cd5 ",(0,r.kt)("inlineCode",{parentName:"li"},"FindOrDefault")," \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W830"},"#I3W830")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlNonQuery")," \u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"UnitOfWork")," \u5faa\u73af\u6267\u884c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W8WW"},"#I3W8WW")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u56e0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u914d\u7f6e\u95ee\u9898\uff0c\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e2d\u4e0d\u80fd\u81ea\u52a8\u643a\u5e26 token \u6388\u6743\u7684\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W934"},"#I3W934")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"SetBody")," \u53c2\u6570\u8bc6\u522b\u4e0d\u4e86",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3WBM1"},"#I3WBM1")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped.Create")," \u91cc\u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"sql.SqlNonQuery()")," \u6216\u8005 ",(0,r.kt)("inlineCode",{parentName:"li"},"obj.insert()")," \u95ee\u9898",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3WB5O"},"#I3WB5O")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u8c03\u7528\u51fd\u6570\u6216\u5b58\u50a8\u8fc7\u7a0b\uff0c\u600e\u4e48\u51fa\u53c2\u6570\u636e\u81ea\u5b9a\u4e49\u5bf9\u8c61\uff1f\u5982 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oracle"),"\u6570\u636e\u5e93\u7684\u6570\u7ec4\u6216\u8bb0\u5f55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W71W"},"#I3W71W")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65e0\u6548]"," \u6570\u636e\u5e93\u5c0f\u5199\u4e0b\u5212\u7ebf\u5b57\u6bb5\uff0c\u65e0\u6cd5\u81ea\u52a8\u6620\u5c04\u6210\u5c0f\u9a7c\u5cf0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3W021"},"#I3W021")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EfCore 5")," \u76f4\u63a5\u591a\u5bf9\u591a\u65f6\u8fdb\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"SeedData")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3WDRJ"},"#I3WDRJ"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v270280-\u5df2\u53d1\u5e03"},"v2.7.0/2.8.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},'throw Oops.On("\u5f02\u5e38\u6d88\u606f")')," \u5e94\u7528\u591a\u8bed\u8a00\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UYC2"},"#I3UYC2")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetMSRepository()")," \u83b7\u53d6\u4e3b\u4ece\u5e93\u4ed3\u50a8\u9759\u6001\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UBSJ"},"#I3UBSJ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5de5\u4f5c\u5355\u5143\u7279\u6027\uff0c\u652f\u6301\u9759\u6001\u7c7b\u5f3a\u5236\u6027\u5f00\u542f\u5171\u4eab\u4e8b\u52a1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3S9N8"},"#I3S9N8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u6a21\u5f0f\u6253\u5370\u65e5\u5fd7 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SE8X"},"#I3SE8X")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u652f\u6301\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpClient")," \u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SI17"},"#I3SI17")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"\u77ed ID")," \u751f\u6210\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3T7JP"},"#I3T7JP")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[SensitiveDetection]")," \u652f\u6301\u914d\u7f6e\u66ff\u6362\u654f\u611f\u8bcd\u6c47 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3THIA"},"#I3THIA")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationDocumentBuilder.DocumentGroups")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationDocumentBuilder.CheckApiDescriptionInCurrentGroup(currentGroup, apiDescription)")," \u516c\u5f00\u65b9\u6cd5",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UDSY"},"#I3UDSY")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u81ea\u52a8\u626b\u63cf ",(0,r.kt)("inlineCode",{parentName:"li"},".json")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},".xml")," \u6587\u4ef6\u5e76\u52a0\u8f7d\u5230\u914d\u7f6e\u4e2d\u7684\u4ee3\u7801\u548c\u89c4\u5219\uff0c\u540c\u65f6\u79fb\u9664\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},".xml")," \u6587\u4ef6\u52a0\u8f7d\uff0c\u53ea\u4fdd\u7559 ",(0,r.kt)("inlineCode",{parentName:"li"},".json")," \u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UJ3L"},"#I3UJ3L")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u5206\u5e03\u5f0f\u8fde\u7eed ",(0,r.kt)("inlineCode",{parentName:"li"},"GUID")," \u4ee3\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UBK0"},"#I3UBK0")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"Scoped.CreateUnitOfWork")," \u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},"Scoped.CreateUow")," ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I3SJPU"},"#I3SJPU"))),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWTEncryption.Validate")," \u8fd4\u56de\u503c\uff0c\u652f\u6301\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"TokenValidationResult")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3S2ND"},"#I3S2ND")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[DataValidation]")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"[SensitiveDetection]")," \u591a\u8bed\u8a00\u5e94\u7528\u5931\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UH6U"},"#I3UH6U")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped")," \u7cfb\u5217\u65b9\u6cd5\u5f02\u6b65\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Task is cancel")," \u60c5\u51b5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SJF6"},"#I3SJF6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mysql")," \u6570\u636e\u5e93\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ToPagedList")," \u65b9\u6cd5\u8fd4\u56de\u7684\u7ed3\u679c\u8fdb\u884c\u904d\u5386\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"MySqlConnection is aleady use")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SJQ3"},"#I3SJQ3")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"tool/cli.psl")," \u6ca1\u6709\u5305\u542b\u9879\u76ee\u540d\u79f0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3S1T6"},"#I3S1T6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u505a\u4e0a\u4f20\u6587\u4ef6\u65f6\uff0c\u6ca1\u6709\u4f20\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"Body"),"\uff0c\u7a0b\u5e8f\u76f4\u63a5\u8df3\u8fc7 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TKFH"},"#I3TKFH")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"multipart/form-data")," \u5185\u5bb9\u5206\u5272\u7b26\u7f3a\u5931 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TNO9"},"#I3TNO9")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u62e6\u622a\u65b9\u5f0f\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpResponseMessage")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3V161"},"#I3V161")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"repository.Database.SetCommandTimeout(600)")," \u65e0\u6cd5\u751f\u6548",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VAQS"},"#I3VAQS")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u652f\u6301\u89c4\u8303\u5316\u7ed3\u679c\u4e2d\u95f4\u4ef6\u5224\u65ad\u662f\u5426\u8df3\u8fc7\u89c4\u8303\u5316\u7ed3\u679c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3T2AA"},"#I3T2AA")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u66f4\u65b0\u90e8\u5206\u5217 ",(0,r.kt)("inlineCode",{parentName:"li"},"UpdateIncludeNowAsync")," \u5177\u6709\u4e8c\u4e49\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RW9Q"},"#I3RW9Q")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("strong",{parentName:"li"},"\u6846\u67b6\u5e95\u5c42\u6027\u80fd\uff0c\u5927\u5927\u51cf\u5c11\u5185\u5b58\u5360\u7528\u548c\u6ea2\u51fa\u60c5\u51b5\uff0c\u542f\u52a8\u5185\u5b58\u4ece\u4e4b\u524d ",(0,r.kt)("inlineCode",{parentName:"strong"},"136M")," \u4e0b\u5c06\u5230 ",(0,r.kt)("inlineCode",{parentName:"strong"},"86M"))),(0,r.kt)("li",{parentName:"ul"},"[\u5176\u4ed6]"," \u5220\u9664\u65e0\u7528\u4ee3\u7801\uff0c\u4f18\u5316\u4e0d\u89c4\u8303\u547d\u540d\u7b49"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Inject")," \u8bf4\u660e\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TITA"},"#I3TITA")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," 4.2.9 \u7684\u793a\u4f8b\u4ee3\u7801\u6587\u6863\uff0c\u65b9\u6cd5\u6ca1\u6709\u653e\u5728 class \u4e2d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3S9T5"},"#I3S9T5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u6b63]"," \u89c4\u8303\u5316\u7ed3\u679c 6.5.6 \u591a\u5206\u7ec4\u6392\u5e8f\u56fe\u7247\u5f15\u7528\u9519\u8bef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UBOQ"},"#I3UBOQ")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u9759\u6001\u7c7b ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped")," \u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"MasterDbContextLocator")," \u4e0d\u968f\u81ea\u5b9a\u4e49\u7684\u53c2\u6570\u751f\u6210 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SDBB"},"#I3SDBB")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u4e8b\u4ef6\u603b\u7ebf\u4e2d\u8ba2\u9605\u5904\u7406\u7a0b\u5e8f\u7c7b\u83b7\u53d6\u4e0d\u5230\u7528\u6237\u4fe1\u606f\uff0c\u8fd9\u4e2a\u6b63\u5e38\u5417 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SS0U"},"#I3SS0U")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5728\u6709\u591a\u79df\u6237\u8fc7\u6ee4\u5668\u7684\u60c5\u51b5\u4e0b\uff0c\u662f\u5426\u6709\u4e00\u79cd\u65b9\u5f0f\u67e5\u8be2\u5168\u91cf\u7684\u6570\u636e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3T0VI"},"#I3T0VI")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," mysql \u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},'&"tools/cli.ps1"')," \u9875\u9762\u5316\u52a0\u8f7d\u8868\u7ed3\u6784\u5931\u8d25 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3T4F8"},"#I3T4F8")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5176\u4ed6 Web \u5c42\u7684 Startup \u4f18\u5148\u6267\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3T8IP"},"#I3T8IP")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u8f85\u52a9\u89d2\u8272\u670d\u52a1\u5b9e\u73b0\u5efa\u8bae ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3T906"},"#I3T906")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5f00\u542f ",(0,r.kt)("inlineCode",{parentName:"li"},"easy connection")," \u540e\u540c\u4e00\u5185\u7f51\u5730\u5740\u6d4f\u89c8\u5668\u53ef\u4ee5\u6b63\u5e38\u8bbf\u95ee\uff0c\u8fdc\u7a0b\u8bf7\u6c42\u5219\u65e0\u6cd5\u8bbf\u95ee",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TA2U"},"#I3TA2U")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"scope.ServiceProvider.GetService"),"\u4e0d\u5b58\u5728 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TQMV"},"#I3TQMV")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u80fd\u5426\u5728 WPF \u9879\u76ee\u4e2d\u4f7f\u7528\u5462\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TMCC"},"#I3TMCC")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Dapper")," \u591a\u4e2a\u6570\u636e\u6e90 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TM9B"},"#I3TM9B")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"L.GetSelectCulture()")," \u65b9\u6cd5\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TQS4"},"#I3TQS4")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5faa\u73af\u4e2d\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"IDGen.NextID()")," \u5f97\u5230\u7684\u7ed3\u679c\u5e76\u4e0d\u662f\u8fde\u7eed\u7684 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UAF6"},"#I3UAF6")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6a21\u5757\u5316\u52a8\u6001\u52a0\u8f7d\u63d2\u4ef6\u652f\u6301\u901a\u914d\u7b26\u5339\u914d.dll ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UDT8"},"#I3UDT8")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MVC")," \u6a21\u5f0f\uff0c\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Controller")," \u91cc\u5feb\u6377\u65b9\u5f0f\u521b\u5efa ",(0,r.kt)("inlineCode",{parentName:"li"},"View")," \u9875\u9762\u51fa\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UFGB"},"#I3UFGB")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6570\u636e\u5e93\u8fc1\u79fb\u6ca1\u6709\u79cd\u5b50\u6570\u636e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UI7G"},"#I3UI7G")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SpareTimeAttribute")," \u4e2d \u6839\u636e Cron \u8868\u8fbe\u5f0f \u81ea\u52a8\u5339\u914d Cron \u8868\u8fbe\u5f0f\u683c\u5f0f\u5316\u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UTKQ"},"#I3UTKQ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"workService")," \u96c6\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3V8HJ"},"#I3V8HJ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"sqlserver 2008")," \u5206\u9875\u62a5\u9519\u5982\u4f55\u89e3\u51b3\u5462 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3VF96"},"#I3VF96")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u6dfb\u52a0\u4ee4\u724c\u6876\u9650\u6d41\u7b97\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SCDV"},"#I3SCDV")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5b9a\u65f6\u4efb\u52a1\u7acb\u5373\u6267\u884c\u9700\u6c42 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3SF4A"},"#I3SF4A")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u6587\u6863\u5efa\u8bae \u5173\u4e8e reids \u548c es \u3001\u6d88\u606f\u961f\u5217\u7684 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3T90I"},"#I3T90I")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," IP \u9ad8\u9891\u7387\u8bf7\u6c42\u9650\u5236 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3UHE1"},"#I3UHE1")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Url")," \u8f6c\u53d1\u5927\u6a21\u5757 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3TZHO"},"#I3TZHO"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v250260-\u5df2\u53d1\u5e03"},"v2.5.0/2.6.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u865a\u62df\u6587\u4ef6\u670d\u52a1\uff0c\u652f\u6301\u7269\u7406\u6587\u4ef6\u548c\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RBR9"},"#I3RBR9")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236\u4ed3\u50a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"IMSRepository")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"IMSRepository")," \u4ed3\u50a8\uff0c\u53ef\u8fdb\u884c\u968f\u673a\u6216\u81ea\u5b9a\u4e49\u83b7\u53d6\u4ece\u5e93"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6570\u636e\u8131\u654f\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3R5ZF"},"#I3R5ZF")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"InsertOrUpdate")," \u4e00\u7cfb\u5217\u6570\u636e\u5e93\u64cd\u4f5c\u65b9\u6cd5")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RI9L"},"#I3RI9L")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u6240\u6709\u5305\u542b ",(0,r.kt)("inlineCode",{parentName:"li"},"Exists")," \u5355\u8bcd\u7684\u6570\u636e\u5e93\u64cd\u4f5c\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RJ0T"},"#I3RJ0T")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u5206\u5e03\u5f0f GUID ",(0,r.kt)("inlineCode",{parentName:"li"},"IDGenerater")," \u9759\u6001\u7c7b\u540d\u79f0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"IDGen")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RGUA"},"#I3RGUA")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8c03\u7528\u65b9\u6cd5\u9519\u8bef\uff0c\u8bf7\u6c42\u62a5\u6587\u5934 ",(0,r.kt)("inlineCode",{parentName:"li"},"Headers")," \u4e0d\u80fd\u6dfb\u52a0\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"IHttpDispatchProxy")," \u7684\u5b50\u63a5\u53e3\u4e0a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RAF7"},"#I3RAF7")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u5e94\u7528\u542f\u52a8\u6027\u80fd\uff0c\u51cf\u5c11\u5185\u5b58\u5206\u914d"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8131\u654f\u5904\u7406\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3R6WZ"},"#I3R6WZ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6587\u4ef6\u7cfb\u7edf\u6587\u6863\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"FS")," \u9759\u6001\u7c7b\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RCC4"},"#I3RCC4")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236\u3001\u6570\u636e\u5e93\u4ed3\u50a8\u6587\u6863\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"Db")," \u9759\u6001\u7c7b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3R3B6"},"#I3R3B6")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u96c6\u7fa4\u90e8\u7f72 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3R3J4"},"#I3R3J4")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5347\u7ea7\u6700\u65b0\u6846\u67b6\u4ee5\u540e\uff0c \u6570\u636e\u5e93\u751f\u6210\u6a21\u578b\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3R7TP"},"#I3R7TP")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e8b\u52a1\u6267\u884c\u4e2d\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"SaveNow")," \u6267\u884c\u540e\u6709\u8b66\u544a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RAJI"},"#I3RAJI")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Hangfire")," \u4f7f\u7528\u4e8b\u52a1\u51fa\u73b0\u9519\u8bef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ROQ5"},"#I3ROQ5")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5982\u4f55\u5b9e\u73b0 cli \u4e0d\u6267\u884c\u67d0\u4e9b\u8868\u7684\u8fc1\u79fb\uff0cweb \u8bf7\u6c42\u53ef\u4ee5\u6b63\u5e38\u64cd\u4f5c\u5462\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ROU5"},"#I3ROU5")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5728\u4f7f\u7528\u5b9a\u65f6\u4efb\u52a1\u65f6\u5019\u51fa\u73b0\u7684\u95ee\u9898\uff1a\u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"li"},"ISpareTimeWorker")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RRZS"},"#I3RRZS")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MySql")," \u65f6\u95f4\u5dee 8 \u5c0f\u65f6\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RSCO"},"#I3RSCO")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetRepository<>")," \u65b9\u6cd5\u7ed3\u5408 ",(0,r.kt)("inlineCode",{parentName:"li"},"[UnitOfWork]")," \u540e\u4e0d\u53ef\u7528 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RUK5"},"#I3RUK5")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u4e8b\u52a1\u5f00\u542f\u5931\u8d25\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RYJY"},"#I3RYJY")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"DbProvider")," \u53ef\u52a8\u6001\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RYPE"},"#I3RYPE")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"WorkService")," \u4f9d\u8d56\u6ce8\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"ISingleton")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3RZ1L"},"#I3RZ1L")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ISpareTimeWorker")," \u8fd0\u884c\u671f\u52a8\u6001\u4fee\u6539 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3S33Q"},"#I3S33Q")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u62d2\u7edd]"," \u6709\u5e8f ",(0,r.kt)("inlineCode",{parentName:"li"},"Guid")," \u7cbe\u5ea6\u662f\u56fa\u5b9a\u7684\u6beb\u79d2\u7ea7\uff1a1 \u6beb\u79d2\u5185\u751f\u6210\u7684\u591a\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"Guid")," \u662f\u65e0\u5e8f\u7684 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3R59J"},"#I3R59J")),(0,r.kt)("li",{parentName:"ul"},"[\u62d2\u7edd]"," \u5efa\u8bae:JWTEncryption.Validate \u65b9\u6cd5\u8fd4\u56de JWT \u7684\u68c0\u67e5\u5931\u8d25\u65f6\u7684\u539f\u56e0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3S1F2"},"#I3S1F2"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v240-\u5df2\u53d1\u5e03"},"v2.4.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301\u81ea\u52a8\u52a0\u8f7d\u6a21\u5757\u5316/\u63d2\u4ef6 ",(0,r.kt)("inlineCode",{parentName:"li"},".xml")," \u6ce8\u91ca\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Q7XY"},"#I3Q7XY")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext.FailedAutoRollback")," \u5c5e\u6027\uff0c\u53ef\u914d\u7f6e\u4e8b\u52a1\u662f\u5426\u81ea\u52a8\u56de\u6eda ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QOUS"},"#I3QOUS")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," ",(0,r.kt)("strong",{parentName:"li"},".NET 5 SDK \u4e3a 5.0.6 \u7248\u672c")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IJsonSerializerProvider.GetSerializerOptions()")," \u63a5\u53e3\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QIJN"},"#I3QIJN")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddInject()")," \u65b9\u5f0f\u6ce8\u518c\uff0c\u6a21\u5757\u5316/\u63d2\u4ef6\u4e0d\u52a0\u8f7d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3Q7XH"},"#I3Q7XH")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u79cd\u5b50\u6570\u636e\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"null")," \u62a5\u7a7a\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QCM5"},"#I3QCM5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"Clay.Object")," \u521b\u5efa\u7c98\u571f\u5bf9\u8c61\u540e\u5c5e\u6027\u53d8\u5c0f\u5199\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QRV3"},"#I3QRV3")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6846\u67b6\u5e95\u5c42\u6027\u80fd\uff0c\u51cf\u5c11\u5185\u5b58\u5360\u7528\uff0c\u63d0\u9ad8\u5e94\u7528\u521d\u59cb\u5316\u901f\u5ea6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/commit/92f8cc1"},"92f8cc1")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," JSON \u5e8f\u5217\u5316\u6587\u6863\u3001\u89c4\u8303\u5316\u7ed3\u679c\u6587\u6863\u3001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"InsertOrUpdateNowAsync")," \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QKO5"},"#I3QKO5")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5b9a\u65f6\u4efb\u52a1\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},"Failed")," \u4e8b\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QCM2"},"#I3QCM2")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u6a21\u5757\u5316\u52a8\u6001\u751f\u6210\u6570\u636e\u5e93\u8868 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QH3G"},"#I3QH3G")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae\u4e8b\u4ef6\u603b\u7ebf\u65b0\u589e MQ \u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3QWZ4"},"#I3QWZ4")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u91cd\u6784\u89c4\u8303\u5316\u6574\u4e2a\u6a21\u5757\u4ee3\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NFT7"},"#I3NFT7"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v230-\u5df2\u53d1\u5e03"},"v2.3.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.DatabaseAccessor.MongoDB")," \u62d3\u5c55\u5305\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PKST"},"#I3PKST")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001\u7c98\u571f\u7c7b\u578b\u76f4\u63a5\u8f6c ",(0,r.kt)("inlineCode",{parentName:"li"},"object")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"li"},"dynamic")," \u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OY27"},"#I3OY27")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Retry")," \u65b9\u6cd5\uff0c\u652f\u6301\u8bbe\u7f6e\u65b9\u6cd5\u8c03\u7528\u5931\u8d25\u8fdb\u884c\u91cd\u8bd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PJKQ"},"#I3PJKQ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWTSettings")," \u914d\u7f6e\u8282\u70b9 ",(0,r.kt)("inlineCode",{parentName:"li"},"Algorithm"),"\uff0c\u7528\u4e8e\u914d\u7f6e\u52a0\u5bc6\u7b97\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PQGV"},"#I3PQGV")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"repository.EnsureTransaction()")," \u65b9\u6cd5\u786e\u4fdd\u5de5\u4f5c\u5355\u5143\u4e8b\u52a1\u6709\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PVF1"},"#I3PVF1")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u652f\u6301]"," \u652f\u6301 .NET 6.0.0 Preview 3 \u7248\u672c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3P2C7"},"#I3P2C7")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4f7f\u7528\u6570\u636e\u5e93\u751f\u6210\u6a21\u578b ",(0,r.kt)("inlineCode",{parentName:"li"},"tools/cli.ps1"),"\uff0c\u4ece\u6570\u636e\u5e93\u8868\u751f\u6210\u7684\u5b9e\u4f53\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PL18"},"#I3PL18")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8d34\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"[NonUntify]")," \u7279\u6027\u540e\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Example Value")," \u6ca1\u6709\u5339\u914d\u6b63\u786e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PK0L"},"#I3PK0L")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SpareTimer.Tally")," \u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Cron")," \u8868\u8fbe\u5f0f\u4e2d\u8ba1\u6570\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PWSE"},"#I3PWSE")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u6846\u67b6\u9ed8\u8ba4\u5e8f\u5217\u5316\u5e94\u8be5\u4ece\u914d\u7f6e\u4e2d\u8bfb\u53d6\uff0c\u800c\u975e\u624b\u52a8\u7f16\u5199 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3P1SJ"},"#I3P1SJ")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u62d3\u5c55\u5e93\uff0c\u652f\u6301\u975e\u6cdb\u578b\u4ed3\u50a8\u83b7\u53d6\u4e0a\u4e0b\u6587\u64cd\u4f5c\u5bf9\u8c61 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PK2N"},"#I3PK2N")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u652f\u6301\u5206\u5e03\u5f0f\u5185\u5b58\u7f13\u5b58\u53ef\u914d\u7f6e\u5316 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3POKD"},"#I3POKD")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6587\u6863]"," \u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWTSettings")," \u914d\u7f6e\u72ec\u7acb\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PQGW"},"#I3PQGW")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u8f6f\u5220\u9664\u5982\u679c\u6570\u636e\u4e0d\u5b58\u5728\uff0c\u5219\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PTVB"},"#I3PTVB")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u591a\u4e2a\u7c7b\u96c6\u6210\u6d4b\u8bd5\u4f1a\u9020\u6210\u6570\u636e\u5e93\u5b9a\u4f4d\u5668\u591a\u6b21\u6ce8\u518c\uff0c\u65e0\u6cd5\u8fd0\u884c\u6240\u6709\u6d4b\u8bd5\uff0c\u53ea\u80fd\u4e00\u4e2a\u7c7b\u4e00\u4e2a\u7c7b\u7684\u8fd0\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PXGY"},"#I3PXGY")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," CAS \u652f\u6301",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3PIET"},"#I3PIET"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v220-\u5df2\u53d1\u5e03"},"v2.2.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Clay")," \u7c98\u571f\u7c7b\u578b\uff0c\u652f\u6301\u8ba9 ",(0,r.kt)("inlineCode",{parentName:"li"},"C#")," \u521b\u5efa\u4e00\u4e2a\u5f31\u7c7b\u578b\u5bf9\u8c61\u5e76\u64cd\u4f5c\u5f31\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O2QQ"},"#I3O2QQ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped.Create")," \u5e26\u8fd4\u56de\u503c\u91cd\u8f7d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O47J"},"#I3O47J")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped.Create()")," \u4e00\u7cfb\u5217\u65b9\u6cd5\u652f\u6301\u4f20\u5165\u4f5c\u7528\u57df\u5de5\u5382 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OAP5"},"#I3OAP5")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301\u4e8b\u4ef6\u603b\u7ebf\u540c\u6b65\u6267\u884c\u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OAW2"},"#I3OAW2")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[DataValidation]")," \u8df3\u8fc7\u7a7a\u5b57\u7b26\u4e32\u548c\u7a7a\u503c\u9a8c\u8bc1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OGEN"},"#I3OGEN")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u53ef\u914d\u7f6e\u662f\u5426\u81ea\u52a8\u6ce8\u518c ",(0,r.kt)("inlineCode",{parentName:"li"},"Worker")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OLW4"},"#I3OLW4")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b9a\u65f6\u4efb\u52a1\u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"cancelInNoneNextTime: false")," \u4e00\u6b21\u4e5f\u4e0d\u6267\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O3N0"},"#I3O3N0")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," SpareTime \u81ea\u5b9a\u4e49\u4e0b\u6b21\u6267\u884c\u65f6\u95f4\u51fa\u73b0\u7a7a\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O46X"},"#I3O46X")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MiniProfiler")," \u8bbe\u7f6e\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"false")," \u65f6\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u63d0\u4ea4\u62e6\u622a\u5668\u672a\u6dfb\u52a0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OAWX"},"#I3OAWX")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},'[Consumes("application/x-www-form-urlencoded")]')," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"ModelQuery")," \u914d\u7f6e\u540c\u65f6\u914d\u7f6e\u5bfc\u81f4\u7a7a\u5f15\u7528\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ODUR"},"#I3ODUR")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5728 Grpc \u4e2d\u4f7f\u7528 jwt \u6388\u6743\u51fa\u73b0\u7a7a\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OW3I"},"#I3OW3I")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u652f\u6301\u53d1\u5e03\u540e\u4ee3\u7801\u7cbe\u7b80\u914d\u7f6e\uff0c\u51cf\u5c11\u4e0d\u5fc5\u8981\u7684\u6587\u4ef6\u5939\u8f93\u51fa ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OAPF"},"#I3OAPF")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u81ea\u52a8\u5237\u65b0 Token \u673a\u5236\uff0c\u65b0\u589e\u5bb9\u9519\u503c\u5904\u7406\uff0c\u89e3\u51b3\u5e76\u53d1 Token \u5237\u65b0\u5931\u8d25\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OGYF"},"#I3OGYF")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7c98\u571f\u5bf9\u8c61\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OG18"},"#I3OG18")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u52a8\u6001 WebAPI \u5982\u4f55\u83b7\u53d6\u63a5\u6536\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O29B"},"#I3O29B")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5b9a\u65f6\u4efb\u52a1\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Scope.CreateUow")," \u5f15\u53d1\u7684\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O2CD"},"#I3O2CD")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5355\u6587\u4ef6\u53d1\u5e03\u7a0b\u5e8f\u5de5\u4f5c\u4e0d\u6b63\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O4D8"},"#I3O4D8")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u540c\u65f6\u914d\u7f6e\u79df\u6237\u8fc7\u6ee4\u5668\u548c\u8f6f\u5220\u9664\u8fc7\u6ee4\u5668\uff0c\u6700\u7ec8\u7684 sql \u53ea\u751f\u6210\u4e86\u4e00\u79cd\u8fc7\u6ee4\u6761\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OB0A"},"#I3OB0A")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," HTTP \u91cd\u5b9a\u5411 HTTPS \u540e\u8de8\u57df\u5931\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OB8R"},"#I3OB8R")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5728 PostgreSql \u6570\u636e\u5e93\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"rep.FirstOrDefault(u => u.Id == UserId);")," \u5f15\u8d77\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3O5OF"},"#I3O5OF")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5b9a\u65f6\u4efb\u52a1\u6709\u65f6\u80fd\u89e6\u53d1\u6709\u65f6\u4e0d\u80fd\u89e6\u53d1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ORBE"},"#I3ORBE")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f5c\u5e9f]"," \u6846\u67b6\u4e2d\u7684 swagger \u662f\u5426\u6709\u63d0\u4f9b\u5bfc\u51fa\u6587\u6863\u4e3a markdwon/word \u7684\u529f\u80fd\u8ba1\u5212\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OL8O"},"#I3OL8O")),(0,r.kt)("li",{parentName:"ul"},"[\u4f5c\u5e9f]"," \u6570\u636e\u5e93\u5b9e\u4f53\u7236\u5b50\u7ee7\u627f\uff0c\u5b50\u7c7b\u751f\u6210\u7684 SQL \u4e0d\u4e00\u6837 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NHU3"},"#I3NHU3")),(0,r.kt)("li",{parentName:"ul"},"[\u4f5c\u5e9f]"," \u652f\u6301\u7b2c\u4e09\u65b9\u6570\u636e\u5e93 ORM ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3OXA3"},"#I3OXA3"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v210-\u5df2\u53d1\u5e03"},"v2.1.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e\u5b9a\u65f6\u4efb\u52a1 ",(0,r.kt)("inlineCode",{parentName:"li"},"ISpareTimeWorker")," \u65b9\u5f0f\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},'[SpareTime("{\u914d\u7f6e\u8def\u5f84}}]')," \u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NTUX"},"#I3NTUX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9a\u65f6\u4efb\u52a1\u652f\u6301\u5f02\u6b65\u59d4\u6258 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NP96"},"#I3NP96")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8f7b\u91cf\u7ea7\u5206\u5e03\u5f0f\u8fde\u7eed GUID \u751f\u6210\u5668 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NKLZ"},"#I3NKLZ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ClayObject")," \u6a21\u5757\uff0c\u5904\u7406 ",(0,r.kt)("inlineCode",{parentName:"li"},"ExpandoObject")," \u53ca ",(0,r.kt)("inlineCode",{parentName:"li"},"IDictionary")," \u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3N3J4"},"#I3N3J4")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Scoped.CreateUow(handler)")," \u521b\u5efa\u4f5c\u7528\u57df\u5e76\u81ea\u52a8\u63d0\u4ea4\u6570\u636e\u5e93\u66f4\u6539\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NU3G"},"#I3NU3G")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u89c4\u8303\u5316\u7ed3\u679c\u63a5\u53e3 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnResponseStatusCodes")," \u65b9\u6cd5\uff0c\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"UnifyResultStatusCodesOptions")," \u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NDB9"},"#I3NDB9")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("strong",{parentName:"li"},"\u96ea\u82b1 ID \u5b9e\u73b0\u4ee3\u7801 ",(0,r.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I3NKLZ"},"#I3NKLZ"))))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e0d\u80fd\u652f\u6301\u975e int \u7c7b\u578b\u7684\u679a\u4e3e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NQM8"},"#I3NQM8")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u7ebf\u7a0b\u6c60\u591a\u7ebf\u7a0b\u5e76\u53d1\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NR4L"},"#I3NR4L")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u5b9a\u4e49\u63a7\u5236\u5668\u8def\u7531\u540e\u4e14\u4e3a\u65b9\u6cd5\u53c2\u6570\u6307\u5b9a\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"[ApiSeat]")," \u540e\u751f\u6210\u8def\u7531\u91cd\u590d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NRF6"},"#I3NRF6")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u652f\u6301\u5e94\u7528\u542f\u52a8\u7684\u65f6\u5019\u8fc1\u79fb\u79cd\u5b50\u6570\u636e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NH3M"},"#I3NH3M")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5206\u5e03\u5f0f ID \u751f\u6210\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3B6CX"},"#I3B6CX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e\u6a21\u5757\u5316\u5f00\u53d1\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NSUS"},"#I3NSUS")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," 20.4 \u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u5f0f > \u9519\u8bef",(0,r.kt)("inlineCode",{parentName:"li"},"ToAESDecrypt")," \u5199\u6210\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"ToToAESDecrypt")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NNKV"},"#")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6709\u5173\u3010\u5b9a\u65f6\u4efb\u52a1/\u59d4\u6258\u3011\u7684\u7591\u95ee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3N3EW"},"#I3N3EW")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u7edf\u4e00\u8fd4\u56de\u683c\u5f0f\u652f\u6301\u81ea\u5b9a\u4e49 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NU1G"},"#I3NU1G")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f5c\u5e9f]"," \u671f\u5f85 IEnumerableExtensions \u6269\u5c55 OrderBy \u51fd\u6570\u6765\u652f\u6301\u5206\u9875\u6392\u5e8f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3NOQ9"},"#I3NOQ9"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v200-\u5df2\u53d1\u5e03"},"v2.0.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u53ca Worker Services \u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3K4DG"},"#I3K4DG")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b8c\u6574\u4efb\u52a1\u8c03\u5ea6\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IRUX"},"#I3IRUX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Cron")," \u8868\u8fbe\u5f0f\u89e3\u6790 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IQ9Y"},"#I3IQ9Y")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u81ea\u5b9a\u4e49\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"swagger.json")," \u5730\u5740\u6a21\u677f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IHMX"},"#I3IHMX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301\u914d\u7f6e\u52a8\u6001 WebApi \u533a\u57df ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IJAZ"},"#I3IJAZ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u65b0\u589e\u652f\u6301\u4f20\u5165\u670d\u52a1\u63d0\u4f9b\u5668 ",(0,r.kt)("inlineCode",{parentName:"li"},"IServiceProvider")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IVBL"},"#I3IVBL")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u914d\u7f6e\u9009\u578b ",(0,r.kt)("inlineCode",{parentName:"li"},"SupportPackageNamePrefixs")," \u914d\u7f6e\uff0c\u652f\u6301\u914d\u7f6e\u5305\u524d\u7f00 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3K0SN"},"#I3K0SN")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5e94\u7528\u542f\u52a8\u65f6\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"referenceassembly")," \u7c7b\u578b\u7a0b\u5e8f\u96c6\u626b\u63cf ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3K0SN"},"#I3K0SN")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4f9d\u8d56\u6ce8\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"AOP")," \u62e6\u622a\u83b7\u53d6\u65b9\u6cd5\u771f\u5b9e\u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3LZBX"},"#I3LZBX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," EFCore \u624b\u52a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"SaveChanges()")," \u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3N01Y"},"#I3N01Y")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Cors")," \u8de8\u57df\u66f4\u591a\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3N2J0"},"#I3N2J0")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u5b8c\u6574\u4efb\u52a1\u8c03\u5ea6\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IRUX"},"#I3IRUX")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u65e5\u5fd7\u6a21\u5757\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J2K0"},"#I3J2K0")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u6a21\u677f\u5f15\u64ce\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J46E"},"#I3J46E")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u5e95\u5c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCoreRepository")," \u4ed3\u50a8 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J6W5"},"#I3J6W5")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," sql \u5b57\u7b26\u4e32\u62d3\u5c55\u5e95\u5c42\u4ee3\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IVCE"},"#I3IVCE")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u5e95\u5c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlRepository")," \u6240\u6709\u903b\u8f91\u4ee3\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J6V6"},"#I3J6V6")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u6570\u636e\u5e93\u5b9e\u4f53\u62d3\u5c55\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J609"},"#I3J609")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u4e8b\u4ef6\u4e8b\u4ef6\u603b\u7ebf\u540c\u6b65\u6267\u884c\u4e3a\u5f02\u6b65\u65b9\u5f0f\u6267\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J0WA"},"#I3J0WA")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u6846\u67b6\u5e95\u5c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContext.IsAjaxRequest()")," \u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IVAA"},"#I3IVAA")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationTypes.Required")," \u9a8c\u8bc1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3KR85"},"#I3KR85")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5173\u95ed ",(0,r.kt)("inlineCode",{parentName:"li"},"InjectMiniProfiler")," \u53c2\u6570\u540e\u5185\u5b58\u7f13\u5b58\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IHLR"},"#I3IHLR")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5728\u591a\u79df\u6237\u4e2d\u8c03\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Tenant")," \u5c5e\u6027\u51fa\u73b0\u5076\u7136\u6027\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u88ab\u91ca\u653e\u7684\u60c5\u51b5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IC70"},"#I3IC70")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," Sql \u4ee3\u7406\u4e2d\u5982\u679c\u8fd4\u56de\u57fa\u5143\u7c7b\u578b\u629b\u51fa\u4e0d\u80fd\u5c06 object \u8f6c\u6362\u6210\u5bf9\u5e94\u7c7b\u578b\u7684\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IC84"},"#I3IC84")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b58\u50a8\u8fc7\u7a0b\u591a\u8fd4\u56de\u503c\u7684\u65f6\u5019\uff0coutputvalues \u7684 name \u4e0d\u662f\u5b9a\u4e49\u7684 MSG \u7684 name\uff0c\u662f Msg \u7c7b\u578b\u3002 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IC7Y"},"#I3IC7Y")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," PhoneNumber \u624b\u673a\u53f7\u9a8c\u8bc1\u6b63\u5219\u8868\u8fbe\u5f0f\u9519\u8bef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ID10"},"#I3ID10")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4f9d\u8d56\u6ce8\u5165 AOP \u62e6\u622a\u65e0\u6cd5\u6355\u83b7\u5185\u90e8\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IGCC"},"#I3IGCC")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5168\u5c40\u62e6\u622a\u6807\u8bb0\u5f02\u5e38\u5df2\u88ab\u5904\u7406\u540e\u5f02\u5e38\u8fc7\u6ee4\u5668\u4f9d\u7136\u6267\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J463"},"#I3J463")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u5b9a\u4e49\u5168\u5c40\u5f02\u5e38\u62e6\u622a\u5668\u4e0d\u8d77\u4f5c\u7528 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3K1SJ"},"#I3K1SJ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5728 WorkerService \u6a21\u5f0f\u4e0b\uff0c\u8fd8\u662f\u4f7f\u7528 WebHostEnvironment \u6765\u5224\u65ad Host \u73af\u5883\uff0c\u4f1a\u5bfc\u81f4\u9519\u8bef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3LCQY"},"#I3LCQY")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5b9a\u65f6\u4efb\u52a1 ",(0,r.kt)("inlineCode",{parentName:"li"},"DoOnce")," \u629b\u7a7a\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3M0ZT"},"#I3M0ZT")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u542f\u52a8\u65f6\u7a0b\u5e8f\u96c6\u626b\u63cf\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3K0SN"},"#I3K0SN")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," ",(0,r.kt)("inlineCode",{parentName:"li"},'App.GetConfig<>("key")')," \u4e0d\u652f\u6301\u83b7\u53d6\u5355\u4e2a\u503c\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ILF1"},"#I3ILF1")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," UrlEncode \u5e94\u8be5\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Uri.EscapeDataString()")," \u800c\u4e0d\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpUtility.UrlEncode")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ICTK"},"#I3ICTK")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9a\u4f4d\u4efb\u52a1\u3001\u540e\u53f0\u4efb\u52a1\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3JHHG"},"#I3JHHG")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8f85\u52a9\u89d2\u8272\u670d\u52a1\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3K5GN"},"#I3K5GN")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u52a8\u6001 WebAPI\u3001\u89c4\u8303\u5316\u6587\u6863\u3001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6570\u636e\u6821\u9a8c\uff0c\u81ea\u5b9a\u4e49 ErrorMessage \u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ICL3"},"#I3ICL3")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6700\u65b0 issue \u4e2d\u65b0\u589e\u7684\u201c\u65b0\u589e\u5e38\u7528\u7684 JSON \u5e8f\u5217\u5316\u65b9\u6cd5\u201d \u4f1a\u5bfc\u81f4 AOP \u62e6\u622a\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3I7VE"},"#I3I7VE")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Furion.DatabaseAccessor.PrivateEntityBase \u4e2d\u7684 TenantId \u6570\u636e\u7c7b\u578b\u8bbe\u7f6e\u4e3a object ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IQV6"},"#I3IQV6")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6709\u5173\u5f02\u5e38\u62e6\u622a\u548c\u5904\u7406\u7684\u7591\u95ee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IUFZ"},"#I3IUFZ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DataValidation")," \u5728\u7a7a\u503c\u7684\u60c5\u51b5\u4e0b\u88ab\u5ffd\u7565\u6389\u4e86",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IWSM"},"#I3IWSM")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u65e5\u5fd7\u6587\u6863\u6ca1\u6709\u66f4\u65b0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J1DX"},"#I3J1DX")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5bf9\u4e8e webapi \u7b80\u5355\u7c7b\u578b\u53c2\u6570\uff0c\u662f\u5426\u53ef\u4ee5\u4ee5 json \u65b9\u5f0f\u63d0\u4ea4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J18I"},"#I3J18I")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IUnifyResultProvider")," \u5b9e\u73b0\u4e2d\u5982\u679c ",(0,r.kt)("inlineCode",{parentName:"li"},"UnifyModel")," \u7684 type \u4e0d\u662f\u8303\u578b\u4f1a\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3JBXF"},"#I3JBXF")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5982\u4f55\u6a21\u5757\u5316\u5f00\u53d1\u65b0\u529f\u80fd\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3J7ZZ"},"#I3J7ZZ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5efa\u8bae\u589e\u52a0\u5fae\u670d\u52a1\u4e2d\u95f4\u4ef6\u7684\u96c6\u6210 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3JTZQ"},"#I3JTZQ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u4e8c\u7ea7\u865a\u62df\u76ee\u5f55\u90e8\u7f72\u7684 swagger \u7684 MiniProfiler js \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3IWLR"},"#I3IWLR")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f5c\u5e9f]"," \u5728\u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7\u4e2d\u5bf9\u8d34\u6709 DisableAuditing \u7279\u6027\u7684\u5b57\u6bb5\u81ea\u52a8\u8fc7\u6ee4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DHAN"},"#I3DHAN"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v1190-\u5df2\u53d1\u5e03"},"v1.19.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore 5.0")," \u652f\u6301 ",(0,r.kt)("strong",{parentName:"li"},"SqlServer 2005-2008")," \u6570\u636e\u5e93 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HZZ6"},"#I3HZZ6")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u9ad8\u7ea7\u4ee3\u7406\u652f\u6301\u6a21\u677f\u66ff\u6362\u4e86 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HHWU"},"#I3HHWU")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HH2T"},"#I3HH2T")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"PBKDF2")," \u52a0\u5bc6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HN7A"},"#I3HN7A")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5e38\u7528\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON")," \u64cd\u4f5c\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HUYO"},"#I3HUYO")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6240\u6709\u89e3\u6790\u670d\u52a1\u7684\u65b9\u6cd5\u90fd\u652f\u6301\u4f20\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"IServiceProvidier")," \u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HXEU"},"#I3HXEU")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," .NET 5 SDK \u81f3 5.0.5 \u7248\u672c"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"application/x-www-form-urlencoded")," \u81ea\u52a8\u88ab\u8f6c\u7801\u4e86 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HDPC"},"#I3HDPC")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ISqlDispatchProxy")," \u8c03\u7528\u5e26\u8fd4\u56de\u503c\u7684\u5b58\u50a8\u8fc7\u7a0b\u51fa\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HISS"},"#I3HISS")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u6570\u636e\u5e93\u5de5\u4f5c\u5355\u5143\u5f02\u5e38\u65e0\u6cd5\u56de\u6eda\u6570\u636e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3I2KN"},"#I3I2KN")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/zuohuaijun/Admin.NET/issues/I3HYN5"},"#I3HYN5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," Serilog \u65e5\u5fd7\u751f\u6210\u592a\u591a\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3I2PN"},"#I3I2PN")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"1.18.0")," \u7248\u672c\u6570\u636e\u5e93\u8fde\u63a5\u6c60\u5b58\u5728\u8fde\u63a5\u6cc4\u6f0f\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3I5KO"},"#I3I5KO")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," Sqlite \u63d0\u793a\u4e8b\u52a1\u5df2\u5b8c\u6210\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3I9F2"},"#I3I9F2")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u89c6\u56fe\u6a21\u677f\u529f\u80fd\uff0c\u9ed8\u8ba4\u652f\u6301\u53ef\u679a\u4e3e\u6cdb\u578b\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3GYEE"},"#I3GYEE")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u5f00\u53d1\u9636\u6bb5 MiniProfiler \u6253\u5370\u6570\u636e\u5e93\u76f8\u5173\u4fe1\u606f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3I8VQ"},"#I3I8VQ")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," EFCore 5.0 \u672a\u63d0\u4f9b Sqlite \u6570\u636e\u5e93 DataAdapter \u7684\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3I9FC"},"#I3I9FC")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3001\u591a\u79df\u6237\u3001\u4ed3\u50a8\u3001\u65e5\u5fd7\u3001\u5e8f\u5217\u5316\u7b49\u6587\u6863\u3002"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5efa\u8bae MVC \u6a21\u5f0f\u4e0b\u589e\u52a0 Furion \u7684\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3GY4R"},"#I3GY4R")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6570\u636e\u5e93\u5173\u8054\u64cd\u4f5c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3H5QP"},"#I3H5QP")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," 1.17.5 \u7248\u672c suagger \u65e0\u6cd5\u751f\u6210 swagger.json ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HGPZ"},"#I3HGPZ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Serilog \u6269\u5c55+dll \u542f\u52a8\u4e0e swagger \u7684 MiniProfiler \u51b2\u7a81 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HWJM"},"#I3HWJM")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Sql \u9ad8\u7ea7\u4ee3\u7406\u8fd4\u56de DataTable \u65f6\uff0c\u7ed3\u679c\u4e3a\u7a7a\u53d6\u4e0d\u5230\u8bb0\u5f55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HUWG"},"#I3HUWG")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Task.Run \u64cd\u4f5c\u6570\u636e\u5e93\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3HZ9D"},"#I3HZ9D")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v1180-\u5df2\u53d1\u5e03"},"v1.18.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Oracle")," 11 \u7248\u672c\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EVL5"},"#I3EVL5")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mysql")," \u5b98\u65b9\u5305 ",(0,r.kt)("inlineCode",{parentName:"li"},"MySql.EntityFrameworkCore")," \u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3E6J1"},"#I3E6J1")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"WebApi")," \u53c2\u6570 ",(0,r.kt)("inlineCode",{parentName:"li"},"[FromQury]")," \u5316 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EFYJ"},"#I3EFYJ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u516c\u5f00\u6846\u67b6\u5e95\u5c42\u4f9d\u8d56\u6ce8\u5165\u626b\u63cf\u6ce8\u518c\u62d3\u5c55 ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddRisterTypes(types)")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EIV3"},"#I3EIV3")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," SqlSugar \u5de5\u4f5c\u5355\u5143\u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EJO5"},"#I3EJO5")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6c60\u4e00\u65e6\u6709\u4e0a\u4e0b\u6587\u64cd\u4f5c\u5931\u8d25\u8fd8\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u51fa\u73b0\u4e8c\u6b21\u63d0\u4ea4\u6570\u636e\u5e93\u7684\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EIJJ"},"#I3EIJJ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4e0d\u540c\u6570\u636e\u5e93\u547d\u4ee4\u53c2\u6570\u524d\u7f00\u90fd\u6dfb\u52a0\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"@")," \u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EBJP"},"#I3EBJP")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5c1d\u8bd5\u4fee\u590d\u4e8b\u4ef6\u603b\u7ebf\u7ebf\u7a0b\u5b89\u5168\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EGSB"},"#I3EGSB")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/236"},"#PR236")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContextExtensions")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"SignoutToSwagger")," \u65b9\u6cd5\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EHNQ"},"#I3EHNQ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5982\u679c\u52a8\u6001 WebApi \u8d34\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"[ApiController]")," \u7279\u6027\u540e\uff0c\u5bfc\u81f4\u8def\u7531\u53c2\u6570\u91cd\u590d\u751f\u6210 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EOQQ"},"#I3EOQQ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5982\u679c\u6ca1\u6709\u4efb\u4f55 webapi \u63a7\u5236\u5668\u65f6\uff0c\u6587\u6863\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EVLB"},"#I3EVLB")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4f9d\u8d56\u6ce8\u5165\u6cdb\u578b\u7c7b\u578b\u6ce8\u518c\u5931\u8d25 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EX66"},"#I3EX66")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," SqlSugar \u62d3\u5c55\u5e93\u4ed3\u50a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"Context")," \u5c5e\u6027\u7c7b\u578b\u672a ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugarClient")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EHXA"},"#I3EHXA")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u5237\u65b0 Token \u9ed1\u540d\u5355 Redis \u4e2d\u5206\u7ec4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EQWO"},"#I3EQWO")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u8fdc\u7a0b\u8bf7\u6c42\u5728\u8bf7\u6c42\u62e6\u622a\u6b21\u53d1\u8d77\u4e8c\u6b21\u8bf7\u6c42\u5bfc\u81f4\u5f02\u5e38\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ER71"},"#I3ER71")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u591a\u79df\u6237\u9ed8\u8ba4\u7f13\u5b58\u6539\u4e3a\u5206\u5e03\u5f0f\u7f13\u5b58 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EXEU"},"#I3EXEU")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u6570\u636e\u5e93\u64cd\u4f5c\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3E84X"},"#I3E84X")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5982\u4f55\u65b9\u4fbf\u7684\u83b7\u53d6 ",(0,r.kt)("inlineCode",{parentName:"li"},"IDynamicApiController")," API \u4ea7\u751f\u7684 url \u548c \u8c13\u8bcd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ED17"},"#I3ED17")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Code First -\u6267\u884c\u547d\u4ee4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Add-Migration")," \u9047\u5230\u4e86\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EHD0"},"#I3EHD0")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," tools v1.16.0 \u65e0\u6cd5\u751f\u6210\u5b9e\u4f53\uff0c\u4e00\u76f4\u63d0\u793a Missing required argument ",(0,r.kt)("inlineCode",{parentName:"li"},""),". ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ENZ8"},"#I3ENZ8")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Authorize \u7684 Logout \u6309\u94ae\uff0c\u65e0\u6cd5\u5b9e\u65f6\u8bf7\u7a7a token",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3EOF9"},"#I3EOF9")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v1170-\u5df2\u53d1\u5e03"},"v1.17.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001 WebAPI \u652f\u6301\u7ee7\u627f\u57fa\u7c7b\u914d\u7f6e\u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3D5PX"},"#I3D5PX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"multipart/form-data")," \u5185\u5bb9\u7c7b\u578b\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3D7KG"},"#I3D7KG")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b57\u7b26\u4e32\u52a0\u5bc6\u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DHBW"},"#I3DHBW")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65b0\u589e\u8fdc\u7a0b\u8bf7\u6c42\u53ef\u76f4\u63a5\u4e0b\u8f7d\u8fd4\u56de\u503c\u5185\u5bb9\u8f6c\u4e3a string \u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DIGR"},"#I3DIGR")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u5730\u5740\u652f\u6301\u6a21\u677f\u5f15\u64ce ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3D5Y8"},"#I3D5Y8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[DataValidation]")," \u9519\u8bef\u6d88\u606f\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"string.Format")," \u64cd\u4f5c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3E08W"},"#I3E08W")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpRequestMessage")," \u62d3\u5c55\u65b9\u6cd5 ",(0,r.kt)("inlineCode",{parentName:"li"},"AppendQueries()")," \u8ffd\u52a0\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"li"},"query")," \u53c2\u6570\u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3E3DI"},"#I3E3DI")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IRepository.AsAsyncEnumerable()")," \u8fd4\u56de\u503c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DIQ1"},"#I3DIQ1"),"\uff0c\u8c03\u6574\u4e3a\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"rep.AsQueryable().ToListAsync()")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u9a8c\u8bc1\u5931\u8d25\u540e\u4e5f\u6253\u5370\u4e86\u6210\u529f\u7684\u5b57\u6bb5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CVBS"},"#I3CVBS")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"contentType")," \u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"application/x-www-form-urlencoded")," \u65e0\u6548\u95ee\u9898",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CWBS"},"#I3CWBS")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u65e0\u6cd5\u6253\u5370\u5b8c\u6574\u7684\u8bf7\u6c42\u5730\u5740\uff0c\u6bd4\u5982\u914d\u7f6e\u4e86 HttpClient \u4e4b\u540e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CY42"},"#I3CY42")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u7a0b\u5e8f\u542f\u52a8\u65f6\u6392\u9664\u9ed8\u8ba4\u914d\u7f6e\u6587\u4ef6\u7b97\u6cd5\u4e0d\u5bf9\uff0c\u5e94\u8be5\u91c7\u7528\u6b63\u5219\u8868\u8fbe\u5f0f\u5339\u914d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3D9E7"},"#I3D9E7")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u6210\u529f\u8bf7\u6c42\u62e6\u622a\u4e0d\u751f\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DOE4"},"#I3DOE4")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Dapper")," \u62d3\u5c55\u6570\u636e\u5e93\u5207\u6362\u4e3a oracle \u65f6\uff0c\u7cfb\u7edf\u627e\u4e0d\u5230\u6307\u5b9a\u7684\u6587\u4ef6 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oracle.ManagedDataAccess.Core")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DYM3"},"#I3DYM3")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u83b7\u53d6 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT token")," \u4fe1\u606f\u652f\u6301\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u524d\u7f00\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"li"},"Bearer ")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DJIV"},"#I3DJIV")),(0,r.kt)("li",{parentName:"ul"},"[\u6539\u8fdb]"," \u5237\u65b0 Token \u9ed1\u540d\u5355\u5b58\u50a8\u65b9\u5f0f\uff0c\u5c06\u5185\u5b58\u7f13\u5b58\u8c03\u6574\u4e3a\u5206\u5e03\u5f0f\u7f13\u5b58 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DPBR"},"#I3DPBR")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u8fdc\u7a0b\u8bf7\u6c42\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CPJO"},"#I3CPJO")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"LinqExpression.And")," \u6ca1\u6709 2 \u4e2a\u53c2\u6570\u7684\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CXKZ"},"#I3CXKZ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5f02\u5e38\u4fe1\u606f \u5982\u4f55\u8bb0\u5f55\u5230\u6570\u636e\u5e93\u4e2d:) ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DDGO"},"#I3DDGO")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u65e0\u952e\u5b9e\u4f53\u9009\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntityNotKey")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DWRF"},"#I3DWRF")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6839\u636e\u4e3b\u952e\u5220\u9664\u4e00\u6761\u8bb0\u5f55\u4e0d\u6210\u529f\uff0c\u65e0\u9519\u8bef\u4fe1\u606f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DWWF"},"#I3DWWF")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5982\u4f55\u81ea\u5b9a\u4e49\u63a5\u53e3\u8fd4\u56de\u683c\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3DZN6"},"#I3DZN6")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," DynamicApiController \u5982\u4f55\u5728\u8fd0\u884c\u65f6\u51b3\u5b9a\u662f\u5426\u516c\u5f00\u4e00\u4e2a Action ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3D5UL"},"#I3D5UL")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.DatabaseAccessor.DbHelpers")," \u65b9\u6cd5\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"ConvertToDbParameters")," \u662f\u4e0d\u662f\u5e94\u8be5\u8fc7\u6ee4\u6389\u8d34 ",(0,r.kt)("inlineCode",{parentName:"li"},"NotMapped")," \u7684\u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3E2XS"},"#I3E2XS")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u6846\u67b6\u662f\u5426\u63d0\u4f9b ",(0,r.kt)("inlineCode",{parentName:"li"},"ISoftDelete")," \u7c7b\u4f3c\u63a5\u53e3 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CP93"},"#I3CP93"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v1160-\u5df2\u53d1\u5e03"},"v1.16.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IDGenerator")," \u96ea\u82b1 ID \u7b97\u6cd5\uff0c\u611f\u8c22 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/yitter/idgenerator"},"idgenerator")," \u4f5c\u8005\u63d0\u4ea4 PR ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/204"},"#PR204")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3B60S"},"#I3B60S")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DbContext")," \u5237\u65b0\u591a\u79df\u6237\u7f13\u5b58\u62d3\u5c55\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39N5U"},"#I39N5U")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u81ea\u5b9a\u4e49\u914d\u7f6e\u5355\u4e2a\u63a7\u5236\u5668\u540d\u79f0\u89c4\u8303\uff0c\u5982\u5c0f\u5199\u8def\u7531 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3A5XL"},"#I3A5XL")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u83b7\u53d6\u5f53\u524d\u9009\u62e9\u533a\u57df\u8bed\u8a00\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BSDH"},"#I3BSDH")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," .NET 5 SDK \u81f3 5.0.4 \u7248\u672c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ASTL"},"#I3ASTL")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u8fdc\u7a0b\u8bf7\u6c42\u6240\u6709\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2LB7M"},"#I2LB7M")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON")," \u5e8f\u5217\u5316\u529f\u80fd\uff0c\u63d0\u4f9b\u7edf\u4e00\u7684\u62bd\u8c61\u63a5\u53e3\uff0c\u65b9\u4fbf\u81ea\u7531\u66ff\u6362 ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON")," \u5e93 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39GT9"},"#I39GT9")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u9a8c\u8bc1\u5931\u8d25\u8fd4\u56de\u6d88\u606f\u6a21\u578b\u53ca\u89c4\u8303\u5316\u63a5\u53e3\u9a8c\u8bc1\u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AFQW"},"#I3AFQW")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u63d2\u4ef6\u5f0f\u5f00\u53d1\u70ed\u63d2\u62d4\u529f\u80fd\uff0c\u5b9e\u73b0\u52a8\u6001\u52a0\u8f7d\u5378\u8f7d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/200"},"#PR200"),", \u611f\u8c22 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/samwangcoder"},"@SamWangCoder")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u79fb\u9664 ",(0,r.kt)("inlineCode",{parentName:"li"},"JsonSerializerUtility")," \u9759\u6001\u7c7b\u53ca\u79fb\u9664\u5c5e\u6027\u5927\u5199\u5e8f\u5217\u5316\u62d3\u5c55\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AFRJ"},"#I3AFRJ")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MVC")," \u6a21\u5f0f\u4e0b\u4e0d\u652f\u6301\u9a8c\u8bc1\u81ea\u5b9a\u4e49\u9a8c\u8bc1\u903b\u8f91 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39LM5"},"#I39LM5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u9a8c\u8bc1\u6570\u503c\u7c7b\u578b\u6b63\u5219\u8868\u8fbe\u5f0f\u4e0d\u652f\u6301\u8d1f\u6570 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39YUV"},"#I39YUV")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6846\u67b6\u542f\u52a8\u65f6\u65e0\u6cd5\u52a0\u8f7d\u672a\u88ab\u5f15\u7528\u7684\u7a0b\u5e8f\u96c6 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3A3Z4"},"#I3A3Z4")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCoreRepository.IsAttached()")," \u65b9\u6cd5\u5224\u65ad\u9519\u8bef bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3A824"},"#I3A824")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"\u52a8\u6001API")," \u9a7c\u5cf0\u663e\u793a\u914d\u7f6e\u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AF32"},"#I3AF32")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"cli.ps1")," \u4e0d\u652f\u6301\u65b0\u7248\u672c ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3APO9"},"#I3APO9")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u5b9e\u4f53\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"[Table]")," \u7279\u6027\u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BAYH"},"#I3BAYH")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u52a8\u6001 WebAPI ",(0,r.kt)("inlineCode",{parentName:"li"},"CheckIsSplitCamelCase")," bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BLKX"},"#I3BLKX")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u52a8\u6001 WebAPI \u914d\u7f6e\u4fdd\u7559 Action \u7684 Async \u540e\u7f00\u65e0\u6548\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3C3DA"},"#I3C3DA")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT")," Token \u5237\u65b0\u540e\u65e7\u7684\u5237\u65b0 Token \u4f9d\u65e7\u53ef\u7528 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3C8ZH"},"#I3C8ZH")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u8bed\u8a00 ",(0,r.kt)("inlineCode",{parentName:"li"},"Razor")," \u89c6\u56fe\u53d8\u91cf\u591a\u8bed\u8a00\u4e71\u7801\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CBMU"},"#I3CBMU")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u9ed8\u8ba4\u5e8f\u5217\u5316\u63d0\u4f9b\u5668 ",(0,r.kt)("inlineCode",{parentName:"li"},"System.Text.Json")," \u53cd\u5e8f\u5217\u5316\u5b57\u7b26\u4e32\u65f6\u533a\u5206\u5927\u5c0f\u5199\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BSXV"},"#I3BSXV")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u4f18\u5316 ",(0,r.kt)("inlineCode",{parentName:"li"},"MessageCenter")," \u6027\u80fd\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39PRR"},"#I39PRR")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6c60\u5c0f\u6027\u80fd\u4f18\u5316"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Docker")," \u73af\u5883\u4e0b\u81ea\u52a8\u5316\u90e8\u7f72 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/209"},"#PR209")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON")," \u5e8f\u5217\u5316 \u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3B6D8"},"#I3B6D8")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u8de8\u57df\u3001\u5b89\u5168\u6388\u6743\u3001\u5373\u65f6\u901a\u4fe1\u6587\u6863\u3001\u591a\u8bed\u8a00\u3001\u89c4\u8303\u5316\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.DatabaseAccessor.SqlSugar")," \u914d\u7f6e\u591a\u4e2a\u6570\u636e\u5e93\u6253\u5370 SQL \u8bed\u53e5\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39PDC"},"#I39PDC")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ORACLE")," \u6570\u636e\u5e93\u591a\u79df\u6237\u6a21\u5f0f\u4e0b\u8fd4\u56de\u503c\u4e3a\u6307\u5b9a\u7c7b\u578b\u65f6\u7cfb\u7edf\u5361\u6b7b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39RNH"},"#I39RNH")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5047\u5220\u9664\u6307\u5411\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I39XZA"},"#I39XZA")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u591a\u8bed\u8a00\u914d\u7f6e\u8282\u662f\u653e\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"AppSettings")," \u91cc\u9762\u8fd8\u662f\u5916\u9762\u5462\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3A4SB"},"#I3A4SB")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6ca1\u627e\u5230\u6570\u636e\u5e93\u4e0a\u4e0b\u6587 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3A5HS"},"#I3A5HS")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u6709 ",(0,r.kt)("inlineCode",{parentName:"li"},"QQ")," \u4ea4\u6d41\u7fa4\u5417\uff1f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AAM7"},"#I3AAM7")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Vue3")," \u73af\u5883\u4e0b\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"SignalR")," \u8de8\u57df\u51fa\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ALQ7"},"#I3ALQ7")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u53c2\u6570\u975e\u5fc5\u586b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AT02"},"#I3AT02")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," EFCore \u8c03\u7528 Insert \u65f6\u62a5 ",(0,r.kt)("inlineCode",{parentName:"li"},"Unknown column 'Discriminator' in 'field list'")," \u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3B2LC"},"#I3B2LC")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u9006\u5411 ",(0,r.kt)("inlineCode",{parentName:"li"},"mysql")," \u6570\u636e\u5e93\u65f6 ",(0,r.kt)("inlineCode",{parentName:"li"},"cli")," \u51fa\u73b0\u9519\u8bef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3B64F"},"#I3B64F")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Sql \u9ad8\u7ea7\u4ee3\u7406\u4f7f\u7528\u8fc7\u7a0b\u4e2d DateTime \u7c7b\u578b\u7684\u53c2\u6570\u5e8f\u5217\u5316\u5931\u8d25 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AZXK"},"#I3AZXK")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u4f7f\u7528 Mysql \u6267\u884c Add-Migration \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3B8EW"},"#I3B8EW")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," Saas \u591a\u79df\u6237\u6a21\u5f0f-\u72ec\u7acb Database \u6a21\u5f0f\u4e0b\u65e0\u6cd5\u83b7\u53d6 Tenant, \u5bfc\u81f4\u65e0\u6cd5\u81ea\u52a8\u5207\u6362\u7684\u95ee\u9898",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AVXU"},"#I3AVXU")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5982\u4f55\u81ea\u5b9a\u4e49 WebAPI \u7edf\u4e00\u7ed3\u679c\u6a21\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BBYW"},"#I3BBYW")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BBYV"},"#I3BBYV")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Web.Entry")," \u9879\u76ee\u65b0\u5efa\u4e86\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"Controller"),"\uff0c\u591a\u4e86\u672a\u77e5\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BKH5"},"#I3BKH5")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AOP")," \u62e6\u622a\u5982\u4f55\u89e3\u6790\u670d\u52a1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BUM3"},"#I3BUM3")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u52a8\u6001 WebAPI \u8fd4\u56de\u53c2\u6570\u88ab\u7701\u7565 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3C2XR"},"#I3C2XR")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5982\u4f55\u8bbe\u7f6e\u67d0\u4e00\u4e2a\u63a5\u53e3\u54cd\u5e94\u6570\u636e\u4e0d\u81ea\u52a8\u8f6c\u5c0f\u5199\uff0c\u6309\u539f\u59cb\u5b57\u6bb5\u540d\u8fd4\u56de ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38L9B"},"#I38L9B")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," code first \u5982\u4f55\u914d\u7f6e\u81ea\u52a8\u8fc1\u79fb ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CCR0"},"#I3CCR0")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," webapi \u6df7\u5408\u6388\u6743\u5982\u4f55\u533a\u5206\u4e0d\u540c\u7cfb\u7edf ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CJCY"},"#I3CJCY")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," EFCore \u4e0d\u652f\u6301\u9012\u5f52\u65e0\u9650\u7ea7\u904d\u5386\u5173\u7cfb ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3CET9"},"#I3CET9")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u53ef\u914d\u7f6e\u5916\u952e\u5173\u7cfb\u5bfc\u822a\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3994X"},"#I3994X")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae\u5c06 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u5265\u79bb\u51fa\u6765\uff0c\u4f5c\u4e3a\u63d2\u4ef6\u7684\u5f62\u5f0f\u63d0\u4f9b\u3002\u8fd9\u6837\u53ef\u4ee5\u9009\u62e9\u81ea\u5df1\u559c\u6b22\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ORM")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ABNX"},"#I3ABNX")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u4e8b\u4ef6\u603b\u7ebf\u80fd\u5426\u63d0\u4f9b\u8fd4\u56de\u503c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AWL6"},"#I3AWL6")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," Sql \u6a21\u677f\u80fd\u4eff\u7167 Mybatis \u4e00\u6837\u52a0\u5404\u79cd\u6807\u7b7e\u5417\uff1f",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3ASRS"},"#I3ASRS")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," EFCore \u66f4\u65b0\u6216\u6392\u9664\u66f4\u65b0\u6307\u5b9a\u5217\u652f\u6301\u4f20\u5165 DTO \u6a21\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3AS5K"},"#I3AS5K")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"UnitOfWork")," \u4e8b\u52a1\u5b8c\u6210\u4e8b\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3BRMI"},"#I3BRMI"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v1150-\u5df2\u53d1\u5e03"},"v1.15.0 \uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8df3\u8fc7\u7279\u5b9a\u5b9e\u4f53\u6570\u636e\u5e93\u64cd\u4f5c\u76d1\u542c\u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I386LB"},"#I386LB")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntityChangedListener")," \u589e\u52a0\u5bf9 ",(0,r.kt)("inlineCode",{parentName:"li"},"OldEntity")," \u7684\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I385X2"},"#I385X2")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9e\u65f6\u901a\u4fe1\u81ea\u52a8\u914d\u7f6e\u96c6\u7ebf\u5668\u62d3\u5c55\u53ca\u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I387QX"},"#I387QX")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mapster")," \u62d3\u5c55\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"IMapper")," \u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38C7C"},"#I38C7C")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[AppDbContext]")," \u7279\u6027\u9ed8\u8ba4\u6784\u9020\u51fd\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38J97"},"#I38J97")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"UnifyContext.GetExceptionMetadata(context)")," \u8fd4\u56de\u9519\u8bef\u7801\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38ONX"},"#I38ONX")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u6b21\u5faa\u73af\u4e2d\u8c03\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetNewDbContext()")," \u8fd8\u662f\u83b7\u53d6\u5230\u540c\u4e00\u4e2a\u5bf9\u8c61 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38NNP"},"#I38NNP")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u8fc7\u6ee4\u6389 ",(0,r.kt)("inlineCode",{parentName:"li"},"object ")," \u7c7b\u578b\u5c5e\u6027\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38FHL"},"#I38FHL")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u540c\u4e00\u7c7b\u4e0d\u652f\u6301\u591a\u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntityChangedListener")," \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38UQJ"},"#I38UQJ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u5b9a\u4e49\u5e8f\u5217\u5316\u5c5e\u6027\u540d\u79f0\u5bfc\u81f4\u9a8c\u8bc1\u5931\u8d25\u5c5e\u6027\u4e0d\u5339\u914d\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38W8Z"},"#I38W8Z")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u4ee3\u7801\u4e0d\u89c4\u8303\u547d\u540d\u5bfc\u81f4\u5f00\u53d1\u8005\u9605\u8bfb\u4ee3\u7801\u65f6\u4ea7\u751f\u6b67\u4e49"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"FluentValidation")," \u96c6\u6210\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38IOT"},"#I38IOT")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6846\u67b6\u7248\u672c\u5411\u4e0b\u517c\u5bb9\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38WMZ"},"#I38WMZ")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u6dfb\u52a0\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38G4M"},"#I38G4M")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae ",(0,r.kt)("inlineCode",{parentName:"li"},"MessageCenter")," \u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Channel")," \u5b9e\u73b0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38BP8"},"#I38BP8")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae\u63a5\u53e3\u6587\u6863\u6574\u5408 Knife4jUI \u6216 Redoc ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I38S70"},"#I38S70"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v1140\u5df2\u53d1\u5e03"},"v1.14.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," 5.0 \u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oracle")," \u6570\u636e\u5e93\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37Z8E"},"#I37Z8E")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u63a7\u5236\u662f\u5426\u5728\u5f00\u53d1\u73af\u5883\u4e0b\u663e\u793a\u6570\u636e\u5e93\u8fde\u63a5\u4fe1\u606f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37YQ2"},"#I37YQ2")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[NonUnify]")," \u652f\u6301\u5728\u7c7b\u4e2d\u8d34\u6b64\u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I359Q6"},"#I359Q6")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"\u7f51\u7edc\u8bf7\u6c42")," \u5b57\u7b26\u4e32 ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpClient")," \u62e6\u622a\u5668 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I35F3E"},"#I35F3E")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContext")," \u53ca ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpRequest")," \u83b7\u53d6\u8fdc\u7a0b\u5730\u5740\u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3688Z"},"#I3688Z")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddMvcFilter<>")," \u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Mvc")," \u8fc7\u6ee4\u5668\u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I368BH"},"#I368BH")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," \u6846\u67b6\u4f9d\u8d56\u7684 .NET 5 SDK \u81f3\u6700\u65b0\u7248 5.0.3 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37YQQ"},"#I37YQQ")),(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swashbuckle.AspNetCore")," \u7ec4\u4ef6\u5305\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"6.0.x")," \u7248\u672c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37EZK"},"#I37EZK")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6846\u67b6 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT")," \u62d3\u5c55\u7c7b\uff0c\u53ea\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.Authentication.JwtBearer")," \u4e2d\u4fdd\u7559 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I35D59"},"#I35D59")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4f20\u5165\u9519\u8bef ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT Token")," \u5b57\u7b26\u4e32\u5bfc\u81f4\u81ea\u52a8\u5237\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u51fa\u73b0\u5b57\u7b26\u4e32\u8fb9\u754c\u503c\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34ZE5"},"#I34ZE5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u77ac\u65f6\u4f5c\u7528\u57df\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e5f\u4f1a\u81ea\u52a8\u52a0\u5165\u5de5\u4f5c\u5355\u5143\u5bfc\u81f4\u5199\u65e5\u5fd7\u65f6\u8fde\u9501\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37WTV"},"#I37WTV")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u83b7\u53d6\u7cfb\u7edf\u73af\u5883\u53c2\u6570\u7684\u6027\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36SR5"},"#I36SR5")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u5e95\u5c42\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Mvc")," \u8fc7\u6ee4\u5668\u4ee3\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36SKA"},"#I36SKA")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u6dfb\u52a0\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Json")," \u5e8f\u5217\u5316\u65f6\u95f4\u9ed8\u8ba4\u65f6\u95f4\u683c\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36SL0"},"#I36SL0")),(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," \u5347\u7ea7 ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u62d3\u5c55\u5305\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"5.0.2.6")," \u7248\u672c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36SIG"},"#I36SIG")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6570\u636e\u5e93\u5165\u95e8\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37Z8S"},"#I37Z8S")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u66f4\u65b0\u65e5\u5fd7\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36PI0"},"#I36PI0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7\u3001\u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u66f4\u65b0\u65e5\u5fd7\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36PIK"},"#I36PIK")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u524d\u7aef\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"axios")," \u8de8\u57df\u914d\u7f6e\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36PIT"},"#I36PIT")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App")," \u9759\u6001\u7c7b\u83b7\u53d6\u5e94\u7528\u3001\u73af\u5883\u66f4\u591a\u4fe1\u606f\u6570\u636e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I36SOV"},"#I36SOV")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u82f1\u6587\u7248 ",(0,r.kt)("inlineCode",{parentName:"li"},"README.md")," \u4ecb\u7ecd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37QHP"},"#I37QHP")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u591a\u8bed\u8a00\u8d44\u6e90\u6587\u4ef6\u81ea\u52a8\u521b\u5efa ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I35AA4"},"#I35AA4")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae\u591a\u8bed\u8a00\u52a0\u4e0a\u7ef4\u543e\u5c14\u8bed\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I37X1L"},"#I37X1L"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v1130\u5df2\u53d1\u5e03"},"v1.13.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u591a\u8bed\u8a00\u529f\u80fd\u53ca\u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DOCL"},"#I2DOCL")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4e8b\u4ef6\u603b\u7ebf\u529f\u80fd\u53ca\u6d88\u606f\u4e2d\u5fc3 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I23BKN"},"#I23BKN")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5206\u7ec4\u663e\u793a\u9690\u85cf\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AHH8"},"#I2AHH8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.Logging.Serilog")," \u62d3\u5c55\u63d2\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AAN8"},"#I2AAN8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"cli.ps")," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"-Namespace")," \u547d\u540d\u7a7a\u95f4\u6307\u5b9a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2A175"},"#I2A175")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u89c4\u8303\u5316\u5316\u6587\u6863\u6388\u6743\u5931\u6548\u540e\u81ea\u52a8\u53d6\u6d88\u6388\u6743\u9501 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AIWC"},"#I2AIWC")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Request.Body")," \u652f\u6301\u91cd\u590d\u8bfb\u529f\u80fd\uff0c\u4e3b\u8981\u89e3\u51b3\u5fae\u4fe1 SDK \u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AMG0"},"#I2AMG0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7f51\u7edc\u8bf7\u6c42\u529f\u80fd\u53ca\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2APGJ"},"#I2APGJ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u62d3\u5c55\u5305\u652f\u6301\u6253\u5370 ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"MiniProfiler")," \u4e2d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2ASLS"},"#I2ASLS")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.DatabaseAccesssor.Dapper")," \u62d3\u5c55\u63d2\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2ASYA"},"#I2ASYA")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.DatabaseAccessor.PetaPoco")," \u62d3\u5c55\u63d2\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AUGA"},"#I2AUGA")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7f51\u7edc\u8bf7\u6c42\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CPQ0"},"#I2CPQ0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u62d3\u5c55\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"PagedList")," \u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CW99"},"#I2CW99")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u652f\u6301\u53c2\u6570\u7279\u6027\u9a8c\u8bc1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CX5L"},"#I2CX5L")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.User")," \u83b7\u53d6\u5f53\u524d\u6388\u6743\u7528\u6237\u4fe1\u606f\u4fbf\u6377\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CZLO"},"#I2CZLO")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c4\u8303\u5316\u6587\u6863\u53ef\u914d\u7f6e\u529f\u80fd\uff0c\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"appsettings.json")," \u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D1K9"},"#I2D1K9")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u62e6\u622a\u5668\u6dfb\u52a0\u65b9\u6cd5\u548c\u65b9\u6cd5\u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D2CM"},"#I2D2CM")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42\u51fa\u9519\u8fd4\u56de\u9ed8\u8ba4\u503c\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D44M"},"#I2D44M")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"body")," \u53c2\u6570\u5e8f\u5217\u5316\u652f\u6301\u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"PropertyNamingPolicy")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D685"},"#I2D685")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8fdc\u7a0b\u670d\u52a1\u63a5\u53e3\u5ba2\u6237\u7aef\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D7PS"},"#I2D7PS")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AddInject")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"UseInject")," \u5141\u8bb8\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},"SecurityDefinitions")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"SwaggerUI")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DIMG"},"#I2DIMG")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[SecurityDefine]")," \u9ed8\u8ba4\u6784\u9020\u51fd\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DNXT"},"#I2DNXT")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AspectDispatchProxy")," \u52a8\u6001\u4ee3\u7406\u7c7b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DO6I"},"#I2DO6I")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[QueryParameters]")," \u7279\u6027\uff0c\u652f\u6301\u4e00\u952e\u5c06 ",(0,r.kt)("inlineCode",{parentName:"li"},"Action")," \u53c2\u6570\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"[FromQuery]")," \u7279\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2G8TF"},"#I2G8TF")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001\u65e5\u5fd7\u914d\u7f6e\u53ca\u62d3\u5c55\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2GDGD"},"#I2GDGD")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"WebApi")," \u8bf7\u6c42\u8c13\u8bcd\u9ed8\u8ba4\u89c4\u5219\u914d\u7f6e\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2M70X"},"#I2M70X")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".NET 5")," SDK \u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},".NET 5.0.2")," \u7248\u672c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D0PZ"},"#I2D0PZ")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u6846\u67b6\u5185\u6240\u6709\u62d3\u5c55\u7c7b\u547d\u540d\u7a7a\u95f4\uff0c\u5168\u90e8\u8fc1\u79fb\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.\u6a21\u5757.Extensions")," \u4e0b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AH54"},"#I2AH54")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u8bb0\u4f4f\u6388\u6743\u5b58\u50a8\u65b9\u5f0f\uff0c\u66ff\u6362 ",(0,r.kt)("inlineCode",{parentName:"li"},"Session")," \u5b58\u50a8\u65b9\u5f0f\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"LocalStorage")," \u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AKUA"},"#I2AKUA")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6846\u67b6\u5305\u63cf\u8ff0\u6587\u4ef6\uff0c\u51cf\u5c11\u6846\u67b6\u4f53\u79ef ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2APAU"},"#I2APAU")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.CanBeScanTypes")," \u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"App.EffectiveTypes")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2B0ZR"},"#I2B0ZR")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.ServiceProvider")," \u5c5e\u6027\u5e76\u79fb\u9664 ",(0,r.kt)("inlineCode",{parentName:"li"},"App.GetDuplicateXXX")," \u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CYZE"},"#I2CYZE")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetDuplicateDbContext")," \u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetNewDbContext")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CZ04"},"#I2CZ04")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetSqlDispatchProxy")," \u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetSqlProxy")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DO9T"},"#I2DO9T")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Aop")," \u670d\u52a1\u62e6\u622a\u5668\uff0c\u652f\u6301\u5f02\u6b65\u3001\u540c\u6b65\u4e24\u79cd\u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2B9HQ"},"#I2B9HQ")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u7f51\u7edc\u8bf7\u6c42\u6240\u6709\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BMR7"},"#I2BMR7")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u89c4\u8303\u5316\u5316\u7ed3\u679c\u4e0d\u4e00\u81f4 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2ACF3"},"#I2ACF3")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u65b0\u589e\u6216\u66f4\u65b0\u5ffd\u7565\u7a7a\u503c\u64cd\u4f5c\u65b9\u6cd5\u62a5\u7a7a\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AB6C"},"#I2AB6C")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Startup.cs")," Aop \u5168\u5c40\u62e6\u622a\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2A7T2"},"#I2A7T2")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u8fc7\u671f\u540e\u81ea\u52a8\u5237\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u65e0\u6cd5\u83b7\u53d6\u6700\u65b0\u7684\u7528\u6237\u4fe1\u606f bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AWQI"},"#I2AWQI")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},'[ApiDescriptionSettings(Tag="xx")]')," \u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"li"},"swagger.json")," \u62a5\u9519 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2B47R"},"#I2B47R")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mysql")," sql \u6570\u636e\u5e93\u67e5\u8be2\u7ed3\u679c ",(0,r.kt)("inlineCode",{parentName:"li"},"tinyint")," \u7c7b\u578b\u8f6c\u6362\u51fa\u9519 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BEBM"},"#I2BEBM")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c4\u8303\u5316\u7ed3\u679c\u591a\u6b21\u5305\u88f9\u7c7b\u578b bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BHHZ"},"#I2BHHZ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u52a8\u6001 Api \u57fa\u5143\u7c7b\u578b\u6570\u7ec4\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BMS5"},"#I2BMS5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u67e5\u8be2\u679a\u4e3e\u7c7b\u578b\u8f6c\u6362\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BS2Y"},"#I2BS2Y")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"string.SqlQuerizeAsync()")," \u62d3\u5c55\u8fd4\u56de\u9519\u8bef bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BSTS"},"#I2BSTS")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u52a8\u6001 Api \u5b50\u7c7b\u91cd\u5199\u7236\u7c7b\u65b9\u6cd5\u5e76\u53d6\u522b\u540d\u540e ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2C9VP"},"#I2C9VP")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u7f51\u7edc\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"application/json")," \u5e8f\u5217\u5316\u5927\u5c0f\u5199\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CRJC"},"#I2CRJC")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u6570\u636e\u5e93\u5b9a\u4f4d\u5668\u5b9e\u4f53\u5d4c\u5957\u5173\u8054 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CVN0"},"#I2CVN0")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8de8\u57df\u54cd\u5e94\u5934\u8bbe\u7f6e\u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CW5T"},"#I2CW5T")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u7f51\u7edc\u8bf7\u6c42\u4ee3\u7406\u6253\u5370\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"MiniProfiler")," bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CZBC"},"#I2CZBC")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8fdc\u7a0b\u8bf7\u6c42\u54cd\u5e94\u62e6\u622a\u5668 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D4DG"},"#I2D4DG")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u6846\u67b6 ",(0,r.kt)("inlineCode",{parentName:"li"},"AsQueryable()")," \u4e00\u76f4\u8ffd\u52a0\u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DH1D"},"#I2DH1D")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u52a8\u5237\u65b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u7a7a\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DO29"},"#I2DO29")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT Token")," \u4e0d\u4f20\u8fc7\u671f\u65f6\u95f4\u51fa\u73b0\u9a8c\u8bc1 401 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DO8L"},"#I2DO8L")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppStartup")," \u6392\u5e8f\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DVD2"},"#I2DVD2")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u672a\u542f\u7528\u591a\u8bed\u8a00\u670d\u52a1\u65f6\u53cb\u597d\u5f02\u5e38\u548c\u9a8c\u8bc1\u51fa\u73b0\u7a7a\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2ECUJ"},"#I2ECUJ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u6821\u9a8c\u5b57\u6bcd\u548c\u6570\u5b57\u7ec4\u5408\u65e0\u6cd5\u5339\u914d bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2EF2Q"},"#I2EF2Q")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u6821\u9a8c\u624b\u673a\u6216\u56fa\u8bdd\u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2M5IZ"},"#I2M5IZ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Dapper")," \u62d3\u5c55\u89e3\u6790 ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlConnection")," \u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2M5P2"},"#I2M5P2")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5f00\u542f\u591a\u8bed\u8a00\u540e\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"EF")," \u8fc1\u79fb\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2M7DT"},"#I2M7DT")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntityTypeBuilder")," \u4e0d\u652f\u6301\u591a\u91cd\u7ee7\u627f bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2PAOD"},"#I2PAOD")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JwtHandler")," \u8bbe\u7f6e\u81ea\u52a8\u5237\u65b0\u540e\uff0c\u533f\u540d\u8bbf\u95ee\u65e0\u6cd5\u901a\u8fc7 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2SDOX"},"#I2SDOX")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Dapper")," \u62d3\u5c55\u4e2d ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlServer")," \u6570\u636e\u5e93\u83b7\u53d6\u8fde\u63a5\u5bf9\u8c61\u7c7b\u578b bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/159"},"#PR159")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u79fb\u9664 ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u67e5\u8be2\u7ed3\u679c\u6620\u5c04\u68c0\u67e5 ",(0,r.kt)("inlineCode",{parentName:"li"},"[NotMapper]")," \u7279\u6027\u673a\u5236 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XD0"},"#I34XD0")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u4f9d\u8d56\u6ce8\u5165\u65f6\u6392\u9664 ",(0,r.kt)("inlineCode",{parentName:"li"},"IDynamicApiController")," \u63a5\u53e3 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2ECTG"},"#I2ECTG")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MD5")," \u52a0\u5bc6\u6027\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/158"},"#PR158")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u6587\u6863\u9996\u9875 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XBR"},"#I34XBR")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7f51\u7edc\u8bf7\u6c42\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2APGJ"},"#I2APGJ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u591a\u8bed\u8a00\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DOCL"},"#I2DOCL")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6587\u6863\u5168\u6587\u641c\u7d22\u5f15\u64ce ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XAW"},"#I34XAW")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u9759\u6001\u7c7b\u7c7b\u578b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XB4"},"#I34XB4")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6846\u67b6\u53ef\u914d\u7f6e\u9009\u9879\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XB9"},"#I34XB9")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u4e8b\u4ef6\u603b\u7ebf\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XBI"},"#I34XBI")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6570\u636e\u52a0\u89e3\u5bc6\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XC0"},"#I34XC0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u8d21\u732e\u6307\u5357\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XC8"},"#I34XC8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContext")," \u53ca ",(0,r.kt)("inlineCode",{parentName:"li"},"\u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d")," \u535a\u5ba2\u6587\u7ae0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I34XCB"},"#I34XCB")),(0,r.kt)("li",{parentName:"ul"},"[\u5176\u4ed6]"," \u6587\u6863\u5c0f\u8c03\u6574\uff0c\u5c0f\u4f18\u5316"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u8de8\u57df\u8bbe\u7f6e\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2ASNJ"},"#I2ASNJ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MVC")," \u89c6\u56fe\u65e0\u6548\uff0c\u539f\u56e0\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},".cshtml")," \u6587\u4ef6\u6ca1\u6709\u8bbe\u7f6e\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"\u5185\u5bb9")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AXUU"},"#I2AXUU")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\u53ef\u4ee5\u5b9e\u73b0\u4e8b\u52a1\u5417\uff1f",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2B0NX"},"#I2B0NX")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IRepository")," \u64cd\u4f5c\u6570\u636e\u5e93\u4f1a\u6253\u5f00\u591a\u6b21\u6570\u636e\u5e93\u8fde\u63a5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BB7B"},"#I2BB7B")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5982\u4f55\u8fdb\u5165\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},"AppAuthorizeHandler")," \u65ad\u70b9 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BGXY"},"#I2BGXY")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u6ce8\u5165\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2C2AQ"},"#I2C2AQ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5efa\u8bae\u589e\u52a0 API \u7b7e\u540d\u9a8c\u8bc1\uff0c\u65f6\u6548\u9a8c\u8bc1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2C6ET"},"#I2C6ET")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u591a\u6570\u636e\u5e93\u591a\u79df\u6237\u540c\u65f6\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Add-Migration")," \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CEHS"},"#I2CEHS")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ISqlSugarRepository")," \u6ca1\u6709 ",(0,r.kt)("inlineCode",{parentName:"li"},"Getxxx")," \u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CJLZ"},"#I2CJLZ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"cli.ps1")," \u5982\u4f55\u5c06 ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u91cc\u7684\u8868\u5bfc\u51fa\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"model")," \u7c7b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CSUL"},"#I2CSUL")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u624b\u52a8\u4fee\u6539 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u7ec8\u7ed3\u70b9\u8def\u5f84\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D608"},"#I2D608")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DefaultDbContext")," \u4e0d\u80fd\u8bc6\u522b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DCZX"},"#I2DCZX")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5404\u5206\u5c42\u9879\u76ee ",(0,r.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Configuration")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DDUP"},"#I2DDUP")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Aop")," \u65e0\u6cd5\u62e6\u622a\uff0c\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DEY8"},"#I2DEY8")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"mysql")," \u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"Add-Migration")," \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DSB8"},"#I2DSB8"),"\\"),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Entity")," \u521b\u5efa\u65f6\u95f4\u548c\u662f\u5426\u5220\u9664\u6dfb\u52a0\u9ed8\u8ba4\u503c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2E04H"},"#I2E04H")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"swagger")," \u4e2d\u591a\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"servers")," \u8bbe\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2E0IF"},"#I2E0IF")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5168\u5c40\u7b5b\u9009\u5668 \u6ca1\u6709\u6267\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2E5R4"},"#I2E5R4")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u591a\u6570\u636e\u5e93\u5b9a\u4f4d\u5668\u7591\u95ee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2E77T"},"#I2E77T")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"cli.ps")," \u9006\u5411\u5de5\u7a0b ",(0,r.kt)("inlineCode",{parentName:"li"},"Mysql")," \u6570\u636e\u5e93\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2E7I5"},"#I2E7I5")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5f00\u53d1\u73af\u5883 ",(0,r.kt)("inlineCode",{parentName:"li"},"applicationsettings.json")," \u4e2d\u6587\u4e71\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2EAG1"},"#I2EAG1")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u589e\u52a0\u6307\u5b9a\u8def\u5f84\u7a0b\u5e8f\u96c6\u6620\u5c04 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2EEO2"},"#I2EEO2")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u52a8\u6001\u7f16\u8bd1 ",(0,r.kt)("inlineCode",{parentName:"li"},"cs")," \u811a\u672c\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2EH66"},"#I2EH66")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6\uff0c\u8fd4\u56de\u7684\u9519\u8bef\u6ca1\u6709\u89c4\u8303\u5316\u7ed3\u679c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2NV8S"},"#I2NV8S")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5faa\u73af\u5f15\u7528\u8bbe\u7f6e\u751f\u6210\u6587\u6863\u5c42\u7ea7\u65e0\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2PLQQ"},"#I2PLQQ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u914d\u7f6e\u6587\u4ef6\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"yaml")," \u6587\u4ef6\u5417? ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2TJ3N"},"#I2TJ3N")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u4fee\u6539\u6570\u636e\u5e93\u672a ",(0,r.kt)("inlineCode",{parentName:"li"},"mysql")," \u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"Add-Migration")," \u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2VR64"},"#I2VR64")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u591a\u6570\u636e\u5e93\u4f7f\u7528\u5b9a\u4f4d\u5668\u65f6\u62a5\u9519 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2VR8F"},"#I2VR8F")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Migration To Oracle")," \u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2WBYQ"},"#I2WBYQ")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5f00\u53d1\u65f6\u663e\u793a ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger"),"\uff0c\u4e0a\u7ebf\u65f6\u5173\u95ed ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger"),"\uff0c\u8fd9\u9700\u8981\u600e\u4e48\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2WOYV"},"#I2WOYV")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u517c\u5bb9 Mvc \u590d\u6742\u9a8c\u8bc1\u6ca1\u6709\u8bd5\u9a8c\u6210\u529f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2X3GV"},"#I2X3GV")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Aop")," \u80fd\u4e0d\u80fd\u652f\u6301\u65e0\u63a5\u53e3\u7684\u7c7b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2X8AS"},"#I2X8AS")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT Token")," \u81ea\u52a8\u5237\u65b0\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2YD4K"},"#I2YD4K")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u80fd\u5426\u589e\u52a0\u4e00\u4e2a\u62d3\u5c55\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Entity"),"\uff0c\u589e\u52a0\u4e00\u4e9b\u62d3\u5c55\u7684\u5c5e\u6027 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2YDKT"},"#I2YDKT")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u65e0\u6cd5\u8fd8\u539f\u5305\uff0c\u4f7f\u7528",(0,r.kt)("inlineCode",{parentName:"li"},"Nuget")," \u4e0b\u8f7d\u548c\u901a\u8fc7\u6700\u65b0\u7684\u7684\u811a\u624b\u67b6\u4e0b\u8f7d\u90fd\u63d0\u793a\u8fd9\u4e2a\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I30446"},"#I30446")),(0,r.kt)("li",{parentName:"ul"},"[\u7b54\u7591]"," \u590d\u6742\u6821\u9a8c\u4e0e\u7279\u6027\u9a8c\u8bc1\u4e0d\u80fd\u5e76\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I3046U"},"#I3046U")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5f15\u5165 Webhook \u673a\u5236 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2A3I0"},"#I2A3I0")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u589e\u52a0 blog \u5b58\u50a8\u670d\u52a1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AMBP"},"#I2AMBP")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," Blazor Server \u73af\u5883\u4e0b EF \u7684 DbContext \u591a\u7ebf\u7a0b\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AMD2"},"#I2AMD2")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5e0c\u671b\u5b9e\u73b0\u5de5\u4f5c\u5355\u5143\u64cd\u4f5c\u63a5\u53e3\uff08IUnitOfWork\uff09",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AOR5"},"#I2AOR5")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"string.ToPagedListAsync()")," \u64cd\u4f5c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2BZ3Z"},"#I2BZ3Z")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"GraphQL"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"OData")," \u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2C9EH"},"#I2C9EH")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u8feb\u5207\u671f\u671b\u652f\u6301 CAP \u5206\u5e03\u5f0f\u4e8b\u52a1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CBRF"},"#I2CBRF")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5982\u4f55\u8ba9\u67d0\u4e2a\u65b9\u6cd5\u6216\u5b9e\u4f53\u53d8\u5316\u540e\uff0c\u4e0d\u88ab ",(0,r.kt)("inlineCode",{parentName:"li"},"SavingChangesEvent")," \u7b49\u62e6\u622a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CEM9"},"#I2CEM9")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5efa\u8bae\u65e5\u5fd7\u5c01\u88c5\u589e\u52a0\u66f4\u591a\u62d3\u5c55\uff0c\u6bd4\u5982\uff1a\u81ea\u5b9a\u4e49\u4fdd\u5b58\u65e5\u5fd7\u6587\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2CW8V"},"#I2CW8V")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5bf9 ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u7684\u652f\u6301\uff0c\u589e\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Nuget")," \u811a\u624b\u67b6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2D91U"},"#I2D91U")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Middleware")," \u5b9e\u73b0\u53cd\u5411\u4ee3\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2DKM1"},"#I2DKM1")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u652f\u6301\u914d\u7f6e\u591a\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"Aop")," \u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2E6Z2"},"#I2E6Z2")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u662f\u5426\u8ba1\u5212\u5f00\u53d1\u7c7b\u4f3c\u7f51\u5173\u7684\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2PD1L"},"#I2PD1L")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"waring CS8002"),": \u5f15\u7528\u7a0b\u5e8f\u96c6 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6ca1\u6709\u5f3a\u540d\u79f0 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2WDN2"},"#I2WDN2")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," Oracle \u6570\u636e\u5e93\u9a71\u52a8\u96c6\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"Devart.Data.Oracle.Entity.EFCore")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2XJIU"},"#I2XJIU"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v170\u5df2\u53d1\u5e03"},"v1.7.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.ObjectMapper.Mapster")," \u62d3\u5c55\u5305 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29LSJ"},"#I29LSJ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.Logging.Serilog")," \u62d3\u5c55\u5305 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AAN8"},"#I2AAN8")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Extras.Web.HttpContext")," \u62d3\u5c55\u5305 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29LSM"},"#I29LSM")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5185\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u5237\u65b0\u673a\u5236\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29K57"},"#I29K57")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u652f\u6301\u8fd0\u884c\u65f6\u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"OnModelCreating")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28UDT"},"#I28UDT")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u652f\u6301\u4f9d\u8d56\u6ce8\u5165\u6392\u9664\u6307\u5b9a\u63a5\u53e3 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29693"},"#I29693")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c4\u8303\u5316\u7ed3\u679c\u8fd4\u56de\u65f6\u95f4\u6233\u5b57\u6bb5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29697"},"#I29697")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u57fa\u7840 ",(0,r.kt)("inlineCode",{parentName:"li"},"CURD")," \u7236\u7c7b\u64cd\u4f5c\u4f8b\u5b50 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I296SR"},"#I296SR")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},'sql.Change("\u5b9a\u4f4d\u5668\u5b8c\u6574\u7c7b\u578b\u540d\u79f0")')," \u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29LAB"},"#I29LAB")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"UpdateInclude")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"UpdateExclude")," \u5ffd\u7565\u7a7a\u53c2\u6570\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29VUG"},"#I29VUG")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5185\u7f6e\u5047\u5220\u9664\u67e5\u8be2\u8fc7\u6ee4\u5668\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29Y2R"},"#I29Y2R")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5ffd\u7565\u7a7a\u503c\u6392\u9664\u9ed8\u8ba4\u65f6\u95f4\u683c\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29VUV"},"#I29VUV")),(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MiniProfiler")," \u7ec4\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I297R9"},"#I297R9")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"AppAuthorizeHandler")," \u6388\u6743\u7ba1\u9053\u4e3a\u5f02\u6b65\u5904\u7406 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29MD9"},"#I29MD9")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u9ed8\u8ba4\u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"JWT")," \u6388\u6743\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29LI4"},"#I29LI4")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContextUtilities")," \u540d\u79f0\u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContextLocal")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29KQE"},"#I29KQE")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"UnifyResultContext")," \u540d\u79f0\u6539\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"UnifyContext")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29LLZ"},"#I29LLZ")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u53ea\u6709\u6267\u884c\u8fc1\u79fb\u547d\u4ee4\u624d\u626b\u63cf\u79cd\u5b50\u6570\u636e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29E6P"},"#I29E6P")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u89c4\u8303\u5316\u7ed3\u679c ",(0,r.kt)("inlineCode",{parentName:"li"},"Successed")," \u5c5e\u6027\u540d\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Succeeded")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29NMV"},"#I29NMV")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mapster")," \u5bf9\u8c61\u7ec4\u4ef6\uff0c\u91c7\u7528\u63d0\u4f9b\u62d3\u5c55\u65b9\u5f0f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29D2M"},"#I29D2M")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"CacheManager")," \u62d3\u5c55\u7c7b ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29LU1"},"#I29LU1")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SaveChanges")," \u62e6\u622a\u5668 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I292LO"},"#I292LO")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u672a\u6ce8\u518c\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e5f\u88ab\u5f15\u7528\u5168\u5c40\u67e5\u8be2\u62e6\u622a\u5668 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29ZXJ"},"#I29ZXJ")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u624b\u52a8\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"BadObjectResult")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationProblemDetails")," \u7ed3\u679c\u7c7b\u578b\u65f6\u89c4\u8303\u5316\u7ed3\u679c\u5931\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29ZU9"},"#I29ZU9")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u52a8\u6001 WebApi ",(0,r.kt)("inlineCode",{parentName:"li"},"KeepName"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"KeepVerb"),"\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"SplitCamelCase")," \u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29X90"},"#I29X90")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql\u4ee3\u7406")," \u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"\u5143\u7ec4")," \u7c7b\u578b\u51fa\u9519 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29SMV"},"#I29SMV")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"401\uff0c403")," \u72b6\u6001\u7801\u89c4\u8303\u5316\u8fd4\u56de\u503c\u5c5e\u6027\u53d8\u5927\u5199 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29M8Y"},"#I29M8Y")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContext")," \u7a7a\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29LU4"},"#I29LU4")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u63a5\u53e3\u65e0\u8fd4\u56de\u503c\u6ca1\u6709\u5e94\u7528\u89c4\u8303\u5316\u7ed3\u679c bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29GT7"},"#I29GT7")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u524d\u7aef ",(0,r.kt)("inlineCode",{parentName:"li"},"Less")," \u914d\u7f6e\u6587\u4ef6\u5bfc\u81f4\u4e3b\u673a\u542f\u52a8\u5931\u8d25 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29E7P"},"#I29E7P")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u7ed3\u679c\u8f6c\u6cdb\u578b\u540e\u5c5e\u6027\u91cd\u590d\u8d4b\u503c bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29BUO"},"#I29BUO")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5173\u95ed ",(0,r.kt)("inlineCode",{parentName:"li"},"MiniProfiler")," \u4e4b\u540e ",(0,r.kt)("inlineCode",{parentName:"li"},"\u7ec4\u4e2d\u7ec4")," \u5931\u6548 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29789"},"#I29789")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u672a\u542f\u7528\u89c4\u8303\u5316\u7ed3\u679c\u65f6\u5f02\u5e38\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"System.Object")," \u5b57\u7b26 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2969A"},"#I2969A")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6b63\u6570\u6570\u636e\u9a8c\u8bc1 0 \u4e5f\u9a8c\u8bc1\u901a\u8fc7 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2955T"},"#I2955T")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u975e\u6cdb\u578b\u7c7b\u96c6\u6210\u6cdb\u578b\u63a5\u53e3\u4f9d\u8d56\u6ce8\u5165 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I294YT"},"#I294YT")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"new")," \u8986\u76d6\u7236\u7c7b\u7684 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28Z1A"},"#I28Z1A")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JsonSerializerUtility")," \u6ca1\u6709\u516c\u5f00 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28WMI"},"#I28WMI")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlSugar")," \u62d3\u5c55\u67e5\u8be2\u6cdb\u578b\u7c7b\u578b\u6ce8\u518c\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28VMT"},"#I28VMT")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion Tools")," \u4e0d\u652f\u6301\u751f\u6210\u4e0d\u540c\u547d\u540d\u7a7a\u95f4\u7684\u5b9e\u4f53 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2A175"},"#I2A175")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5168\u5c40\u62e6\u622a\u5668\u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2A7T2"},"#I2A7T2")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u65b0\u589e\u6216\u66f4\u65b0\u5ffd\u7565\u7a7a\u503c\u7a7a\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2AB6C"},"#I2AB6C")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Token")," \u751f\u6210\u52a0\u5bc6\u7b97\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29KIH"},"#I29KIH")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u65e5\u5fd7\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28Y9D"},"#I28Y9D")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3001\u5b9e\u4f53\u62e6\u622a\u5668\u3001\u914d\u7f6e\u3001\u4e00\u5206\u949f\u5165\u95e8\u7b49\u7b49\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u95ee\u7b54]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5982\u4f55\u5b9e\u73b0\u6388\u6743\u8bbf\u95ee ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I294F2"},"#I294F2")),(0,r.kt)("li",{parentName:"ul"},"[\u95ee\u7b54]"," \u5982\u4f55\u5b9e\u73b0\u591a\u4e2a\u6570\u636e\u5e93\u591a\u5bf9\u591a\u5b9e\u4f53\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29G6S"},"#I29G6S")),(0,r.kt)("li",{parentName:"ul"},"[\u95ee\u7b54]"," \u52a8\u6001 WebApi \u652f\u6301\u6587\u4ef6\u4e0a\u4f20\u5417 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29R5E"},"#I29R5E")),(0,r.kt)("li",{parentName:"ul"},"[\u7591\u95ee]"," \u591a\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u65e0\u6cd5\u751f\u6210\u8fc1\u79fb\u4ee3\u7801 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2A6II"},"#I2A6II")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u4e0d\u505a\u5b9e\u73b0")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5b9e\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"BuildChange")," \u4f20\u5165\u8868\u540d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I292SN"},"#I292SN")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u6267\u884c\u6570\u636e\u5e93\u64cd\u4f5c\u7ed3\u679c\u4e0d\u652f\u6301\u5c5e\u6027\u5ffd\u7565\u5927\u5c0f\u5199\u8d4b\u503c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I29DRQ"},"#I29DRQ")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5f15\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"Webhook")," \u673a\u5236 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2A3I0"},"#I2A3I0"))))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v140\u5df2\u53d1\u5e03"},"v1.4.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u652f\u6301\u4e8c\u7ea7\u865a\u62df\u76ee\u5f55\u90e8\u7f72\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28B77"},"#I28B77")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Template.RazorWithWebApi")," \u811a\u624b\u67b6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28QGI"},"#I28QGI")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Template.BlazorWithWebApi")," \u811a\u624b\u67b6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27Z3O"},"#I27Z3O")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u65f6\u6001\u67e5\u8be2\u62d3\u5c55 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28AJ6"},"#I28AJ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[AppDbContext(\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u6570\u636e\u5e93\u7c7b\u578b)]")," \u914d\u7f6e\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28QTB"},"#I28QTB")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTimeOffset")," \u8f6c ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTime")," \u62d3\u5c55\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27MQA"},"#I27MQA")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationTypes")," \u9a8c\u8bc1\u6b63\u5219\u8868\u8fbe\u5f0f\u667a\u80fd\u63d0\u793a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2801V"},"#I2801V")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValiationTypes.WordWithNumber")," \u9a8c\u8bc1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2805A"},"#I2805")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u83b7\u53d6\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u7aef IP \u5730\u5740 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28QV9"},"#I28QV9")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5347\u7ea7]"," .NET 5.0 \u7248\u672c\u81f3 .NET 5.0.1 \u7248\u672c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28QU1"},"#I28QU")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u89c6\u56fe\u5f15\u64ce\u529f\u80fd\uff0c\u4f18\u5316\u4e0d\u89c4\u8303\u547d\u540d\u548c\u65b0\u589e\u5b57\u7b26\u4e32\u6a21\u677f\u7f16\u8bd1 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28G0S"},"#I28G0S")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u6570\u636e\u5e93\u5b9e\u4f53\u67e5\u627e\u7b97\u6cd5\uff0c\u5e76\u4f18\u5316\u6027\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28QUQ"},"#I28QUQ")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u5e94\u7528\u542f\u52a8\u521d\u59cb\u5316\u6027\u80fd\u548c\u6570\u636e\u5e93\u7b2c\u4e00\u6b21\u81ea\u52a8\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"DbSet")," \u6027\u80fd"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u914d\u7f6e\u5b9a\u4f4d\u5668\u540e\u5b9e\u4f53\u65e0\u6cd5\u6b63\u786e\u751f\u6210 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2888L"},"#I2888L")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9e\u4f53\u751f\u6210 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2891G"},"#I2891G")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5bf9\u8c61\u9a8c\u8bc1\u5931\u8d25\u63d0\u793a\u6d88\u606f\u6ca1\u6709\u5e94\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"JSON")," \u5927\u5c0f\u5199\u914d\u7f6e bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27UTX"},"#I27UTX")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4ed3\u50a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"Insert")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"li"},"Update")," \u65b9\u6cd5\u6307\u5b9a ",(0,r.kt)("inlineCode",{parentName:"li"},"ignoreNullValues")," \u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27UN6"},"#I27UN6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Controller")," \u6d3e\u751f\u7c7b\u5982\u679c\u8d34\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"[Route]")," \u7279\u6027\u540e\u51fa\u73b0\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e2d bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27TN7"},"#I27TN7")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlScalar")," \u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"Nullable")," \u7c7b\u578b\u51fa\u73b0\u8f6c\u6362\u5931\u8d25 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27S2N"},"#I27S2N")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[UnitOfWork]")," \u7279\u6027\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27MLM"},"#I27MLM")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u9759\u6001\u6267\u884c\u65b9\u5f0f\u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"sql")," \u9ad8\u7ea7\u4ee3\u7406\u65e0\u6cd5\u76d1\u542c\u6570\u636e\u5e93\u8fde\u63a5\u72b6\u6001 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27M4F"},"#I27M4F")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4fee\u590d\u66f4\u6362 Json \u5e8f\u5217\u5316\u5e93\u65e0\u6548 bug\uff0c\u5982\u66ff\u6362\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Microsoft.AspNetCore.Mvc.NewtonsoftJson")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27M43"},"#I27M43")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion Tools")," \u5de5\u5177\u751f\u6210\u6a21\u578b bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27XI5"},"#I27XI5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u8f6f\u5220\u9664\u6ca1\u6709\u751f\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2804I"},"#I2804I")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion Tools")," \u8bc6\u522b\u5e26\u591a\u4e2a ",(0,r.kt)("inlineCode",{parentName:"li"},"\\\\")," \u7684\u8fde\u63a5\u5b57\u7b26\u4e32\u8bc6\u522b bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I280TS"},"#I280TS"),"\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/91"},"#PR91")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion Tools")," \u65e0\u6cd5\u53d6\u6d88\u751f\u6210 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2816M"},"#I2816M")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTimeOffset")," \u8f6c\u672c\u5730\u65f6\u95f4\u5dee 8 \u5c0f\u65f6 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28BA9"},"#I28BA9")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"bundle js&css")," \u538b\u7f29\u540e\u542f\u52a8\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28KRP"},"#I28KR")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidationTypes.Required")," \u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/98"},"#PR98")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c4\u8303\u5316\u7ed3\u679c",(0,r.kt)("inlineCode",{parentName:"li"},"OnValidateFailed")," \u53c2\u6570\u540d\u62fc\u5199\u9519\u8bef bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/93"},"#PR93"),"\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/92"},"#PR92")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6388\u6743\u7ba1\u9053\u9a8c\u8bc1\u5931\u8d25\u8fd8\u663e\u793a\u7ed3\u679c bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/89"},"#PR89")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," README.md \u53cb\u60c5\u8fde\u63a5\u5730\u5740 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/88"},"#PR88")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u6a21\u677f\u811a\u624b\u67b6\u6e90\u7801\uff0c\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore Tools")," \u5e93 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/87"},"#PR87")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," README.md Nuget \u56fe\u6807 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/85"},"#PR85")),(0,r.kt)("li",{parentName:"ul"},"[\u5e9f\u5f03]"," \u5c06 ",(0,r.kt)("inlineCode",{parentName:"li"},"List")," \u8f6c ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTable")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/97"},"#PR97")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u89c6\u56fe\u5f15\u64ce\u6a21\u677f\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27ZVA"},"#I27ZVA")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u65f6\u6001\u67e5\u8be2\u6587\u6863 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28AJ6"},"#I28AJ"),", ",(0,r.kt)("a",{parentName:"li",href:"https://dotnetchina.gitee.io/furion/docs/dbcontext-hight-query/#91111-%E6%97%B6%E6%80%81%E6%9F%A5%E8%AF%A2"},"DOC")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u4ed3\u50a8\u6587\u6863\u4e66\u5199\u7eb0\u6f0f bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/90"},"#PR90")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u9009\u9879\u6587\u6863\u9519\u8bef bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/86"},"#PR86")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"\u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668")," \u6587\u6863\u4e66\u5199\u9519\u8bef bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/83/files"},"#PR83")),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3001\u591a\u6570\u636e\u5e93\u3001\u811a\u624b\u67b6\u7b49\u6587\u6863"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u7b54\u7b54\u7591")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5efa\u8bae]"," \u5e0c\u671b ",(0,r.kt)("inlineCode",{parentName:"li"},"api")," \u8fd4\u56de\u7684\u503c\u81ea\u52a8\u5c06 null \u8f6c\u4e3a '' \u6216 ","[][#I286IJ]","(",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I286IJ)%EF%BC%8C%E3%80%90%E5%B7%B2%E5%85%B3%E9%97%AD%E3%80%91"},"https://gitee.com/dotnetchina/Furion/issues/I286IJ)\uff0c\u3010\u5df2\u5173\u95ed\u3011")),(0,r.kt)("li",{parentName:"ul"},"[\u5efa\u8bae]"," \u6dfb\u52a0\u7f51\u5173\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27TP7"},"#I27TP7"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011"),(0,r.kt)("li",{parentName:"ul"},"[\u5efa\u8bae]"," \u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlQuery")," \u83b7\u53d6\u5355\u6761\u8bb0\u5f55\u65b9\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28M1V"},"#I28M1V"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011"),(0,r.kt)("li",{parentName:"ul"},"[\u5efa\u8bae]"," \u5e0c\u671b\u53ef\u4ee5\u63d0\u4f9b\u96c6\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"Serilog")," \u4f8b\u5b50 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I282J4"},"#I282J4"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011"),(0,r.kt)("li",{parentName:"ul"},"[\u7591\u95ee]"," \u5982\u4f55\u901a\u8fc7\u7279\u6027\u914d\u7f6e\u552f\u4e00\u7ea6\u675f ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2891L"},"#I2891L"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011"),(0,r.kt)("li",{parentName:"ul"},"[\u7591\u95ee]"," \u600e\u4e48\u8bfb\u53d6 ",(0,r.kt)("inlineCode",{parentName:"li"},"appsettings.json")," \u6570\u7ec4 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27WUR"},"#I27WU"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011"),(0,r.kt)("li",{parentName:"ul"},"[\u7591\u95ee]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"IRepository")," \u51fa\u73b0\u7a7a\u5f02\u5e38 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I281IE"},"#I281IE"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011"),(0,r.kt)("li",{parentName:"ul"},"[\u7591\u95ee]"," \u89c4\u8303\u5316\u63a5\u53e3\u95ee\u9898\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28NMZ"},"#I28NMZ"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011"),(0,r.kt)("li",{parentName:"ul"},"[\u7591\u95ee]"," \u7edf\u4e00\u8fd4\u56de\u503c\u6a21\u578b\u4e2d OnResponseStatusCodes \u672a\u6267\u884c ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I28NNL"},"#I28NNL"),"\uff0c\u3010\u5df2\u5173\u95ed\u3011")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v120\u5df2\u53d1\u5e03"},"v1.2.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u96ea\u82b1\u7b97\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26OXG"},"#I26OXG"),", ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/78"},"#PR78")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"[AppDbContext]")," \u914d\u7f6e\u6570\u636e\u5e93\u63d0\u4f9b\u5668\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27G3T"},"#I27G3T")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9e\u4f53\u8868\u6570\u636e\u66f4\u6539\u76d1\u542c\u63a5\u53e3 ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntityDataChangedListener")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I278DD"},"#I278DD"),", ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I278LQ"},"#I278LQ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u670d\u52a1\u63a5\u53e3 AOP \u62e6\u622a\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I278CP"},"#I278CP")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9a\u4f4d\u5668\u4ed3\u50a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"IDbRepository")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I276Q3"},"#I276Q3")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6570\u636e\u5e93\u64cd\u4f5c ",(0,r.kt)("inlineCode",{parentName:"li"},"InsertOrUpdate")," \u652f\u6301\u6392\u9664\u7a7a\u5b57\u7b26\u4e32\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I272OG"},"#I272OG")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6570\u636e\u5e93\u64cd\u4f5c ",(0,r.kt)("inlineCode",{parentName:"li"},"UpdateInclude")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"UpdateExclude")," \u533f\u540d\u5bf9\u8c61\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I271X0"},"#I271X0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6570\u636e\u9a8c\u8bc1\u4f20\u5165\u7a7a\u5bf9\u8c61\u8df3\u8fc7\u9a8c\u8bc1\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I273R4"},"#I273R4")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5e94\u7528\u542f\u52a8\u65f6\u652f\u6301\u6392\u9664\u7279\u5b9a\u914d\u7f6e\u6587\u4ef6\u81ea\u52a8\u52a0\u8f7d ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26U0A"},"#I26U0A")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5355\u4e2a\u5b9e\u4f53\u8868\u540d\u524d\u7f00\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26LX0"},"#I26LX0")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MySql")," \u6570\u636e\u5e93\u81ea\u52a8\u914d\u7f6e\u9ed8\u8ba4\u7248\u672c\u53f7 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26XQ6"},"#I26XQ6")),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u6388\u6743\u5904\u7406\u7a0b\u5e8f\u4ee3\u7801"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b9e\u4f53\u8868\u6570\u636e\u66f4\u6539\u76d1\u542c\u63a5\u53e3 ",(0,r.kt)("inlineCode",{parentName:"li"},"IEntityDataChangedListener")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I278DD"},"#I278DD"),", ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I278LQ"},"#I278LQ")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u670d\u52a1\u63a5\u53e3 AOP \u62e6\u622a\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I278CP"},"#I278CP")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u96ea\u82b1\u7b97\u6cd5 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26OXG"},"#I26OXG"),", ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/78"},"#PR78")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c6\u56fe\u5f15\u64ce\u52a0\u8f7d\u5916\u90e8\u7a0b\u5e8f\u96c6\u51fa\u9519 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u4f9d\u8d56\u6ce8\u5165\u4ee3\u7406\u63a5\u53e3\u62a5\u7a7a\u5bf9\u8c61\u5f02\u5e38 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u53d6\u6d88\u9644\u52a0\u5b9e\u4f53\u51fa\u9519 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u4ed3\u50a8\u5728\u975e Web \u8bf7\u6c42\u4e0b\u51fa\u73b0\u7a7a\u5f02\u5e38 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u591a\u4e2a\u6388\u6743\u7b56\u7565\u5171\u5b58\u95ee\u9898\u51fa\u73b0\u65e0\u6548 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u53cb\u597d\u5f02\u5e38 ",(0,r.kt)("inlineCode",{parentName:"li"},"Oop.Oh")," \u4e0d\u652f\u6301\u666e\u901a\u65b9\u6cd5 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u83b7\u53d6\u591a\u79df\u6237\u5bf9\u8c61\u65f6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u51fa\u73b0\u4f5c\u7528\u57df\u9a8c\u8bc1\u5931\u8d25 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5de5\u4f5c\u5355\u5143\u4e0d\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql\u4ee3\u7406")," \u62e6\u622a bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27GST"},"#I27GST")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5173\u95ed][#I26O1F]","(",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26O1F"},"https://gitee.com/dotnetchina/Furion/issues/I26O1F"),"), ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27B2I"},"#I27B2I"),", ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27BJ6"},"#I27BJ6"),", ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27E5Z"},"#I27E5Z"),", ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I27EL4"},"#I27EL4")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e][\u5b9e\u4f53\u6570\u636e\u76d1\u542c\u5668]","(",(0,r.kt)("a",{parentName:"li",href:"https://dotnetchina.gitee.io/furion/docs/dbcontext-entitytrigger"},"https://dotnetchina.gitee.io/furion/docs/dbcontext-entitytrigger"),") \u6587\u6863"),(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u4e00\u5206\u949f\u5165\u95e8\u3001\u5e94\u7528\u542f\u52a8\u3001\u5b98\u65b9\u811a\u624b\u67b6\u3001\u6570\u636e\u5e93\u64cd\u4f5c\u6307\u5357\u3001\u5bf9\u8c61\u6620\u5c04\u3001\u89c4\u8303\u5316\u6587\u6863\u3001\u5f02\u5e38\u5904\u7406\u3001\u9274\u6743\u6388\u6743\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v110\u5df2\u53d1\u5e03"},"v1.1.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetDbContext()")," \u83b7\u53d6\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u65b9\u6cd5"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContextUtility.GetCurrentHttpContext()")," \u83b7\u53d6\u5168\u5c40 ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContext")," \u4e0a\u4e0b\u6587"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.GetRequiredService<>")," \u89e3\u6790\u670d\u52a1\u65b9\u6cd5"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"object.GetService<>")," \u5bf9\u8c61\u62d3\u5c55\u65b9\u6cd5"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7b56\u7565\u6388\u6743 ",(0,r.kt)("inlineCode",{parentName:"li"},"PolicyPipeline")," \u57fa\u7c7b\u65b9\u6cd5\uff0c\u652f\u6301\u591a\u91cd\u5224\u65ad\u6388\u6743"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"JWTEncryption.ValidateJwtBearerToken")," \u624b\u52a8\u9a8c\u8bc1\u9759\u6001\u65b9\u6cd5"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u6570\u636e\u5e93\u4e0a\u4e0b\u6587 ",(0,r.kt)("inlineCode",{parentName:"li"},"InsertOrUpdateIgnoreNullValues")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"EnabledEntityStateTracked")," \u5168\u5c40\u914d\u7f6e"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger Jwt\u6388\u6743")," \u5168\u5c40\u6388\u6743\u53c2\u6570 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26GLR"},"#I26GLR")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"InsertOrUpdate")," \u652f\u6301\u81ea\u5b9a\u4e49\u5224\u65ad\u6761\u4ef6\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I269Q1"},"#I269Q1")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b57\u7b26\u4e32\u5b57\u6bb5\u5c0f\u5199\u547d\u540d\u652f\u6301 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2695D"},"#I2695D")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5b57\u7b26\u4e32\u6587\u672c\u5bf9\u6bd4\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I268LE"},"#I268LE")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u5168\u5c40\u5f02\u5e38\u7279\u6027\u6d88\u606f\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2662O"},"#I2662O")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Insert")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"li"},"Update")," \u6570\u636e\u5e93\u5ffd\u7565\u7a7a\u503c\u529f\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I264Q4"},"#I264Q4")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Fur")," \u9879\u76ee\u540d\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetRequestDbContext<>()")," \u547d\u540d\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetDbContext<>()")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetDbContext<>()")," \u547d\u540d\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Db.GetDuplicateDbContext<>()")),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.GetService<>")," \u89e3\u6790\u670d\u52a1\u7684\u5e95\u5c42\u903b\u8f91\uff0c\u5927\u5927\u63d0\u9ad8\u4e86\u89e3\u6790\u670d\u52a1\u7684\u6027\u80fd"),(0,r.kt)("li",{parentName:"ul"},"[\u91cd\u6784]"," \u6388\u6743\u6838\u5fc3\u4ee3\u7801\uff0c\u4fdd\u6301\u548c\u5fae\u8f6f\u4e00\u81f4\u7684\u6388\u6743\u89c4\u8303 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26DCB"},"#I26DCB")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.GetRequestService<>")," \u65b9\u6cd5"),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ValidateJwtBearer")," Jwt \u6388\u6743\u65b9\u6cd5\uff0c\u65e0\u9700\u624b\u52a8\u5224\u65ad\u4e86"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," Furion \u5b98\u65b9\u811a\u624b\u67b6\u751f\u6210\u540e\u7f16\u8bd1\u5f02\u5e38 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Tenant")," \u5185\u7f6e\u5c5e\u6027\u4e0d\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"virtual")," \u4fee\u9970 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"dockerfile")," \u65b0\u547d\u540d\u6784\u5efa\u5931\u8d25 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u81ea\u5b9a\u4e49\u89d2\u8272\u6388\u6743\u548c\u591a\u4e2a\u6388\u6743\u5171\u5b58\u51fa\u73b0 403 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26H1L"},"#I26H1L")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"httpContext.GetEndpoint()")," \u7a7a\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/73"},"#PR73")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Oops.Oh")," \u7a7a\u5f02\u5e38\u548c\u4e0d\u652f\u6301\u670d\u52a1\u629b\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26EFU"},"#I26EFU"),"\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26GM4"},"#I26GM4")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"cli.ps")," \u751f\u6210\u6587\u4ef6\u7f16\u7801\u4e71\u7801 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26DVT"},"#I26DVT")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u6587\u4ef6\u4e0a\u4f20\u6309\u94ae\u4e0d\u663e\u793a ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26B6U"},"#I26B6U")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u89c4\u8303\u5316\u7ed3\u679c\u6388\u6743\u72b6\u6001\u7801\u5e8f\u5217\u5316\u5927\u5c0f\u5199\u4e0d\u4e00\u81f4\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26B26"},"#I26B26")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u672a\u542f\u7528\u89c4\u8303\u5316\u7ed3\u679c\u65f6\u4e2d\u6587\u4e71\u7801 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I268T5"},"#I268T5")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MySql")," \u5f02\u6b65\u5f02\u5e38\u6355\u83b7\u4e0d\u5230 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I265SO"},"#I265SO")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"cli.ps1")," \u63d0\u793a\u627e\u4e0d\u5230\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2647U"},"#I2647U")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u5176\u4ed6]"," \u4ee3\u7801\u6027\u80fd\u5c0f\u4f18\u5316\u548c\u5c0f\u8c03\u6574"),(0,r.kt)("li",{parentName:"ul"},"[\u5173\u95ed][#I265JV]","(",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I265JV)%EF%BC%8C%5B#I26ERA%5D(https://gitee.com/dotnetchina/Furion/issues/I26ERA)%EF%BC%8C"},"https://gitee.com/dotnetchina/Furion/issues/I265JV)\uff0c[#I26ERA](https://gitee.com/dotnetchina/Furion/issues/I26ERA)\uff0c")," ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26EVW"},"#I26EVW"),"\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26GHC"},"#I26GHC"),"\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26GJ1"},"#I26GJ1"),"\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I26O1F"},"#I26O1F")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u4e00\u5206\u949f\u5165\u95e8\u3001\u5b89\u5168\u9274\u6743\u3001\u6570\u636e\u5e93\u7b49\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v103\u5df2\u53d1\u5e03"},"v1.0.3\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," Mvc \u6a21\u677f\u811a\u624b\u67b6\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Fur.Template.Mvc")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," WebApi \u6a21\u677f\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Fur.Template.Api")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," Mvc/WebApi \u6a21\u677f\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Fur.Template.App")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," Razar Pages \u6a21\u677f\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Fur.Template.Razor")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," Blazor \u6a21\u677f\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Fur.Template.Blazor")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"PagedList")," \u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"System.Collections.Generic")," \u547d\u540d\u7a7a\u95f4\u4e0b"),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u89e3\u6790\u670d\u52a1\u6027\u80fd\u95ee\u9898\uff0c\u5e95\u5c42\u4ee3\u7801\u5927\u91cf\u4f18\u5316"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"ApiSears.ControllerEnd"),"\u4e0d\u8d77\u4f5c\u7528 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I25KH6"},"#I25KH6")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"RemoteRequest")," \u8bf7\u6c42\u5b8c\u6210\u7ed3\u679c\u5e8f\u5217\u5316\u5c5e\u6027\u5927\u5c0f\u5199\u95ee\u9898 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I25I8R"},"#I25I8R")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"HttpContext.GetEndpoinet()")," \u7a7a\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/73"},"#PR73")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"\u65e0"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u5165\u95e8\u6587\u6863\u3001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6587\u6863\u3001\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v102\u5df2\u53d1\u5e03"},"v1.0.2\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Pomelo.EntityFrameworkCore.MySql")," \u6700\u65b0 .NET 5 \u5305\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24ZQK"},"#I24ZQK")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".AddDateTimeJsonConverter(format)")," \u65f6\u95f4\u683c\u5f0f\u5e8f\u5217\u5316\u914d\u7f6e"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTime")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTimeOffset")," \u7c7b\u578b\u5e8f\u5217\u5316\u683c\u5f0f\u914d\u7f6e ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I253FI"},"#I253FI")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mapster")," \u5305\u81f3 ",(0,r.kt)("inlineCode",{parentName:"li"},"7.0.0")," \u7248"),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.Services")," \u540d\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"App.ServiceProvider")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"App.ApplicationServices")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"App.GetRequestService<>()")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u975e Web \u4e3b\u673a\u6ce8\u5165\u62d3\u5c55"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"services.AddFriendlyException()")," \u7f3a\u5c11\u914d\u7f6e\u6ce8\u5165 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6c60\u88ab\u91ca\u653e\u548c\u9ad8\u5e76\u53d1\u4e0b\u5185\u5b58\u6ea2\u51fa bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I2524K"},"#I2524K"),"\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24UMN"},"#I24UMN")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql\u4ee3\u7406")," \u8fd4\u56de\u7a7a\u6570\u636e\u65f6\u5f02\u5e38 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24TCK"},"#I24TCK")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5de5\u4f5c\u5355\u5143 ",(0,r.kt)("inlineCode",{parentName:"li"},"[UnitOfWork]")," \u591a\u6570\u636e\u5e93\u88ab\u91ca\u653e bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24Q6W"},"#I24Q6W")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"EntityBase")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Entity")," \u6240\u6709\u5c5e\u6027\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"vitural")," \u4fee\u9970"),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Jwt")," \u8bfb\u53d6\u548c\u89e3\u6790\u6027\u80fd"),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u4f18\u5316\u4ee3\u7801\u652f\u6301 C# 9.0 \u6700\u65b0\u8bed\u6cd5"),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"MD5")," \u52a0\u5bc6\u6027\u80fd ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/71"},"#PR71")),(0,r.kt)("li",{parentName:"ul"},"[\u79fb\u9664]"," \u65e0\u7528\u6216\u672a\u4f7f\u7528\u4ee3\u7801"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3001\u591a\u6570\u636e\u5e93\u3001\u4e00\u5206\u949f\u5165\u95e8\u6587\u6863")))),(0,r.kt)("hr",null),(0,r.kt)("h2",{id:"v100\u5df2\u53d1\u5e03"},"v1.0.0\uff08\u5df2\u53d1\u5e03\uff09"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7279\u6027")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u7f51\u7edc\u8bf7\u6c42 ",(0,r.kt)("inlineCode",{parentName:"li"},"RemoteRequest")," \u7ec4\u4ef6 ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I1YYWD"},"#I1YYWD")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},".AddInjectBase()")," \u6ce8\u5165\uff0c\u53ea\u5305\u542b\u57fa\u7840\u670d\u52a1\u6ce8\u5165"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u6240\u6709\u670d\u52a1\u90fd\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"IServiceCollection")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"IMvcBuilder")," \u6ce8\u5165"),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," \u629b\u5f02\u5e38\u72b6\u6001\u7801\u8bbe\u7f6e\u529f\u80fd ",(0,r.kt)("inlineCode",{parentName:"li"},"StatusCode")),(0,r.kt)("li",{parentName:"ul"},"[\u65b0\u589e]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5e8f\u5217\u5316\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Pascal")," \u5c5e\u6027\u547d\u540d\u65b9\u5f0f"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u7a81\u7834\u6027\u53d8\u5316")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," ",(0,r.kt)("strong",{parentName:"li"},"\u6240\u6709\u7684\u5305\u4e3a ",(0,r.kt)("inlineCode",{parentName:"strong"},".NET 5")," \u6b63\u5f0f\u7248")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u95ee\u9898\u4fee\u590d")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"SqlProxy")," \u4ee3\u7406\u5f02\u6b65\u5904\u7406 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u7c7b\u578b ",(0,r.kt)("inlineCode",{parentName:"li"},"Datetime")," \u8f6c ",(0,r.kt)("inlineCode",{parentName:"li"},"DateTimeOffset")," bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5c5e\u6027\u9996\u5b57\u6bcd\u5927\u5c0f\u5199\u5e8f\u5217\u5316\u4e0d\u5339\u914d\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"null")," bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5bf9\u8c61\u5e8f\u5217\u5316\u4e2d\u6587\u51fa\u73b0\u4e71\u7801 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u9ed8\u8ba4\u5e8f\u5217\u5316\u914d\u7f6e\u65e0\u6548 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u6570\u636e\u5e93\u975e\u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f\u63d0\u4ea4\u65e0\u6548 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5e94\u7528\u7a0b\u5e8f\u6c60\u63d0\u4ea4\u6240\u6709 ",(0,r.kt)("inlineCode",{parentName:"li"},"DbContext")," \u7a7a\u5f02\u5e38 bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Saas")," \u591a\u79df\u6237 ",(0,r.kt)("inlineCode",{parentName:"li"},"Tenant")," \u7c7b\u578b\u5b57\u7b26\u4e32\u5c5e\u6027\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"MySql")," \u6570\u636e\u5e93\u4e0b\u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"li"},"longtext")," \u7c7b\u578b bug"),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Mvc")," \u81ea\u52a8\u9a8c\u8bc1\u5b57\u7b26\u4e32\u7a7a\u503c bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24M2T"},"#I24M2T")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u679a\u4e3e\u6ce8\u91ca\u88ab\u8986\u76d6 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24N6J"},"#I24N6J")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5ffd\u7565\u89c4\u8303\u5316\u7ed3\u679c\u65e0\u6548 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24B8P"},"#I24B8P")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"ContentType")," \u4e0d\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"applicaiton/json")," bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24F3U"},"#I24F3U")),(0,r.kt)("li",{parentName:"ul"},"[\u4fee\u590d]"," \u5185\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"System.Text.Json")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"Newtonsoft.Json")," \u51b2\u7a81 bug ",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/issues/I24F3U"},"#I24F3U")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u5176\u4ed6\u66f4\u6539")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," ",(0,r.kt)("inlineCode",{parentName:"li"},"Fur")," \u6846\u67b6\u57df\u540d\u4e3a\uff1a",(0,r.kt)("a",{parentName:"li",href:"https://furion.icu"},"https://furion.icu")),(0,r.kt)("li",{parentName:"ul"},"[\u8c03\u6574]"," \u4ed3\u50a8 ",(0,r.kt)("inlineCode",{parentName:"li"},"FromSqlRaw")," \u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"FromSqlInterpolated")," \u63a5\u53e3\u4f4d\u7f6e"),(0,r.kt)("li",{parentName:"ul"},"[\u4f18\u5316]"," \u6570\u636e\u52a0\u89e3\u5bc6\u6027\u80fd\uff0c",(0,r.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion/pulls/70"},"#PR70")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"\u6587\u6863")),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"[\u66f4\u65b0]"," README.md\u3001\u6846\u67b6\u4ecb\u7ecd\u3001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3001\u914d\u7f6e\u9009\u9879\u3001\u591a\u79df\u6237\u3001\u8de8\u57df\u6587\u6863")))))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/4d87bc8d.4aafd3e2.js b/handbook/build/assets/js/4d87bc8d.4aafd3e2.js deleted file mode 100644 index f0ab0cabf6..0000000000 --- a/handbook/build/assets/js/4d87bc8d.4aafd3e2.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[3021],{6901:function(e,n,r){r.r(n),r.d(n,{assets:function(){return c},contentTitle:function(){return d},default:function(){return m},frontMatter:function(){return o},metadata:function(){return i},toc:function(){return p}});var t=r(3117),u=r(102),a=(r(7294),r(3905)),s=["components"],o={id:"dbcontext-add-or-update",title:"9.7 \u65b0\u589e\u6216\u66f4\u65b0\u64cd\u4f5c",sidebar_label:"9.7 \u65b0\u589e\u6216\u66f4\u65b0\u64cd\u4f5c"},d=void 0,i={unversionedId:"dbcontext-add-or-update",id:"dbcontext-add-or-update",title:"9.7 \u65b0\u589e\u6216\u66f4\u65b0\u64cd\u4f5c",description:"\u4ee5\u4e0b\u5185\u5bb9\u5728 Furion 2.5.1 + \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002\u6b64\u64cd\u4f5c\u8ba9\u5f88\u591a\u4e0d\u4e86\u89e3 EFCore \u7684\u5f00\u53d1\u8005\u4ea7\u751f\u4e86\u5f88\u5927\u7684\u8bef\u89e3\uff0c\u4e0d\u77e5\u4f55\u65f6\u65b0\u589e\u6216\u4f55\u65f6\u66f4\u65b0\uff0c\u6545\u79fb\u9664\u6b64\u529f\u80fd\u3002",source:"@site/docs/dbcontext-add-or-update.mdx",sourceDirName:".",slug:"/dbcontext-add-or-update",permalink:"/furion/docs/dbcontext-add-or-update",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-add-or-update.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"dbcontext-add-or-update",title:"9.7 \u65b0\u589e\u6216\u66f4\u65b0\u64cd\u4f5c",sidebar_label:"9.7 \u65b0\u589e\u6216\u66f4\u65b0\u64cd\u4f5c"},sidebar:"docs",previous:{title:"9.6 \u66f4\u65b0\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-update"},next:{title:"9.8 \u5220\u9664\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-delete"}},c={},p=[{value:"9.7.1 \u65b0\u589e\u6216\u66f4\u65b0\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09",id:"971-\u65b0\u589e\u6216\u66f4\u65b0\u4e0d\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.7.2 \u65b0\u589e\u6216\u66f4\u65b0\uff08\u7acb\u5373\u63d0\u4ea4\uff09",id:"972-\u65b0\u589e\u6216\u66f4\u65b0\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.7.3 \u65b0\u589e\u6216\u66f4\u65b0\u90e8\u5206\u5217\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09",id:"973-\u65b0\u589e\u6216\u66f4\u65b0\u90e8\u5206\u5217\u4e0d\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.7.4 \u65b0\u589e\u6216\u66f4\u65b0\u90e8\u5206\u5217\uff08\u7acb\u5373\u63d0\u4ea4\uff09",id:"974-\u65b0\u589e\u6216\u66f4\u65b0\u90e8\u5206\u5217\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.7.5 \u65b0\u589e\u6216\u66f4\u65b0\u6392\u9664\u7279\u5b9a\u5217\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09",id:"975-\u65b0\u589e\u6216\u66f4\u65b0\u6392\u9664\u7279\u5b9a\u5217\u4e0d\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.7.6 \u65b0\u589e\u6216\u66f4\u65b0\u6392\u9664\u7279\u5b9a\u5217\uff08\u7acb\u5373\u63d0\u4ea4\uff09",id:"976-\u65b0\u589e\u6216\u66f4\u65b0\u6392\u9664\u7279\u5b9a\u5217\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.7.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"977-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],l={toc:p};function m(e){var n=e.components,r=(0,u.Z)(e,s);return(0,a.kt)("wrapper",(0,t.Z)({},l,r,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{title:"\u529f\u80fd\u79fb\u9664\u58f0\u660e",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 2.5.1 +")," \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002\u6b64\u64cd\u4f5c\u8ba9\u5f88\u591a\u4e0d\u4e86\u89e3 ",(0,a.kt)("inlineCode",{parentName:"p"},"EFCore")," \u7684\u5f00\u53d1\u8005\u4ea7\u751f\u4e86\u5f88\u5927\u7684\u8bef\u89e3\uff0c\u4e0d\u77e5\u4f55\u65f6\u65b0\u589e\u6216\u4f55\u65f6\u66f4\u65b0\uff0c\u6545\u79fb\u9664\u6b64\u529f\u80fd\u3002")),(0,a.kt)("h2",{id:"971-\u65b0\u589e\u6216\u66f4\u65b0\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.7.1 \u65b0\u589e\u6216\u66f4\u65b0\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.InsertOrUpdate(user);\n\n// \u793a\u4f8b\u4e8c\nuser.InsertOrUpdate();\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.InsertOrUpdateAsync(user);\n\n// \u793a\u4f8b\u4e8c\nawait user.InsertOrUpdateAsync();\n")),(0,a.kt)("h2",{id:"972-\u65b0\u589e\u6216\u66f4\u65b0\u7acb\u5373\u63d0\u4ea4"},"9.7.2 \u65b0\u589e\u6216\u66f4\u65b0\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.InsertOrUpdateNow(user);\n\n// \u793a\u4f8b\u4e8c\nuser.InsertOrUpdateNow();\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.InsertOrUpdateNowAsync(user);\n\n// \u793a\u4f8b\u4e8c\nawait user.InsertOrUpdateNowAsync();\n")),(0,a.kt)("h2",{id:"973-\u65b0\u589e\u6216\u66f4\u65b0\u90e8\u5206\u5217\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.7.3 \u65b0\u589e\u6216\u66f4\u65b0\u90e8\u5206\u5217\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.InsertOrUpdateInclude(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nrepository.InsertOrUpdateInclude(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nrepository.InsertOrUpdateInclude(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nrepository.InsertOrUpdateInclude(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nuser.InsertOrUpdateInclude(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nuser.InsertOrUpdateInclude("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nuser.InsertOrUpdateInclude(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nuser.InsertOrUpdateInclude(new[] {"Age", "Name"});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.InsertOrUpdateIncludeAsync(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nawait repository.InsertOrUpdateIncludeAsync(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nawait repository.InsertOrUpdateIncludeAsync(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nawait repository.InsertOrUpdateIncludeAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nawait user.InsertOrUpdateIncludeAsync(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nawait user.InsertOrUpdateIncludeAsync("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nawait user.InsertOrUpdateIncludeAsync(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nawait user.InsertOrUpdateIncludeAsync(new[] {"Age", "Name"});\n')),(0,a.kt)("h2",{id:"974-\u65b0\u589e\u6216\u66f4\u65b0\u90e8\u5206\u5217\u7acb\u5373\u63d0\u4ea4"},"9.7.4 \u65b0\u589e\u6216\u66f4\u65b0\u90e8\u5206\u5217\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.InsertOrUpdateIncludeNow(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nrepository.InsertOrUpdateIncludeNow(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nrepository.InsertOrUpdateIncludeNow(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nrepository.InsertOrUpdateIncludeNow(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nuser.InsertOrUpdateIncludeNow(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nuser.InsertOrUpdateIncludeNow("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nuser.InsertOrUpdateIncludeNow(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nuser.InsertOrUpdateIncludeNow(new[] {"Age", "Name"});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.InsertOrUpdateIncludeNowAsync(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nawait repository.InsertOrUpdateIncludeNowAsync(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nawait repository.InsertOrUpdateIncludeNowAsync(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nawait repository.InsertOrUpdateIncludeNowAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nawait user.InsertOrUpdateIncludeNowAsync(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nawait user.InsertOrUpdateIncludeNowAsync("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nawait user.InsertOrUpdateIncludeNowAsync(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nawait user.InsertOrUpdateIncludeNowAsync(new[] {"Age", "Name"});\n')),(0,a.kt)("h2",{id:"975-\u65b0\u589e\u6216\u66f4\u65b0\u6392\u9664\u7279\u5b9a\u5217\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.7.5 \u65b0\u589e\u6216\u66f4\u65b0\u6392\u9664\u7279\u5b9a\u5217\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.InsertOrUpdateExclude(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nrepository.InsertOrUpdateExclude(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nrepository.InsertOrUpdateExclude(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nrepository.InsertOrUpdateExclude(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nuser.InsertOrUpdateExclude(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nuser.InsertOrUpdateExclude("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nuser.InsertOrUpdateExclude(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nuser.InsertOrUpdateExclude(new[] {"Age", "Name"});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.InsertOrUpdateExcludeAsync(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nawait repository.InsertOrUpdateExcludeAsync(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nawait repository.InsertOrUpdateExcludeAsync(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nawait repository.InsertOrUpdateExcludeAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nawait user.InsertOrUpdateExcludeAsync(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nawait user.InsertOrUpdateExcludeAsync("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nawait user.InsertOrUpdateExcludeAsync(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nawait user.InsertOrUpdateExcludeAsync(new[] {"Age", "Name"});\n')),(0,a.kt)("h2",{id:"976-\u65b0\u589e\u6216\u66f4\u65b0\u6392\u9664\u7279\u5b9a\u5217\u7acb\u5373\u63d0\u4ea4"},"9.7.6 \u65b0\u589e\u6216\u66f4\u65b0\u6392\u9664\u7279\u5b9a\u5217\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.InsertOrUpdateExcludeNow(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nrepository.InsertOrUpdateExcludeNow(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nrepository.InsertOrUpdateExcludeNow(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nrepository.InsertOrUpdateExcludeNow(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nuser.InsertOrUpdateExcludeNow(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nuser.InsertOrUpdateExcludeNow("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nuser.InsertOrUpdateExcludeNow(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nuser.InsertOrUpdateExcludeNow(new[] {"Age", "Name"});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.InsertOrUpdateExcludeNowAsync(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nawait repository.InsertOrUpdateExcludeNowAsync(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nawait repository.InsertOrUpdateExcludeNowAsync(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nawait repository.InsertOrUpdateExcludeNowAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nawait user.InsertOrUpdateExcludeNowAsync(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nawait user.InsertOrUpdateExcludeNowAsync("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nawait user.InsertOrUpdateExcludeNowAsync(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nawait user.InsertOrUpdateExcludeNowAsync(new[] {"Age", "Name"});\n')),(0,a.kt)("h2",{id:"977-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.7.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0},3905:function(e,n,r){r.d(n,{Zo:function(){return c},kt:function(){return m}});var t=r(7294);function u(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function a(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function s(e){for(var n=1;n=0||(u[r]=e[r]);return u}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(u[r]=e[r])}return u}var d=t.createContext({}),i=function(e){var n=t.useContext(d),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},c=function(e){var n=i(e.components);return t.createElement(d.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},l=t.forwardRef((function(e,n){var r=e.components,u=e.mdxType,a=e.originalType,d=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),l=i(r),m=u,w=l["".concat(d,".").concat(m)]||l[m]||p[m]||a;return r?t.createElement(w,s(s({ref:n},c),{},{components:r})):t.createElement(w,s({ref:n},c))}));function m(e,n){var r=arguments,u=n&&n.mdxType;if("string"==typeof e||u){var a=r.length,s=new Array(a);s[0]=l;var o={};for(var d in n)hasOwnProperty.call(n,d)&&(o[d]=n[d]);o.originalType=e,o.mdxType="string"==typeof e?e:u,s[1]=o;for(var i=2;i=0||(u[r]=e[r]);return u}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(u[r]=e[r])}return u}var d=t.createContext({}),i=function(e){var n=t.useContext(d),r=n;return e&&(r="function"==typeof e?e(n):s(s({},n),e)),r},c=function(e){var n=i(e.components);return t.createElement(d.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},l=t.forwardRef((function(e,n){var r=e.components,u=e.mdxType,a=e.originalType,d=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),l=i(r),m=u,w=l["".concat(d,".").concat(m)]||l[m]||p[m]||a;return r?t.createElement(w,s(s({ref:n},c),{},{components:r})):t.createElement(w,s({ref:n},c))}));function m(e,n){var r=arguments,u=n&&n.mdxType;if("string"==typeof e||u){var a=r.length,s=new Array(a);s[0]=l;var o={};for(var d in n)hasOwnProperty.call(n,d)&&(o[d]=n[d]);o.originalType=e,o.mdxType="string"==typeof e?e:u,s[1]=o;for(var i=2;iu.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nrepository.InsertOrUpdateInclude(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nrepository.InsertOrUpdateInclude(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nrepository.InsertOrUpdateInclude(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nuser.InsertOrUpdateInclude(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nuser.InsertOrUpdateInclude("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nuser.InsertOrUpdateInclude(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nuser.InsertOrUpdateInclude(new[] {"Age", "Name"});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.InsertOrUpdateIncludeAsync(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nawait repository.InsertOrUpdateIncludeAsync(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nawait repository.InsertOrUpdateIncludeAsync(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nawait repository.InsertOrUpdateIncludeAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nawait user.InsertOrUpdateIncludeAsync(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nawait user.InsertOrUpdateIncludeAsync("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nawait user.InsertOrUpdateIncludeAsync(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nawait user.InsertOrUpdateIncludeAsync(new[] {"Age", "Name"});\n')),(0,a.kt)("h2",{id:"974-\u65b0\u589e\u6216\u66f4\u65b0\u90e8\u5206\u5217\u7acb\u5373\u63d0\u4ea4"},"9.7.4 \u65b0\u589e\u6216\u66f4\u65b0\u90e8\u5206\u5217\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.InsertOrUpdateIncludeNow(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nrepository.InsertOrUpdateIncludeNow(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nrepository.InsertOrUpdateIncludeNow(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nrepository.InsertOrUpdateIncludeNow(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nuser.InsertOrUpdateIncludeNow(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nuser.InsertOrUpdateIncludeNow("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nuser.InsertOrUpdateIncludeNow(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nuser.InsertOrUpdateIncludeNow(new[] {"Age", "Name"});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.InsertOrUpdateIncludeNowAsync(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nawait repository.InsertOrUpdateIncludeNowAsync(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nawait repository.InsertOrUpdateIncludeNowAsync(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nawait repository.InsertOrUpdateIncludeNowAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nawait user.InsertOrUpdateIncludeNowAsync(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nawait user.InsertOrUpdateIncludeNowAsync("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nawait user.InsertOrUpdateIncludeNowAsync(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nawait user.InsertOrUpdateIncludeNowAsync(new[] {"Age", "Name"});\n')),(0,a.kt)("h2",{id:"975-\u65b0\u589e\u6216\u66f4\u65b0\u6392\u9664\u7279\u5b9a\u5217\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.7.5 \u65b0\u589e\u6216\u66f4\u65b0\u6392\u9664\u7279\u5b9a\u5217\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.InsertOrUpdateExclude(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nrepository.InsertOrUpdateExclude(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nrepository.InsertOrUpdateExclude(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nrepository.InsertOrUpdateExclude(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nuser.InsertOrUpdateExclude(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nuser.InsertOrUpdateExclude("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nuser.InsertOrUpdateExclude(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nuser.InsertOrUpdateExclude(new[] {"Age", "Name"});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.InsertOrUpdateExcludeAsync(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nawait repository.InsertOrUpdateExcludeAsync(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nawait repository.InsertOrUpdateExcludeAsync(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nawait repository.InsertOrUpdateExcludeAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nawait user.InsertOrUpdateExcludeAsync(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nawait user.InsertOrUpdateExcludeAsync("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nawait user.InsertOrUpdateExcludeAsync(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nawait user.InsertOrUpdateExcludeAsync(new[] {"Age", "Name"});\n')),(0,a.kt)("h2",{id:"976-\u65b0\u589e\u6216\u66f4\u65b0\u6392\u9664\u7279\u5b9a\u5217\u7acb\u5373\u63d0\u4ea4"},"9.7.6 \u65b0\u589e\u6216\u66f4\u65b0\u6392\u9664\u7279\u5b9a\u5217\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.InsertOrUpdateExcludeNow(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nrepository.InsertOrUpdateExcludeNow(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nrepository.InsertOrUpdateExcludeNow(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nrepository.InsertOrUpdateExcludeNow(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nuser.InsertOrUpdateExcludeNow(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nuser.InsertOrUpdateExcludeNow("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nuser.InsertOrUpdateExcludeNow(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nuser.InsertOrUpdateExcludeNow(new[] {"Age", "Name"});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.InsertOrUpdateExcludeNowAsync(user, u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u4e8c\nawait repository.InsertOrUpdateExcludeNowAsync(user, "Age", "Name");\n\n// \u793a\u4f8b\u4e09\nawait repository.InsertOrUpdateExcludeNowAsync(user, new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u56db\nawait repository.InsertOrUpdateExcludeNowAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nawait user.InsertOrUpdateExcludeNowAsync(u=>u.Name, u=>u.Age);\n\n// \u793a\u4f8b\u516d\nawait user.InsertOrUpdateExcludeNowAsync("Age", "Name");\n\n// \u793a\u4f8b\u4e03\nawait user.InsertOrUpdateExcludeNowAsync(new[] { u=>u.Name, u=>u.Age});\n\n// \u793a\u4f8b\u516b\nawait user.InsertOrUpdateExcludeNowAsync(new[] {"Age", "Name"});\n')),(0,a.kt)("h2",{id:"977-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.7.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/51c11da7.6ea72f85.js b/handbook/build/assets/js/51c11da7.6ea72f85.js deleted file mode 100644 index 4a7f5f6613..0000000000 --- a/handbook/build/assets/js/51c11da7.6ea72f85.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[8832],{7857:function(e,n,t){t.r(n),t.d(n,{assets:function(){return c},contentTitle:function(){return s},default:function(){return u},frontMatter:function(){return l},metadata:function(){return p},toc:function(){return d}});var a=t(3117),r=t(102),o=(t(7294),t(3905)),i=["components"],l={id:"dbcontext-sql-proxy",title:"9.17 Sql \u9ad8\u7ea7\u4ee3\u7406",sidebar_label:"9.17 Sql \u9ad8\u7ea7\u4ee3\u7406"},s=void 0,p={unversionedId:"dbcontext-sql-proxy",id:"dbcontext-sql-proxy",title:"9.17 Sql \u9ad8\u7ea7\u4ee3\u7406",description:"9.17.1 \u5173\u4e8e Sql \u4ee3\u7406",source:"@site/docs/dbcontext-sql-proxy.mdx",sourceDirName:".",slug:"/dbcontext-sql-proxy",permalink:"/furion/docs/dbcontext-sql-proxy",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-sql-proxy.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1657624814,formattedLastUpdatedAt:"Jul 12, 2022",frontMatter:{id:"dbcontext-sql-proxy",title:"9.17 Sql \u9ad8\u7ea7\u4ee3\u7406",sidebar_label:"9.17 Sql \u9ad8\u7ea7\u4ee3\u7406"},sidebar:"docs",previous:{title:"9.16 Sql \u6a21\u677f",permalink:"/furion/docs/dbcontext-sql-template"},next:{title:"9.18 \u591a\u79cd\u6570\u636e\u5e93\u64cd\u4f5c \u2728",permalink:"/furion/docs/dbcontext-multi-database"}},c={},d=[{value:"9.17.1 \u5173\u4e8e Sql \u4ee3\u7406",id:"9171-\u5173\u4e8e-sql-\u4ee3\u7406",level:2},{value:"9.17.2 \u4e86\u89e3 ISqlDispatchProxy",id:"9172-\u4e86\u89e3-isqldispatchproxy",level:2},{value:"9.17.3 \u5f00\u59cb\u9886\u7565 Sql \u4ee3\u7406",id:"9173-\u5f00\u59cb\u9886\u7565-sql-\u4ee3\u7406",level:2},{value:"9.17.3.1 \u6784\u9020\u51fd\u6570\u65b9\u5f0f",id:"91731-\u6784\u9020\u51fd\u6570\u65b9\u5f0f",level:3},{value:"9.17.3.2 \u65b9\u6cd5\u53c2\u6570\u6ce8\u5165",id:"91732-\u65b9\u6cd5\u53c2\u6570\u6ce8\u5165",level:3},{value:"9.17.3.3 Db.GetSqlDispatchProxy<ISql>()",id:"91733-dbgetsqldispatchproxyisql",level:3},{value:"9.17.4 Sql \u64cd\u4f5c",id:"9174-sql-\u64cd\u4f5c",level:2},{value:"9.17.4.1 \u8fd4\u56de DataTable",id:"91741-\u8fd4\u56de-datatable",level:3},{value:"9.17.4.2 \u8fd4\u56de List<T>",id:"91742-\u8fd4\u56de-listt",level:3},{value:"9.17.4.3 \u8fd4\u56de DataSet",id:"91743-\u8fd4\u56de-dataset",level:3},{value:"9.17.4.4 \u8fd4\u56de Tuple<T1,...T8>",id:"91744-\u8fd4\u56de-tuplet1t8",level:3},{value:"9.17.4.5 \u8fd4\u56de \u5355\u884c\u5355\u5217",id:"91745-\u8fd4\u56de-\u5355\u884c\u5355\u5217",level:3},{value:"9.17.4.6 \u65e0\u8fd4\u56de\u503c",id:"91746-\u65e0\u8fd4\u56de\u503c",level:3},{value:"9.17.4.7 \u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570",id:"91747-\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570",level:3},{value:"9.17.5 \u5b58\u50a8\u8fc7\u7a0b \u64cd\u4f5c",id:"9175-\u5b58\u50a8\u8fc7\u7a0b-\u64cd\u4f5c",level:2},{value:"9.17.5.1 \u8fd4\u56de DataTable",id:"91751-\u8fd4\u56de-datatable",level:3},{value:"9.17.5.2 \u8fd4\u56de List<T>",id:"91752-\u8fd4\u56de-listt",level:3},{value:"9.17.5.3 \u8fd4\u56de DataSet",id:"91753-\u8fd4\u56de-dataset",level:3},{value:"9.17.5.4 \u8fd4\u56de Tuple(T1,...T8)",id:"91754-\u8fd4\u56de-tuplet1t8",level:3},{value:"9.17.5.5 \u8fd4\u56de \u5355\u884c\u5355\u5217",id:"91755-\u8fd4\u56de-\u5355\u884c\u5355\u5217",level:3},{value:"9.17.5.6 \u65e0\u8fd4\u56de\u503c",id:"91756-\u65e0\u8fd4\u56de\u503c",level:3},{value:"9.17.5.7 \u5e26 OUTPUT/RETURN \u8fd4\u56de",id:"91757-\u5e26-outputreturn-\u8fd4\u56de",level:3},{value:"9.17.5.8 \u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570",id:"91758-\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570",level:3},{value:"9.17.6 \u51fd\u6570 \u64cd\u4f5c",id:"9176-\u51fd\u6570-\u64cd\u4f5c",level:2},{value:"9.17.7 Sql \u6a21\u677f\u66ff\u6362",id:"9177-sql-\u6a21\u677f\u66ff\u6362",level:2},{value:"9.17.8 \u5207\u6362\u6570\u636e\u5e93",id:"9178-\u5207\u6362\u6570\u636e\u5e93",level:2},{value:"9.17.8.1 \u5355\u4e2a\u65b9\u6cd5\u65b9\u5f0f",id:"91781-\u5355\u4e2a\u65b9\u6cd5\u65b9\u5f0f",level:3},{value:"9.17.8.2 \u63a5\u53e3\u65b9\u5f0f",id:"91782-\u63a5\u53e3\u65b9\u5f0f",level:3},{value:"9.17.8.3 \u8fd0\u884c\u65f6 .Change \u65b9\u6cd5\u5207\u6362",id:"91783-\u8fd0\u884c\u65f6-change-\u65b9\u6cd5\u5207\u6362",level:3},{value:"9.17.9 Sql \u4ee3\u7406\u62e6\u622a",id:"9179-sql-\u4ee3\u7406\u62e6\u622a",level:2},{value:"9.17.10 \u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4",id:"91710-\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4",level:2},{value:"9.17.11 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"91711-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:d};function u(e){var n=e.components,t=(0,r.Z)(e,i);return(0,o.kt)("wrapper",(0,a.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"9171-\u5173\u4e8e-sql-\u4ee3\u7406"},"9.17.1 \u5173\u4e8e ",(0,o.kt)("inlineCode",{parentName:"h2"},"Sql")," \u4ee3\u7406"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u662f ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u5bf9 ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u64cd\u4f5c\u4e00\u4e2a\u975e\u5e38\u91cd\u8981\u7684\u6982\u5ff5\uff0c\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\u53ef\u4ee5\u5927\u5927\u63d0\u9ad8 ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4e66\u5199\u6548\u7387\uff0c\u800c\u4e14\u540e\u671f\u6781\u6613\u7ef4\u62a4\u3002"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u5c5e\u4e8e ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u4e00\u4e2a\u9ad8\u7ea7\u529f\u80fd\u3002"),(0,o.kt)("h2",{id:"9172-\u4e86\u89e3-isqldispatchproxy"},"9.17.2 \u4e86\u89e3 ",(0,o.kt)("inlineCode",{parentName:"h2"},"ISqlDispatchProxy")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"ISqlDispatchProxy")," \u63a5\u53e3\u662f ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u5b9e\u73b0",(0,o.kt)("strong",{parentName:"p"},"\u88ab\u4ee3\u7406\u63a5\u53e3"),"\u7684\u552f\u4e00\u4f9d\u8d56\uff0c\u4efb\u4f55\u516c\u5f00\u7684\u63a5\u53e3\u4e00\u65e6\u96c6\u6210\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"ISqlDispatchProxy")," \u63a5\u53e3\uff0c\u90a3\u4e48\u8fd9\u4e2a\u63a5\u53e3\u5c31\u662f",(0,o.kt)("strong",{parentName:"p"},"\u88ab\u6258\u7ba1\u62e6\u622a"),"\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u64cd\u4f5c\u63a5\u53e3\u3002"),(0,o.kt)("p",null,"\u7b80\u5355\u5b9a\u4e49\u4e00\u4e2a ",(0,o.kt)("strong",{parentName:"p"},"Sql \u4ee3\u7406\u63a5\u53e3")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"":!0,"{1,5}":!0},"using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n }\n}\n")),(0,o.kt)("p",null,"\u4e00\u65e6\u8fd9\u4e2a\u63a5\u53e3\u7ee7\u627f\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"ISqlDispatchProxy"),"\uff0c\u90a3\u4e48\u5b83\u5c31\u4f1a",(0,o.kt)("strong",{parentName:"p"},"\u52a8\u6001\u521b\u5efa\u63a5\u53e3\u5b9e\u4f8b\uff0c\u800c\u4e14\u652f\u6301\u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c\u83b7\u53d6\u5b9e\u4f8b"),"\u3002"),(0,o.kt)("h2",{id:"9173-\u5f00\u59cb\u9886\u7565-sql-\u4ee3\u7406"},"9.17.3 \u5f00\u59cb\u9886\u7565 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Sql")," \u4ee3\u7406"),(0,o.kt)("p",null,"\u4e0b\u9762\u6211\u5c06\u901a\u8fc7\u591a\u4e2a\u4f8b\u5b50\u6765\u6f14\u793a ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u7684\u7528\u6cd5\uff0c\u4e3a\u4ec0\u4e48\u63a8\u8350\u8fd9\u79cd\u65b9\u5f0f\u64cd\u4f5c ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql"),"\u3002"),(0,o.kt)("p",null,"\u652f\u6301\u5404\u79cd\u65b9\u5f0f\u83b7\u53d6\u5b9e\u4f8b\uff1a"),(0,o.kt)("h3",{id:"91731-\u6784\u9020\u51fd\u6570\u65b9\u5f0f"},"9.17.3.1 \u6784\u9020\u51fd\u6570\u65b9\u5f0f"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-2}",showLineNumbers:!0,"":!0,"{1-2}":!0},"private readonly ISql _sql;\npublic FurionService(ISql sql)\n{\n _sql = sql;\n}\n")),(0,o.kt)("h3",{id:"91732-\u65b9\u6cd5\u53c2\u6570\u6ce8\u5165"},"9.17.3.2 \u65b9\u6cd5\u53c2\u6570\u6ce8\u5165"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"public async Task> GetAll([FromServices] ISql, string keyword)\n{\n}\n")),(0,o.kt)("h3",{id:"91733-dbgetsqldispatchproxyisql"},"9.17.3.3 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Db.GetSqlDispatchProxy()")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var sql = Db.GetSqlDispatchProxy();\n")),(0,o.kt)("h2",{id:"9174-sql-\u64cd\u4f5c"},"9.17.4 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Sql")," \u64cd\u4f5c"),(0,o.kt)("h3",{id:"91741-\u8fd4\u56de-datatable"},"9.17.4.1 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"DataTable")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8,12,16,20}",showLineNumbers:!0,"":!0,"{8,12,16,20}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u57fa\u5143\u7c7b\u578b\n [SqlExecute("select * from person where id >@id and name like @name")]\n DataTable GetPerson(int id, string name);\n\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u5bf9\u8c61\u7c7b\u578b\n [SqlExecute("select * from person where id >@id and name like @name")]\n DataTable GetPerson(MyParam paras);\n\n // \u6267\u884c\u5b58\u50a8\u8fc7\u7a0b sql\uff0c\u652f\u6301\u8bbe\u7f6e\u53c2\u6570\u7c7b\u578b\n [SqlExecute("exec PROP_NAME @id", CommandType = CommandType.StoredProcedure)]\n DataTable GetPerson(int id);\n\n // \u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\n [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator))]\n DataTable GetPerson();\n\n // \u5f02\u6b65\u65b9\u5f0f\n [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator))]\n Task GetPersonAsync();\n }\n}\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u53c2\u6570",type:"important"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u53c2\u6570\u67e5\u627e\u89c4\u5219\uff1a"),(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u65b9\u6cd5\u7684\u53c2\u6570\u662f ",(0,o.kt)("inlineCode",{parentName:"p"},"\u57fa\u5143\u7c7b\u578b"),"\uff08\u6216 ",(0,o.kt)("inlineCode",{parentName:"p"},"string"),"\u3001",(0,o.kt)("inlineCode",{parentName:"p"},"\u503c\u7c7b\u578b"),"\uff09\uff0c\u5219\u81ea\u52a8\u5c06\u8fd9\u4e9b\u7c7b\u578b\u7ec4\u5408\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"Dictionary")," \u4f5c\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u53c2\u6570\u3002\u547d\u4ee4\u53c2\u6570\u53ef\u4f7f\u7528\u65b9\u6cd5\u540c\u540d\u53c2\u6570\u52a0 ",(0,o.kt)("inlineCode",{parentName:"p"},"@")," \u7b26\u53f7\u3002"),(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u65b9\u6cd5\u7684\u53c2\u6570\u662f ",(0,o.kt)("inlineCode",{parentName:"p"},"\u7c7b\u7c7b\u578b"),"\uff0c\u90a3\u4e48\u81ea\u52a8\u904d\u5386\u8be5\u7c7b\u516c\u5f00\u5b9e\u4f8b\u5c5e\u6027\u751f\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"DbParameter[]")," \u6570\u7ec4\uff0c\u6bcf\u4e00\u4e2a\u5c5e\u6027\u540d\u90fd\u5c06\u662f\u547d\u4ee4\u53c2\u6570\uff0c",(0,o.kt)("strong",{parentName:"p"},"\u5927\u90e8\u5206\u6570\u636e\u5e93\u662f\u4e0d\u533a\u5206\u5927\u5c0f\u5199\uff0c\u4e2a\u522b\u6570\u636e\u5e93\u9664\u5916"),"\uff0c\u5982 ",(0,o.kt)("inlineCode",{parentName:"p"},"Sqlite"),"\uff0c\u5982\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public class MyModel\n{\n public int Id {get;set;}\n public string Name {get; set;}\n}\n")),(0,o.kt)("p",{parentName:"admonition"},"\u90a3\u4e48 ",(0,o.kt)("inlineCode",{parentName:"p"},"sql")," \u8bed\u53e5\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528\u5c5e\u6027\u540d\u4f5c\u4e3a\u53c2\u6570\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-sql",metastring:"showLineNumbers",showLineNumbers:!0},"select * from person where id > @id and name = @name;\n"))),(0,o.kt)("h3",{id:"91742-\u8fd4\u56de-listt"},"9.17.4.2 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"List")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8,12,16,20}",showLineNumbers:!0,"":!0,"{8,12,16,20}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u57fa\u5143\u7c7b\u578b\n [SqlExecute("select * from person where id >@id and name like @name")]\n List GetPerson(int id, string name);\n\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u5bf9\u8c61\u7c7b\u578b\n [SqlExecute("select * from person where id >@id and name like @name")]\n List GetPerson(MyParam paras);\n\n // \u6267\u884c\u5b58\u50a8\u8fc7\u7a0b sql\uff0c\u652f\u6301\u8bbe\u7f6e\u53c2\u6570\u7c7b\u578b\n [SqlExecute("exec PROP_NAME @id", CommandType = CommandType.StoredProcedure)]\n List GetPerson(int id);\n\n // \u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\n [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]\n List GetPerson();\n\n // \u5f02\u6b65\u65b9\u5f0f\n [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]\n Task> GetPersonAsync();\n }\n}\n')),(0,o.kt)("h3",{id:"91743-\u8fd4\u56de-dataset"},"9.17.4.3 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"DataSet")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8-10,14-16,20-22,26-28,32-35}",showLineNumbers:!0,"":!0,"{8-10,14-16,20-22,26-28,32-35}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u57fa\u5143\u7c7b\u578b\n [SqlExecute(@"\n select * from person where id >@id and name like @name;\n select top 10 * from student where Id >@id;")]\n DataSet GetData(int id, string name);\n\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u5bf9\u8c61\u7c7b\u578b\n [SqlExecute(@"\n select * from person where id >@id and name like @name;\n select top 10 * from student where Id >@id;")]\n DataSet GetData(MyParam paras);\n\n // \u6267\u884c\u5b58\u50a8\u8fc7\u7a0b sql\uff0c\u652f\u6301\u8bbe\u7f6e\u53c2\u6570\u7c7b\u578b\n [SqlExecute(@"\n exec PROP_NAME @id;\n select * from person;", CommandType = CommandType.StoredProcedure)]\n DataSet GetData(int id);\n\n // \u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\n [SqlExecute(@"\n select * from person;\n select * from student;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]\n DataSet GetData();\n\n // \u5f02\u6b65\u65b9\u5f0f\n [SqlExecute(@"\n select * from person;\n select * from student;\n select 1;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]\n Task GetDataAsync());\n }\n}\n')),(0,o.kt)("h3",{id:"91744-\u8fd4\u56de-tuplet1t8"},"9.17.4.4 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"Tuple")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8-10,14-16,20-22,26-28,32-35,38-42}",showLineNumbers:!0,"":!0,"{8-10,14-16,20-22,26-28,32-35,38-42}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u57fa\u5143\u7c7b\u578b\n [SqlExecute(@"\n select * from person where id >@id and name like @name;\n select top 10 * from student where Id >@id;")]\n (List,List) GetData(int id, string name);\n\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u5bf9\u8c61\u7c7b\u578b\n [SqlExecute(@"\n select * from person where id >@id and name like @name;\n select top 10 * from student where Id >@id;")]\n (List,List) GetData(MyParam paras);\n\n // \u6267\u884c\u5b58\u50a8\u8fc7\u7a0b sql\uff0c\u652f\u6301\u8bbe\u7f6e\u53c2\u6570\u7c7b\u578b\n [SqlExecute(@"\n exec PROP_NAME @id;\n select * from person;", CommandType = CommandType.StoredProcedure)]\n (List,List) GetData(int id);\n\n // \u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\n [SqlExecute(@"\n select * from person;\n select * from student;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]\n (List,List) GetData();\n\n // \u5f02\u6b65\u65b9\u5f0f\n [SqlExecute(@"\n select * from person;\n select * from student;\n select 1;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]\n Task<(List,List,List)> GetDataAsync();\n\n // \u81ea v3.7.3+ \u7248\u672c\u652f\u6301\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570\n [SqlExecute(@"\n select * from person where id =@id;\n select * from person")]\n (Person, List) GetData(int id); // \u6ce8\u610f\u8fd4\u56de\u503c\u662f `(Person, List)` \u7ec4\u5408\n}\n')),(0,o.kt)("h3",{id:"91745-\u8fd4\u56de-\u5355\u884c\u5355\u5217"},"9.17.4.5 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"\u5355\u884c\u5355\u5217")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlExecute("select Name from person where id = @id")]\n string GetValue(int id);\n\n [SqlExecute("select age from person where id = @id")]\n int GetValue(int id);\n\n [SqlExecute("select Name from person where id = @id")]\n Task GetValueAsync(int id);\n }\n}\n')),(0,o.kt)("h3",{id:"91746-\u65e0\u8fd4\u56de\u503c"},"9.17.4.6 \u65e0\u8fd4\u56de\u503c"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlExecute("insert into person(Name,Age) values(@name,@age)")]\n void Insert(MyParam dto);\n\n [SqlExecute("delete from person where id = @id")]\n void Delete(int id);\n\n [SqlExecute("update person set name=@name where id=@id")]\n void Update(int id, string name);\n }\n}\n')),(0,o.kt)("h3",{id:"91747-\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570"},"9.17.4.7 \u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570"),(0,o.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 3.7.1 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-5}",showLineNumbers:!0,"{3-5}":!0},'public interface ISql : ISqlDispatchProxy\n{\n // \u81ea v3.7.3+ \u7248\u672c\u652f\u6301\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570\n [SqlExecute("select * from person where id=@id")]\n Person GetPerson(int id);\n}\n')),(0,o.kt)("h2",{id:"9175-\u5b58\u50a8\u8fc7\u7a0b-\u64cd\u4f5c"},"9.17.5 ",(0,o.kt)("inlineCode",{parentName:"h2"},"\u5b58\u50a8\u8fc7\u7a0b")," \u64cd\u4f5c"),(0,o.kt)("h3",{id:"91751-\u8fd4\u56de-datatable"},"9.17.5.1 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"DataTable")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlProcedure("PROC_Name")]\n DataTable GetPersons(MyParam dto);\n\n [SqlProcedure("PROC_Name")]\n DataTable GetPersons(int id);\n\n [SqlProcedure("PROC_Name")]\n DataTable GetPersons(int id, string name);\n }\n}\n')),(0,o.kt)("h3",{id:"91752-\u8fd4\u56de-listt"},"9.17.5.2 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"List")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlProcedure("PROC_Name")]\n List GetPersons(MyParam dto);\n\n [SqlProcedure("PROC_Name")]\n List GetPersons(int id);\n\n [SqlProcedure("PROC_Name")]\n List GetPersons(int id, string name);\n }\n}\n')),(0,o.kt)("h3",{id:"91753-\u8fd4\u56de-dataset"},"9.17.5.3 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"DataSet")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlProcedure("PROC_Name")]\n DataSet GetData(MyParam dto);\n\n [SqlProcedure("PROC_Name")]\n DataSet GetData(int id);\n\n [SqlProcedure("PROC_Name")]\n DataSet GetData(int id, string name);\n }\n}\n')),(0,o.kt)("h3",{id:"91754-\u8fd4\u56de-tuplet1t8"},"9.17.5.4 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"Tuple(T1,...T8)")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13,16-18}",showLineNumbers:!0,"":!0,"{7,10,13,16-18}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlProcedure("PROC_Name")]\n (List, List) GetData(MyParam dto);\n\n [SqlProcedure("PROC_Name")]\n (List, List) GetData(int id);\n\n [SqlProcedure("PROC_Name")]\n (List, List, Person, int) GetData(int id, string name);\n\n // \u81ea v3.7.3+ \u7248\u672c\u652f\u6301\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570\n [SqlProcedure(@"PROC_Name)]\n (Person, List) GetData(int id); // \u6ce8\u610f\u8fd4\u56de\u503c\u662f `(Person, List)` \u7ec4\u5408\n }\n}\n')),(0,o.kt)("h3",{id:"91755-\u8fd4\u56de-\u5355\u884c\u5355\u5217"},"9.17.5.5 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"\u5355\u884c\u5355\u5217")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlProcedure("PROC_Name")]\n object GetValue(MyParam dto);\n\n [SqlProcedure("PROC_Name")]\n string GetValue(int id);\n\n [SqlProcedure("PROC_Name")]\n int GetValue(int id, string name);\n }\n}\n')),(0,o.kt)("h3",{id:"91756-\u65e0\u8fd4\u56de\u503c"},"9.17.5.6 \u65e0\u8fd4\u56de\u503c"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlProcedure("PROC_Name")]\n void GetValue(MyParam dto);\n\n [SqlProcedure("PROC_Name")]\n void GetValue(int id);\n\n [SqlProcedure("PROC_Name")]\n void GetValue(int id, string name);\n }\n}\n')),(0,o.kt)("h3",{id:"91757-\u5e26-outputreturn-\u8fd4\u56de"},"9.17.5.7 \u5e26 ",(0,o.kt)("inlineCode",{parentName:"h3"},"OUTPUT/RETURN")," \u8fd4\u56de"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlProcedure("PROC_Name")]\n ProcedureOutputResult GetOutput(ProcOutputModel pams);\n\n [SqlProcedure("PROC_Name")]\n ProcedureOutputResult GetOutput(ProcOutputModel pams);\n\n [SqlProcedure("PROC_Name")]\n ProcedureOutputResult<(List, List)> GetOutput(ProcOutputModel pams);\n }\n}\n')),(0,o.kt)("h3",{id:"91758-\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570"},"9.17.5.8 \u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570"),(0,o.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 3.7.1 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-5}",showLineNumbers:!0,"{3-5}":!0},'public interface ISql : ISqlDispatchProxy\n{\n // \u81ea v3.7.3+ \u7248\u672c\u652f\u6301\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570\n [SqlProcedure("PROC_Name")]\n Person GetPerson(int id);\n}\n')),(0,o.kt)("h2",{id:"9176-\u51fd\u6570-\u64cd\u4f5c"},"9.17.6 ",(0,o.kt)("inlineCode",{parentName:"h2"},"\u51fd\u6570")," \u64cd\u4f5c"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10}",showLineNumbers:!0,"":!0,"{7,10}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlFunction("FN_Name")] // \u6807\u91cf\u51fd\u6570\n string GetValue(MyParam dto);\n\n [SqlProcedure("FN_Name")] // \u8868\u503c\u51fd\u6570\n List GetPersons(int id);\n }\n}\n')),(0,o.kt)("admonition",{title:"\u8865\u5145\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u4f1a\u81ea\u52a8\u5224\u65ad\u8fd4\u56de\u503c\u7136\u540e\u81ea\u52a8\u6267\u884c\u7279\u5b9a\u51fd\u6570\u7c7b\u578b\u3002")),(0,o.kt)("h2",{id:"9177-sql-\u6a21\u677f\u66ff\u6362"},"9.17.7 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Sql")," \u6a21\u677f\u66ff\u6362"),(0,o.kt)("p",null,"\u5728\u6700\u65b0\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"1.18.3")," \u7248\u672c\u4e2d\u63d0\u4f9b\u4e86\u6a21\u677f\u66ff\u6362\u529f\u80fd\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[SqlExecute("select * from person where id > {id} and name like {name} and age > {user.Age}")]\nList GetPerson(int id, string name, User user);\n')),(0,o.kt)("admonition",{title:"\u4e24\u8005\u533a\u522b",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u6a21\u677f\u5b57\u7b26\u4e32\u6709\u522b\u4e8e\u547d\u4ee4\u53c2\u6570\u66ff\u6362\uff0c\u6a21\u677f\u5b57\u7b26\u4e32\u91c7\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"{ }")," \u65b9\u5f0f\uff0c\u8fd0\u884c\u65f6\u76f4\u63a5\u66ff\u6362\u4e3a\u5b9e\u9645\u7684\u5185\u5bb9\uff0c ",(0,o.kt)("inlineCode",{parentName:"p"},"@")," \u800c\u662f\u8f6c\u6362\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"DbParameter")," \u53c2\u6570\u3002")),(0,o.kt)("h2",{id:"9178-\u5207\u6362\u6570\u636e\u5e93"},"9.17.8 \u5207\u6362\u6570\u636e\u5e93"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u65b9\u5f0f\u7684\u652f\u6301\u4e09\u79cd\u5207\u6362\u6570\u636e\u5e93\u7684\u65b9\u5f0f\uff1a"),(0,o.kt)("h3",{id:"91781-\u5355\u4e2a\u65b9\u6cd5\u65b9\u5f0f"},"9.17.8.1 \u5355\u4e2a\u65b9\u6cd5\u65b9\u5f0f"),(0,o.kt)("p",null,"\u4e3b\u8981\u901a\u8fc7\u5728\u65b9\u6cd5\u4e0a\u8d34 ",(0,o.kt)("inlineCode",{parentName:"p"},"[SqlDbContextLocator]")," \u7279\u6027"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'[SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]\nList GetPerson();\n')),(0,o.kt)("h3",{id:"91782-\u63a5\u53e3\u65b9\u5f0f"},"9.17.8.2 \u63a5\u53e3\u65b9\u5f0f"),(0,o.kt)("p",null,"\u5728\u63a5\u53e3\u4e2d\u8d34 ",(0,o.kt)("inlineCode",{parentName:"p"},"[SqlDbContextLocator]")," \u7279\u6027\uff0c\u6b64\u65b9\u5f0f\u4e0b\uff0c\u63a5\u53e3\u6240\u6709\u65b9\u6cd5\u5c06\u91c7\u7528\u6307\u5b9a\u7684\u6570\u636e\u5e93\u6267\u884c\u3002"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'[SqlDbContextLocator(typeof(MySqlDbContextLocator)]\npublic interface ISql : ISqlDispatchProxy\n{\n [SqlFunction("FN_Name")] // \u6807\u91cf\u51fd\u6570\n string GetValue(MyParam dto);\n\n [SqlProcedure("FN_Name")] // \u8868\u503c\u51fd\u6570\n List GetPersons(int id);\n}\n')),(0,o.kt)("h3",{id:"91783-\u8fd0\u884c\u65f6-change-\u65b9\u6cd5\u5207\u6362"},"9.17.8.3 \u8fd0\u884c\u65f6 ",(0,o.kt)("inlineCode",{parentName:"h3"},".Change")," \u65b9\u6cd5\u5207\u6362"),(0,o.kt)("p",null,"\u9664\u4e86\u4ee5\u4e0a\u4e24\u79cd ",(0,o.kt)("inlineCode",{parentName:"p"},"\u9759\u6001")," \u914d\u7f6e\u65b9\u5f0f\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u8fd8\u63d0\u4f9b ",(0,o.kt)("inlineCode",{parentName:"p"},"\u52a8\u6001")," \u65b9\u5f0f\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6}",showLineNumbers:!0,"":!0,"{2,6}":!0},"// \u5c06 sql \u4ee3\u7406\u6570\u636e\u5e93\u5207\u6362\u6210\u7279\u5b9a\u6570\u636e\u5e93\n_sql.Change();\n_sql.GetPerson();\n\n// \u591a\u6b21\u5207\u6362\n_sql.Change();\n_sql.GetPerson();\n\n// \u8fd8\u652f\u6301\u91cd\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u4e3a\u521d\u59cb\u72b6\u6001\n_sql.ResetIt();\n_sql.GetPerson();\n")),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u4f18\u5148\u7ea7\u95ee\u9898",type:"important"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},".Change<>")," \u4f18\u5148\u7ea7\u5927\u4e8e ",(0,o.kt)("inlineCode",{parentName:"p"},"\u65b9\u6cd5\u8d34 [SqlDbContextLocator]")," \u5927\u4e8e ",(0,o.kt)("inlineCode",{parentName:"p"},"\u63a5\u53e3\u8d34 [SqlDbContextLocator]"),"\u3002"),(0,o.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u4e0d\u6307\u5b9a ",(0,o.kt)("inlineCode",{parentName:"p"},"DbContextLocator")," \u5c5e\u6027\uff0c\u5219\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"MasterDbContextLocator"),"\u3002")),(0,o.kt)("h2",{id:"9179-sql-\u4ee3\u7406\u62e6\u622a"},"9.17.9 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Sql")," \u4ee3\u7406\u62e6\u622a"),(0,o.kt)("p",null,"\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion v2.13 +")," \u7248\u672c\u65b0\u589e\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u62e6\u622a\u529f\u80fd\uff0c\u53ef\u4ee5\u7be1\u6539\u7279\u5b9a\u65b9\u6cd5\u6216\u6240\u6709\u4ee3\u7406\u65b9\u6cd5\u5b9e\u9645\u6267\u884c\u7684\u53c2\u6570\uff0c\u5982 ",(0,o.kt)("inlineCode",{parentName:"p"},"sql\u8bed\u53e5\u3001\u53c2\u6570\u3001\u6267\u884c\u5bf9\u8c61\u7b49\u7b49"),"\u3002"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u82e5\u5728 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Sql")," \u4ee3\u7406\u4e2d\u5b9e\u73b0\u62e6\u622a\u529f\u80fd\uff0c\u5fc5\u987b\u6ee1\u8db3\u4e24\u4e2a\u6761\u4ef6"),"\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u65b9\u6cd5\u5fc5\u987b\u662f ",(0,o.kt)("inlineCode",{parentName:"li"},"static")," \u9759\u6001\u65b9\u6cd5\u4e14\u8fd4\u56de\u503c\u4e3a ",(0,o.kt)("inlineCode",{parentName:"li"},"void")," \u4e14\u53ea\u6709\u4e00\u4e2a ",(0,o.kt)("inlineCode",{parentName:"li"},"SqlProxyMethod")," \u53c2\u6570"),(0,o.kt)("li",{parentName:"ul"},"\u65b9\u6cd5\u5fc5\u987b\u8d34 ",(0,o.kt)("inlineCode",{parentName:"li"},"[Interceptor]")," \u7279\u6027")),(0,o.kt)("p",null,"\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,13-17,20-24,26-30,32-36}",showLineNumbers:!0,"":!0,"{9,13-17,20-24,26-30,32-36}":!0},'public interface ISql : ISqlDispatchProxy\n{\n [SqlFunction("FN_Name")]\n string GetValue(MyParam dto);\n\n [SqlProcedure("FN_Name")]\n List GetPersons(int id);\n\n [SqlExecute("select name from person", InterceptorId = "GetPersonsByName")] // \u901a\u8fc7 InterceptorId \u89e3\u51b3\u65b9\u6cd5\u540d\u91cd\u8f7d\u95ee\u9898\n Task> GetPersons();\n\n // \u53ea\u62e6\u622a GetValue \u65b9\u6cd5\n [Interceptor(nameof(GetValue))]\n static void \u62e6\u622a1(SqlProxyMethod method)\n {\n method.FinalSql += " where id > 1"; // \u7be1\u6539\u6700\u7ec8\u6267\u884c sql\n }\n\n // \u62e6\u622a GetValue \u548c GetPersons \u65b9\u6cd5\n [Interceptor(nameof(GetValue), nameof(GetPersons))]\n static void \u62e6\u622a2(SqlProxyMethod method)\n {\n method.FinalSql += " where id > 1"; // \u7be1\u6539\u6700\u7ec8\u6267\u884c sql\n }\n\n [Interceptor("GetPersonsByName")] // \u5bf9\u5e94\u4e0a\u9762\u7684 InterceptorId \u914d\u7f6e\n static void \u89e3\u51b3\u65b9\u6cd5\u540d\u91cd\u8f7d\u62e6\u622a(SqlProxyMethod method)\n {\n // \u3002\u3002\u3002\n }\n\n [Interceptor]\n static void \u5168\u5c40\u62e6\u622a(SqlProxyMethod method)\n {\n // \u8fd9\u91cc\u4f1a\u62e6\u622a\u6240\u6709\u7684\u65b9\u6cd5\n }\n}\n')),(0,o.kt)("h2",{id:"91710-\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4"},"9.17.10 \u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[Timeout(1000)]\npublic interface ISql : ISqlDispatchProxy\n{\n [SqlFunction("FN_Name"), Timeout(500)] // \u5355\u4f4d\u79d2\n string GetValue(MyParam dto);\n}\n')),(0,o.kt)("h2",{id:"91711-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.17.11 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}u.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return c},kt:function(){return u}});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function i(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),p=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},c=function(e){var n=p(e.components);return a.createElement(s.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),m=p(t),u=r,N=m["".concat(s,".").concat(u)]||m[u]||d[u]||o;return t?a.createElement(N,i(i({ref:n},c),{},{components:t})):a.createElement(N,i({ref:n},c))}));function u(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var o=t.length,i=new Array(o);i[0]=m;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:r,i[1]=l;for(var p=2;p=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),p=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},c=function(e){var n=p(e.components);return a.createElement(s.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),m=p(t),u=r,N=m["".concat(s,".").concat(u)]||m[u]||d[u]||o;return t?a.createElement(N,i(i({ref:n},c),{},{components:t})):a.createElement(N,i({ref:n},c))}));function u(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var o=t.length,i=new Array(o);i[0]=m;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:r,i[1]=l;for(var p=2;pSql \u4ee3\u7406",id:"9171-\u5173\u4e8e-sql-\u4ee3\u7406",level:2},{value:"9.17.2 \u4e86\u89e3 ISqlDispatchProxy",id:"9172-\u4e86\u89e3-isqldispatchproxy",level:2},{value:"9.17.3 \u5f00\u59cb\u9886\u7565 Sql \u4ee3\u7406",id:"9173-\u5f00\u59cb\u9886\u7565-sql-\u4ee3\u7406",level:2},{value:"9.17.3.1 \u6784\u9020\u51fd\u6570\u65b9\u5f0f",id:"91731-\u6784\u9020\u51fd\u6570\u65b9\u5f0f",level:3},{value:"9.17.3.2 \u65b9\u6cd5\u53c2\u6570\u6ce8\u5165",id:"91732-\u65b9\u6cd5\u53c2\u6570\u6ce8\u5165",level:3},{value:"9.17.3.3 Db.GetSqlDispatchProxy<ISql>()",id:"91733-dbgetsqldispatchproxyisql",level:3},{value:"9.17.4 Sql \u64cd\u4f5c",id:"9174-sql-\u64cd\u4f5c",level:2},{value:"9.17.4.1 \u8fd4\u56de DataTable",id:"91741-\u8fd4\u56de-datatable",level:3},{value:"9.17.4.2 \u8fd4\u56de List<T>",id:"91742-\u8fd4\u56de-listt",level:3},{value:"9.17.4.3 \u8fd4\u56de DataSet",id:"91743-\u8fd4\u56de-dataset",level:3},{value:"9.17.4.4 \u8fd4\u56de Tuple<T1,...T8>",id:"91744-\u8fd4\u56de-tuplet1t8",level:3},{value:"9.17.4.5 \u8fd4\u56de \u5355\u884c\u5355\u5217",id:"91745-\u8fd4\u56de-\u5355\u884c\u5355\u5217",level:3},{value:"9.17.4.6 \u65e0\u8fd4\u56de\u503c",id:"91746-\u65e0\u8fd4\u56de\u503c",level:3},{value:"9.17.4.7 \u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570",id:"91747-\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570",level:3},{value:"9.17.5 \u5b58\u50a8\u8fc7\u7a0b \u64cd\u4f5c",id:"9175-\u5b58\u50a8\u8fc7\u7a0b-\u64cd\u4f5c",level:2},{value:"9.17.5.1 \u8fd4\u56de DataTable",id:"91751-\u8fd4\u56de-datatable",level:3},{value:"9.17.5.2 \u8fd4\u56de List<T>",id:"91752-\u8fd4\u56de-listt",level:3},{value:"9.17.5.3 \u8fd4\u56de DataSet",id:"91753-\u8fd4\u56de-dataset",level:3},{value:"9.17.5.4 \u8fd4\u56de Tuple(T1,...T8)",id:"91754-\u8fd4\u56de-tuplet1t8",level:3},{value:"9.17.5.5 \u8fd4\u56de \u5355\u884c\u5355\u5217",id:"91755-\u8fd4\u56de-\u5355\u884c\u5355\u5217",level:3},{value:"9.17.5.6 \u65e0\u8fd4\u56de\u503c",id:"91756-\u65e0\u8fd4\u56de\u503c",level:3},{value:"9.17.5.7 \u5e26 OUTPUT/RETURN \u8fd4\u56de",id:"91757-\u5e26-outputreturn-\u8fd4\u56de",level:3},{value:"9.17.5.8 \u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570",id:"91758-\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570",level:3},{value:"9.17.6 \u51fd\u6570 \u64cd\u4f5c",id:"9176-\u51fd\u6570-\u64cd\u4f5c",level:2},{value:"9.17.7 Sql \u6a21\u677f\u66ff\u6362",id:"9177-sql-\u6a21\u677f\u66ff\u6362",level:2},{value:"9.17.8 \u5207\u6362\u6570\u636e\u5e93",id:"9178-\u5207\u6362\u6570\u636e\u5e93",level:2},{value:"9.17.8.1 \u5355\u4e2a\u65b9\u6cd5\u65b9\u5f0f",id:"91781-\u5355\u4e2a\u65b9\u6cd5\u65b9\u5f0f",level:3},{value:"9.17.8.2 \u63a5\u53e3\u65b9\u5f0f",id:"91782-\u63a5\u53e3\u65b9\u5f0f",level:3},{value:"9.17.8.3 \u8fd0\u884c\u65f6 .Change \u65b9\u6cd5\u5207\u6362",id:"91783-\u8fd0\u884c\u65f6-change-\u65b9\u6cd5\u5207\u6362",level:3},{value:"9.17.9 Sql \u4ee3\u7406\u62e6\u622a",id:"9179-sql-\u4ee3\u7406\u62e6\u622a",level:2},{value:"9.17.10 \u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4",id:"91710-\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4",level:2},{value:"9.17.11 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"91711-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:d};function u(e){var n=e.components,t=(0,r.Z)(e,i);return(0,o.kt)("wrapper",(0,a.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"9171-\u5173\u4e8e-sql-\u4ee3\u7406"},"9.17.1 \u5173\u4e8e ",(0,o.kt)("inlineCode",{parentName:"h2"},"Sql")," \u4ee3\u7406"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u662f ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u5bf9 ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u64cd\u4f5c\u4e00\u4e2a\u975e\u5e38\u91cd\u8981\u7684\u6982\u5ff5\uff0c\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\u53ef\u4ee5\u5927\u5927\u63d0\u9ad8 ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4e66\u5199\u6548\u7387\uff0c\u800c\u4e14\u540e\u671f\u6781\u6613\u7ef4\u62a4\u3002"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u5c5e\u4e8e ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u4e00\u4e2a\u9ad8\u7ea7\u529f\u80fd\u3002"),(0,o.kt)("h2",{id:"9172-\u4e86\u89e3-isqldispatchproxy"},"9.17.2 \u4e86\u89e3 ",(0,o.kt)("inlineCode",{parentName:"h2"},"ISqlDispatchProxy")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"ISqlDispatchProxy")," \u63a5\u53e3\u662f ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u5b9e\u73b0",(0,o.kt)("strong",{parentName:"p"},"\u88ab\u4ee3\u7406\u63a5\u53e3"),"\u7684\u552f\u4e00\u4f9d\u8d56\uff0c\u4efb\u4f55\u516c\u5f00\u7684\u63a5\u53e3\u4e00\u65e6\u96c6\u6210\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"ISqlDispatchProxy")," \u63a5\u53e3\uff0c\u90a3\u4e48\u8fd9\u4e2a\u63a5\u53e3\u5c31\u662f",(0,o.kt)("strong",{parentName:"p"},"\u88ab\u6258\u7ba1\u62e6\u622a"),"\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u64cd\u4f5c\u63a5\u53e3\u3002"),(0,o.kt)("p",null,"\u7b80\u5355\u5b9a\u4e49\u4e00\u4e2a ",(0,o.kt)("strong",{parentName:"p"},"Sql \u4ee3\u7406\u63a5\u53e3")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"":!0,"{1,5}":!0},"using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n }\n}\n")),(0,o.kt)("p",null,"\u4e00\u65e6\u8fd9\u4e2a\u63a5\u53e3\u7ee7\u627f\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"ISqlDispatchProxy"),"\uff0c\u90a3\u4e48\u5b83\u5c31\u4f1a",(0,o.kt)("strong",{parentName:"p"},"\u52a8\u6001\u521b\u5efa\u63a5\u53e3\u5b9e\u4f8b\uff0c\u800c\u4e14\u652f\u6301\u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c\u83b7\u53d6\u5b9e\u4f8b"),"\u3002"),(0,o.kt)("h2",{id:"9173-\u5f00\u59cb\u9886\u7565-sql-\u4ee3\u7406"},"9.17.3 \u5f00\u59cb\u9886\u7565 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Sql")," \u4ee3\u7406"),(0,o.kt)("p",null,"\u4e0b\u9762\u6211\u5c06\u901a\u8fc7\u591a\u4e2a\u4f8b\u5b50\u6765\u6f14\u793a ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u7684\u7528\u6cd5\uff0c\u4e3a\u4ec0\u4e48\u63a8\u8350\u8fd9\u79cd\u65b9\u5f0f\u64cd\u4f5c ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql"),"\u3002"),(0,o.kt)("p",null,"\u652f\u6301\u5404\u79cd\u65b9\u5f0f\u83b7\u53d6\u5b9e\u4f8b\uff1a"),(0,o.kt)("h3",{id:"91731-\u6784\u9020\u51fd\u6570\u65b9\u5f0f"},"9.17.3.1 \u6784\u9020\u51fd\u6570\u65b9\u5f0f"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-2}",showLineNumbers:!0,"":!0,"{1-2}":!0},"private readonly ISql _sql;\npublic FurionService(ISql sql)\n{\n _sql = sql;\n}\n")),(0,o.kt)("h3",{id:"91732-\u65b9\u6cd5\u53c2\u6570\u6ce8\u5165"},"9.17.3.2 \u65b9\u6cd5\u53c2\u6570\u6ce8\u5165"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"public async Task> GetAll([FromServices] ISql, string keyword)\n{\n}\n")),(0,o.kt)("h3",{id:"91733-dbgetsqldispatchproxyisql"},"9.17.3.3 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Db.GetSqlDispatchProxy()")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var sql = Db.GetSqlDispatchProxy();\n")),(0,o.kt)("h2",{id:"9174-sql-\u64cd\u4f5c"},"9.17.4 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Sql")," \u64cd\u4f5c"),(0,o.kt)("h3",{id:"91741-\u8fd4\u56de-datatable"},"9.17.4.1 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"DataTable")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8,12,16,20}",showLineNumbers:!0,"":!0,"{8,12,16,20}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u57fa\u5143\u7c7b\u578b\n [SqlExecute("select * from person where id >@id and name like @name")]\n DataTable GetPerson(int id, string name);\n\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u5bf9\u8c61\u7c7b\u578b\n [SqlExecute("select * from person where id >@id and name like @name")]\n DataTable GetPerson(MyParam paras);\n\n // \u6267\u884c\u5b58\u50a8\u8fc7\u7a0b sql\uff0c\u652f\u6301\u8bbe\u7f6e\u53c2\u6570\u7c7b\u578b\n [SqlExecute("exec PROP_NAME @id", CommandType = CommandType.StoredProcedure)]\n DataTable GetPerson(int id);\n\n // \u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\n [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator))]\n DataTable GetPerson();\n\n // \u5f02\u6b65\u65b9\u5f0f\n [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator))]\n Task GetPersonAsync();\n }\n}\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u53c2\u6570",type:"important"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u53c2\u6570\u67e5\u627e\u89c4\u5219\uff1a"),(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u65b9\u6cd5\u7684\u53c2\u6570\u662f ",(0,o.kt)("inlineCode",{parentName:"p"},"\u57fa\u5143\u7c7b\u578b"),"\uff08\u6216 ",(0,o.kt)("inlineCode",{parentName:"p"},"string"),"\u3001",(0,o.kt)("inlineCode",{parentName:"p"},"\u503c\u7c7b\u578b"),"\uff09\uff0c\u5219\u81ea\u52a8\u5c06\u8fd9\u4e9b\u7c7b\u578b\u7ec4\u5408\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"Dictionary")," \u4f5c\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u53c2\u6570\u3002\u547d\u4ee4\u53c2\u6570\u53ef\u4f7f\u7528\u65b9\u6cd5\u540c\u540d\u53c2\u6570\u52a0 ",(0,o.kt)("inlineCode",{parentName:"p"},"@")," \u7b26\u53f7\u3002"),(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u65b9\u6cd5\u7684\u53c2\u6570\u662f ",(0,o.kt)("inlineCode",{parentName:"p"},"\u7c7b\u7c7b\u578b"),"\uff0c\u90a3\u4e48\u81ea\u52a8\u904d\u5386\u8be5\u7c7b\u516c\u5f00\u5b9e\u4f8b\u5c5e\u6027\u751f\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"DbParameter[]")," \u6570\u7ec4\uff0c\u6bcf\u4e00\u4e2a\u5c5e\u6027\u540d\u90fd\u5c06\u662f\u547d\u4ee4\u53c2\u6570\uff0c",(0,o.kt)("strong",{parentName:"p"},"\u5927\u90e8\u5206\u6570\u636e\u5e93\u662f\u4e0d\u533a\u5206\u5927\u5c0f\u5199\uff0c\u4e2a\u522b\u6570\u636e\u5e93\u9664\u5916"),"\uff0c\u5982 ",(0,o.kt)("inlineCode",{parentName:"p"},"Sqlite"),"\uff0c\u5982\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public class MyModel\n{\n public int Id {get;set;}\n public string Name {get; set;}\n}\n")),(0,o.kt)("p",{parentName:"admonition"},"\u90a3\u4e48 ",(0,o.kt)("inlineCode",{parentName:"p"},"sql")," \u8bed\u53e5\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528\u5c5e\u6027\u540d\u4f5c\u4e3a\u53c2\u6570\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-sql",metastring:"showLineNumbers",showLineNumbers:!0},"select * from person where id > @id and name = @name;\n"))),(0,o.kt)("h3",{id:"91742-\u8fd4\u56de-listt"},"9.17.4.2 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"List")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8,12,16,20}",showLineNumbers:!0,"":!0,"{8,12,16,20}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u57fa\u5143\u7c7b\u578b\n [SqlExecute("select * from person where id >@id and name like @name")]\n List GetPerson(int id, string name);\n\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u5bf9\u8c61\u7c7b\u578b\n [SqlExecute("select * from person where id >@id and name like @name")]\n List GetPerson(MyParam paras);\n\n // \u6267\u884c\u5b58\u50a8\u8fc7\u7a0b sql\uff0c\u652f\u6301\u8bbe\u7f6e\u53c2\u6570\u7c7b\u578b\n [SqlExecute("exec PROP_NAME @id", CommandType = CommandType.StoredProcedure)]\n List GetPerson(int id);\n\n // \u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\n [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]\n List GetPerson();\n\n // \u5f02\u6b65\u65b9\u5f0f\n [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]\n Task> GetPersonAsync();\n }\n}\n')),(0,o.kt)("h3",{id:"91743-\u8fd4\u56de-dataset"},"9.17.4.3 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"DataSet")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8-10,14-16,20-22,26-28,32-35}",showLineNumbers:!0,"":!0,"{8-10,14-16,20-22,26-28,32-35}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u57fa\u5143\u7c7b\u578b\n [SqlExecute(@"\n select * from person where id >@id and name like @name;\n select top 10 * from student where Id >@id;")]\n DataSet GetData(int id, string name);\n\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u5bf9\u8c61\u7c7b\u578b\n [SqlExecute(@"\n select * from person where id >@id and name like @name;\n select top 10 * from student where Id >@id;")]\n DataSet GetData(MyParam paras);\n\n // \u6267\u884c\u5b58\u50a8\u8fc7\u7a0b sql\uff0c\u652f\u6301\u8bbe\u7f6e\u53c2\u6570\u7c7b\u578b\n [SqlExecute(@"\n exec PROP_NAME @id;\n select * from person;", CommandType = CommandType.StoredProcedure)]\n DataSet GetData(int id);\n\n // \u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\n [SqlExecute(@"\n select * from person;\n select * from student;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]\n DataSet GetData();\n\n // \u5f02\u6b65\u65b9\u5f0f\n [SqlExecute(@"\n select * from person;\n select * from student;\n select 1;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]\n Task GetDataAsync());\n }\n}\n')),(0,o.kt)("h3",{id:"91744-\u8fd4\u56de-tuplet1t8"},"9.17.4.4 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"Tuple")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8-10,14-16,20-22,26-28,32-35,38-42}",showLineNumbers:!0,"":!0,"{8-10,14-16,20-22,26-28,32-35,38-42}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u57fa\u5143\u7c7b\u578b\n [SqlExecute(@"\n select * from person where id >@id and name like @name;\n select top 10 * from student where Id >@id;")]\n (List,List) GetData(int id, string name);\n\n // \u6267\u884csql\u5e76\u4f20\u5165\u53c2\u6570\uff0c\u5bf9\u8c61\u7c7b\u578b\n [SqlExecute(@"\n select * from person where id >@id and name like @name;\n select top 10 * from student where Id >@id;")]\n (List,List) GetData(MyParam paras);\n\n // \u6267\u884c\u5b58\u50a8\u8fc7\u7a0b sql\uff0c\u652f\u6301\u8bbe\u7f6e\u53c2\u6570\u7c7b\u578b\n [SqlExecute(@"\n exec PROP_NAME @id;\n select * from person;", CommandType = CommandType.StoredProcedure)]\n (List,List) GetData(int id);\n\n // \u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\n [SqlExecute(@"\n select * from person;\n select * from student;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]\n (List,List) GetData();\n\n // \u5f02\u6b65\u65b9\u5f0f\n [SqlExecute(@"\n select * from person;\n select * from student;\n select 1;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]\n Task<(List,List,List)> GetDataAsync();\n\n // \u81ea v3.7.3+ \u7248\u672c\u652f\u6301\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570\n [SqlExecute(@"\n select * from person where id =@id;\n select * from person")]\n (Person, List) GetData(int id); // \u6ce8\u610f\u8fd4\u56de\u503c\u662f `(Person, List)` \u7ec4\u5408\n}\n')),(0,o.kt)("h3",{id:"91745-\u8fd4\u56de-\u5355\u884c\u5355\u5217"},"9.17.4.5 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"\u5355\u884c\u5355\u5217")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlExecute("select Name from person where id = @id")]\n string GetValue(int id);\n\n [SqlExecute("select age from person where id = @id")]\n int GetValue(int id);\n\n [SqlExecute("select Name from person where id = @id")]\n Task GetValueAsync(int id);\n }\n}\n')),(0,o.kt)("h3",{id:"91746-\u65e0\u8fd4\u56de\u503c"},"9.17.4.6 \u65e0\u8fd4\u56de\u503c"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlExecute("insert into person(Name,Age) values(@name,@age)")]\n void Insert(MyParam dto);\n\n [SqlExecute("delete from person where id = @id")]\n void Delete(int id);\n\n [SqlExecute("update person set name=@name where id=@id")]\n void Update(int id, string name);\n }\n}\n')),(0,o.kt)("h3",{id:"91747-\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570"},"9.17.4.7 \u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570"),(0,o.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 3.7.1 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-5}",showLineNumbers:!0,"{3-5}":!0},'public interface ISql : ISqlDispatchProxy\n{\n // \u81ea v3.7.3+ \u7248\u672c\u652f\u6301\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570\n [SqlExecute("select * from person where id=@id")]\n Person GetPerson(int id);\n}\n')),(0,o.kt)("h2",{id:"9175-\u5b58\u50a8\u8fc7\u7a0b-\u64cd\u4f5c"},"9.17.5 ",(0,o.kt)("inlineCode",{parentName:"h2"},"\u5b58\u50a8\u8fc7\u7a0b")," \u64cd\u4f5c"),(0,o.kt)("h3",{id:"91751-\u8fd4\u56de-datatable"},"9.17.5.1 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"DataTable")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlProcedure("PROC_Name")]\n DataTable GetPersons(MyParam dto);\n\n [SqlProcedure("PROC_Name")]\n DataTable GetPersons(int id);\n\n [SqlProcedure("PROC_Name")]\n DataTable GetPersons(int id, string name);\n }\n}\n')),(0,o.kt)("h3",{id:"91752-\u8fd4\u56de-listt"},"9.17.5.2 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"List")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlProcedure("PROC_Name")]\n List GetPersons(MyParam dto);\n\n [SqlProcedure("PROC_Name")]\n List GetPersons(int id);\n\n [SqlProcedure("PROC_Name")]\n List GetPersons(int id, string name);\n }\n}\n')),(0,o.kt)("h3",{id:"91753-\u8fd4\u56de-dataset"},"9.17.5.3 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"DataSet")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlProcedure("PROC_Name")]\n DataSet GetData(MyParam dto);\n\n [SqlProcedure("PROC_Name")]\n DataSet GetData(int id);\n\n [SqlProcedure("PROC_Name")]\n DataSet GetData(int id, string name);\n }\n}\n')),(0,o.kt)("h3",{id:"91754-\u8fd4\u56de-tuplet1t8"},"9.17.5.4 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"Tuple(T1,...T8)")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13,16-18}",showLineNumbers:!0,"":!0,"{7,10,13,16-18}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlProcedure("PROC_Name")]\n (List, List) GetData(MyParam dto);\n\n [SqlProcedure("PROC_Name")]\n (List, List) GetData(int id);\n\n [SqlProcedure("PROC_Name")]\n (List, List, Person, int) GetData(int id, string name);\n\n // \u81ea v3.7.3+ \u7248\u672c\u652f\u6301\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570\n [SqlProcedure(@"PROC_Name)]\n (Person, List) GetData(int id); // \u6ce8\u610f\u8fd4\u56de\u503c\u662f `(Person, List)` \u7ec4\u5408\n }\n}\n')),(0,o.kt)("h3",{id:"91755-\u8fd4\u56de-\u5355\u884c\u5355\u5217"},"9.17.5.5 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"\u5355\u884c\u5355\u5217")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlProcedure("PROC_Name")]\n object GetValue(MyParam dto);\n\n [SqlProcedure("PROC_Name")]\n string GetValue(int id);\n\n [SqlProcedure("PROC_Name")]\n int GetValue(int id, string name);\n }\n}\n')),(0,o.kt)("h3",{id:"91756-\u65e0\u8fd4\u56de\u503c"},"9.17.5.6 \u65e0\u8fd4\u56de\u503c"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlProcedure("PROC_Name")]\n void GetValue(MyParam dto);\n\n [SqlProcedure("PROC_Name")]\n void GetValue(int id);\n\n [SqlProcedure("PROC_Name")]\n void GetValue(int id, string name);\n }\n}\n')),(0,o.kt)("h3",{id:"91757-\u5e26-outputreturn-\u8fd4\u56de"},"9.17.5.7 \u5e26 ",(0,o.kt)("inlineCode",{parentName:"h3"},"OUTPUT/RETURN")," \u8fd4\u56de"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10,13}",showLineNumbers:!0,"":!0,"{7,10,13}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlProcedure("PROC_Name")]\n ProcedureOutputResult GetOutput(ProcOutputModel pams);\n\n [SqlProcedure("PROC_Name")]\n ProcedureOutputResult GetOutput(ProcOutputModel pams);\n\n [SqlProcedure("PROC_Name")]\n ProcedureOutputResult<(List, List)> GetOutput(ProcOutputModel pams);\n }\n}\n')),(0,o.kt)("h3",{id:"91758-\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570"},"9.17.5.8 \u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570"),(0,o.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 3.7.1 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-5}",showLineNumbers:!0,"{3-5}":!0},'public interface ISql : ISqlDispatchProxy\n{\n // \u81ea v3.7.3+ \u7248\u672c\u652f\u6301\u8fd4\u56de\u5355\u4e2a\u7c7b\u7c7b\u578b\u53c2\u6570\n [SqlProcedure("PROC_Name")]\n Person GetPerson(int id);\n}\n')),(0,o.kt)("h2",{id:"9176-\u51fd\u6570-\u64cd\u4f5c"},"9.17.6 ",(0,o.kt)("inlineCode",{parentName:"h2"},"\u51fd\u6570")," \u64cd\u4f5c"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,10}",showLineNumbers:!0,"":!0,"{7,10}":!0},'using Furion.DatabaseAccessor;\n\nnamespace Furion.Application\n{\n public interface ISql : ISqlDispatchProxy\n {\n [SqlFunction("FN_Name")] // \u6807\u91cf\u51fd\u6570\n string GetValue(MyParam dto);\n\n [SqlProcedure("FN_Name")] // \u8868\u503c\u51fd\u6570\n List GetPersons(int id);\n }\n}\n')),(0,o.kt)("admonition",{title:"\u8865\u5145\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u4f1a\u81ea\u52a8\u5224\u65ad\u8fd4\u56de\u503c\u7136\u540e\u81ea\u52a8\u6267\u884c\u7279\u5b9a\u51fd\u6570\u7c7b\u578b\u3002")),(0,o.kt)("h2",{id:"9177-sql-\u6a21\u677f\u66ff\u6362"},"9.17.7 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Sql")," \u6a21\u677f\u66ff\u6362"),(0,o.kt)("p",null,"\u5728\u6700\u65b0\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"1.18.3")," \u7248\u672c\u4e2d\u63d0\u4f9b\u4e86\u6a21\u677f\u66ff\u6362\u529f\u80fd\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[SqlExecute("select * from person where id > {id} and name like {name} and age > {user.Age}")]\nList GetPerson(int id, string name, User user);\n')),(0,o.kt)("admonition",{title:"\u4e24\u8005\u533a\u522b",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u6a21\u677f\u5b57\u7b26\u4e32\u6709\u522b\u4e8e\u547d\u4ee4\u53c2\u6570\u66ff\u6362\uff0c\u6a21\u677f\u5b57\u7b26\u4e32\u91c7\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"{ }")," \u65b9\u5f0f\uff0c\u8fd0\u884c\u65f6\u76f4\u63a5\u66ff\u6362\u4e3a\u5b9e\u9645\u7684\u5185\u5bb9\uff0c ",(0,o.kt)("inlineCode",{parentName:"p"},"@")," \u800c\u662f\u8f6c\u6362\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"DbParameter")," \u53c2\u6570\u3002")),(0,o.kt)("h2",{id:"9178-\u5207\u6362\u6570\u636e\u5e93"},"9.17.8 \u5207\u6362\u6570\u636e\u5e93"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u65b9\u5f0f\u7684\u652f\u6301\u4e09\u79cd\u5207\u6362\u6570\u636e\u5e93\u7684\u65b9\u5f0f\uff1a"),(0,o.kt)("h3",{id:"91781-\u5355\u4e2a\u65b9\u6cd5\u65b9\u5f0f"},"9.17.8.1 \u5355\u4e2a\u65b9\u6cd5\u65b9\u5f0f"),(0,o.kt)("p",null,"\u4e3b\u8981\u901a\u8fc7\u5728\u65b9\u6cd5\u4e0a\u8d34 ",(0,o.kt)("inlineCode",{parentName:"p"},"[SqlDbContextLocator]")," \u7279\u6027"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'[SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]\nList GetPerson();\n')),(0,o.kt)("h3",{id:"91782-\u63a5\u53e3\u65b9\u5f0f"},"9.17.8.2 \u63a5\u53e3\u65b9\u5f0f"),(0,o.kt)("p",null,"\u5728\u63a5\u53e3\u4e2d\u8d34 ",(0,o.kt)("inlineCode",{parentName:"p"},"[SqlDbContextLocator]")," \u7279\u6027\uff0c\u6b64\u65b9\u5f0f\u4e0b\uff0c\u63a5\u53e3\u6240\u6709\u65b9\u6cd5\u5c06\u91c7\u7528\u6307\u5b9a\u7684\u6570\u636e\u5e93\u6267\u884c\u3002"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'[SqlDbContextLocator(typeof(MySqlDbContextLocator)]\npublic interface ISql : ISqlDispatchProxy\n{\n [SqlFunction("FN_Name")] // \u6807\u91cf\u51fd\u6570\n string GetValue(MyParam dto);\n\n [SqlProcedure("FN_Name")] // \u8868\u503c\u51fd\u6570\n List GetPersons(int id);\n}\n')),(0,o.kt)("h3",{id:"91783-\u8fd0\u884c\u65f6-change-\u65b9\u6cd5\u5207\u6362"},"9.17.8.3 \u8fd0\u884c\u65f6 ",(0,o.kt)("inlineCode",{parentName:"h3"},".Change")," \u65b9\u6cd5\u5207\u6362"),(0,o.kt)("p",null,"\u9664\u4e86\u4ee5\u4e0a\u4e24\u79cd ",(0,o.kt)("inlineCode",{parentName:"p"},"\u9759\u6001")," \u914d\u7f6e\u65b9\u5f0f\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u8fd8\u63d0\u4f9b ",(0,o.kt)("inlineCode",{parentName:"p"},"\u52a8\u6001")," \u65b9\u5f0f\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6}",showLineNumbers:!0,"":!0,"{2,6}":!0},"// \u5c06 sql \u4ee3\u7406\u6570\u636e\u5e93\u5207\u6362\u6210\u7279\u5b9a\u6570\u636e\u5e93\n_sql.Change();\n_sql.GetPerson();\n\n// \u591a\u6b21\u5207\u6362\n_sql.Change();\n_sql.GetPerson();\n\n// \u8fd8\u652f\u6301\u91cd\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u4e3a\u521d\u59cb\u72b6\u6001\n_sql.ResetIt();\n_sql.GetPerson();\n")),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u4f18\u5148\u7ea7\u95ee\u9898",type:"important"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},".Change<>")," \u4f18\u5148\u7ea7\u5927\u4e8e ",(0,o.kt)("inlineCode",{parentName:"p"},"\u65b9\u6cd5\u8d34 [SqlDbContextLocator]")," \u5927\u4e8e ",(0,o.kt)("inlineCode",{parentName:"p"},"\u63a5\u53e3\u8d34 [SqlDbContextLocator]"),"\u3002"),(0,o.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u4e0d\u6307\u5b9a ",(0,o.kt)("inlineCode",{parentName:"p"},"DbContextLocator")," \u5c5e\u6027\uff0c\u5219\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"MasterDbContextLocator"),"\u3002")),(0,o.kt)("h2",{id:"9179-sql-\u4ee3\u7406\u62e6\u622a"},"9.17.9 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Sql")," \u4ee3\u7406\u62e6\u622a"),(0,o.kt)("p",null,"\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion v2.13 +")," \u7248\u672c\u65b0\u589e\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u62e6\u622a\u529f\u80fd\uff0c\u53ef\u4ee5\u7be1\u6539\u7279\u5b9a\u65b9\u6cd5\u6216\u6240\u6709\u4ee3\u7406\u65b9\u6cd5\u5b9e\u9645\u6267\u884c\u7684\u53c2\u6570\uff0c\u5982 ",(0,o.kt)("inlineCode",{parentName:"p"},"sql\u8bed\u53e5\u3001\u53c2\u6570\u3001\u6267\u884c\u5bf9\u8c61\u7b49\u7b49"),"\u3002"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u82e5\u5728 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Sql")," \u4ee3\u7406\u4e2d\u5b9e\u73b0\u62e6\u622a\u529f\u80fd\uff0c\u5fc5\u987b\u6ee1\u8db3\u4e24\u4e2a\u6761\u4ef6"),"\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u65b9\u6cd5\u5fc5\u987b\u662f ",(0,o.kt)("inlineCode",{parentName:"li"},"static")," \u9759\u6001\u65b9\u6cd5\u4e14\u8fd4\u56de\u503c\u4e3a ",(0,o.kt)("inlineCode",{parentName:"li"},"void")," \u4e14\u53ea\u6709\u4e00\u4e2a ",(0,o.kt)("inlineCode",{parentName:"li"},"SqlProxyMethod")," \u53c2\u6570"),(0,o.kt)("li",{parentName:"ul"},"\u65b9\u6cd5\u5fc5\u987b\u8d34 ",(0,o.kt)("inlineCode",{parentName:"li"},"[Interceptor]")," \u7279\u6027")),(0,o.kt)("p",null,"\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,13-17,20-24,26-30,32-36}",showLineNumbers:!0,"":!0,"{9,13-17,20-24,26-30,32-36}":!0},'public interface ISql : ISqlDispatchProxy\n{\n [SqlFunction("FN_Name")]\n string GetValue(MyParam dto);\n\n [SqlProcedure("FN_Name")]\n List GetPersons(int id);\n\n [SqlExecute("select name from person", InterceptorId = "GetPersonsByName")] // \u901a\u8fc7 InterceptorId \u89e3\u51b3\u65b9\u6cd5\u540d\u91cd\u8f7d\u95ee\u9898\n Task> GetPersons();\n\n // \u53ea\u62e6\u622a GetValue \u65b9\u6cd5\n [Interceptor(nameof(GetValue))]\n static void \u62e6\u622a1(SqlProxyMethod method)\n {\n method.FinalSql += " where id > 1"; // \u7be1\u6539\u6700\u7ec8\u6267\u884c sql\n }\n\n // \u62e6\u622a GetValue \u548c GetPersons \u65b9\u6cd5\n [Interceptor(nameof(GetValue), nameof(GetPersons))]\n static void \u62e6\u622a2(SqlProxyMethod method)\n {\n method.FinalSql += " where id > 1"; // \u7be1\u6539\u6700\u7ec8\u6267\u884c sql\n }\n\n [Interceptor("GetPersonsByName")] // \u5bf9\u5e94\u4e0a\u9762\u7684 InterceptorId \u914d\u7f6e\n static void \u89e3\u51b3\u65b9\u6cd5\u540d\u91cd\u8f7d\u62e6\u622a(SqlProxyMethod method)\n {\n // \u3002\u3002\u3002\n }\n\n [Interceptor]\n static void \u5168\u5c40\u62e6\u622a(SqlProxyMethod method)\n {\n // \u8fd9\u91cc\u4f1a\u62e6\u622a\u6240\u6709\u7684\u65b9\u6cd5\n }\n}\n')),(0,o.kt)("h2",{id:"91710-\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4"},"9.17.10 \u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[Timeout(1000)]\npublic interface ISql : ISqlDispatchProxy\n{\n [SqlFunction("FN_Name"), Timeout(500)] // \u5355\u4f4d\u79d2\n string GetValue(MyParam dto);\n}\n')),(0,o.kt)("h2",{id:"91711-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.17.11 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/51c14d7f.062a1d65.js b/handbook/build/assets/js/51c14d7f.062a1d65.js deleted file mode 100644 index 2fe595162e..0000000000 --- a/handbook/build/assets/js/51c14d7f.062a1d65.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[8559],{6509:function(e,n,t){t.r(n),t.d(n,{assets:function(){return d},contentTitle:function(){return s},default:function(){return u},frontMatter:function(){return l},metadata:function(){return c},toc:function(){return p}});var r=t(3117),o=t(102),i=(t(7294),t(3905)),a=(t(1402),["components"]),l={id:"deploy-docker-auto",title:"35.1 Docker \u73af\u5883\u6301\u7eed\u90e8\u7f72",sidebar_label:"35.1 Docker \u73af\u5883\u6301\u7eed\u90e8\u7f72"},s=void 0,c={unversionedId:"deploy-docker-auto",id:"deploy-docker-auto",title:"35.1 Docker \u73af\u5883\u6301\u7eed\u90e8\u7f72",description:"",source:"@site/docs/deploy-docker-auto.mdx",sourceDirName:".",slug:"/deploy-docker-auto",permalink:"/furion/docs/deploy-docker-auto",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/deploy-docker-auto.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1653889755,formattedLastUpdatedAt:"May 30, 2022",frontMatter:{id:"deploy-docker-auto",title:"35.1 Docker \u73af\u5883\u6301\u7eed\u90e8\u7f72",sidebar_label:"35.1 Docker \u73af\u5883\u6301\u7eed\u90e8\u7f72"},sidebar:"docs",previous:{title:"34.6 pm2 \u90e8\u7f72",permalink:"/furion/docs/pm2"},next:{title:"35.2 \u6301\u7eed\u90e8\u7f72\u96c6\u6210",permalink:"/furion/docs/devops"}},d={},p=[{value:"35.1.1 \u5173\u4e8e\u5168 Docker \u73af\u5883\u90e8\u7f72",id:"3511-\u5173\u4e8e\u5168-docker-\u73af\u5883\u90e8\u7f72",level:2},{value:"35.1.2 \u5b89\u88c5 Docker \u7248 Jenkins",id:"3512-\u5b89\u88c5-docker-\u7248-jenkins",level:2},{value:"35.1.2.1 \u4f7f\u7528 Dockerfile \u5236\u4f5c\u955c\u50cf",id:"35121-\u4f7f\u7528-dockerfile-\u5236\u4f5c\u955c\u50cf",level:3},{value:"35.1.2.2 \u8fd0\u884c Jenkins:dotnet \u955c\u50cf",id:"35122-\u8fd0\u884c-jenkinsdotnet-\u955c\u50cf",level:3},{value:"35.1.3 Jenkins \u7684\u81ea\u52a8\u5316\u90e8\u7f72",id:"3513-jenkins-\u7684\u81ea\u52a8\u5316\u90e8\u7f72",level:2},{value:"35.1.3.1 \u7f16\u5199 Shell \u811a\u672c",id:"35131-\u7f16\u5199-shell-\u811a\u672c",level:3},{value:"35.1.4 Jenkins \u7684\u81ea\u52a8\u5316\u8fdc\u7a0b\u90e8\u7f72",id:"3514-jenkins-\u7684\u81ea\u52a8\u5316\u8fdc\u7a0b\u90e8\u7f72",level:2},{value:"35.1.4.1 \u5b89\u88c5\u63d2\u4ef6",id:"35141-\u5b89\u88c5\u63d2\u4ef6",level:3},{value:"35.1.4.2 \u914d\u7f6e",id:"35142-\u914d\u7f6e",level:3},{value:"35.1.4.3 \u5199\u811a\u672c",id:"35143-\u5199\u811a\u672c",level:3},{value:"35.1.4.4 \u6784\u5efa\u540e\u64cd\u4f5c\uff08\u5173\u952e\uff09",id:"35144-\u6784\u5efa\u540e\u64cd\u4f5c\u5173\u952e",level:3},{value:"35.1.4.5 \u8fdc\u7a0b\u6267\u884c",id:"35145-\u8fdc\u7a0b\u6267\u884c",level:3},{value:"35.1.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"3515-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],k={toc:p};function u(e){var n=e.components,t=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},k,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"3511-\u5173\u4e8e\u5168-docker-\u73af\u5883\u90e8\u7f72"},"35.1.1 \u5173\u4e8e\u5168 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Docker")," \u73af\u5883\u90e8\u7f72"),(0,i.kt)("p",null,"\u5229\u7528\u62e5\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET")," \u73af\u5883\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Jenkins"),"\uff0c\u8fdb\u884c\u6301\u7eed\u5316\u90e8\u7f72"),(0,i.kt)("h2",{id:"3512-\u5b89\u88c5-docker-\u7248-jenkins"},"35.1.2 \u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Docker")," \u7248 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Jenkins")),(0,i.kt)("p",null,"\u6b63\u5e38\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Docker")," \u4e2d\u62c9\u53d6\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Jenkins:lts")," \u662f\u65e0\u6cd5\u6267\u884c ",(0,i.kt)("inlineCode",{parentName:"p"},"dotnet")," \u547d\u4ee4\u7684\uff08\u5c31\u7b97\u4f60\u5bbf\u4e3b\u673a\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"dotnet")," \u73af\u5883\u3001",(0,i.kt)("inlineCode",{parentName:"p"},"docker")," \u4e2d\u4e5f\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"dotnet")," \u73af\u5883\u4e5f\u4e0d\u53ef\u4ee5\uff09\uff0c\n\u6240\u4ee5\u6211\u4eec\u53ea\u80fd\u6784\u5efa\u4e00\u4e2a\u5305\u542b ",(0,i.kt)("inlineCode",{parentName:"p"},"dotnet")," \u7684\u955c\u50cf"),(0,i.kt)("h3",{id:"35121-\u4f7f\u7528-dockerfile-\u5236\u4f5c\u955c\u50cf"},"35.1.2.1 \u4f7f\u7528 Dockerfile \u5236\u4f5c\u955c\u50cf"),(0,i.kt)("p",null,"\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Dockerfile")," \u521b\u5efa\u5305\u542b ",(0,i.kt)("inlineCode",{parentName:"p"},"dotnet")," \u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Jenkins")," \u955c\u50cf"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\ud83d\udc49 \u7f16\u5199 ",(0,i.kt)("inlineCode",{parentName:"li"},"Dockerfile"))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},'# \u5c01\u88c5Jenkins\u955c\u50cf\uff08\u5e26\u6709dotnet\u73af\u5883\u7684\uff09 sdk=5.1\nFROM jenkins/jenkins:lts\nUSER root\nWORKDIR /dotnet\nRUN apt-get update && apt-get install -y wget && rm -rf /var/lib/apt/lists/*\nRUN wget -O dotnet.tar.gz https://download.visualstudio.microsoft.com/download/pr/820db713-c9a5-466e-b72a-16f2f5ed00e2/628aa2a75f6aa270e77f4a83b3742fb8/dotnet-sdk-5.0.100-linux-x64.tar.gz\nRUN tar zxf dotnet.tar.gz -C ./\nRUN rm -rf dotnet.tar.gz\nENV PATH="${PATH}:/dotnet:/var/jenkins_home/.dotnet/tools"\nENV DOTNET_ROOT="/dotnet"\nRUN apt update -y\nRUN apt install icu-devtools vim zip unzip -y\nRUN usermod -a -G root jenkins\nUSER jenkins\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\ud83d\udc49 \u547d\u4ee4\u89e3\u91ca")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"- 1. \u8fd9\u4e2aDocker\u955c\u50cf\u57fa\u4e8ejenkins\n- 2. \u8bbe\u7f6e\u5f53\u524d\u7528\u6237\u4e3aroot\uff0c\u56e0\u4e3a\u540e\u9762\u5b89\u88c5\u9700\u8981\u4f7f\u7528root\n- 3. \u8bbe\u7f6e\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u4e3adotnet\n- 4. \u4e0b\u8f7ddotnet SDK\u5305\uff0c\u4fdd\u5b58\u4e3adotnet.tar.gz\u3002\u8fd9\u91cc\u8981\u6ce8\u610f\u4e0b\u8f7d\u6b63\u786e\u7248\u672c\u7684SDK\uff0c\u53ef\u524d\u5f80\u5fae\u8f6f\u5b98\u65b9\u7f51\u7ad9\u83b7\u53d6\u4e0b\u8f7d\u94fe\u63a5\uff1ahttps://dotnet.microsoft.com/download\n- 5. \u89e3\u538bdotnet SDK\u5230\u5f53\u524d\u76ee\u5f55\uff0c\u5373/dotnet\u76ee\u5f55\n- 6. \u5220\u9664dotnet SDK\u5305\n- 7. \u628adotnet\u76ee\u5f55\u548cdotnet tools\u76ee\u5f55\u6dfb\u52a0\u5230\u73af\u5883\u53d8\u91cfPATH\uff0c\u8fd9\u6837\u5c31\u53ef\u4ee5\u4f7f\u7528dotnet\u547d\u4ee4\u4e86\n- 8. \u8bbe\u7f6eDOTNET_ROOT\u53d8\u91cf\n- 9. \u66f4\u65b0\u6e90\n- 10. \u5b89\u88c5\u4e00\u4e9b\u5fc5\u9700\u7684\uff0c\u5e38\u7528\u7684\u5de5\u5177\u5305\uff0c\u5176\u4e2dicu-devtools\u662f\u8fd0\u884cdotnet\u9700\u8981\u7684\n- 11. \u4fee\u6539jenkins\u7528\u6237\u5230root\u9644\u52a0\u7ec4\n- 12. \u8bbe\u7f6e\u5f53\u524d\u7528\u6237\u4e3ajenkins\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\ud83d\udc49 \u6784\u5efa ",(0,i.kt)("inlineCode",{parentName:"li"},"Docker")," \u955c\u50cf ",(0,i.kt)("inlineCode",{parentName:"li"},"name=jenkins:dotnet"))),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"cd")," \u5230\u6839\u76ee\u5f55\u4e0b\uff08\u5fc5\u987b\u542b ",(0,i.kt)("inlineCode",{parentName:"p"},"Dockerfile"),"\uff09 \u53ea\u9700\u6784\u5efa\u547d\u4ee4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0}," docker build -t jenkins:dotnet .\n")),(0,i.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed3\u5c3e ",(0,i.kt)("inlineCode",{parentName:"p"},".")," \u4e0d\u80fd\u7701\u7565")),(0,i.kt)("h3",{id:"35122-\u8fd0\u884c-jenkinsdotnet-\u955c\u50cf"},"35.1.2.2 \u8fd0\u884c ",(0,i.kt)("inlineCode",{parentName:"h3"},"Jenkins:dotnet")," \u955c\u50cf"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},'docker run -d -p 8080:8080 -p 50000:50000 --name mjenkins \\\n --privileged=true \\\n --restart always \\\n -u root \\\n -e TZ="Asia/Shanghai" \\\n -v /mudata/jenkins:/var/jenkins_home \\\n -v /usr/bin/docker:/usr/bin/docker \\\n -v /var/run/docker.sock:/var/run/docker.sock \\\n -v /mudata/webroot/:/mudata/webroot \\\n jenkins:dotnet\n')),(0,i.kt)("p",null,"\u63a5\u4e0b\u6765\u5c31\u662f\u6bd4\u8f83\u4fd7\u5957\u7684\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},"Jenkins")," \u6b65\u9aa4\uff0c\u7f51\u4e0a\u8d44\u6599\u5f88\u591a\uff0c\u4e0d\u5c55\u5f00\u4e86\u3002"),(0,i.kt)("h2",{id:"3513-jenkins-\u7684\u81ea\u52a8\u5316\u90e8\u7f72"},"35.1.3 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Jenkins")," \u7684\u81ea\u52a8\u5316\u90e8\u7f72"),(0,i.kt)("h3",{id:"35131-\u7f16\u5199-shell-\u811a\u672c"},"35.1.3.1 \u7f16\u5199 Shell \u811a\u672c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"# Jenkins \u6784\u5efa \u6d4b\u8bd5\u670d\n\necho '============\u67e5\u770b\u6253\u5305\u73af\u5883================'\npwd\nls\necho $PATH\n\nimage_version=`date +%Y%m%d%H%M`;\necho $image_version;\n\ndotnet --info\ndotnet --version\n\n# \u83b7\u53d6\u77ed\u7248\u672c\u53f7\nGITHASH=`git rev-parse --short HEAD`\n\necho '============================begin restore======================================='\ndotnet restore\necho '============================end restore======================================='\n\n#\u8981\u6784\u5efa\u7684\u89e3\u51b3\u65b9\u6848\u540d\u79f0\nsolutionName=MUSaas.SCM.BasicData\n#docker run\u7684\u5bb9\u5668\u540d\u79f0\ncontainerName=jenkinsscmbasic\n#\u6307\u5b9arun\u7684\u7aef\u53e3\nport=9994\n#.sln\u6587\u4ef6\u5168\u8def\u5f84\n#solutionDir=20-Solution/${solutionName}.sln\n#.csproj\u6587\u4ef6\u5168\u8def\u5f84\ncsprojDir=${solutionName}/${solutionName}.csproj\n\n#\u9879\u76ee\u53d1\u5e03\u7684\u76ee\u5f55\nwebDir=/mudata/webroot/jenkins/publish/webapp\n\n#\u5f52\u6863\u76ee\u5f55\narchivesDir=/mudata/webroot/jenkins/publish/archives\n\n#\u6e05\u7a7a\u6587\u4ef6\u5939\nrm -rf ${webDir}/${JOB_NAME}/*\n\n#\u53d1\u5e03\u7f51\u7ad9\u5230webDir\ndotnet publish ${JENKINS_HOME}/workspace/${JOB_NAME}/${csprojDir} -c Release -o ${webDir}/${JOB_NAME} /p:Version=1.0.${BUILD_NUMBER}\n#\u590d\u5236\u914d\u7f6e\u6587\u4ef6\n#cp -rf /vdb1/jenkins/DotNetCoreWebPublishToDockerCommonConfigs/* ${webDir}/${JOB_NAME}/\n\n#\u5224\u65b7\u662f\u5426\u5b58\u5728\nCID=$(docker ps | grep \"${containerName}\" | awk '{print $1}')\necho $CID\nif [ \"$CID\" != \"\" ];then\n docker stop ${containerName}\n docker rm ${containerName}\n docker rmi ${containerName}\n#docker stop $CID\n#docker rm $CID\nfi\n\n\n#\u901a\u8fc7Dockerfile\u91cd\u65b0\u6784\u5efa\u955c\u50cf\ndocker build -t ${containerName} ${webDir}/${JOB_NAME}/.\n#docker run\u5bb9\u5668\u5e76\u7ed1\u5b9a\u5230\u7aef\u53e3\n#docker run -d -p ${port}:80 --name ${containerName} ${containerName}\ndocker run --name ${containerName} --restart=always -d -p ${port}:${port} -v /etc/localtime:/etc/localtime:ro ${containerName}\necho \"success!\"\n\n")),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u5c31\u8fd9\u6837\u81ea\u52a8\u5316\u90e8\u7f72\u5c31\u597d\u4e86\u3002 \u6d4b\u8bd5\u670d\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Jenkins")," \u5c06\u6e90\u7801\u62c9\u4e0b\u6765\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Publish\uff0cDocker Build\uff0cDocker Run"),"\u3002")),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u8fd9\u91cc\u60f3\u8981\u53d1\u5e03\u7684\u65f6\u5019\uff0c\u6bcf\u6b21\u90fd\u9700\u8981\u624b\u52a8\u53bb\u70b9\u51fb\u201c\u6784\u5efa\u201d\u624d\u4f1a\u6267\u884c\u3002\u4e5f\u53ef\u4ee5\u505a\u6210\u5f53\u5206\u652f\u5408\u5e76\u6210\u529f\u540e\u81ea\u52a8\u8fd0\u884c\u3002\u53cd\u6b63 ",(0,i.kt)("inlineCode",{parentName:"p"},"Jenkins")," \u88c5\u597d\u4e4b\u540e\uff0c\u4f60\u60f3\u8981\u4ec0\u4e48\u90fd\u80fd\u73a9\u8d77\u6765\u3002\u6bd4\u5982\u6307\u5b9a\u5206\u652f\u63d0\u4ea4\u540e\u81ea\u52a8\u201c\u6784\u5efa\u201d\u3001\u6bd4\u5982\u6784\u5efa\u6210\u529f\u540e\u5408\u5e76\u5230 Master \u7b49\u7b49")),(0,i.kt)("h2",{id:"3514-jenkins-\u7684\u81ea\u52a8\u5316\u8fdc\u7a0b\u90e8\u7f72"},"35.1.4 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Jenkins")," \u7684\u81ea\u52a8\u5316\u8fdc\u7a0b\u90e8\u7f72"),(0,i.kt)("h3",{id:"35141-\u5b89\u88c5\u63d2\u4ef6"},"35.1.4.1 \u5b89\u88c5\u63d2\u4ef6"),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},(0,i.kt)("inlineCode",{parentName:"p"},"Publish Over SSH"))),(0,i.kt)("h3",{id:"35142-\u914d\u7f6e"},"35.1.4.2 \u914d\u7f6e"),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u7cfb\u7edf\u7ba1\u7406 => ",(0,i.kt)("inlineCode",{parentName:"p"},"Publish over SSH"))),(0,i.kt)("h3",{id:"35143-\u5199\u811a\u672c"},"35.1.4.3 \u5199\u811a\u672c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"# Jenkins \u6784\u5efa \u6b63\u5f0f\u670d\n\necho '============\u67e5\u770b\u6253\u5305\u73af\u5883================'\npwd\nls\necho $PATH\n\nimage_version=`date +%Y%m%d%H%M`;\necho $image_version;\n\ndotnet --info\ndotnet --version\n\n# \u83b7\u53d6\u77ed\u7248\u672c\u53f7\nGITHASH=`git rev-parse --short HEAD`\n\necho '============================begin restore======================================='\ndotnet restore\necho '============================end restore======================================='\n\n#\u8981\u6784\u5efa\u7684\u89e3\u51b3\u65b9\u6848\u540d\u79f0\nsolutionName=MUSaas.SCM.BulkOrder\n#docker run\u7684\u5bb9\u5668\u540d\u79f0\ncontainerName=jenkinsscmbulk\n#\u6307\u5b9arun\u7684\u7aef\u53e3\nport=9986\n#.csproj\u6587\u4ef6\u5168\u8def\u5f84\ncsprojDir=/${solutionName}/${solutionName}.csproj\n\n#\u9879\u76ee\u53d1\u5e03\u7684\u76ee\u5f55\nwebDir=/mudata/webroot/jenkins/publish/webapp\n\n#\u5f52\u6863\u76ee\u5f55\narchivesDir=/mudata/webroot/jenkins/publish/archives\n\n#\u6e05\u7a7a\u6587\u4ef6\u5939\nrm -rf ${webDir}/${JOB_NAME}/*\n\n#\u53d1\u5e03\u7f51\u7ad9\u5230webDir\ndotnet publish ${JENKINS_HOME}/workspace/${JOB_NAME}/${csprojDir} -c Release -o ${webDir}/${JOB_NAME} /p:Version=1.0.${BUILD_NUMBER}\n#\u590d\u5236\u914d\u7f6e\u6587\u4ef6\n#cp -rf /vdb1/jenkins/DotNetCoreWebPublishToDockerCommonConfigs/* ${webDir}/${JOB_NAME}/\n\n\n#\u6784\u5efa\u8fdc\u7a0b\u5305\n\nrm -rf ${JENKINS_HOME}/workspace/${JOB_NAME}/publish\nmkdir ${JENKINS_HOME}/workspace/${JOB_NAME}/publish\n\ntar -czvf ${JENKINS_HOME}/workspace/${JOB_NAME}/publish/${JOB_NAME}.${BUILD_NUMBER}.tar.gz -C ${webDir}/${JOB_NAME} .\n\necho \"success!\"\n")),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u5927\u6982\u903b\u8f91\u5c31\u662f\u53d1\u5e03\u540e\uff0c\u6253\u4e2a\u5305\u3002\u7136\u540e\u4e22\u7ed9\u8fdc\u7a0b\uff0c\u8fdc\u7a0b\u518d\u6267\u884c ",(0,i.kt)("inlineCode",{parentName:"p"},"shell"))),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u6ce8\u610f\u8fd9\u91cc\u4e00\u5b9a\u8981\u53d1\u5e03\u5230\u81ea\u5df1\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"workspace")," \u4e0b\uff0c\u9632\u6b62\u4e0b\u4e00\u6b65\u6b7b\u6d3b\u627e\u4e0d\u5230\u4f4d\u7f6e\u3002\u5982\u679c\u627e\u4e0d\u5230\u4f4d\u7f6e\uff0c\u53ea\u80fd\u6162\u6162\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"ls")," \u547d\u4ee4\uff0c\u4e00\u7ea7\u4e00\u7ea7\u53bb\u6d4b\uff0c\u5f88\u9ebb\u70e6")),(0,i.kt)("h3",{id:"35144-\u6784\u5efa\u540e\u64cd\u4f5c\u5173\u952e"},"35.1.4.4 \u6784\u5efa\u540e\u64cd\u4f5c\uff08\u5173\u952e\uff09"),(0,i.kt)("p",null,"\u9009\u62e9 ",(0,i.kt)("inlineCode",{parentName:"p"},"Send Build artifacts over SSH")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"Source files: publish/\nRemove prefix(\u4e0d\u586b)\nRemote directory:/mudata/webroot/publish/\nExec command:bash /mudata/shell/publish.sh ${JOB_NAME} jenkinsscmbase ${JOB_NAME}.${BUILD_NUMBER} 9994\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u9009\u62e9\u81ea\u5df1\u7684 SSH \u670d\u52a1\u5668"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Source files"),"\uff1a\u4e00\u5b9a\u662f ",(0,i.kt)("inlineCode",{parentName:"li"},"workspace")," \u4e0b\u7684\u5730\u5740"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Remote directory"),"\uff1a\u8fdc\u7a0b\u5730\u5740\uff0c\u4ece\u6839\u76ee\u5f55\u5f00\u59cb"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Exec command"),"\uff1a\u8981\u6267\u884c\u7684 shell\u3002\u8fd9\u91cc\u6240\u6709\u7684 ",(0,i.kt)("inlineCode",{parentName:"li"},"Jenkins")," \u73af\u5883\u53d8\u91cf\u90fd\u53ef\u4ee5\u7528")),(0,i.kt)("h3",{id:"35145-\u8fdc\u7a0b\u6267\u884c"},"35.1.4.5 \u8fdc\u7a0b\u6267\u884c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:'showLineNumbers title="publish.sh"',showLineNumbers:!0,"":!0,title:'"publish.sh"'},'# Jenkins Prod\u670d \u8c03\u7528\u811a\u672c\nsolutionName=$1\ncontainerName=$2\nfilename=$3\nport=$4\n#.publis\necho ${solutionName}\necho ${containerName}\necho ${filename}\nbaseDir=/mudata/webroot/publish\n\nwebDir=${baseDir}/publish/${filename}\n\nrm -rf ${webDir}\nmkdir ${webDir}\n\ntar -zxvf ${baseDir}/publish/${filename}.tar.gz -C ${webDir}/\nrm -f ${webDir}/appsettings.json && mv ${webDir}/appsettings.Prod.json ${webDir}/appsettings.json\n\n#\u5224\u65b7\u662f\u5426\u5b58\u5728\nCID=$(docker ps | grep "${containerName}" | awk \'{print $1}\')\necho $CID\nif [ "$CID" != "" ];then\n docker stop ${containerName}\n docker rm ${containerName}\n docker rmi ${containerName}\n#docker stop $CID\n#docker rm $CID\nfi\n\ncd ${webDir}/ && docker build -t ${containerName} .\ndocker run --name ${containerName} --restart=always -d -p ${port}:${port} --link myredis:myredis -v /etc/localtime:/etc/localtime:ro ${containerName}\n')),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u8fd9\u91cc\u7684\u903b\u8f91\u5c31\u662f\u89e3\u538b\uff0c\u7136\u540e ",(0,i.kt)("inlineCode",{parentName:"p"},"Docker")," \u76f8\u5173\u3002\u6bcf\u6b21\u6784\u5efa\u90fd\u662f\u5e26\u7740\u7248\u672c\u53f7\u6765\u7684\u3002")),(0,i.kt)("h2",{id:"3515-\u53cd\u9988\u4e0e\u5efa\u8bae"},"35.1.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}u.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return d},kt:function(){return u}});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function a(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var s=r.createContext({}),c=function(e){var n=r.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},d=function(e){var n=c(e.components);return r.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},k=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),k=c(t),u=o,m=k["".concat(s,".").concat(u)]||k[u]||p[u]||i;return t?r.createElement(m,a(a({ref:n},d),{},{components:t})):r.createElement(m,a({ref:n},d))}));function u(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=k;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var c=2;c=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var s=r.createContext({}),c=function(e){var n=r.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},d=function(e){var n=c(e.components);return r.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},k=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),k=c(t),u=o,m=k["".concat(s,".").concat(u)]||k[u]||p[u]||i;return t?r.createElement(m,a(a({ref:n},d),{},{components:t})):r.createElement(m,a({ref:n},d))}));function u(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=k;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var c=2;cDocker \u73af\u5883\u90e8\u7f72",id:"3511-\u5173\u4e8e\u5168-docker-\u73af\u5883\u90e8\u7f72",level:2},{value:"35.1.2 \u5b89\u88c5 Docker \u7248 Jenkins",id:"3512-\u5b89\u88c5-docker-\u7248-jenkins",level:2},{value:"35.1.2.1 \u4f7f\u7528 Dockerfile \u5236\u4f5c\u955c\u50cf",id:"35121-\u4f7f\u7528-dockerfile-\u5236\u4f5c\u955c\u50cf",level:3},{value:"35.1.2.2 \u8fd0\u884c Jenkins:dotnet \u955c\u50cf",id:"35122-\u8fd0\u884c-jenkinsdotnet-\u955c\u50cf",level:3},{value:"35.1.3 Jenkins \u7684\u81ea\u52a8\u5316\u90e8\u7f72",id:"3513-jenkins-\u7684\u81ea\u52a8\u5316\u90e8\u7f72",level:2},{value:"35.1.3.1 \u7f16\u5199 Shell \u811a\u672c",id:"35131-\u7f16\u5199-shell-\u811a\u672c",level:3},{value:"35.1.4 Jenkins \u7684\u81ea\u52a8\u5316\u8fdc\u7a0b\u90e8\u7f72",id:"3514-jenkins-\u7684\u81ea\u52a8\u5316\u8fdc\u7a0b\u90e8\u7f72",level:2},{value:"35.1.4.1 \u5b89\u88c5\u63d2\u4ef6",id:"35141-\u5b89\u88c5\u63d2\u4ef6",level:3},{value:"35.1.4.2 \u914d\u7f6e",id:"35142-\u914d\u7f6e",level:3},{value:"35.1.4.3 \u5199\u811a\u672c",id:"35143-\u5199\u811a\u672c",level:3},{value:"35.1.4.4 \u6784\u5efa\u540e\u64cd\u4f5c\uff08\u5173\u952e\uff09",id:"35144-\u6784\u5efa\u540e\u64cd\u4f5c\u5173\u952e",level:3},{value:"35.1.4.5 \u8fdc\u7a0b\u6267\u884c",id:"35145-\u8fdc\u7a0b\u6267\u884c",level:3},{value:"35.1.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"3515-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],k={toc:p};function u(e){var n=e.components,t=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},k,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"3511-\u5173\u4e8e\u5168-docker-\u73af\u5883\u90e8\u7f72"},"35.1.1 \u5173\u4e8e\u5168 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Docker")," \u73af\u5883\u90e8\u7f72"),(0,i.kt)("p",null,"\u5229\u7528\u62e5\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET")," \u73af\u5883\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Jenkins"),"\uff0c\u8fdb\u884c\u6301\u7eed\u5316\u90e8\u7f72"),(0,i.kt)("h2",{id:"3512-\u5b89\u88c5-docker-\u7248-jenkins"},"35.1.2 \u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Docker")," \u7248 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Jenkins")),(0,i.kt)("p",null,"\u6b63\u5e38\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Docker")," \u4e2d\u62c9\u53d6\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Jenkins:lts")," \u662f\u65e0\u6cd5\u6267\u884c ",(0,i.kt)("inlineCode",{parentName:"p"},"dotnet")," \u547d\u4ee4\u7684\uff08\u5c31\u7b97\u4f60\u5bbf\u4e3b\u673a\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"dotnet")," \u73af\u5883\u3001",(0,i.kt)("inlineCode",{parentName:"p"},"docker")," \u4e2d\u4e5f\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"dotnet")," \u73af\u5883\u4e5f\u4e0d\u53ef\u4ee5\uff09\uff0c\n\u6240\u4ee5\u6211\u4eec\u53ea\u80fd\u6784\u5efa\u4e00\u4e2a\u5305\u542b ",(0,i.kt)("inlineCode",{parentName:"p"},"dotnet")," \u7684\u955c\u50cf"),(0,i.kt)("h3",{id:"35121-\u4f7f\u7528-dockerfile-\u5236\u4f5c\u955c\u50cf"},"35.1.2.1 \u4f7f\u7528 Dockerfile \u5236\u4f5c\u955c\u50cf"),(0,i.kt)("p",null,"\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Dockerfile")," \u521b\u5efa\u5305\u542b ",(0,i.kt)("inlineCode",{parentName:"p"},"dotnet")," \u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Jenkins")," \u955c\u50cf"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\ud83d\udc49 \u7f16\u5199 ",(0,i.kt)("inlineCode",{parentName:"li"},"Dockerfile"))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},'# \u5c01\u88c5Jenkins\u955c\u50cf\uff08\u5e26\u6709dotnet\u73af\u5883\u7684\uff09 sdk=5.1\nFROM jenkins/jenkins:lts\nUSER root\nWORKDIR /dotnet\nRUN apt-get update && apt-get install -y wget && rm -rf /var/lib/apt/lists/*\nRUN wget -O dotnet.tar.gz https://download.visualstudio.microsoft.com/download/pr/820db713-c9a5-466e-b72a-16f2f5ed00e2/628aa2a75f6aa270e77f4a83b3742fb8/dotnet-sdk-5.0.100-linux-x64.tar.gz\nRUN tar zxf dotnet.tar.gz -C ./\nRUN rm -rf dotnet.tar.gz\nENV PATH="${PATH}:/dotnet:/var/jenkins_home/.dotnet/tools"\nENV DOTNET_ROOT="/dotnet"\nRUN apt update -y\nRUN apt install icu-devtools vim zip unzip -y\nRUN usermod -a -G root jenkins\nUSER jenkins\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\ud83d\udc49 \u547d\u4ee4\u89e3\u91ca")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"- 1. \u8fd9\u4e2aDocker\u955c\u50cf\u57fa\u4e8ejenkins\n- 2. \u8bbe\u7f6e\u5f53\u524d\u7528\u6237\u4e3aroot\uff0c\u56e0\u4e3a\u540e\u9762\u5b89\u88c5\u9700\u8981\u4f7f\u7528root\n- 3. \u8bbe\u7f6e\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u4e3adotnet\n- 4. \u4e0b\u8f7ddotnet SDK\u5305\uff0c\u4fdd\u5b58\u4e3adotnet.tar.gz\u3002\u8fd9\u91cc\u8981\u6ce8\u610f\u4e0b\u8f7d\u6b63\u786e\u7248\u672c\u7684SDK\uff0c\u53ef\u524d\u5f80\u5fae\u8f6f\u5b98\u65b9\u7f51\u7ad9\u83b7\u53d6\u4e0b\u8f7d\u94fe\u63a5\uff1ahttps://dotnet.microsoft.com/download\n- 5. \u89e3\u538bdotnet SDK\u5230\u5f53\u524d\u76ee\u5f55\uff0c\u5373/dotnet\u76ee\u5f55\n- 6. \u5220\u9664dotnet SDK\u5305\n- 7. \u628adotnet\u76ee\u5f55\u548cdotnet tools\u76ee\u5f55\u6dfb\u52a0\u5230\u73af\u5883\u53d8\u91cfPATH\uff0c\u8fd9\u6837\u5c31\u53ef\u4ee5\u4f7f\u7528dotnet\u547d\u4ee4\u4e86\n- 8. \u8bbe\u7f6eDOTNET_ROOT\u53d8\u91cf\n- 9. \u66f4\u65b0\u6e90\n- 10. \u5b89\u88c5\u4e00\u4e9b\u5fc5\u9700\u7684\uff0c\u5e38\u7528\u7684\u5de5\u5177\u5305\uff0c\u5176\u4e2dicu-devtools\u662f\u8fd0\u884cdotnet\u9700\u8981\u7684\n- 11. \u4fee\u6539jenkins\u7528\u6237\u5230root\u9644\u52a0\u7ec4\n- 12. \u8bbe\u7f6e\u5f53\u524d\u7528\u6237\u4e3ajenkins\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\ud83d\udc49 \u6784\u5efa ",(0,i.kt)("inlineCode",{parentName:"li"},"Docker")," \u955c\u50cf ",(0,i.kt)("inlineCode",{parentName:"li"},"name=jenkins:dotnet"))),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"cd")," \u5230\u6839\u76ee\u5f55\u4e0b\uff08\u5fc5\u987b\u542b ",(0,i.kt)("inlineCode",{parentName:"p"},"Dockerfile"),"\uff09 \u53ea\u9700\u6784\u5efa\u547d\u4ee4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0}," docker build -t jenkins:dotnet .\n")),(0,i.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed3\u5c3e ",(0,i.kt)("inlineCode",{parentName:"p"},".")," \u4e0d\u80fd\u7701\u7565")),(0,i.kt)("h3",{id:"35122-\u8fd0\u884c-jenkinsdotnet-\u955c\u50cf"},"35.1.2.2 \u8fd0\u884c ",(0,i.kt)("inlineCode",{parentName:"h3"},"Jenkins:dotnet")," \u955c\u50cf"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},'docker run -d -p 8080:8080 -p 50000:50000 --name mjenkins \\\n --privileged=true \\\n --restart always \\\n -u root \\\n -e TZ="Asia/Shanghai" \\\n -v /mudata/jenkins:/var/jenkins_home \\\n -v /usr/bin/docker:/usr/bin/docker \\\n -v /var/run/docker.sock:/var/run/docker.sock \\\n -v /mudata/webroot/:/mudata/webroot \\\n jenkins:dotnet\n')),(0,i.kt)("p",null,"\u63a5\u4e0b\u6765\u5c31\u662f\u6bd4\u8f83\u4fd7\u5957\u7684\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},"Jenkins")," \u6b65\u9aa4\uff0c\u7f51\u4e0a\u8d44\u6599\u5f88\u591a\uff0c\u4e0d\u5c55\u5f00\u4e86\u3002"),(0,i.kt)("h2",{id:"3513-jenkins-\u7684\u81ea\u52a8\u5316\u90e8\u7f72"},"35.1.3 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Jenkins")," \u7684\u81ea\u52a8\u5316\u90e8\u7f72"),(0,i.kt)("h3",{id:"35131-\u7f16\u5199-shell-\u811a\u672c"},"35.1.3.1 \u7f16\u5199 Shell \u811a\u672c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"# Jenkins \u6784\u5efa \u6d4b\u8bd5\u670d\n\necho '============\u67e5\u770b\u6253\u5305\u73af\u5883================'\npwd\nls\necho $PATH\n\nimage_version=`date +%Y%m%d%H%M`;\necho $image_version;\n\ndotnet --info\ndotnet --version\n\n# \u83b7\u53d6\u77ed\u7248\u672c\u53f7\nGITHASH=`git rev-parse --short HEAD`\n\necho '============================begin restore======================================='\ndotnet restore\necho '============================end restore======================================='\n\n#\u8981\u6784\u5efa\u7684\u89e3\u51b3\u65b9\u6848\u540d\u79f0\nsolutionName=MUSaas.SCM.BasicData\n#docker run\u7684\u5bb9\u5668\u540d\u79f0\ncontainerName=jenkinsscmbasic\n#\u6307\u5b9arun\u7684\u7aef\u53e3\nport=9994\n#.sln\u6587\u4ef6\u5168\u8def\u5f84\n#solutionDir=20-Solution/${solutionName}.sln\n#.csproj\u6587\u4ef6\u5168\u8def\u5f84\ncsprojDir=${solutionName}/${solutionName}.csproj\n\n#\u9879\u76ee\u53d1\u5e03\u7684\u76ee\u5f55\nwebDir=/mudata/webroot/jenkins/publish/webapp\n\n#\u5f52\u6863\u76ee\u5f55\narchivesDir=/mudata/webroot/jenkins/publish/archives\n\n#\u6e05\u7a7a\u6587\u4ef6\u5939\nrm -rf ${webDir}/${JOB_NAME}/*\n\n#\u53d1\u5e03\u7f51\u7ad9\u5230webDir\ndotnet publish ${JENKINS_HOME}/workspace/${JOB_NAME}/${csprojDir} -c Release -o ${webDir}/${JOB_NAME} /p:Version=1.0.${BUILD_NUMBER}\n#\u590d\u5236\u914d\u7f6e\u6587\u4ef6\n#cp -rf /vdb1/jenkins/DotNetCoreWebPublishToDockerCommonConfigs/* ${webDir}/${JOB_NAME}/\n\n#\u5224\u65b7\u662f\u5426\u5b58\u5728\nCID=$(docker ps | grep \"${containerName}\" | awk '{print $1}')\necho $CID\nif [ \"$CID\" != \"\" ];then\n docker stop ${containerName}\n docker rm ${containerName}\n docker rmi ${containerName}\n#docker stop $CID\n#docker rm $CID\nfi\n\n\n#\u901a\u8fc7Dockerfile\u91cd\u65b0\u6784\u5efa\u955c\u50cf\ndocker build -t ${containerName} ${webDir}/${JOB_NAME}/.\n#docker run\u5bb9\u5668\u5e76\u7ed1\u5b9a\u5230\u7aef\u53e3\n#docker run -d -p ${port}:80 --name ${containerName} ${containerName}\ndocker run --name ${containerName} --restart=always -d -p ${port}:${port} -v /etc/localtime:/etc/localtime:ro ${containerName}\necho \"success!\"\n\n")),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u5c31\u8fd9\u6837\u81ea\u52a8\u5316\u90e8\u7f72\u5c31\u597d\u4e86\u3002 \u6d4b\u8bd5\u670d\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Jenkins")," \u5c06\u6e90\u7801\u62c9\u4e0b\u6765\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Publish\uff0cDocker Build\uff0cDocker Run"),"\u3002")),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u8fd9\u91cc\u60f3\u8981\u53d1\u5e03\u7684\u65f6\u5019\uff0c\u6bcf\u6b21\u90fd\u9700\u8981\u624b\u52a8\u53bb\u70b9\u51fb\u201c\u6784\u5efa\u201d\u624d\u4f1a\u6267\u884c\u3002\u4e5f\u53ef\u4ee5\u505a\u6210\u5f53\u5206\u652f\u5408\u5e76\u6210\u529f\u540e\u81ea\u52a8\u8fd0\u884c\u3002\u53cd\u6b63 ",(0,i.kt)("inlineCode",{parentName:"p"},"Jenkins")," \u88c5\u597d\u4e4b\u540e\uff0c\u4f60\u60f3\u8981\u4ec0\u4e48\u90fd\u80fd\u73a9\u8d77\u6765\u3002\u6bd4\u5982\u6307\u5b9a\u5206\u652f\u63d0\u4ea4\u540e\u81ea\u52a8\u201c\u6784\u5efa\u201d\u3001\u6bd4\u5982\u6784\u5efa\u6210\u529f\u540e\u5408\u5e76\u5230 Master \u7b49\u7b49")),(0,i.kt)("h2",{id:"3514-jenkins-\u7684\u81ea\u52a8\u5316\u8fdc\u7a0b\u90e8\u7f72"},"35.1.4 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Jenkins")," \u7684\u81ea\u52a8\u5316\u8fdc\u7a0b\u90e8\u7f72"),(0,i.kt)("h3",{id:"35141-\u5b89\u88c5\u63d2\u4ef6"},"35.1.4.1 \u5b89\u88c5\u63d2\u4ef6"),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},(0,i.kt)("inlineCode",{parentName:"p"},"Publish Over SSH"))),(0,i.kt)("h3",{id:"35142-\u914d\u7f6e"},"35.1.4.2 \u914d\u7f6e"),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u7cfb\u7edf\u7ba1\u7406 => ",(0,i.kt)("inlineCode",{parentName:"p"},"Publish over SSH"))),(0,i.kt)("h3",{id:"35143-\u5199\u811a\u672c"},"35.1.4.3 \u5199\u811a\u672c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"# Jenkins \u6784\u5efa \u6b63\u5f0f\u670d\n\necho '============\u67e5\u770b\u6253\u5305\u73af\u5883================'\npwd\nls\necho $PATH\n\nimage_version=`date +%Y%m%d%H%M`;\necho $image_version;\n\ndotnet --info\ndotnet --version\n\n# \u83b7\u53d6\u77ed\u7248\u672c\u53f7\nGITHASH=`git rev-parse --short HEAD`\n\necho '============================begin restore======================================='\ndotnet restore\necho '============================end restore======================================='\n\n#\u8981\u6784\u5efa\u7684\u89e3\u51b3\u65b9\u6848\u540d\u79f0\nsolutionName=MUSaas.SCM.BulkOrder\n#docker run\u7684\u5bb9\u5668\u540d\u79f0\ncontainerName=jenkinsscmbulk\n#\u6307\u5b9arun\u7684\u7aef\u53e3\nport=9986\n#.csproj\u6587\u4ef6\u5168\u8def\u5f84\ncsprojDir=/${solutionName}/${solutionName}.csproj\n\n#\u9879\u76ee\u53d1\u5e03\u7684\u76ee\u5f55\nwebDir=/mudata/webroot/jenkins/publish/webapp\n\n#\u5f52\u6863\u76ee\u5f55\narchivesDir=/mudata/webroot/jenkins/publish/archives\n\n#\u6e05\u7a7a\u6587\u4ef6\u5939\nrm -rf ${webDir}/${JOB_NAME}/*\n\n#\u53d1\u5e03\u7f51\u7ad9\u5230webDir\ndotnet publish ${JENKINS_HOME}/workspace/${JOB_NAME}/${csprojDir} -c Release -o ${webDir}/${JOB_NAME} /p:Version=1.0.${BUILD_NUMBER}\n#\u590d\u5236\u914d\u7f6e\u6587\u4ef6\n#cp -rf /vdb1/jenkins/DotNetCoreWebPublishToDockerCommonConfigs/* ${webDir}/${JOB_NAME}/\n\n\n#\u6784\u5efa\u8fdc\u7a0b\u5305\n\nrm -rf ${JENKINS_HOME}/workspace/${JOB_NAME}/publish\nmkdir ${JENKINS_HOME}/workspace/${JOB_NAME}/publish\n\ntar -czvf ${JENKINS_HOME}/workspace/${JOB_NAME}/publish/${JOB_NAME}.${BUILD_NUMBER}.tar.gz -C ${webDir}/${JOB_NAME} .\n\necho \"success!\"\n")),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u5927\u6982\u903b\u8f91\u5c31\u662f\u53d1\u5e03\u540e\uff0c\u6253\u4e2a\u5305\u3002\u7136\u540e\u4e22\u7ed9\u8fdc\u7a0b\uff0c\u8fdc\u7a0b\u518d\u6267\u884c ",(0,i.kt)("inlineCode",{parentName:"p"},"shell"))),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u6ce8\u610f\u8fd9\u91cc\u4e00\u5b9a\u8981\u53d1\u5e03\u5230\u81ea\u5df1\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"workspace")," \u4e0b\uff0c\u9632\u6b62\u4e0b\u4e00\u6b65\u6b7b\u6d3b\u627e\u4e0d\u5230\u4f4d\u7f6e\u3002\u5982\u679c\u627e\u4e0d\u5230\u4f4d\u7f6e\uff0c\u53ea\u80fd\u6162\u6162\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"ls")," \u547d\u4ee4\uff0c\u4e00\u7ea7\u4e00\u7ea7\u53bb\u6d4b\uff0c\u5f88\u9ebb\u70e6")),(0,i.kt)("h3",{id:"35144-\u6784\u5efa\u540e\u64cd\u4f5c\u5173\u952e"},"35.1.4.4 \u6784\u5efa\u540e\u64cd\u4f5c\uff08\u5173\u952e\uff09"),(0,i.kt)("p",null,"\u9009\u62e9 ",(0,i.kt)("inlineCode",{parentName:"p"},"Send Build artifacts over SSH")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"Source files: publish/\nRemove prefix(\u4e0d\u586b)\nRemote directory:/mudata/webroot/publish/\nExec command:bash /mudata/shell/publish.sh ${JOB_NAME} jenkinsscmbase ${JOB_NAME}.${BUILD_NUMBER} 9994\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u9009\u62e9\u81ea\u5df1\u7684 SSH \u670d\u52a1\u5668"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Source files"),"\uff1a\u4e00\u5b9a\u662f ",(0,i.kt)("inlineCode",{parentName:"li"},"workspace")," \u4e0b\u7684\u5730\u5740"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Remote directory"),"\uff1a\u8fdc\u7a0b\u5730\u5740\uff0c\u4ece\u6839\u76ee\u5f55\u5f00\u59cb"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Exec command"),"\uff1a\u8981\u6267\u884c\u7684 shell\u3002\u8fd9\u91cc\u6240\u6709\u7684 ",(0,i.kt)("inlineCode",{parentName:"li"},"Jenkins")," \u73af\u5883\u53d8\u91cf\u90fd\u53ef\u4ee5\u7528")),(0,i.kt)("h3",{id:"35145-\u8fdc\u7a0b\u6267\u884c"},"35.1.4.5 \u8fdc\u7a0b\u6267\u884c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:'showLineNumbers title="publish.sh"',showLineNumbers:!0,"":!0,title:'"publish.sh"'},'# Jenkins Prod\u670d \u8c03\u7528\u811a\u672c\nsolutionName=$1\ncontainerName=$2\nfilename=$3\nport=$4\n#.publis\necho ${solutionName}\necho ${containerName}\necho ${filename}\nbaseDir=/mudata/webroot/publish\n\nwebDir=${baseDir}/publish/${filename}\n\nrm -rf ${webDir}\nmkdir ${webDir}\n\ntar -zxvf ${baseDir}/publish/${filename}.tar.gz -C ${webDir}/\nrm -f ${webDir}/appsettings.json && mv ${webDir}/appsettings.Prod.json ${webDir}/appsettings.json\n\n#\u5224\u65b7\u662f\u5426\u5b58\u5728\nCID=$(docker ps | grep "${containerName}" | awk \'{print $1}\')\necho $CID\nif [ "$CID" != "" ];then\n docker stop ${containerName}\n docker rm ${containerName}\n docker rmi ${containerName}\n#docker stop $CID\n#docker rm $CID\nfi\n\ncd ${webDir}/ && docker build -t ${containerName} .\ndocker run --name ${containerName} --restart=always -d -p ${port}:${port} --link myredis:myredis -v /etc/localtime:/etc/localtime:ro ${containerName}\n')),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u8fd9\u91cc\u7684\u903b\u8f91\u5c31\u662f\u89e3\u538b\uff0c\u7136\u540e ",(0,i.kt)("inlineCode",{parentName:"p"},"Docker")," \u76f8\u5173\u3002\u6bcf\u6b21\u6784\u5efa\u90fd\u662f\u5e26\u7740\u7248\u672c\u53f7\u6765\u7684\u3002")),(0,i.kt)("h2",{id:"3515-\u53cd\u9988\u4e0e\u5efa\u8bae"},"35.1.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/52821183.1a0f0bc7.js b/handbook/build/assets/js/52821183.1a0f0bc7.js deleted file mode 100644 index 5740c3eddc..0000000000 --- a/handbook/build/assets/js/52821183.1a0f0bc7.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[8445],{8968:function(e,t,n){n.r(t),n.d(t,{assets:function(){return p},contentTitle:function(){return u},default:function(){return d},frontMatter:function(){return c},metadata:function(){return l},toc:function(){return f}});var r=n(3117),o=n(102),i=(n(7294),n(3905)),a=["components"],c={id:"bingfa",title:"36.4 \u5e76\u53d1\u6d4b\u8bd5",sidebar_label:"36.4 \u5e76\u53d1\u6d4b\u8bd5"},u=void 0,l={unversionedId:"bingfa",id:"bingfa",title:"36.4 \u5e76\u53d1\u6d4b\u8bd5",description:"\u3010\u5e76\u53d1\u6d4b\u8bd5\u89c6\u9891\u6559\u7a0b\u3011",source:"@site/docs/bingfa.mdx",sourceDirName:".",slug:"/bingfa",permalink:"/furion/docs/bingfa",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/bingfa.mdx",tags:[],version:"current",lastUpdatedBy:"\u767e\u5c0f\u50e7",lastUpdatedAt:1627754425,formattedLastUpdatedAt:"Jul 31, 2021",frontMatter:{id:"bingfa",title:"36.4 \u5e76\u53d1\u6d4b\u8bd5",sidebar_label:"36.4 \u5e76\u53d1\u6d4b\u8bd5"},sidebar:"docs",previous:{title:"36.3 \u57fa\u51c6\u6d4b\u8bd5",permalink:"/furion/docs/benchmark"},next:{title:"37. \u7f16\u5199\u5305\u7ba1\u7406\u5de5\u5177 (Tools)",permalink:"/furion/docs/dotnet-tools"}},p={},f=[],s={toc:f};function d(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},s,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{title:"\u89c6\u9891\u6559\u7a0b",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u3010",(0,i.kt)("a",{parentName:"p",href:"https://www.bilibili.com/video/BV1eo4y1Q7sJ/"},"\u5e76\u53d1\u6d4b\u8bd5\u89c6\u9891\u6559\u7a0b"),"\u3011")),(0,i.kt)("p",null,"\u6587\u6863\u7d27\u6025\u7f16\u5199\u4e2d\uff0c\u53ef\u4ee5\u5148\u770b\u65e7\u6587\u6863\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://monksoul.gitbook.io/hoa/"},"https://monksoul.gitbook.io/hoa/")))}d.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return p},kt:function(){return d}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),l=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(u.Provider,{value:t},e.children)},f={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},s=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),s=l(n),d=o,m=s["".concat(u,".").concat(d)]||s[d]||f[d]||i;return n?r.createElement(m,a(a({ref:t},p),{},{components:n})):r.createElement(m,a({ref:t},p))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=s;var c={};for(var u in t)hasOwnProperty.call(t,u)&&(c[u]=t[u]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var l=2;l=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),l=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(u.Provider,{value:t},e.children)},f={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},s=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),s=l(n),d=o,m=s["".concat(u,".").concat(d)]||s[d]||f[d]||i;return n?r.createElement(m,a(a({ref:t},p),{},{components:n})):r.createElement(m,a({ref:t},p))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=s;var c={};for(var u in t)hasOwnProperty.call(t,u)&&(c[u]=t[u]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var l=2;lClay \u5bf9\u8c61",id:"292-clay-\u5bf9\u8c61",level:2},{value:"29.3 \u5982\u4f55\u4f7f\u7528",id:"293-\u5982\u4f55\u4f7f\u7528",level:2},{value:"29.3.1 \u521b\u5efa\u4e00\u4e2a\u5bf9\u8c61",id:"2931-\u521b\u5efa\u4e00\u4e2a\u5bf9\u8c61",level:3},{value:"29.3.2 \u8bfb\u53d6/\u83b7\u53d6\u5c5e\u6027",id:"2932-\u8bfb\u53d6\u83b7\u53d6\u5c5e\u6027",level:3},{value:"29.3.3 \u65b0\u589e\u5c5e\u6027",id:"2933-\u65b0\u589e\u5c5e\u6027",level:3},{value:"29.3.4 \u66f4\u65b0\u5c5e\u6027\u503c",id:"2934-\u66f4\u65b0\u5c5e\u6027\u503c",level:3},{value:"29.3.5 \u5220\u9664\u5c5e\u6027",id:"2935-\u5220\u9664\u5c5e\u6027",level:3},{value:"29.3.6 \u5224\u65ad\u5c5e\u6027\u662f\u5426\u5b58\u5728",id:"2936-\u5224\u65ad\u5c5e\u6027\u662f\u5426\u5b58\u5728",level:3},{value:"29.3.7 \u904d\u5386\u5bf9\u8c61",id:"2937-\u904d\u5386\u5bf9\u8c61",level:3},{value:"29.3.8 \u8f6c\u6362\u6210\u5177\u4f53\u5bf9\u8c61",id:"2938-\u8f6c\u6362\u6210\u5177\u4f53\u5bf9\u8c61",level:3},{value:"29.3.9 \u56fa\u5316\u7c98\u571f",id:"2939-\u56fa\u5316\u7c98\u571f",level:3},{value:"29.3.10 \u8f93\u51fa JSON",id:"29310-\u8f93\u51fa-json",level:3},{value:"29.3.11 \u8f93\u51fa XML \u5bf9\u8c61",id:"29311-\u8f93\u51fa-xml-\u5bf9\u8c61",level:3},{value:"29.3.12 \u5173\u952e\u5b57\u5904\u7406",id:"29312-\u5173\u952e\u5b57\u5904\u7406",level:3},{value:"29.3.13 \u8f6c\u6362\u6210\u5b57\u5178\u7c7b\u578b",id:"29313-\u8f6c\u6362\u6210\u5b57\u5178\u7c7b\u578b",level:3},{value:"29.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"294-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:u};function p(e){var n=e.components,t=(0,r.Z)(e,o);return(0,i.kt)("wrapper",(0,a.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 2.1.12 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,i.kt)("h2",{id:"291-\u5173\u4e8e\u7c98\u571f\u5bf9\u8c61"},"29.1 \u5173\u4e8e\u7c98\u571f\u5bf9\u8c61"),(0,i.kt)("p",null,"\u7c98\u571f\u5bf9\u8c61\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u81ea\u521b\u7684\u4e00\u79cd\u6982\u5ff5\uff0c\u662f\u4e00\u79cd\u53ef\u4ee5\u6a21\u62df\u5f31\u8bed\u8a00\u7279\u6027\u7684\u5bf9\u8c61\uff0c\u7c7b\u4f3c ",(0,i.kt)("inlineCode",{parentName:"p"},"Javascript")," \u4e00\u6837\u64cd\u4f5c\u5bf9\u8c61\u3002\u53ea\u9700\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"Clay")," \u7c7b\u521d\u59cb\u5316\u5373\u53ef\u3002"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u4e3a\u4ec0\u4e48\u8d77\u540d\u4e3a \u201c\u7c98\u571f\u201d \u5462\uff1f\u56e0\u4e3a\u8fd9\u4e2a\u5bf9\u8c61\u53ef\u4ee5\u81ea\u7531\u7684\u6dfb\u52a0\u5c5e\u6027\uff0c\u79fb\u9664\u5c5e\u6027\uff0c\u53c8\u53ef\u4ee5\u56fa\u5316\u6210\u4efb\u4f55\u5bf9\u8c61\uff0c\u5177\u6709\u53ef\u62d3\u5c55\u3001\u53ef\u5851\u9020\u7684\u7279\u70b9\u3002")),(0,i.kt)("h3",{id:"2911-\u4f7f\u7528\u573a\u666f"},"29.1.1 \u4f7f\u7528\u573a\u666f"),(0,i.kt)("p",null,"\u7c98\u571f\u5bf9\u8c61\u5e38\u7528\u4e8e\u9700\u8981\u52a8\u6001\u6784\u5efa\u5bf9\u8c61\u7684\u5730\u65b9\uff0c\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"CMS")," \u7cfb\u7edf\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"ViewModel"),"\uff0c\u6216\u8005\u8fd0\u884c\u65f6\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u5bf9\u8c61\uff0c\u6216\u8005\u8bf7\u6c42\u7b2c\u4e09\u65b9 ",(0,i.kt)("inlineCode",{parentName:"p"},"API")," \u60c5\u51b5\u3002"),(0,i.kt)("h3",{id:"2912-\u5173\u4e8e\u6027\u80fd"},"29.1.2 \u5173\u4e8e\u6027\u80fd"),(0,i.kt)("p",null,"\u7c98\u571f\u6027\u80fd\u5b9e\u9645\u4e0a\u5e76\u4e0d\u9ad8\u6548\uff0c\u4f46\u662f\u6027\u80fd\u4e5f\u5e76\u4e0d\u4f4e\u4e0b\uff0c\u53ea\u4e0d\u8fc7\u7565\u8f93\u4e8e\u5f3a\u7c7b\u578b\u8c03\u7528\u3002\u4ec0\u4e48\u65f6\u5019\u4f7f\u7528\u53ef\u4ee5\u770b\u4ee5\u4e0a\u7684\u3010\u4f7f\u7528\u573a\u666f\u3011\u3002"),(0,i.kt)("h2",{id:"292-clay-\u5bf9\u8c61"},"29.2 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Clay")," \u5bf9\u8c61"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Clay")," \u5bf9\u8c61\u662f\u7ee7\u627f\u81ea ",(0,i.kt)("inlineCode",{parentName:"p"},"DynamicObject")," \u7684\u4e00\u4e2a\u7279\u6b8a\u5bf9\u8c61\uff0c\u63d0\u4f9b\u4e86\u50cf\u5f31\u8bed\u8a00\u4e00\u6837\u64cd\u4f5c\u5bf9\u8c61\u7684\u65b9\u6cd5\u53ca\u7d22\u5f15\u3002"),(0,i.kt)("h2",{id:"293-\u5982\u4f55\u4f7f\u7528"},"29.3 \u5982\u4f55\u4f7f\u7528"),(0,i.kt)("h3",{id:"2931-\u521b\u5efa\u4e00\u4e2a\u5bf9\u8c61"},"29.3.1 \u521b\u5efa\u4e00\u4e2a\u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u521b\u5efa\u4e00\u4e2a\u7a7a\u7684\u7c98\u571f\u5bf9\u8c61\ndynamic clay = new Clay();\n\n// \u4ece\u73b0\u6709\u7684\u5bf9\u8c61\u521b\u5efa\ndynamic clay2 = Clay.Object(new {});\n\n// \u4ece json \u5b57\u7b26\u4e32\u521b\u5efa\uff0c\u53ef\u7528\u4e8e\u7b2c\u4e09\u65b9 API \u5bf9\u63a5\uff0c\u975e\u5e38\u6709\u7528\ndynamic clay3 = Clay.Parse(@"{""foo"":""json"", ""bar"":100, ""nest"":{ ""foobar"":true } }");\n')),(0,i.kt)("h3",{id:"2932-\u8bfb\u53d6\u83b7\u53d6\u5c5e\u6027"},"29.3.2 \u8bfb\u53d6/\u83b7\u53d6\u5c5e\u6027"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n }\n});\n\nvar r1 = clay.Foo; // "json" - string\u7c7b\u578b\nvar r2 = clay.Bar; // 100 - double\u7c7b\u578b\nvar r3 = clay.Nest.Foobar; // true - bool\u7c7b\u578b\nvar r4 = clay["Nest"]["Foobar"]; // \u8fd8\u53ef\u4ee5\u548c Javascript \u4e00\u6837\u901a\u8fc7\u7d22\u5f15\u5668\u83b7\u53d6\n')),(0,i.kt)("h3",{id:"2933-\u65b0\u589e\u5c5e\u6027"},"29.3.3 \u65b0\u589e\u5c5e\u6027"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n }\n});\n\n// \u65b0\u589e\nclay.Arr = new string[] { "NOR", "XOR" }; // \u6dfb\u52a0\u4e00\u4e2a\u6570\u7ec4\nclay.Obj1 = new City { }; // \u65b0\u589e\u4e00\u4e2a\u5b9e\u4f8b\u5bf9\u8c61\nclay.Obj2 = new { Foo = "abc", Bar = 100 }; // \u65b0\u589e\u4e00\u4e2a\u533f\u540d\u7c7b\n')),(0,i.kt)("h3",{id:"2934-\u66f4\u65b0\u5c5e\u6027\u503c"},"29.3.4 \u66f4\u65b0\u5c5e\u6027\u503c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n }\n});\n\n// \u66f4\u65b0\nclay.Foo = "Furion";\nclay["Nest"].Foobar = false;\nclay.Nest["Foobar"] = true;\n')),(0,i.kt)("h3",{id:"2935-\u5220\u9664\u5c5e\u6027"},"29.3.5 \u5220\u9664\u5c5e\u6027"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n },\n Arr = new string[] { "NOR", "XOR" }\n});\n\n// \u5220\u9664\u64cd\u4f5c\nclay.Delete("Foo"); // \u901a\u8fc7 Delete \u65b9\u6cd5\u5220\u9664\nclay.Arr.Delete(0); // \u652f\u6301\u6570\u7ec4 Delete \u7d22\u5f15\u5220\u9664\nclay("Bar"); // \u652f\u6301\u76f4\u63a5\u901a\u8fc7\u5bf9\u8c61\u4f5c\u4e3a\u65b9\u6cd5\u5220\u9664\nclay.Arr(1); // \u652f\u6301\u6570\u7ec4\u4f5c\u4e3a\u65b9\u6cd5\u5220\u9664\n')),(0,i.kt)("h3",{id:"2936-\u5224\u65ad\u5c5e\u6027\u662f\u5426\u5b58\u5728"},"29.3.6 \u5224\u65ad\u5c5e\u6027\u662f\u5426\u5b58\u5728"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n },\n Arr = new string[] { "NOR", "XOR" }\n});\n\n// \u5224\u65ad\u5c5e\u6027\u662f\u5426\u5b58\u5728\nvar a = clay.IsDefined("Foo"); // true\nvar b = clay.IsDefined("Foooo"); // false\nvar c = clay.Foo(); // true\nvar d = clay.Foooo(); // false;\n')),(0,i.kt)("h3",{id:"2937-\u904d\u5386\u5bf9\u8c61"},"29.3.7 \u904d\u5386\u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n },\n Arr = new string[] { "NOR", "XOR" }\n});\n\n// \u904d\u5386\u6570\u7ec4\nforeach (string item in clay.Arr)\n{\n Console.WriteLine(item); // NOR, XOR\n}\n\n// \u904d\u5386\u6574\u4e2a\u5bf9\u8c61\u5c5e\u6027\u53ca\u503c\uff0c\u7c7b\u4f3c JavaScript \u7684 for (var p in obj)\nforeach (KeyValuePair item in clay)\n{\n Console.WriteLine(item.Key + ":" + item.Value); // Foo:json, Bar: 100, Nest: { "Foobar":true}, Arr:["NOR","XOR"]\n}\n')),(0,i.kt)("h3",{id:"2938-\u8f6c\u6362\u6210\u5177\u4f53\u5bf9\u8c61"},"29.3.8 \u8f6c\u6362\u6210\u5177\u4f53\u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = new Clay();\nclay.Arr = new string[] { "Furion", "Fur" };\n\n// \u6570\u7ec4\u8f6c\u6362\u793a\u4f8b\nvar a1 = clay.Arr.Deserialize(); // \u901a\u8fc7 Deserialize \u65b9\u6cd5\nvar a2 = (string[])clay.Arr; // \u5f3a\u5236\u8f6c\u6362\nstring[] a3 = clay.Arr; // \u58f0\u660e\u65b9\u5f0f\n\n// \u5bf9\u8c61\u8f6c\u6362\u793a\u4f8b\nclay.City = new City { Id = 1, Name = "\u4e2d\u5c71\u5e02" };\nvar c1 = clay.City.Deserialize(); // \u901a\u8fc7 Deserialize \u65b9\u6cd5\nvar c2 = (City)clay.City; // \u5f3a\u5236\u8f6c\u6362\nCity c3 = clay.City; // \u58f0\u660e\u65b9\u5f0f\n')),(0,i.kt)("h3",{id:"2939-\u56fa\u5316\u7c98\u571f"},"29.3.9 \u56fa\u5316\u7c98\u571f"),(0,i.kt)("p",null,"\u56fa\u5316\u7c98\u571f\u5728\u5f88\u591a\u65f6\u5019\u548c\u5e8f\u5217\u5316\u5f88\u50cf\uff0c\u4f46\u662f\u5982\u679c\u76f4\u63a5\u8c03\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Deserialize")," \u6216 ",(0,i.kt)("inlineCode",{parentName:"p"},"Deserialize")," \u65e0\u6cd5\u8fd4\u56de\u5b9e\u9645\u7c7b\u578b\uff0c\u6240\u4ee5\u5c31\u6709\u4e86\u56fa\u5316\u7c7b\u578b\u7684\u529f\u80fd\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u8fd4\u56de object\nvar obj = clay.Solidify();\n\n// \u8fd4\u56de dynamic\nvar obj1 = clay.Solidify();\n\n// \u8fd4\u56de\u5176\u4ed6\u4efb\u610f\u7c7b\u578b\nvar obj2 = clay.Solidify();\n")),(0,i.kt)("h3",{id:"29310-\u8f93\u51fa-json"},"29.3.10 \u8f93\u51fa ",(0,i.kt)("inlineCode",{parentName:"h3"},"JSON")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n },\n Arr = new string[] { "NOR", "XOR" }\n});\n\n// \u8f93\u51fa JSON\nvar json = clay.ToString(); // "{\\"Foo\\":\\"json\\",\\"Bar\\":100,\\"Nest\\":{\\"Foobar\\":true},\\"Arr\\":[\\"NOR\\",\\"XOR\\"]}"\n')),(0,i.kt)("admonition",{type:"tip"},(0,i.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Clay")," \u5e8f\u5217\u5316\u6210 ",(0,i.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"JSON")," \u952e\u5927\u5c0f\u5199\u63a7\u5236"),(0,i.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Clay")," \u8f93\u51fa\u6210 ",(0,i.kt)("inlineCode",{parentName:"p"},"JSON")," \u540e\u5c06\u4fdd\u6301\u539f\u6837\u8f93\u51fa\uff0c\u5982\u679c\u9700\u8981\u5b9e\u73b0\u952e\u547d\u540d\u63a7\u5236\uff0c\u5219\u9700\u8981\u5148\u8f6c\u6362\u6210 ",(0,i.kt)("inlineCode",{parentName:"p"},"Dictionary")," \u7136\u540e\u518d\u914d\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"AddJsonOptions")," \u670d\u52a1\uff0c\u5982\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8-9}",showLineNumbers:!0,"{8-9}":!0},"public IActionResult OutputClay()\n{\n dynamic clay = Clay.Object(new\n {\n // ....\n });\n\n // \u8f6c\u6362\u6210 dictionary\n var dic = clay.ToDictionary();\n\n return new JsonResult(dic);\n}\n")),(0,i.kt)("p",{parentName:"admonition"},"\u914d\u7f6e\u5e8f\u5217\u5316 ",(0,i.kt)("inlineCode",{parentName:"p"},"Dictionary")," \u952e\u547d\u540d\u7b56\u7565\u652f\u6301\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,4}",showLineNumbers:!0,"{2,4}":!0},"services.AddControllers()\n .AddJsonOptions(options =>\n {\n options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase; // \u914d\u7f6e Dictionary \u7c7b\u578b\u5e8f\u5217\u5316\u8f93\u51fa\n });\n"))),(0,i.kt)("h3",{id:"29311-\u8f93\u51fa-xml-\u5bf9\u8c61"},"29.3.11 \u8f93\u51fa ",(0,i.kt)("inlineCode",{parentName:"h3"},"XML")," \u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n },\n Arr = new string[] { "NOR", "XOR" }\n});\n\n// \u8f93\u51fa XElement\nvar xml = clay.XmlElement;\n')),(0,i.kt)("h3",{id:"29312-\u5173\u952e\u5b57\u5904\u7406"},"29.3.12 \u5173\u952e\u5b57\u5904\u7406"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = new Clay();\nclay.@int = 1;\nclay.@event = "\u4e8b\u4ef6";\n')),(0,i.kt)("h3",{id:"29313-\u8f6c\u6362\u6210\u5b57\u5178\u7c7b\u578b"},"29.3.13 \u8f6c\u6362\u6210\u5b57\u5178\u7c7b\u578b"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new { name = "\u5f20\u4e09" });\nclay.name = "\u767e\u5c0f\u50e7";\nDictionary parms = clay.ToDictionary();\n')),(0,i.kt)("h2",{id:"294-\u53cd\u9988\u4e0e\u5efa\u8bae"},"29.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}p.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return m},kt:function(){return p}});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function o(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),c=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},m=function(e){var n=c(e.components);return a.createElement(s.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},d=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,s=e.parentName,m=l(e,["components","mdxType","originalType","parentName"]),d=c(t),p=r,y=d["".concat(s,".").concat(p)]||d[p]||u[p]||i;return t?a.createElement(y,o(o({ref:n},m),{},{components:t})):a.createElement(y,o({ref:n},m))}));function p(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,o=new Array(i);o[0]=d;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:r,o[1]=l;for(var c=2;c=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),c=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},m=function(e){var n=c(e.components);return a.createElement(s.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},d=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,s=e.parentName,m=l(e,["components","mdxType","originalType","parentName"]),d=c(t),p=r,y=d["".concat(s,".").concat(p)]||d[p]||u[p]||i;return t?a.createElement(y,o(o({ref:n},m),{},{components:t})):a.createElement(y,o({ref:n},m))}));function p(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,o=new Array(i);o[0]=d;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:r,o[1]=l;for(var c=2;cClay \u5bf9\u8c61",id:"292-clay-\u5bf9\u8c61",level:2},{value:"29.3 \u5982\u4f55\u4f7f\u7528",id:"293-\u5982\u4f55\u4f7f\u7528",level:2},{value:"29.3.1 \u521b\u5efa\u4e00\u4e2a\u5bf9\u8c61",id:"2931-\u521b\u5efa\u4e00\u4e2a\u5bf9\u8c61",level:3},{value:"29.3.2 \u8bfb\u53d6/\u83b7\u53d6\u5c5e\u6027",id:"2932-\u8bfb\u53d6\u83b7\u53d6\u5c5e\u6027",level:3},{value:"29.3.3 \u65b0\u589e\u5c5e\u6027",id:"2933-\u65b0\u589e\u5c5e\u6027",level:3},{value:"29.3.4 \u66f4\u65b0\u5c5e\u6027\u503c",id:"2934-\u66f4\u65b0\u5c5e\u6027\u503c",level:3},{value:"29.3.5 \u5220\u9664\u5c5e\u6027",id:"2935-\u5220\u9664\u5c5e\u6027",level:3},{value:"29.3.6 \u5224\u65ad\u5c5e\u6027\u662f\u5426\u5b58\u5728",id:"2936-\u5224\u65ad\u5c5e\u6027\u662f\u5426\u5b58\u5728",level:3},{value:"29.3.7 \u904d\u5386\u5bf9\u8c61",id:"2937-\u904d\u5386\u5bf9\u8c61",level:3},{value:"29.3.8 \u8f6c\u6362\u6210\u5177\u4f53\u5bf9\u8c61",id:"2938-\u8f6c\u6362\u6210\u5177\u4f53\u5bf9\u8c61",level:3},{value:"29.3.9 \u56fa\u5316\u7c98\u571f",id:"2939-\u56fa\u5316\u7c98\u571f",level:3},{value:"29.3.10 \u8f93\u51fa JSON",id:"29310-\u8f93\u51fa-json",level:3},{value:"29.3.11 \u8f93\u51fa XML \u5bf9\u8c61",id:"29311-\u8f93\u51fa-xml-\u5bf9\u8c61",level:3},{value:"29.3.12 \u5173\u952e\u5b57\u5904\u7406",id:"29312-\u5173\u952e\u5b57\u5904\u7406",level:3},{value:"29.3.13 \u8f6c\u6362\u6210\u5b57\u5178\u7c7b\u578b",id:"29313-\u8f6c\u6362\u6210\u5b57\u5178\u7c7b\u578b",level:3},{value:"29.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"294-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:u};function p(e){var n=e.components,t=(0,r.Z)(e,o);return(0,i.kt)("wrapper",(0,a.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 2.1.12 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,i.kt)("h2",{id:"291-\u5173\u4e8e\u7c98\u571f\u5bf9\u8c61"},"29.1 \u5173\u4e8e\u7c98\u571f\u5bf9\u8c61"),(0,i.kt)("p",null,"\u7c98\u571f\u5bf9\u8c61\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u81ea\u521b\u7684\u4e00\u79cd\u6982\u5ff5\uff0c\u662f\u4e00\u79cd\u53ef\u4ee5\u6a21\u62df\u5f31\u8bed\u8a00\u7279\u6027\u7684\u5bf9\u8c61\uff0c\u7c7b\u4f3c ",(0,i.kt)("inlineCode",{parentName:"p"},"Javascript")," \u4e00\u6837\u64cd\u4f5c\u5bf9\u8c61\u3002\u53ea\u9700\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"Clay")," \u7c7b\u521d\u59cb\u5316\u5373\u53ef\u3002"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u4e3a\u4ec0\u4e48\u8d77\u540d\u4e3a \u201c\u7c98\u571f\u201d \u5462\uff1f\u56e0\u4e3a\u8fd9\u4e2a\u5bf9\u8c61\u53ef\u4ee5\u81ea\u7531\u7684\u6dfb\u52a0\u5c5e\u6027\uff0c\u79fb\u9664\u5c5e\u6027\uff0c\u53c8\u53ef\u4ee5\u56fa\u5316\u6210\u4efb\u4f55\u5bf9\u8c61\uff0c\u5177\u6709\u53ef\u62d3\u5c55\u3001\u53ef\u5851\u9020\u7684\u7279\u70b9\u3002")),(0,i.kt)("h3",{id:"2911-\u4f7f\u7528\u573a\u666f"},"29.1.1 \u4f7f\u7528\u573a\u666f"),(0,i.kt)("p",null,"\u7c98\u571f\u5bf9\u8c61\u5e38\u7528\u4e8e\u9700\u8981\u52a8\u6001\u6784\u5efa\u5bf9\u8c61\u7684\u5730\u65b9\uff0c\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"CMS")," \u7cfb\u7edf\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"ViewModel"),"\uff0c\u6216\u8005\u8fd0\u884c\u65f6\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u5bf9\u8c61\uff0c\u6216\u8005\u8bf7\u6c42\u7b2c\u4e09\u65b9 ",(0,i.kt)("inlineCode",{parentName:"p"},"API")," \u60c5\u51b5\u3002"),(0,i.kt)("h3",{id:"2912-\u5173\u4e8e\u6027\u80fd"},"29.1.2 \u5173\u4e8e\u6027\u80fd"),(0,i.kt)("p",null,"\u7c98\u571f\u6027\u80fd\u5b9e\u9645\u4e0a\u5e76\u4e0d\u9ad8\u6548\uff0c\u4f46\u662f\u6027\u80fd\u4e5f\u5e76\u4e0d\u4f4e\u4e0b\uff0c\u53ea\u4e0d\u8fc7\u7565\u8f93\u4e8e\u5f3a\u7c7b\u578b\u8c03\u7528\u3002\u4ec0\u4e48\u65f6\u5019\u4f7f\u7528\u53ef\u4ee5\u770b\u4ee5\u4e0a\u7684\u3010\u4f7f\u7528\u573a\u666f\u3011\u3002"),(0,i.kt)("h2",{id:"292-clay-\u5bf9\u8c61"},"29.2 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Clay")," \u5bf9\u8c61"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Clay")," \u5bf9\u8c61\u662f\u7ee7\u627f\u81ea ",(0,i.kt)("inlineCode",{parentName:"p"},"DynamicObject")," \u7684\u4e00\u4e2a\u7279\u6b8a\u5bf9\u8c61\uff0c\u63d0\u4f9b\u4e86\u50cf\u5f31\u8bed\u8a00\u4e00\u6837\u64cd\u4f5c\u5bf9\u8c61\u7684\u65b9\u6cd5\u53ca\u7d22\u5f15\u3002"),(0,i.kt)("h2",{id:"293-\u5982\u4f55\u4f7f\u7528"},"29.3 \u5982\u4f55\u4f7f\u7528"),(0,i.kt)("h3",{id:"2931-\u521b\u5efa\u4e00\u4e2a\u5bf9\u8c61"},"29.3.1 \u521b\u5efa\u4e00\u4e2a\u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u521b\u5efa\u4e00\u4e2a\u7a7a\u7684\u7c98\u571f\u5bf9\u8c61\ndynamic clay = new Clay();\n\n// \u4ece\u73b0\u6709\u7684\u5bf9\u8c61\u521b\u5efa\ndynamic clay2 = Clay.Object(new {});\n\n// \u4ece json \u5b57\u7b26\u4e32\u521b\u5efa\uff0c\u53ef\u7528\u4e8e\u7b2c\u4e09\u65b9 API \u5bf9\u63a5\uff0c\u975e\u5e38\u6709\u7528\ndynamic clay3 = Clay.Parse(@"{""foo"":""json"", ""bar"":100, ""nest"":{ ""foobar"":true } }");\n')),(0,i.kt)("h3",{id:"2932-\u8bfb\u53d6\u83b7\u53d6\u5c5e\u6027"},"29.3.2 \u8bfb\u53d6/\u83b7\u53d6\u5c5e\u6027"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n }\n});\n\nvar r1 = clay.Foo; // "json" - string\u7c7b\u578b\nvar r2 = clay.Bar; // 100 - double\u7c7b\u578b\nvar r3 = clay.Nest.Foobar; // true - bool\u7c7b\u578b\nvar r4 = clay["Nest"]["Foobar"]; // \u8fd8\u53ef\u4ee5\u548c Javascript \u4e00\u6837\u901a\u8fc7\u7d22\u5f15\u5668\u83b7\u53d6\n')),(0,i.kt)("h3",{id:"2933-\u65b0\u589e\u5c5e\u6027"},"29.3.3 \u65b0\u589e\u5c5e\u6027"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n }\n});\n\n// \u65b0\u589e\nclay.Arr = new string[] { "NOR", "XOR" }; // \u6dfb\u52a0\u4e00\u4e2a\u6570\u7ec4\nclay.Obj1 = new City { }; // \u65b0\u589e\u4e00\u4e2a\u5b9e\u4f8b\u5bf9\u8c61\nclay.Obj2 = new { Foo = "abc", Bar = 100 }; // \u65b0\u589e\u4e00\u4e2a\u533f\u540d\u7c7b\n')),(0,i.kt)("h3",{id:"2934-\u66f4\u65b0\u5c5e\u6027\u503c"},"29.3.4 \u66f4\u65b0\u5c5e\u6027\u503c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n }\n});\n\n// \u66f4\u65b0\nclay.Foo = "Furion";\nclay["Nest"].Foobar = false;\nclay.Nest["Foobar"] = true;\n')),(0,i.kt)("h3",{id:"2935-\u5220\u9664\u5c5e\u6027"},"29.3.5 \u5220\u9664\u5c5e\u6027"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n },\n Arr = new string[] { "NOR", "XOR" }\n});\n\n// \u5220\u9664\u64cd\u4f5c\nclay.Delete("Foo"); // \u901a\u8fc7 Delete \u65b9\u6cd5\u5220\u9664\nclay.Arr.Delete(0); // \u652f\u6301\u6570\u7ec4 Delete \u7d22\u5f15\u5220\u9664\nclay("Bar"); // \u652f\u6301\u76f4\u63a5\u901a\u8fc7\u5bf9\u8c61\u4f5c\u4e3a\u65b9\u6cd5\u5220\u9664\nclay.Arr(1); // \u652f\u6301\u6570\u7ec4\u4f5c\u4e3a\u65b9\u6cd5\u5220\u9664\n')),(0,i.kt)("h3",{id:"2936-\u5224\u65ad\u5c5e\u6027\u662f\u5426\u5b58\u5728"},"29.3.6 \u5224\u65ad\u5c5e\u6027\u662f\u5426\u5b58\u5728"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n },\n Arr = new string[] { "NOR", "XOR" }\n});\n\n// \u5224\u65ad\u5c5e\u6027\u662f\u5426\u5b58\u5728\nvar a = clay.IsDefined("Foo"); // true\nvar b = clay.IsDefined("Foooo"); // false\nvar c = clay.Foo(); // true\nvar d = clay.Foooo(); // false;\n')),(0,i.kt)("h3",{id:"2937-\u904d\u5386\u5bf9\u8c61"},"29.3.7 \u904d\u5386\u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n },\n Arr = new string[] { "NOR", "XOR" }\n});\n\n// \u904d\u5386\u6570\u7ec4\nforeach (string item in clay.Arr)\n{\n Console.WriteLine(item); // NOR, XOR\n}\n\n// \u904d\u5386\u6574\u4e2a\u5bf9\u8c61\u5c5e\u6027\u53ca\u503c\uff0c\u7c7b\u4f3c JavaScript \u7684 for (var p in obj)\nforeach (KeyValuePair item in clay)\n{\n Console.WriteLine(item.Key + ":" + item.Value); // Foo:json, Bar: 100, Nest: { "Foobar":true}, Arr:["NOR","XOR"]\n}\n')),(0,i.kt)("h3",{id:"2938-\u8f6c\u6362\u6210\u5177\u4f53\u5bf9\u8c61"},"29.3.8 \u8f6c\u6362\u6210\u5177\u4f53\u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = new Clay();\nclay.Arr = new string[] { "Furion", "Fur" };\n\n// \u6570\u7ec4\u8f6c\u6362\u793a\u4f8b\nvar a1 = clay.Arr.Deserialize(); // \u901a\u8fc7 Deserialize \u65b9\u6cd5\nvar a2 = (string[])clay.Arr; // \u5f3a\u5236\u8f6c\u6362\nstring[] a3 = clay.Arr; // \u58f0\u660e\u65b9\u5f0f\n\n// \u5bf9\u8c61\u8f6c\u6362\u793a\u4f8b\nclay.City = new City { Id = 1, Name = "\u4e2d\u5c71\u5e02" };\nvar c1 = clay.City.Deserialize(); // \u901a\u8fc7 Deserialize \u65b9\u6cd5\nvar c2 = (City)clay.City; // \u5f3a\u5236\u8f6c\u6362\nCity c3 = clay.City; // \u58f0\u660e\u65b9\u5f0f\n')),(0,i.kt)("h3",{id:"2939-\u56fa\u5316\u7c98\u571f"},"29.3.9 \u56fa\u5316\u7c98\u571f"),(0,i.kt)("p",null,"\u56fa\u5316\u7c98\u571f\u5728\u5f88\u591a\u65f6\u5019\u548c\u5e8f\u5217\u5316\u5f88\u50cf\uff0c\u4f46\u662f\u5982\u679c\u76f4\u63a5\u8c03\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Deserialize")," \u6216 ",(0,i.kt)("inlineCode",{parentName:"p"},"Deserialize")," \u65e0\u6cd5\u8fd4\u56de\u5b9e\u9645\u7c7b\u578b\uff0c\u6240\u4ee5\u5c31\u6709\u4e86\u56fa\u5316\u7c7b\u578b\u7684\u529f\u80fd\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u8fd4\u56de object\nvar obj = clay.Solidify();\n\n// \u8fd4\u56de dynamic\nvar obj1 = clay.Solidify();\n\n// \u8fd4\u56de\u5176\u4ed6\u4efb\u610f\u7c7b\u578b\nvar obj2 = clay.Solidify();\n")),(0,i.kt)("h3",{id:"29310-\u8f93\u51fa-json"},"29.3.10 \u8f93\u51fa ",(0,i.kt)("inlineCode",{parentName:"h3"},"JSON")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n },\n Arr = new string[] { "NOR", "XOR" }\n});\n\n// \u8f93\u51fa JSON\nvar json = clay.ToString(); // "{\\"Foo\\":\\"json\\",\\"Bar\\":100,\\"Nest\\":{\\"Foobar\\":true},\\"Arr\\":[\\"NOR\\",\\"XOR\\"]}"\n')),(0,i.kt)("admonition",{type:"tip"},(0,i.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Clay")," \u5e8f\u5217\u5316\u6210 ",(0,i.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"JSON")," \u952e\u5927\u5c0f\u5199\u63a7\u5236"),(0,i.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Clay")," \u8f93\u51fa\u6210 ",(0,i.kt)("inlineCode",{parentName:"p"},"JSON")," \u540e\u5c06\u4fdd\u6301\u539f\u6837\u8f93\u51fa\uff0c\u5982\u679c\u9700\u8981\u5b9e\u73b0\u952e\u547d\u540d\u63a7\u5236\uff0c\u5219\u9700\u8981\u5148\u8f6c\u6362\u6210 ",(0,i.kt)("inlineCode",{parentName:"p"},"Dictionary")," \u7136\u540e\u518d\u914d\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"AddJsonOptions")," \u670d\u52a1\uff0c\u5982\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8-9}",showLineNumbers:!0,"{8-9}":!0},"public IActionResult OutputClay()\n{\n dynamic clay = Clay.Object(new\n {\n // ....\n });\n\n // \u8f6c\u6362\u6210 dictionary\n var dic = clay.ToDictionary();\n\n return new JsonResult(dic);\n}\n")),(0,i.kt)("p",{parentName:"admonition"},"\u914d\u7f6e\u5e8f\u5217\u5316 ",(0,i.kt)("inlineCode",{parentName:"p"},"Dictionary")," \u952e\u547d\u540d\u7b56\u7565\u652f\u6301\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,4}",showLineNumbers:!0,"{2,4}":!0},"services.AddControllers()\n .AddJsonOptions(options =>\n {\n options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase; // \u914d\u7f6e Dictionary \u7c7b\u578b\u5e8f\u5217\u5316\u8f93\u51fa\n });\n"))),(0,i.kt)("h3",{id:"29311-\u8f93\u51fa-xml-\u5bf9\u8c61"},"29.3.11 \u8f93\u51fa ",(0,i.kt)("inlineCode",{parentName:"h3"},"XML")," \u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new\n{\n Foo = "json",\n Bar = 100,\n Nest = new\n {\n Foobar = true\n },\n Arr = new string[] { "NOR", "XOR" }\n});\n\n// \u8f93\u51fa XElement\nvar xml = clay.XmlElement;\n')),(0,i.kt)("h3",{id:"29312-\u5173\u952e\u5b57\u5904\u7406"},"29.3.12 \u5173\u952e\u5b57\u5904\u7406"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = new Clay();\nclay.@int = 1;\nclay.@event = "\u4e8b\u4ef6";\n')),(0,i.kt)("h3",{id:"29313-\u8f6c\u6362\u6210\u5b57\u5178\u7c7b\u578b"},"29.3.13 \u8f6c\u6362\u6210\u5b57\u5178\u7c7b\u578b"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'dynamic clay = Clay.Object(new { name = "\u5f20\u4e09" });\nclay.name = "\u767e\u5c0f\u50e7";\nDictionary parms = clay.ToDictionary();\n')),(0,i.kt)("h2",{id:"294-\u53cd\u9988\u4e0e\u5efa\u8bae"},"29.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/5792.06bee9e5.js b/handbook/build/assets/js/5792.06bee9e5.js deleted file mode 100644 index 7e94b5bec1..0000000000 --- a/handbook/build/assets/js/5792.06bee9e5.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[5792],{1485:function(e,t,r){r.d(t,{Z:function(){return Z}});var n=r(102),a=r(7294),l=r(4334),i=r(4832),o=r(4980),c=r(8746),m=r(1614),s="sidebar_re4s",u="sidebarItemTitle_pO2u",d="sidebarItemList_Yudw",f="sidebarItem__DBe",g="sidebarItemLink_mo7H",p="sidebarItemLinkActive_I1ZP";function v(e){var t=e.sidebar;return a.createElement("aside",{className:"col col--3"},a.createElement("nav",{className:(0,l.Z)(s,"thin-scrollbar"),"aria-label":(0,m.I)({id:"theme.blog.sidebar.navAriaLabel",message:"Blog recent posts navigation",description:"The ARIA label for recent posts in the blog sidebar"})},a.createElement("div",{className:(0,l.Z)(u,"margin-bottom--md")},t.title),a.createElement("ul",{className:(0,l.Z)(d,"clean-list")},t.items.map((function(e){return a.createElement("li",{key:e.permalink,className:f},a.createElement(c.Z,{isNavLink:!0,to:e.permalink,className:g,activeClassName:p},e.title))})))))}var h=r(2306);function E(e){var t=e.sidebar;return a.createElement("ul",{className:"menu__list"},t.items.map((function(e){return a.createElement("li",{key:e.permalink,className:"menu__list-item"},a.createElement(c.Z,{isNavLink:!0,to:e.permalink,className:"menu__link",activeClassName:"menu__link--active"},e.title))})))}function b(e){return a.createElement(h.Zo,{component:E,props:e})}function P(e){var t=e.sidebar,r=(0,o.i)();return null!=t&&t.items.length?"mobile"===r?a.createElement(b,{sidebar:t}):a.createElement(v,{sidebar:t}):null}var N=["sidebar","toc","children"];function Z(e){var t=e.sidebar,r=e.toc,o=e.children,c=(0,n.Z)(e,N),m=t&&t.items.length>0;return a.createElement(i.Z,c,a.createElement("div",{className:"container margin-vert--lg"},a.createElement("div",{className:"row"},a.createElement(P,{sidebar:t}),a.createElement("main",{className:(0,l.Z)("col",{"col--7":m,"col--9 col--offset-1":!m}),itemScope:!0,itemType:"http://schema.org/Blog"},o),r&&a.createElement("div",{className:"col col--2"},r))))}},1827:function(e,t,r){r.d(t,{Z:function(){return R}});var n=r(7294),a=r(4334),l=r(7762),i=r(1402);function o(e){var t,r=e.children,a=e.className,o=(0,l.C)(),c=o.frontMatter,m=o.assets,s=(0,i.C)().withBaseUrl,u=null!=(t=m.image)?t:c.image;return n.createElement("article",{className:a,itemProp:"blogPost",itemScope:!0,itemType:"http://schema.org/BlogPosting"},u&&n.createElement("meta",{itemProp:"image",content:s(u,{absolute:!0})}),r)}var c=r(8746),m="title_f1Hy";function s(e){var t=e.className,r=(0,l.C)(),i=r.metadata,o=r.isBlogPostPage,s=i.permalink,u=i.title,d=o?"h1":"h2";return n.createElement(d,{className:(0,a.Z)(m,t),itemProp:"headline"},o?u:n.createElement(c.Z,{itemProp:"url",to:s},u))}var u=r(1614),d=r(7880),f="container_mt6G";function g(e){var t,r=e.readingTime,a=(t=(0,d.c)().selectMessage,function(e){var r=Math.ceil(e);return t(r,(0,u.I)({id:"theme.blog.post.readingTime.plurals",description:'Pluralized label for "{readingTime} min read". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',message:"One min read|{readingTime} min read"},{readingTime:r}))});return n.createElement(n.Fragment,null,a(r))}function p(e){var t=e.date,r=e.formattedDate;return n.createElement("time",{dateTime:t,itemProp:"datePublished"},r)}function v(){return n.createElement(n.Fragment,null," \xb7 ")}function h(e){var t=e.className,r=(0,l.C)().metadata,i=r.date,o=r.formattedDate,c=r.readingTime;return n.createElement("div",{className:(0,a.Z)(f,"margin-vert--md",t)},n.createElement(p,{date:i,formattedDate:o}),void 0!==c&&n.createElement(n.Fragment,null,n.createElement(v,null),n.createElement(g,{readingTime:c})))}function E(e){return e.href?n.createElement(c.Z,e):n.createElement(n.Fragment,null,e.children)}function b(e){var t=e.author,r=e.className,l=t.name,i=t.title,o=t.url,c=t.imageURL,m=t.email,s=o||m&&"mailto:"+m||void 0;return n.createElement("div",{className:(0,a.Z)("avatar margin-bottom--sm",r)},c&&n.createElement(E,{href:s,className:"avatar__photo-link"},n.createElement("img",{className:"avatar__photo",src:c,alt:l})),l&&n.createElement("div",{className:"avatar__intro",itemProp:"author",itemScope:!0,itemType:"https://schema.org/Person"},n.createElement("div",{className:"avatar__name"},n.createElement(E,{href:s,itemProp:"url"},n.createElement("span",{itemProp:"name"},l))),i&&n.createElement("small",{className:"avatar__subtitle",itemProp:"description"},i)))}var P="authorCol_Hf19",N="imageOnlyAuthorRow_pa_O",Z="imageOnlyAuthorCol_G86a";function _(e){var t=e.className,r=(0,l.C)(),i=r.metadata.authors,o=r.assets;if(0===i.length)return null;var c=i.every((function(e){return!e.name}));return n.createElement("div",{className:(0,a.Z)("margin-top--md margin-bottom--sm",c?N:"row",t)},i.map((function(e,t){var r;return n.createElement("div",{className:(0,a.Z)(!c&&"col col--6",c?Z:P),key:t},n.createElement(b,{author:Object.assign({},e,{imageURL:null!=(r=o.authorsImageUrls[t])?r:e.imageURL})}))})))}function y(){return n.createElement("header",null,n.createElement(s,null),n.createElement(h,null),n.createElement(_,null))}var k=r(9861),O=r(2279);function w(e){var t=e.children,r=e.className,i=(0,l.C)().isBlogPostPage;return n.createElement("div",{id:i?k.blogPostContainerID:void 0,className:(0,a.Z)("markdown",r),itemProp:"articleBody"},n.createElement(O.Z,null,t))}var T=r(7612),C=r(8045),x=r(3117),j=r(102),F=["blogPostTitle"];function B(){return n.createElement("b",null,n.createElement(u.Z,{id:"theme.blog.post.readMore",description:"The label used in blog post item excerpts to link to full blog posts"},"Read More"))}function I(e){var t=e.blogPostTitle,r=(0,j.Z)(e,F);return n.createElement(c.Z,(0,x.Z)({"aria-label":(0,u.I)({message:"Read more about {title}",id:"theme.blog.post.readMoreLabel",description:"The ARIA label for the link to full blog posts from excerpts"},{title:t})},r),n.createElement(B,null))}var L="blogPostFooterDetailsFull_mRVl";function M(){var e=(0,l.C)(),t=e.metadata,r=e.isBlogPostPage,i=t.tags,o=t.title,c=t.editUrl,m=t.hasTruncateMarker,s=!r&&m,u=i.length>0;return u||s||c?n.createElement("footer",{className:(0,a.Z)("row docusaurus-mt-lg",r&&L)},u&&n.createElement("div",{className:(0,a.Z)("col",{"col--9":s})},n.createElement(C.Z,{tags:i})),r&&c&&n.createElement("div",{className:"col margin-top--sm"},n.createElement(T.Z,{editUrl:c})),s&&n.createElement("div",{className:(0,a.Z)("col text--right",{"col--3":u})},n.createElement(I,{blogPostTitle:o,to:t.permalink}))):null}function R(e){var t=e.children,r=e.className,i=(0,l.C)().isBlogPostPage?void 0:"margin-bottom--xl";return n.createElement(o,{className:(0,a.Z)(i,r)},n.createElement(y,null),n.createElement(w,null,t),n.createElement(M,null))}},7612:function(e,t,r){r.d(t,{Z:function(){return d}});var n=r(7294),a=r(1614),l=r(8015),i=r(3117),o=r(102),c=r(4334),m="iconEdit_Z9Sw",s=["className"];function u(e){var t=e.className,r=(0,o.Z)(e,s);return n.createElement("svg",(0,i.Z)({fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,c.Z)(m,t),"aria-hidden":"true"},r),n.createElement("g",null,n.createElement("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})))}function d(e){var t=e.editUrl;return n.createElement("a",{href:t,target:"_blank",rel:"noreferrer noopener",className:l.k.common.editThisPage},n.createElement(u,null),n.createElement(a.Z,{id:"theme.common.editThisPage",description:"The link label to edit the current page"},"Edit this page"))}},2279:function(e,t,r){r.d(t,{Z:function(){return i}});var n=r(7294),a=r(3905),l=r(9363);function i(e){var t=e.children;return n.createElement(a.Zo,{components:l.Z},t)}},3500:function(e,t,r){r.d(t,{Z:function(){return i}});var n=r(7294),a=r(4334),l=r(8746);function i(e){var t=e.permalink,r=e.title,i=e.subLabel,o=e.isNext;return n.createElement(l.Z,{className:(0,a.Z)("pagination-nav__link",o?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t},i&&n.createElement("div",{className:"pagination-nav__sublabel"},i),n.createElement("div",{className:"pagination-nav__label"},r))}},4588:function(e,t,r){r.d(t,{Z:function(){return m}});var n=r(7294),a=r(4334),l=r(8746),i="tag_zVej",o="tagRegular_sFm0",c="tagWithCount_h2kH";function m(e){var t=e.permalink,r=e.label,m=e.count;return n.createElement(l.Z,{href:t,className:(0,a.Z)(i,m?c:o)},r,m&&n.createElement("span",null,m))}},8045:function(e,t,r){r.d(t,{Z:function(){return m}});var n=r(7294),a=r(4334),l=r(1614),i=r(4588),o="tags_jXut",c="tag_QGVx";function m(e){var t=e.tags;return n.createElement(n.Fragment,null,n.createElement("b",null,n.createElement(l.Z,{id:"theme.tags.tagsListLabel",description:"The label alongside a tag list"},"Tags:")),n.createElement("ul",{className:(0,a.Z)(o,"padding--none","margin-left--sm")},t.map((function(e){var t=e.label,r=e.permalink;return n.createElement("li",{key:r,className:c},n.createElement(i.Z,{label:t,permalink:r}))}))))}},7762:function(e,t,r){r.d(t,{C:function(){return o},n:function(){return i}});var n=r(7294),a=r(8875),l=n.createContext(null);function i(e){var t=e.children,r=e.content,a=e.isBlogPostPage,i=function(e){var t=e.content,r=e.isBlogPostPage;return(0,n.useMemo)((function(){return{metadata:t.metadata,frontMatter:t.frontMatter,assets:t.assets,toc:t.toc,isBlogPostPage:r}}),[t,r])}({content:r,isBlogPostPage:void 0!==a&&a});return n.createElement(l.Provider,{value:i},t)}function o(){var e=(0,n.useContext)(l);if(null===e)throw new a.i6("BlogPostProvider");return e}},7880:function(e,t,r){r.d(t,{c:function(){return m}});var n=r(7294),a=r(6832),l=["zero","one","two","few","many","other"];function i(e){return l.filter((function(t){return e.includes(t)}))}var o={locale:"en",pluralForms:i(["one","other"]),select:function(e){return 1===e?"one":"other"}};function c(){var e=(0,a.Z)().i18n.currentLocale;return(0,n.useMemo)((function(){try{return t=e,r=new Intl.PluralRules(t),{locale:t,pluralForms:i(r.resolvedOptions().pluralCategories),select:function(e){return r.select(e)}}}catch(n){return console.error('Failed to use Intl.PluralRules for locale "'+e+'".\nDocusaurus will fallback to the default (English) implementation.\nError: '+n.message+"\n"),o}var t,r}),[e])}function m(){var e=c();return{selectMessage:function(t,r){return function(e,t,r){var n=e.split("|");if(1===n.length)return n[0];n.length>r.pluralForms.length&&console.error("For locale="+r.locale+", a maximum of "+r.pluralForms.length+" plural forms are expected ("+r.pluralForms.join(",")+"), but the message contains "+n.length+": "+e);var a=r.select(t),l=r.pluralForms.indexOf(a);return n[Math.min(l,n.length-1)]}(r,t,e)}}}},3905:function(e,t,r){r.d(t,{Zo:function(){return s},kt:function(){return f}});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),m=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},s=function(e){var t=m(e.components);return n.createElement(c.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,l=e.originalType,c=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=m(r),f=a,g=d["".concat(c,".").concat(f)]||d[f]||u[f]||l;return r?n.createElement(g,i(i({ref:t},s),{},{components:r})):n.createElement(g,i({ref:t},s))}));function f(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=r.length,i=new Array(l);i[0]=d;var o={};for(var c in t)hasOwnProperty.call(t,c)&&(o[c]=t[c]);o.originalType=e,o.mdxType="string"==typeof e?e:a,i[1]=o;for(var m=2;mFurion \u529f\u80fd",id:"232-\u96c6\u6210-furion-\u529f\u80fd",level:2},{value:"2.3.3 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"233-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:m};function d(e){var n=e.components,t=(0,a.Z)(e,o);return(0,i.kt)("wrapper",(0,r.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{title:"\u63a8\u8350\u4f7f\u7528\u811a\u624b\u67b6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u5b98\u65b9\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u65b9\u4fbf\u7684\u811a\u624b\u67b6\uff0c\u53ef\u4ee5\u5feb\u901f\u7684\u521b\u5efa\u591a\u5c42\u67b6\u6784\u9879\u76ee\u3002"),(0,i.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u4f7f\u7528 \u300a",(0,i.kt)("a",{parentName:"p",href:"/furion/docs/template"},"2.2 \u5b98\u65b9\u811a\u624b\u67b6"),"\u300b\u4ee3\u66ff\u672c\u7ae0\u8282\u529f\u80fd\u3002")),(0,i.kt)("h2",{id:"231-\u63a8\u8350\u5206\u5c42\u8bbe\u8ba1"},"2.3.1 \u63a8\u8350\u5206\u5c42\u8bbe\u8ba1"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u63a8\u8350\u91c7\u7528\u591a\u5c42\u9879\u76ee\u8bbe\u8ba1\u67b6\u6784\uff0c\u6bcf\u4e00\u4e2a\u9879\u76ee\u5c42\u7684\u4f9d\u8d56\u5206\u522b\u662f\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"YourName.Application"),"\uff1a\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"li"},"YourName.Core")," \u5f15\u7528"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"YourName.Core"),"\uff1a\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5f15\u7528"),"\uff0c",(0,i.kt)("strong",{parentName:"li"},"SqlSugar \u7248\u672c\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion.Pure"))," \ud83c\udf97"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"YourName.Database.Migrations"),"\uff1a\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"li"},"YourName.EntityFramework.Core")," \u5f15\u7528"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"YourName.EntityFramework.Core"),"\uff1a\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"li"},"YourName.Core")," \u5f15\u7528"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"YourName.Web.Core"),"\uff1a\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"li"},"YourName.Application"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"YourName.Database.Migrations")," \u5f15\u7528"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"YourName.Web.Entry"),"\uff1a\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"strong"},"YourName.Web.Core")," \u5f15\u7528 \u548c ",(0,i.kt)("inlineCode",{parentName:"strong"},"Microsoft.EntityFrameworkCore.Tools")," \u5305"))),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"EFCore")," \u4ee5\u5916\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"ORM")," \u6846\u67b6\uff0c\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"SqlSugar"),"\uff0c\u90a3\u4e48\u65e0\u9700\u521b\u5efa ",(0,i.kt)("inlineCode",{parentName:"p"},"YourName.Database.Migrations")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"YourName.EntityFramework.Core")," \u5c42\u3002"),(0,i.kt)("p",{parentName:"admonition"},"\u53e6\u5916 ",(0,i.kt)("inlineCode",{parentName:"p"},"YourName.Web.Entry")," \u65e0\u9700\u5f15\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Microsoft.EntityFrameworkCore.Tools")," \u5305\u3002")),(0,i.kt)("h2",{id:"232-\u96c6\u6210-furion-\u529f\u80fd"},"2.3.2 \u96c6\u6210 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Furion")," \u529f\u80fd"),(0,i.kt)("p",null,"\u9879\u76ee\u642d\u5efa\u597d\u4e4b\u540e\uff0c\u96c6\u6210 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u53ea\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d \u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"p"},"Inject()")," \u65b9\u6cd5\u5373\u53ef\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},".NET5")," \u7248\u672c\uff1a")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {18}",showLineNumbers:!0,"":!0,"{18}":!0},"using Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Hosting;\n\nnamespace YourName.Web.Entry\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args)\n {\n return Host.CreateDefaultBuilder(args)\n .ConfigureWebHostDefaults(webBuilder =>\n {\n webBuilder.Inject()\n .UseStartup();\n });\n }\n }\n}\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},".NET6")," \u7248\u672c")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,11}",showLineNumbers:!0,"{1,3,11}":!0},"var builder = WebApplication.CreateBuilder(args).Inject();\n\nbuilder.Services.AddControllers().AddInject();\n\nvar app = builder.Build();\n\napp.UseHttpsRedirection();\n\napp.UseAuthorization();\n\napp.UseInject();\n\napp.MapControllers();\n\napp.Run();\n")),(0,i.kt)("h2",{id:"233-\u53cd\u9988\u4e0e\u5efa\u8bae"},"2.3.3 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}d.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return s},kt:function(){return d}});var r=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function o(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var p=r.createContext({}),u=function(e){var n=r.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},s=function(e){var n=u(e.components);return r.createElement(p.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},c=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,p=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),c=u(t),d=a,f=c["".concat(p,".").concat(d)]||c[d]||m[d]||i;return t?r.createElement(f,o(o({ref:n},s),{},{components:t})):r.createElement(f,o({ref:n},s))}));function d(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,o=new Array(i);o[0]=c;var l={};for(var p in n)hasOwnProperty.call(n,p)&&(l[p]=n[p]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var u=2;u=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var p=r.createContext({}),u=function(e){var n=r.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},s=function(e){var n=u(e.components);return r.createElement(p.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},c=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,p=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),c=u(t),d=a,f=c["".concat(p,".").concat(d)]||c[d]||m[d]||i;return t?r.createElement(f,o(o({ref:n},s),{},{components:t})):r.createElement(f,o({ref:n},s))}));function d(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,o=new Array(i);o[0]=c;var l={};for(var p in n)hasOwnProperty.call(n,p)&&(l[p]=n[p]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var u=2;uFurion \u529f\u80fd",id:"232-\u96c6\u6210-furion-\u529f\u80fd",level:2},{value:"2.3.3 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"233-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:m};function d(e){var n=e.components,t=(0,a.Z)(e,o);return(0,i.kt)("wrapper",(0,r.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{title:"\u63a8\u8350\u4f7f\u7528\u811a\u624b\u67b6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u5b98\u65b9\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u65b9\u4fbf\u7684\u811a\u624b\u67b6\uff0c\u53ef\u4ee5\u5feb\u901f\u7684\u521b\u5efa\u591a\u5c42\u67b6\u6784\u9879\u76ee\u3002"),(0,i.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u4f7f\u7528 \u300a",(0,i.kt)("a",{parentName:"p",href:"/furion/docs/template"},"2.2 \u5b98\u65b9\u811a\u624b\u67b6"),"\u300b\u4ee3\u66ff\u672c\u7ae0\u8282\u529f\u80fd\u3002")),(0,i.kt)("h2",{id:"231-\u63a8\u8350\u5206\u5c42\u8bbe\u8ba1"},"2.3.1 \u63a8\u8350\u5206\u5c42\u8bbe\u8ba1"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u63a8\u8350\u91c7\u7528\u591a\u5c42\u9879\u76ee\u8bbe\u8ba1\u67b6\u6784\uff0c\u6bcf\u4e00\u4e2a\u9879\u76ee\u5c42\u7684\u4f9d\u8d56\u5206\u522b\u662f\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"YourName.Application"),"\uff1a\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"li"},"YourName.Core")," \u5f15\u7528"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"YourName.Core"),"\uff1a\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5f15\u7528"),"\uff0c",(0,i.kt)("strong",{parentName:"li"},"SqlSugar \u7248\u672c\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion.Pure"))," \ud83c\udf97"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"YourName.Database.Migrations"),"\uff1a\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"li"},"YourName.EntityFramework.Core")," \u5f15\u7528"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"YourName.EntityFramework.Core"),"\uff1a\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"li"},"YourName.Core")," \u5f15\u7528"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"YourName.Web.Core"),"\uff1a\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"li"},"YourName.Application"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"YourName.Database.Migrations")," \u5f15\u7528"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"strong"},"YourName.Web.Entry"),"\uff1a\u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"strong"},"YourName.Web.Core")," \u5f15\u7528 \u548c ",(0,i.kt)("inlineCode",{parentName:"strong"},"Microsoft.EntityFrameworkCore.Tools")," \u5305"))),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"EFCore")," \u4ee5\u5916\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"ORM")," \u6846\u67b6\uff0c\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"SqlSugar"),"\uff0c\u90a3\u4e48\u65e0\u9700\u521b\u5efa ",(0,i.kt)("inlineCode",{parentName:"p"},"YourName.Database.Migrations")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"YourName.EntityFramework.Core")," \u5c42\u3002"),(0,i.kt)("p",{parentName:"admonition"},"\u53e6\u5916 ",(0,i.kt)("inlineCode",{parentName:"p"},"YourName.Web.Entry")," \u65e0\u9700\u5f15\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Microsoft.EntityFrameworkCore.Tools")," \u5305\u3002")),(0,i.kt)("h2",{id:"232-\u96c6\u6210-furion-\u529f\u80fd"},"2.3.2 \u96c6\u6210 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Furion")," \u529f\u80fd"),(0,i.kt)("p",null,"\u9879\u76ee\u642d\u5efa\u597d\u4e4b\u540e\uff0c\u96c6\u6210 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u53ea\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d \u6dfb\u52a0 ",(0,i.kt)("inlineCode",{parentName:"p"},"Inject()")," \u65b9\u6cd5\u5373\u53ef\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},".NET5")," \u7248\u672c\uff1a")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {18}",showLineNumbers:!0,"":!0,"{18}":!0},"using Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Hosting;\n\nnamespace YourName.Web.Entry\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args)\n {\n return Host.CreateDefaultBuilder(args)\n .ConfigureWebHostDefaults(webBuilder =>\n {\n webBuilder.Inject()\n .UseStartup();\n });\n }\n }\n}\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},".NET6")," \u7248\u672c")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,11}",showLineNumbers:!0,"{1,3,11}":!0},"var builder = WebApplication.CreateBuilder(args).Inject();\n\nbuilder.Services.AddControllers().AddInject();\n\nvar app = builder.Build();\n\napp.UseHttpsRedirection();\n\napp.UseAuthorization();\n\napp.UseInject();\n\napp.MapControllers();\n\napp.Run();\n")),(0,i.kt)("h2",{id:"233-\u53cd\u9988\u4e0e\u5efa\u8bae"},"2.3.3 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/58624d73.7c550d93.js b/handbook/build/assets/js/58624d73.7c550d93.js deleted file mode 100644 index c34bd561ae..0000000000 --- a/handbook/build/assets/js/58624d73.7c550d93.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[7667],{436:function(e,t,n){n.r(t),n.d(t,{assets:function(){return m},contentTitle:function(){return p},default:function(){return d},frontMatter:function(){return l},metadata:function(){return s},toc:function(){return u}});var r=n(3117),o=n(102),i=(n(7294),n(3905)),a=["components"],l={id:"dbcontext-repository",title:"9.4 \u4ed3\u50a8\u6a21\u5f0f",sidebar_label:"9.4 \u4ed3\u50a8\u6a21\u5f0f (Repository)"},p=void 0,s={unversionedId:"dbcontext-repository",id:"dbcontext-repository",title:"9.4 \u4ed3\u50a8\u6a21\u5f0f",description:"9.4.1 \u4ec0\u4e48\u662f\u4ed3\u50a8",source:"@site/docs/dbcontext-repository.mdx",sourceDirName:".",slug:"/dbcontext-repository",permalink:"/furion/docs/dbcontext-repository",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-repository.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"dbcontext-repository",title:"9.4 \u4ed3\u50a8\u6a21\u5f0f",sidebar_label:"9.4 \u4ed3\u50a8\u6a21\u5f0f (Repository)"},sidebar:"docs",previous:{title:"9.3 \u6570\u636e\u5e93\u5b9e\u4f53",permalink:"/furion/docs/entity"},next:{title:"9.5 \u65b0\u589e\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-add"}},m={},u=[{value:"9.4.1 \u4ec0\u4e48\u662f\u4ed3\u50a8",id:"941-\u4ec0\u4e48\u662f\u4ed3\u50a8",level:2},{value:"9.4.2 \u5185\u7f6e\u4ed3\u50a8",id:"942-\u5185\u7f6e\u4ed3\u50a8",level:2},{value:"9.4.2.1 \u975e\u6cdb\u578b\u8d85\u7ea7\u4ed3\u50a8",id:"9421-\u975e\u6cdb\u578b\u8d85\u7ea7\u4ed3\u50a8",level:3},{value:"9.4.2.2 \u6cdb\u578b\u5b9e\u4f53\u4ed3\u50a8",id:"9422-\u6cdb\u578b\u5b9e\u4f53\u4ed3\u50a8",level:3},{value:"9.4.2.3 \u6cdb\u578b\u591a\u6570\u636e\u5e93\u5b9e\u4f53\u4ed3\u50a8",id:"9423-\u6cdb\u578b\u591a\u6570\u636e\u5e93\u5b9e\u4f53\u4ed3\u50a8",level:3},{value:"9.4.2.4 Sql \u64cd\u4f5c\u4ed3\u50a8",id:"9424-sql-\u64cd\u4f5c\u4ed3\u50a8",level:3},{value:"9.4.2.5 \u591a\u6570\u636e\u5e93 Sql \u64cd\u4f5c\u4ed3\u50a8",id:"9425-\u591a\u6570\u636e\u5e93-sql-\u64cd\u4f5c\u4ed3\u50a8",level:3},{value:"9.4.2.6 \u53ea\u8bfb\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"9426-\u53ea\u8bfb\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.7 \u53ea\u5199\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"9427-\u53ea\u5199\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.8 \u53ea\u5141\u8bb8\u65b0\u589e\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"9428-\u53ea\u5141\u8bb8\u65b0\u589e\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.9 \u53ea\u5141\u8bb8\u66f4\u65b0\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"9429-\u53ea\u5141\u8bb8\u66f4\u65b0\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.10 \u53ea\u5141\u8bb8\u5220\u9664\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"94210-\u53ea\u5141\u8bb8\u5220\u9664\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.11 \u53ea\u5141\u8bb8\u62d3\u5c55\u64cd\u4f5c\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"94211-\u53ea\u5141\u8bb8\u62d3\u5c55\u64cd\u4f5c\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.12 \u53ea\u5141\u8bb8 Sql \u67e5\u8be2\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"94212-\u53ea\u5141\u8bb8-sql-\u67e5\u8be2\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.13 \u53ea\u5141\u8bb8 Sql \u975e\u67e5\u8be2\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"94213-\u53ea\u5141\u8bb8-sql-\u975e\u67e5\u8be2\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.14 \u8bfb\u5199\u5206\u79bb\u4ed3\u50a8",id:"94214-\u8bfb\u5199\u5206\u79bb\u4ed3\u50a8",level:3},{value:"9.4.2.15 \u5b9a\u4f4d\u5668\u4ed3\u50a8",id:"94215-\u5b9a\u4f4d\u5668\u4ed3\u50a8",level:3},{value:"9.4.3 \u4ed3\u50a8\u4f7f\u7528",id:"943-\u4ed3\u50a8\u4f7f\u7528",level:2},{value:"9.4.3.1 \u6784\u9020\u51fd\u6570\u6ce8\u5165",id:"9431-\u6784\u9020\u51fd\u6570\u6ce8\u5165",level:3},{value:"9.4.3.2 \u65b9\u6cd5\u53c2\u6570\u6ce8\u5165",id:"9432-\u65b9\u6cd5\u53c2\u6570\u6ce8\u5165",level:3},{value:"9.4.3.3 Db.GetRepository \u83b7\u53d6",id:"9433-dbgetrepository-\u83b7\u53d6",level:3},{value:"9.4.4 \u4ed3\u50a8\u9ad8\u7ea7\u7528\u6cd5",id:"944-\u4ed3\u50a8\u9ad8\u7ea7\u7528\u6cd5",level:2},{value:"9.4.4.1 \u52a8\u6001\u5207\u6362\u5b9e\u4f53\u4ed3\u50a8",id:"9441-\u52a8\u6001\u5207\u6362\u5b9e\u4f53\u4ed3\u50a8",level:3},{value:"9.4.4.2 \u52a8\u6001\u5207\u6362\u4ed3\u50a8\u7c7b\u578b",id:"9442-\u52a8\u6001\u5207\u6362\u4ed3\u50a8\u7c7b\u578b",level:3},{value:"9.4.4.3 \u83b7\u53d6 Sql \u64cd\u4f5c\u4ed3\u50a8",id:"9443-\u83b7\u53d6-sql-\u64cd\u4f5c\u4ed3\u50a8",level:3},{value:"9.4.5 \u591a\u6570\u636e\u5e93\u64cd\u4f5c",id:"945-\u591a\u6570\u636e\u5e93\u64cd\u4f5c",level:2},{value:"9.4.5.1 \u52a8\u6001\u5207\u6362\u591a\u4e2a\u6570\u636e\u5e93",id:"9451-\u52a8\u6001\u5207\u6362\u591a\u4e2a\u6570\u636e\u5e93",level:3},{value:"\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93",id:"\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93",level:4},{value:"\u53e6\u5916\u4efb\u4f55\u4ed3\u50a8\u6216\u5b9e\u4f53\u914d\u7f6e\u90fd\u652f\u6301\u591a\u4e2a\u6570\u636e\u5e93\u540c\u65f6\u64cd\u4f5c",id:"\u53e6\u5916\u4efb\u4f55\u4ed3\u50a8\u6216\u5b9e\u4f53\u914d\u7f6e\u90fd\u652f\u6301\u591a\u4e2a\u6570\u636e\u5e93\u540c\u65f6\u64cd\u4f5c",level:4},{value:"9.4.6 \u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528",id:"946-\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528",level:2},{value:"9.4.7 \u81ea\u5b9a\u4e49\u4ed3\u50a8",id:"947-\u81ea\u5b9a\u4e49\u4ed3\u50a8",level:2},{value:"9.4.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"948-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:u};function d(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"941-\u4ec0\u4e48\u662f\u4ed3\u50a8"},"9.4.1 \u4ec0\u4e48\u662f\u4ed3\u50a8"),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u5728\u9886\u57df\u5c42\u548c\u6570\u636e\u6620\u5c04\u5c42\u7684\u4e2d\u4ecb,\u4f7f\u7528\u7c7b\u4f3c\u96c6\u5408\u7684\u63a5\u53e3\u6765\u5b58\u53d6\u9886\u57df\u5bf9\u8c61\uff0c\u5b9e\u9645\u4e0a\uff0c\u4ed3\u50a8\u88ab\u7528\u4e8e\u9886\u57df\u5bf9\u8c61\u5728\u6570\u636e\u5e93\u4e0a\u7684\u64cd\u4f5c\uff08\u5b9e\u4f53 Entity \u548c\u503c\u5bf9\u8c61 Value types\uff09\u3002\u4e00\u822c\u6765\u8bf4,\u6211\u4eec\u9488\u5bf9\u4e0d\u540c\u7684\u5b9e\u4f53(\u6216\u805a\u5408\u6839 Aggregate Root)\u4f1a\u521b\u5efa\u76f8\u5bf9\u5e94\u7684\u4ed3\u50a8\u3002")),(0,i.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u4ed3\u50a8\u5c31\u662f\u6570\u636e\u5b58\u53d6\u64cd\u4f5c\u7684\u8f7d\u4f53\uff0c\u4f46\u4e0d\u9650\u5b9a\u4e8e\u6570\u636e\u5e93\u3002"),(0,i.kt)("h2",{id:"942-\u5185\u7f6e\u4ed3\u50a8"},"9.4.2 \u5185\u7f6e\u4ed3\u50a8"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u5185\u7f6e\u4e86\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u7684\u4ed3\u50a8\uff0c\u65b9\u4fbf\u5927\u5bb6\u62d3\u5c55\u548c\u96c6\u6210\uff1a"),(0,i.kt)("admonition",{title:"\u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165\u8bf4\u660e",type:"info"},(0,i.kt)("p",{parentName:"admonition"},"\u76ee\u524d\u80fd\u591f\u88ab\u4f9d\u8d56\u6ce8\u5165\u89e3\u6790\u670d\u52a1\u7684\u4ed3\u50a8\u6709\uff1a"),(0,i.kt)("ul",{parentName:"admonition"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IMSRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IMSRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IMSRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IDbRepository"))),(0,i.kt)("p",{parentName:"admonition"},"\u8fd8\u6709\u4e24\u4e2a\u79c1\u6709\u4ed3\u50a8\uff0c\u4e5f\u662f\u6240\u6709\u4ed3\u50a8\u7684\u57fa\u7c7b\uff08\u7528\u4e8e\u9ad8\u7ea7\u81ea\u5b9a\u4e49\u5f00\u53d1\uff09"),(0,i.kt)("ul",{parentName:"admonition"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IPrivateRepository"),"\uff1a\u6240\u6709\u5b9e\u4f53\u4ed3\u50a8\u7684\u57fa\u7c7b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IPrivateSqlRepository"),"\uff1a\u6240\u6709\u6570\u636e\u5e93\u64cd\u4f5c\u7684\u57fa\u7c7b")),(0,i.kt)("p",{parentName:"admonition"},"\u9664\u6b64\u4e4b\u540e\u7684\u6240\u6709\u4ed3\u50a8\u53ea\u80fd\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"rep.Constraint()")," \u8fdb\u884c\u7ea6\u675f\u521b\u5efa\uff0c\u5982\uff0c\u53ea\u8bfb\u4ed3\u50a8\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var readRepository = rep.Constraint>();\n"))),(0,i.kt)("h3",{id:"9421-\u975e\u6cdb\u578b\u8d85\u7ea7\u4ed3\u50a8"},"9.4.2.1 \u975e\u6cdb\u578b\u8d85\u7ea7\u4ed3\u50a8"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IRepository"),"\uff1a\u9ed8\u8ba4\u975e\u6cdb\u578b\u4ed3\u50a8\u63a5\u53e3\uff0c\u652f\u6301\u5207\u6362\u5230\u4efb\u4f55\u4ed3\u50a8"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"EFCoreRepository"),"\uff1a\u9ed8\u8ba4\u975e\u6cdb\u578b\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9422-\u6cdb\u578b\u5b9e\u4f53\u4ed3\u50a8"},"9.4.2.2 \u6cdb\u578b\u5b9e\u4f53\u4ed3\u50a8"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"EFCoreRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9423-\u6cdb\u578b\u591a\u6570\u636e\u5e93\u5b9e\u4f53\u4ed3\u50a8"},"9.4.2.3 \u6cdb\u578b\u591a\u6570\u636e\u5e93\u5b9e\u4f53\u4ed3\u50a8"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IRepository"),"\uff1a\u4efb\u610f\u6570\u636e\u5e93\u7684\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"EFCoreRepository"),"\uff1a\u4efb\u610f\u6570\u636e\u5e93\u7684\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9424-sql-\u64cd\u4f5c\u4ed3\u50a8"},"9.4.2.4 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9425-\u591a\u6570\u636e\u5e93-sql-\u64cd\u4f5c\u4ed3\u50a8"},"9.4.2.5 \u591a\u6570\u636e\u5e93 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlRepository"),"\uff1a\u4efb\u610f\u6570\u636e\u5e93\u7684 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlRepository"),"\uff1a\u4efb\u610f\u6570\u636e\u5e93\u7684 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9426-\u53ea\u8bfb\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.6 \u53ea\u8bfb\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IReadableRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u8bfb\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IReadableRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u8bfb\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9427-\u53ea\u5199\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.7 \u53ea\u5199\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IWritableRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u5199\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IWritableRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u5199\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9428-\u53ea\u5141\u8bb8\u65b0\u589e\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.8 \u53ea\u5141\u8bb8\u65b0\u589e\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IInsertableRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u65b0\u589e\u7684\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IInsertableRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u65b0\u589e\u7684\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9429-\u53ea\u5141\u8bb8\u66f4\u65b0\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.9 \u53ea\u5141\u8bb8\u66f4\u65b0\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IUpdateableRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u66f4\u65b0\u7684\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IUpdateableRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u66f4\u65b0\u7684\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"94210-\u53ea\u5141\u8bb8\u5220\u9664\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.10 \u53ea\u5141\u8bb8\u5220\u9664\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IDeletableRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u5220\u9664\u7684\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IDeletableRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u5220\u9664\u7684\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"94211-\u53ea\u5141\u8bb8\u62d3\u5c55\u64cd\u4f5c\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.11 \u53ea\u5141\u8bb8\u62d3\u5c55\u64cd\u4f5c\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("admonition",{title:"\u529f\u80fd\u79fb\u9664\u58f0\u660e",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"\u8be5\u529f\u80fd\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 2.5.1 +")," \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002\u6b64\u64cd\u4f5c\u8ba9\u5f88\u591a\u4e0d\u4e86\u89e3 ",(0,i.kt)("inlineCode",{parentName:"p"},"EFCore")," \u7684\u5f00\u53d1\u8005\u4ea7\u751f\u4e86\u5f88\u5927\u7684\u8bef\u89e3\uff0c\u4e0d\u77e5\u4f55\u65f6\u65b0\u589e\u6216\u4f55\u65f6\u66f4\u65b0\uff0c\u6545\u79fb\u9664\u6b64\u529f\u80fd\u3002")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IOperableRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u62d3\u5c55\u64cd\u4f5c\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IOperableRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u62d3\u5c55\u64cd\u4f5c\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"94212-\u53ea\u5141\u8bb8-sql-\u67e5\u8be2\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.12 \u53ea\u5141\u8bb8 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Sql")," \u67e5\u8be2\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlReaderRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u5141\u8bb8 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u67e5\u8be2\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlReaderRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u5141\u8bb8 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u67e5\u8be2\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"94213-\u53ea\u5141\u8bb8-sql-\u975e\u67e5\u8be2\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.13 \u53ea\u5141\u8bb8 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Sql")," \u975e\u67e5\u8be2\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlExecutableRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u5141\u8bb8 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u975e\u67e5\u8be2\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlExecutableRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u5141\u8bb8 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u975e\u67e5\u8be2\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"94214-\u8bfb\u5199\u5206\u79bb\u4ed3\u50a8"},"9.4.2.14 \u8bfb\u5199\u5206\u79bb\u4ed3\u50a8"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IMSRepository"),"\uff1a\u6700\u591a\u652f\u6301 ",(0,i.kt)("strong",{parentName:"li"},"\u4e00\u4e3b 7 \u4ece")," \u4ed3\u50a8")),(0,i.kt)("h3",{id:"94215-\u5b9a\u4f4d\u5668\u4ed3\u50a8"},"9.4.2.15 \u5b9a\u4f4d\u5668\u4ed3\u50a8"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IDbRepository"),"\uff1a\u521d\u59cb\u5316\u7279\u5b9a\u6570\u636e\u5e93\u4ed3\u50a8")),(0,i.kt)("h2",{id:"943-\u4ed3\u50a8\u4f7f\u7528"},"9.4.3 \u4ed3\u50a8\u4f7f\u7528"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u975e\u5e38\u591a\u7684\u65b9\u5f0f\u521b\u5efa\u4ed3\u50a8\uff0c\u76ee\u7684\u662f\u4e3a\u4e86\u8ba9\u5927\u5bb6\u53ef\u4ee5\u5728\u4e0d\u540c\u7684\u573a\u666f\u4e2d\u4f7f\u7528\u3002"),(0,i.kt)("h3",{id:"9431-\u6784\u9020\u51fd\u6570\u6ce8\u5165"},"9.4.3.1 \u6784\u9020\u51fd\u6570\u6ce8\u5165"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},"private readonly IRepository _personRepository;\npublic FurionService(IRepository personRepository)\n{\n _personRepository = personRepository;\n}\n")),(0,i.kt)("h3",{id:"9432-\u65b9\u6cd5\u53c2\u6570\u6ce8\u5165"},"9.4.3.2 \u65b9\u6cd5\u53c2\u6570\u6ce8\u5165"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"public async Task> GetAll([FromServices] IRepository repository, string keyword)\n{\n var persons = await repository.AsQueryable().ToListAsync();\n return persons.Adapt>();\n}\n")),(0,i.kt)("h3",{id:"9433-dbgetrepository-\u83b7\u53d6"},"9.4.3.3 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Db.GetRepository")," \u83b7\u53d6"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u975e\u6cdb\u578b\u4ed3\u50a8\nvar repository = Db.GetRepository();\n\n// \u6cdb\u578b\u4ed3\u50a8\nvar repository = Db.GetRepository();\n\n// Sql \u4ed3\u50a8\nvar sqlRepository = Db.GetSqlRepository();\n")),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u4e0d\u7ba1\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u90fd\u4fdd\u8bc1\u4e86\u4ed3\u50a8\u4e00\u6b21\u8bf7\u6c42\u552f\u4e00\u6027\u3002\u540c\u65f6 ",(0,i.kt)("inlineCode",{parentName:"p"},"Db.GetRepository()")," \u65b9\u5f0f\u652f\u6301\u4efb\u4f55\u9759\u6001\u7c7b\u4e2d\u4f7f\u7528\u3002")),(0,i.kt)("h2",{id:"944-\u4ed3\u50a8\u9ad8\u7ea7\u7528\u6cd5"},"9.4.4 \u4ed3\u50a8\u9ad8\u7ea7\u7528\u6cd5"),(0,i.kt)("h3",{id:"9441-\u52a8\u6001\u5207\u6362\u5b9e\u4f53\u4ed3\u50a8"},"9.4.4.1 \u52a8\u6001\u5207\u6362\u5b9e\u4f53\u4ed3\u50a8"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var userRepository = personRepository.Change();\n")),(0,i.kt)("h3",{id:"9442-\u52a8\u6001\u5207\u6362\u4ed3\u50a8\u7c7b\u578b"},"9.4.4.2 \u52a8\u6001\u5207\u6362\u4ed3\u50a8\u7c7b\u578b"),(0,i.kt)("p",null,"\u6bd4\u5982\uff0c\u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u5e93\u4ed3\u50a8\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u53ea\u8bfb\u4ed3\u50a8\nvar readRepository = personRepository.Constraint>();\n\n// \u53ea\u5199\u4ed3\u50a8\nvar writeRepository = personRepository.Constraint>();\n")),(0,i.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},".Constraint")," \u652f\u6301\u5207\u6362\u4efb\u4f55\u4ed3\u50a8\u7c7b\u578b\u3002")),(0,i.kt)("h3",{id:"9443-\u83b7\u53d6-sql-\u64cd\u4f5c\u4ed3\u50a8"},"9.4.4.3 \u83b7\u53d6 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var sqlRepository = repository.Sql();\n")),(0,i.kt)("h2",{id:"945-\u591a\u6570\u636e\u5e93\u64cd\u4f5c"},"9.4.5 \u591a\u6570\u636e\u5e93\u64cd\u4f5c"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"DbContextLocator")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u5b9e\u73b0\u591a\u79cd\u6570\u636e\u5e93\u64cd\u4f5c\uff0c\u53ef\u4ee5\u968f\u610f\u5207\u6362\u6570\u636e\u5e93"),(0,i.kt)("h3",{id:"9451-\u52a8\u6001\u5207\u6362\u591a\u4e2a\u6570\u636e\u5e93"},"9.4.5.1 \u52a8\u6001\u5207\u6362\u591a\u4e2a\u6570\u636e\u5e93"),(0,i.kt)("h4",{id:"\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93"},"\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u5207\u6362\u5230 MSSQL \u64cd\u4f5c Person\u8868\nvar mssqlRepository = repository.Change();\n\n// \u5207\u6362\u5230 MySql \u64cd\u4f5c Person\u8868\nvar mysqlRepository = repository.Change();\n\n// \u5207\u6362\u5230 Sqlite \u64cd\u4f5c Person\u8868\nvar sqliteRepository = repository.Change();\n\n// \u5176\u4ed6\u66f4\u591a\u6570\u636e\u5e93\u4e00\u6837\u7684\u64cd\u4f5c\n")),(0,i.kt)("h4",{id:"\u53e6\u5916\u4efb\u4f55\u4ed3\u50a8\u6216\u5b9e\u4f53\u914d\u7f6e\u90fd\u652f\u6301\u591a\u4e2a\u6570\u636e\u5e93\u540c\u65f6\u64cd\u4f5c"},"\u53e6\u5916\u4efb\u4f55\u4ed3\u50a8\u6216\u5b9e\u4f53\u914d\u7f6e\u90fd\u652f\u6301\u591a\u4e2a\u6570\u636e\u5e93\u540c\u65f6\u64cd\u4f5c"),(0,i.kt)("p",null,"\u4ed3\u50a8\u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"IRepository mssqlRepository\n\nISqlRepository mssqlRepository;\n")),(0,i.kt)("p",null,"\u52a8\u6001 ",(0,i.kt)("inlineCode",{parentName:"p"},"sql")," \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'"select * from person".Change().SqlQuery();\n')),(0,i.kt)("p",null,"\u5b9e\u4f53\u914d\u7f6e\u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public class User:Entity\n{\n}\n")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[SqlFunction("funcName", DbContextLocator = typeof(MySqlDbContextLocator))]\nint GetAge(int id);\n')),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Linq")," \u4e2d\u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[QueryableFunction("funcName","dbo", DbContextLocator = typeof(MySqlDbContextLocator))]\nstring GetName()=> throw Oops.Oh("\u4e0d\u652f\u6301\u8be5\u6570\u636e\u5e93\u64cd\u4f5c");\n')),(0,i.kt)("h2",{id:"946-\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528"},"9.4.6 \u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528"),(0,i.kt)("p",null,"\u7531\u4e8e ",(0,i.kt)("inlineCode",{parentName:"p"},"DbContext")," \u9ed8\u8ba4\u6ce8\u518c\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"Scoped")," \u751f\u5b58\u5468\u671f\uff0c\u6240\u4ee5\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"IServiceScopeFactory")," \u83b7\u53d6\u6240\u6709\u670d\u52a1\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public class JobService : BackgroundService\n{\n // \u65e5\u5fd7\u5bf9\u8c61\n private readonly ILogger _logger;\n\n // \u670d\u52a1\u5de5\u5382\n private readonly IServiceScopeFactory _scopeFactory;\n public JobService(ILogger logger\n , IServiceScopeFactory scopeFactory)\n {\n _logger = logger;\n _scopeFactory = scopeFactory;\n }\n\n protected override Task ExecuteAsync(CancellationToken stoppingToken)\n {\n _logger.LogInformation("\u5199\u65e5\u5fd7~~");\n\n using (var scope = _scopeFactory.CreateScope())\n {\n var services = scope.ServiceProvider;\n\n // \u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n var dbContext = Db.GetDbContext(services);\n\n // \u83b7\u53d6\u4ed3\u50a8\n var respository = Db.GetRepository(services);\n\n // \u89e3\u6790\u5176\u4ed6\u670d\u52a1\n var otherService = services.GetService();\n }\n\n return Task.CompletedTask;\n }\n}\n')),(0,i.kt)("admonition",{title:"\u6570\u636e\u5e93\u64cd\u4f5c\u6ce8\u610f",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f5c\u7528\u57df\u4e2d\u5bf9",(0,i.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u6709\u4efb\u4f55\u53d8\u66f4\u64cd\u4f5c"),"\uff0c\u9700\u624b\u52a8\u8c03\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216\u5e26 ",(0,i.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u65b9\u6cd5\u3002\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Scoped.CreateUow(handler)")," \u4ee3\u66ff\u3002")),(0,i.kt)("h2",{id:"947-\u81ea\u5b9a\u4e49\u4ed3\u50a8"},"9.4.7 \u81ea\u5b9a\u4e49\u4ed3\u50a8"),(0,i.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u9700\u8981\u81ea\u5b9a\u4e49\u4ed3\u50a8\uff0c\u62d3\u5c55\u73b0\u6709\u7684\u4ed3\u50a8\u529f\u80fd\uff0c\u53ef\u53c2\u8003\u4ee5\u4e0b\u4ee3\u7801\uff08\u542b\u5b9a\u4f4d\u5668\u4ed3\u50a8\u548c\u9ed8\u8ba4\u4ed3\u50a8\u5b9e\u73b0\uff09"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'/// \n/// \u81ea\u5b9a\u4e49\u4ed3\u50a8\u63a5\u53e3\n/// \n/// \n/// \npublic interface IMyRepository : IPrivateRepository\n where TEntity : class, IPrivateEntity, new()\n where TDbContextLocator : class, IDbContextLocator\n{\n /// \n /// \u81ea\u5b9a\u4e49\u65b9\u6cd5\n /// \n void MyMethod();\n}\n\n/// \n/// \u81ea\u5b9a\u4e49\u4ed3\u50a8\u5b9e\u73b0\u7c7b\n/// \n/// \n/// \npublic class MyRepository : PrivateRepository, IMyRepository, IScoped\n where TEntity : class, IPrivateEntity, new()\n where TDbContextLocator : class, IDbContextLocator\n{\n /// \n /// \u5b9e\u73b0\u57fa\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public MyRepository(IServiceProvider serviceProvider)\n : base(typeof(TDbContextLocator), serviceProvider)\n {\n }\n\n /// \n /// \u81ea\u5b9a\u4e49\u65b9\u6cd5\n /// \n public void MyMethod()\n {\n throw new System.NotImplementedException();\n }\n}\n\n/// \n/// \u9ed8\u8ba4\u6570\u636e\u5e93\u81ea\u5b9a\u4e49\u4ed3\u50a8\u63a5\u53e3\n/// \n/// \npublic interface IMyRepository : IMyRepository\n where TEntity : class, IPrivateEntity, new()\n{\n}\n\n/// \n/// \u9ed8\u8ba4\u6570\u636e\u5e93\u81ea\u5b9a\u4e49\u4ed3\u50a8\u5b9e\u73b0\n/// \n/// \npublic class MyRepository : MyRepository, IMyRepository, IScoped\n where TEntity : class, IPrivateEntity, new()\n{\n public MyRepository(IServiceProvider serviceProvider) : base(serviceProvider)\n {\n }\n}\n')),(0,i.kt)("h2",{id:"948-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.4.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}d.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return m},kt:function(){return d}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=r.createContext({}),s=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},m=function(e){var t=s(e.components);return r.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},c=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,p=e.parentName,m=l(e,["components","mdxType","originalType","parentName"]),c=s(n),d=o,y=c["".concat(p,".").concat(d)]||c[d]||u[d]||i;return n?r.createElement(y,a(a({ref:t},m),{},{components:n})):r.createElement(y,a({ref:t},m))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=c;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var s=2;s=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=r.createContext({}),s=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},m=function(e){var t=s(e.components);return r.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},c=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,p=e.parentName,m=l(e,["components","mdxType","originalType","parentName"]),c=s(n),d=o,y=c["".concat(p,".").concat(d)]||c[d]||u[d]||i;return n?r.createElement(y,a(a({ref:t},m),{},{components:n})):r.createElement(y,a({ref:t},m))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=c;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var s=2;sSql \u64cd\u4f5c\u4ed3\u50a8",id:"9424-sql-\u64cd\u4f5c\u4ed3\u50a8",level:3},{value:"9.4.2.5 \u591a\u6570\u636e\u5e93 Sql \u64cd\u4f5c\u4ed3\u50a8",id:"9425-\u591a\u6570\u636e\u5e93-sql-\u64cd\u4f5c\u4ed3\u50a8",level:3},{value:"9.4.2.6 \u53ea\u8bfb\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"9426-\u53ea\u8bfb\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.7 \u53ea\u5199\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"9427-\u53ea\u5199\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.8 \u53ea\u5141\u8bb8\u65b0\u589e\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"9428-\u53ea\u5141\u8bb8\u65b0\u589e\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.9 \u53ea\u5141\u8bb8\u66f4\u65b0\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"9429-\u53ea\u5141\u8bb8\u66f4\u65b0\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.10 \u53ea\u5141\u8bb8\u5220\u9664\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"94210-\u53ea\u5141\u8bb8\u5220\u9664\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.11 \u53ea\u5141\u8bb8\u62d3\u5c55\u64cd\u4f5c\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"94211-\u53ea\u5141\u8bb8\u62d3\u5c55\u64cd\u4f5c\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.12 \u53ea\u5141\u8bb8 Sql \u67e5\u8be2\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"94212-\u53ea\u5141\u8bb8-sql-\u67e5\u8be2\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.13 \u53ea\u5141\u8bb8 Sql \u975e\u67e5\u8be2\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09",id:"94213-\u53ea\u5141\u8bb8-sql-\u975e\u67e5\u8be2\u4ed3\u50a8\u652f\u6301\u591a\u5e93",level:3},{value:"9.4.2.14 \u8bfb\u5199\u5206\u79bb\u4ed3\u50a8",id:"94214-\u8bfb\u5199\u5206\u79bb\u4ed3\u50a8",level:3},{value:"9.4.2.15 \u5b9a\u4f4d\u5668\u4ed3\u50a8",id:"94215-\u5b9a\u4f4d\u5668\u4ed3\u50a8",level:3},{value:"9.4.3 \u4ed3\u50a8\u4f7f\u7528",id:"943-\u4ed3\u50a8\u4f7f\u7528",level:2},{value:"9.4.3.1 \u6784\u9020\u51fd\u6570\u6ce8\u5165",id:"9431-\u6784\u9020\u51fd\u6570\u6ce8\u5165",level:3},{value:"9.4.3.2 \u65b9\u6cd5\u53c2\u6570\u6ce8\u5165",id:"9432-\u65b9\u6cd5\u53c2\u6570\u6ce8\u5165",level:3},{value:"9.4.3.3 Db.GetRepository \u83b7\u53d6",id:"9433-dbgetrepository-\u83b7\u53d6",level:3},{value:"9.4.4 \u4ed3\u50a8\u9ad8\u7ea7\u7528\u6cd5",id:"944-\u4ed3\u50a8\u9ad8\u7ea7\u7528\u6cd5",level:2},{value:"9.4.4.1 \u52a8\u6001\u5207\u6362\u5b9e\u4f53\u4ed3\u50a8",id:"9441-\u52a8\u6001\u5207\u6362\u5b9e\u4f53\u4ed3\u50a8",level:3},{value:"9.4.4.2 \u52a8\u6001\u5207\u6362\u4ed3\u50a8\u7c7b\u578b",id:"9442-\u52a8\u6001\u5207\u6362\u4ed3\u50a8\u7c7b\u578b",level:3},{value:"9.4.4.3 \u83b7\u53d6 Sql \u64cd\u4f5c\u4ed3\u50a8",id:"9443-\u83b7\u53d6-sql-\u64cd\u4f5c\u4ed3\u50a8",level:3},{value:"9.4.5 \u591a\u6570\u636e\u5e93\u64cd\u4f5c",id:"945-\u591a\u6570\u636e\u5e93\u64cd\u4f5c",level:2},{value:"9.4.5.1 \u52a8\u6001\u5207\u6362\u591a\u4e2a\u6570\u636e\u5e93",id:"9451-\u52a8\u6001\u5207\u6362\u591a\u4e2a\u6570\u636e\u5e93",level:3},{value:"\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93",id:"\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93",level:4},{value:"\u53e6\u5916\u4efb\u4f55\u4ed3\u50a8\u6216\u5b9e\u4f53\u914d\u7f6e\u90fd\u652f\u6301\u591a\u4e2a\u6570\u636e\u5e93\u540c\u65f6\u64cd\u4f5c",id:"\u53e6\u5916\u4efb\u4f55\u4ed3\u50a8\u6216\u5b9e\u4f53\u914d\u7f6e\u90fd\u652f\u6301\u591a\u4e2a\u6570\u636e\u5e93\u540c\u65f6\u64cd\u4f5c",level:4},{value:"9.4.6 \u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528",id:"946-\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528",level:2},{value:"9.4.7 \u81ea\u5b9a\u4e49\u4ed3\u50a8",id:"947-\u81ea\u5b9a\u4e49\u4ed3\u50a8",level:2},{value:"9.4.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"948-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:u};function d(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"941-\u4ec0\u4e48\u662f\u4ed3\u50a8"},"9.4.1 \u4ec0\u4e48\u662f\u4ed3\u50a8"),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u5728\u9886\u57df\u5c42\u548c\u6570\u636e\u6620\u5c04\u5c42\u7684\u4e2d\u4ecb,\u4f7f\u7528\u7c7b\u4f3c\u96c6\u5408\u7684\u63a5\u53e3\u6765\u5b58\u53d6\u9886\u57df\u5bf9\u8c61\uff0c\u5b9e\u9645\u4e0a\uff0c\u4ed3\u50a8\u88ab\u7528\u4e8e\u9886\u57df\u5bf9\u8c61\u5728\u6570\u636e\u5e93\u4e0a\u7684\u64cd\u4f5c\uff08\u5b9e\u4f53 Entity \u548c\u503c\u5bf9\u8c61 Value types\uff09\u3002\u4e00\u822c\u6765\u8bf4,\u6211\u4eec\u9488\u5bf9\u4e0d\u540c\u7684\u5b9e\u4f53(\u6216\u805a\u5408\u6839 Aggregate Root)\u4f1a\u521b\u5efa\u76f8\u5bf9\u5e94\u7684\u4ed3\u50a8\u3002")),(0,i.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u4ed3\u50a8\u5c31\u662f\u6570\u636e\u5b58\u53d6\u64cd\u4f5c\u7684\u8f7d\u4f53\uff0c\u4f46\u4e0d\u9650\u5b9a\u4e8e\u6570\u636e\u5e93\u3002"),(0,i.kt)("h2",{id:"942-\u5185\u7f6e\u4ed3\u50a8"},"9.4.2 \u5185\u7f6e\u4ed3\u50a8"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u5185\u7f6e\u4e86\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u7684\u4ed3\u50a8\uff0c\u65b9\u4fbf\u5927\u5bb6\u62d3\u5c55\u548c\u96c6\u6210\uff1a"),(0,i.kt)("admonition",{title:"\u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165\u8bf4\u660e",type:"info"},(0,i.kt)("p",{parentName:"admonition"},"\u76ee\u524d\u80fd\u591f\u88ab\u4f9d\u8d56\u6ce8\u5165\u89e3\u6790\u670d\u52a1\u7684\u4ed3\u50a8\u6709\uff1a"),(0,i.kt)("ul",{parentName:"admonition"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IMSRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IMSRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IMSRepository")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IDbRepository"))),(0,i.kt)("p",{parentName:"admonition"},"\u8fd8\u6709\u4e24\u4e2a\u79c1\u6709\u4ed3\u50a8\uff0c\u4e5f\u662f\u6240\u6709\u4ed3\u50a8\u7684\u57fa\u7c7b\uff08\u7528\u4e8e\u9ad8\u7ea7\u81ea\u5b9a\u4e49\u5f00\u53d1\uff09"),(0,i.kt)("ul",{parentName:"admonition"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IPrivateRepository"),"\uff1a\u6240\u6709\u5b9e\u4f53\u4ed3\u50a8\u7684\u57fa\u7c7b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IPrivateSqlRepository"),"\uff1a\u6240\u6709\u6570\u636e\u5e93\u64cd\u4f5c\u7684\u57fa\u7c7b")),(0,i.kt)("p",{parentName:"admonition"},"\u9664\u6b64\u4e4b\u540e\u7684\u6240\u6709\u4ed3\u50a8\u53ea\u80fd\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"rep.Constraint()")," \u8fdb\u884c\u7ea6\u675f\u521b\u5efa\uff0c\u5982\uff0c\u53ea\u8bfb\u4ed3\u50a8\uff1a"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var readRepository = rep.Constraint>();\n"))),(0,i.kt)("h3",{id:"9421-\u975e\u6cdb\u578b\u8d85\u7ea7\u4ed3\u50a8"},"9.4.2.1 \u975e\u6cdb\u578b\u8d85\u7ea7\u4ed3\u50a8"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IRepository"),"\uff1a\u9ed8\u8ba4\u975e\u6cdb\u578b\u4ed3\u50a8\u63a5\u53e3\uff0c\u652f\u6301\u5207\u6362\u5230\u4efb\u4f55\u4ed3\u50a8"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"EFCoreRepository"),"\uff1a\u9ed8\u8ba4\u975e\u6cdb\u578b\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9422-\u6cdb\u578b\u5b9e\u4f53\u4ed3\u50a8"},"9.4.2.2 \u6cdb\u578b\u5b9e\u4f53\u4ed3\u50a8"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"EFCoreRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9423-\u6cdb\u578b\u591a\u6570\u636e\u5e93\u5b9e\u4f53\u4ed3\u50a8"},"9.4.2.3 \u6cdb\u578b\u591a\u6570\u636e\u5e93\u5b9e\u4f53\u4ed3\u50a8"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IRepository"),"\uff1a\u4efb\u610f\u6570\u636e\u5e93\u7684\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"EFCoreRepository"),"\uff1a\u4efb\u610f\u6570\u636e\u5e93\u7684\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9424-sql-\u64cd\u4f5c\u4ed3\u50a8"},"9.4.2.4 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9425-\u591a\u6570\u636e\u5e93-sql-\u64cd\u4f5c\u4ed3\u50a8"},"9.4.2.5 \u591a\u6570\u636e\u5e93 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlRepository"),"\uff1a\u4efb\u610f\u6570\u636e\u5e93\u7684 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlRepository"),"\uff1a\u4efb\u610f\u6570\u636e\u5e93\u7684 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9426-\u53ea\u8bfb\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.6 \u53ea\u8bfb\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IReadableRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u8bfb\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IReadableRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u8bfb\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9427-\u53ea\u5199\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.7 \u53ea\u5199\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IWritableRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u5199\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IWritableRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u5199\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9428-\u53ea\u5141\u8bb8\u65b0\u589e\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.8 \u53ea\u5141\u8bb8\u65b0\u589e\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IInsertableRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u65b0\u589e\u7684\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IInsertableRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u65b0\u589e\u7684\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"9429-\u53ea\u5141\u8bb8\u66f4\u65b0\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.9 \u53ea\u5141\u8bb8\u66f4\u65b0\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IUpdateableRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u66f4\u65b0\u7684\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IUpdateableRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u66f4\u65b0\u7684\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"94210-\u53ea\u5141\u8bb8\u5220\u9664\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.10 \u53ea\u5141\u8bb8\u5220\u9664\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IDeletableRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u5220\u9664\u7684\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IDeletableRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u5220\u9664\u7684\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"94211-\u53ea\u5141\u8bb8\u62d3\u5c55\u64cd\u4f5c\u5b9e\u4f53\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.11 \u53ea\u5141\u8bb8\u62d3\u5c55\u64cd\u4f5c\u5b9e\u4f53\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("admonition",{title:"\u529f\u80fd\u79fb\u9664\u58f0\u660e",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"\u8be5\u529f\u80fd\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 2.5.1 +")," \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002\u6b64\u64cd\u4f5c\u8ba9\u5f88\u591a\u4e0d\u4e86\u89e3 ",(0,i.kt)("inlineCode",{parentName:"p"},"EFCore")," \u7684\u5f00\u53d1\u8005\u4ea7\u751f\u4e86\u5f88\u5927\u7684\u8bef\u89e3\uff0c\u4e0d\u77e5\u4f55\u65f6\u65b0\u589e\u6216\u4f55\u65f6\u66f4\u65b0\uff0c\u6545\u79fb\u9664\u6b64\u529f\u80fd\u3002")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IOperableRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u62d3\u5c55\u64cd\u4f5c\u5b9e\u4f53\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IOperableRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u5141\u8bb8\u62d3\u5c55\u64cd\u4f5c\u5b9e\u4f53\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"94212-\u53ea\u5141\u8bb8-sql-\u67e5\u8be2\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.12 \u53ea\u5141\u8bb8 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Sql")," \u67e5\u8be2\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlReaderRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u5141\u8bb8 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u67e5\u8be2\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlReaderRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u5141\u8bb8 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u67e5\u8be2\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"94213-\u53ea\u5141\u8bb8-sql-\u975e\u67e5\u8be2\u4ed3\u50a8\u652f\u6301\u591a\u5e93"},"9.4.2.13 \u53ea\u5141\u8bb8 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Sql")," \u975e\u67e5\u8be2\u4ed3\u50a8\uff08\u652f\u6301\u591a\u5e93\uff09"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlExecutableRepository"),"\uff1a\u9ed8\u8ba4\u6570\u636e\u5e93\u53ea\u5141\u8bb8 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u975e\u67e5\u8be2\u4ed3\u50a8\u63a5\u53e3"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ISqlExecutableRepository"),"\uff1a\u591a\u6570\u636e\u5e93\u53ea\u5141\u8bb8 ",(0,i.kt)("inlineCode",{parentName:"li"},"Sql")," \u975e\u67e5\u8be2\u4ed3\u50a8\u5b9e\u73b0")),(0,i.kt)("h3",{id:"94214-\u8bfb\u5199\u5206\u79bb\u4ed3\u50a8"},"9.4.2.14 \u8bfb\u5199\u5206\u79bb\u4ed3\u50a8"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IMSRepository"),"\uff1a\u6700\u591a\u652f\u6301 ",(0,i.kt)("strong",{parentName:"li"},"\u4e00\u4e3b 7 \u4ece")," \u4ed3\u50a8")),(0,i.kt)("h3",{id:"94215-\u5b9a\u4f4d\u5668\u4ed3\u50a8"},"9.4.2.15 \u5b9a\u4f4d\u5668\u4ed3\u50a8"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"IDbRepository"),"\uff1a\u521d\u59cb\u5316\u7279\u5b9a\u6570\u636e\u5e93\u4ed3\u50a8")),(0,i.kt)("h2",{id:"943-\u4ed3\u50a8\u4f7f\u7528"},"9.4.3 \u4ed3\u50a8\u4f7f\u7528"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u975e\u5e38\u591a\u7684\u65b9\u5f0f\u521b\u5efa\u4ed3\u50a8\uff0c\u76ee\u7684\u662f\u4e3a\u4e86\u8ba9\u5927\u5bb6\u53ef\u4ee5\u5728\u4e0d\u540c\u7684\u573a\u666f\u4e2d\u4f7f\u7528\u3002"),(0,i.kt)("h3",{id:"9431-\u6784\u9020\u51fd\u6570\u6ce8\u5165"},"9.4.3.1 \u6784\u9020\u51fd\u6570\u6ce8\u5165"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},"private readonly IRepository _personRepository;\npublic FurionService(IRepository personRepository)\n{\n _personRepository = personRepository;\n}\n")),(0,i.kt)("h3",{id:"9432-\u65b9\u6cd5\u53c2\u6570\u6ce8\u5165"},"9.4.3.2 \u65b9\u6cd5\u53c2\u6570\u6ce8\u5165"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"public async Task> GetAll([FromServices] IRepository repository, string keyword)\n{\n var persons = await repository.AsQueryable().ToListAsync();\n return persons.Adapt>();\n}\n")),(0,i.kt)("h3",{id:"9433-dbgetrepository-\u83b7\u53d6"},"9.4.3.3 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Db.GetRepository")," \u83b7\u53d6"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u975e\u6cdb\u578b\u4ed3\u50a8\nvar repository = Db.GetRepository();\n\n// \u6cdb\u578b\u4ed3\u50a8\nvar repository = Db.GetRepository();\n\n// Sql \u4ed3\u50a8\nvar sqlRepository = Db.GetSqlRepository();\n")),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u4e0d\u7ba1\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u90fd\u4fdd\u8bc1\u4e86\u4ed3\u50a8\u4e00\u6b21\u8bf7\u6c42\u552f\u4e00\u6027\u3002\u540c\u65f6 ",(0,i.kt)("inlineCode",{parentName:"p"},"Db.GetRepository()")," \u65b9\u5f0f\u652f\u6301\u4efb\u4f55\u9759\u6001\u7c7b\u4e2d\u4f7f\u7528\u3002")),(0,i.kt)("h2",{id:"944-\u4ed3\u50a8\u9ad8\u7ea7\u7528\u6cd5"},"9.4.4 \u4ed3\u50a8\u9ad8\u7ea7\u7528\u6cd5"),(0,i.kt)("h3",{id:"9441-\u52a8\u6001\u5207\u6362\u5b9e\u4f53\u4ed3\u50a8"},"9.4.4.1 \u52a8\u6001\u5207\u6362\u5b9e\u4f53\u4ed3\u50a8"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var userRepository = personRepository.Change();\n")),(0,i.kt)("h3",{id:"9442-\u52a8\u6001\u5207\u6362\u4ed3\u50a8\u7c7b\u578b"},"9.4.4.2 \u52a8\u6001\u5207\u6362\u4ed3\u50a8\u7c7b\u578b"),(0,i.kt)("p",null,"\u6bd4\u5982\uff0c\u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u5e93\u4ed3\u50a8\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u53ea\u8bfb\u4ed3\u50a8\nvar readRepository = personRepository.Constraint>();\n\n// \u53ea\u5199\u4ed3\u50a8\nvar writeRepository = personRepository.Constraint>();\n")),(0,i.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},".Constraint")," \u652f\u6301\u5207\u6362\u4efb\u4f55\u4ed3\u50a8\u7c7b\u578b\u3002")),(0,i.kt)("h3",{id:"9443-\u83b7\u53d6-sql-\u64cd\u4f5c\u4ed3\u50a8"},"9.4.4.3 \u83b7\u53d6 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var sqlRepository = repository.Sql();\n")),(0,i.kt)("h2",{id:"945-\u591a\u6570\u636e\u5e93\u64cd\u4f5c"},"9.4.5 \u591a\u6570\u636e\u5e93\u64cd\u4f5c"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"DbContextLocator")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u5b9e\u73b0\u591a\u79cd\u6570\u636e\u5e93\u64cd\u4f5c\uff0c\u53ef\u4ee5\u968f\u610f\u5207\u6362\u6570\u636e\u5e93"),(0,i.kt)("h3",{id:"9451-\u52a8\u6001\u5207\u6362\u591a\u4e2a\u6570\u636e\u5e93"},"9.4.5.1 \u52a8\u6001\u5207\u6362\u591a\u4e2a\u6570\u636e\u5e93"),(0,i.kt)("h4",{id:"\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93"},"\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u5207\u6362\u5230 MSSQL \u64cd\u4f5c Person\u8868\nvar mssqlRepository = repository.Change();\n\n// \u5207\u6362\u5230 MySql \u64cd\u4f5c Person\u8868\nvar mysqlRepository = repository.Change();\n\n// \u5207\u6362\u5230 Sqlite \u64cd\u4f5c Person\u8868\nvar sqliteRepository = repository.Change();\n\n// \u5176\u4ed6\u66f4\u591a\u6570\u636e\u5e93\u4e00\u6837\u7684\u64cd\u4f5c\n")),(0,i.kt)("h4",{id:"\u53e6\u5916\u4efb\u4f55\u4ed3\u50a8\u6216\u5b9e\u4f53\u914d\u7f6e\u90fd\u652f\u6301\u591a\u4e2a\u6570\u636e\u5e93\u540c\u65f6\u64cd\u4f5c"},"\u53e6\u5916\u4efb\u4f55\u4ed3\u50a8\u6216\u5b9e\u4f53\u914d\u7f6e\u90fd\u652f\u6301\u591a\u4e2a\u6570\u636e\u5e93\u540c\u65f6\u64cd\u4f5c"),(0,i.kt)("p",null,"\u4ed3\u50a8\u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"IRepository mssqlRepository\n\nISqlRepository mssqlRepository;\n")),(0,i.kt)("p",null,"\u52a8\u6001 ",(0,i.kt)("inlineCode",{parentName:"p"},"sql")," \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'"select * from person".Change().SqlQuery();\n')),(0,i.kt)("p",null,"\u5b9e\u4f53\u914d\u7f6e\u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public class User:Entity\n{\n}\n")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Sql")," \u4ee3\u7406\u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[SqlFunction("funcName", DbContextLocator = typeof(MySqlDbContextLocator))]\nint GetAge(int id);\n')),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Linq")," \u4e2d\u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[QueryableFunction("funcName","dbo", DbContextLocator = typeof(MySqlDbContextLocator))]\nstring GetName()=> throw Oops.Oh("\u4e0d\u652f\u6301\u8be5\u6570\u636e\u5e93\u64cd\u4f5c");\n')),(0,i.kt)("h2",{id:"946-\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528"},"9.4.6 \u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528"),(0,i.kt)("p",null,"\u7531\u4e8e ",(0,i.kt)("inlineCode",{parentName:"p"},"DbContext")," \u9ed8\u8ba4\u6ce8\u518c\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"Scoped")," \u751f\u5b58\u5468\u671f\uff0c\u6240\u4ee5\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"IServiceScopeFactory")," \u83b7\u53d6\u6240\u6709\u670d\u52a1\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public class JobService : BackgroundService\n{\n // \u65e5\u5fd7\u5bf9\u8c61\n private readonly ILogger _logger;\n\n // \u670d\u52a1\u5de5\u5382\n private readonly IServiceScopeFactory _scopeFactory;\n public JobService(ILogger logger\n , IServiceScopeFactory scopeFactory)\n {\n _logger = logger;\n _scopeFactory = scopeFactory;\n }\n\n protected override Task ExecuteAsync(CancellationToken stoppingToken)\n {\n _logger.LogInformation("\u5199\u65e5\u5fd7~~");\n\n using (var scope = _scopeFactory.CreateScope())\n {\n var services = scope.ServiceProvider;\n\n // \u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n var dbContext = Db.GetDbContext(services);\n\n // \u83b7\u53d6\u4ed3\u50a8\n var respository = Db.GetRepository(services);\n\n // \u89e3\u6790\u5176\u4ed6\u670d\u52a1\n var otherService = services.GetService();\n }\n\n return Task.CompletedTask;\n }\n}\n')),(0,i.kt)("admonition",{title:"\u6570\u636e\u5e93\u64cd\u4f5c\u6ce8\u610f",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f5c\u7528\u57df\u4e2d\u5bf9",(0,i.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u6709\u4efb\u4f55\u53d8\u66f4\u64cd\u4f5c"),"\uff0c\u9700\u624b\u52a8\u8c03\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216\u5e26 ",(0,i.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u65b9\u6cd5\u3002\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Scoped.CreateUow(handler)")," \u4ee3\u66ff\u3002")),(0,i.kt)("h2",{id:"947-\u81ea\u5b9a\u4e49\u4ed3\u50a8"},"9.4.7 \u81ea\u5b9a\u4e49\u4ed3\u50a8"),(0,i.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u9700\u8981\u81ea\u5b9a\u4e49\u4ed3\u50a8\uff0c\u62d3\u5c55\u73b0\u6709\u7684\u4ed3\u50a8\u529f\u80fd\uff0c\u53ef\u53c2\u8003\u4ee5\u4e0b\u4ee3\u7801\uff08\u542b\u5b9a\u4f4d\u5668\u4ed3\u50a8\u548c\u9ed8\u8ba4\u4ed3\u50a8\u5b9e\u73b0\uff09"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'/// \n/// \u81ea\u5b9a\u4e49\u4ed3\u50a8\u63a5\u53e3\n/// \n/// \n/// \npublic interface IMyRepository : IPrivateRepository\n where TEntity : class, IPrivateEntity, new()\n where TDbContextLocator : class, IDbContextLocator\n{\n /// \n /// \u81ea\u5b9a\u4e49\u65b9\u6cd5\n /// \n void MyMethod();\n}\n\n/// \n/// \u81ea\u5b9a\u4e49\u4ed3\u50a8\u5b9e\u73b0\u7c7b\n/// \n/// \n/// \npublic class MyRepository : PrivateRepository, IMyRepository, IScoped\n where TEntity : class, IPrivateEntity, new()\n where TDbContextLocator : class, IDbContextLocator\n{\n /// \n /// \u5b9e\u73b0\u57fa\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public MyRepository(IServiceProvider serviceProvider)\n : base(typeof(TDbContextLocator), serviceProvider)\n {\n }\n\n /// \n /// \u81ea\u5b9a\u4e49\u65b9\u6cd5\n /// \n public void MyMethod()\n {\n throw new System.NotImplementedException();\n }\n}\n\n/// \n/// \u9ed8\u8ba4\u6570\u636e\u5e93\u81ea\u5b9a\u4e49\u4ed3\u50a8\u63a5\u53e3\n/// \n/// \npublic interface IMyRepository : IMyRepository\n where TEntity : class, IPrivateEntity, new()\n{\n}\n\n/// \n/// \u9ed8\u8ba4\u6570\u636e\u5e93\u81ea\u5b9a\u4e49\u4ed3\u50a8\u5b9e\u73b0\n/// \n/// \npublic class MyRepository : MyRepository, IMyRepository, IScoped\n where TEntity : class, IPrivateEntity, new()\n{\n public MyRepository(IServiceProvider serviceProvider) : base(serviceProvider)\n {\n }\n}\n')),(0,i.kt)("h2",{id:"948-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.4.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/afff7d91.d4ca715b.js b/handbook/build/assets/js/5b1379ef.a9febb22.js similarity index 34% rename from handbook/build/assets/js/afff7d91.d4ca715b.js rename to handbook/build/assets/js/5b1379ef.a9febb22.js index fcded5fe20..09c6cd6ad7 100644 --- a/handbook/build/assets/js/afff7d91.d4ca715b.js +++ b/handbook/build/assets/js/5b1379ef.a9febb22.js @@ -1 +1 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[746],{5745:function(u){u.exports=JSON.parse('{"name":"docusaurus-plugin-content-pages","id":"default"}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[1041],{1386:function(u){u.exports=JSON.parse('{"name":"docusaurus-plugin-content-pages","id":"default"}')}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/5edfa151.0fad3db0.js b/handbook/build/assets/js/5edfa151.0fad3db0.js deleted file mode 100644 index f571f868c4..0000000000 --- a/handbook/build/assets/js/5edfa151.0fad3db0.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[5809],{4457:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return s},default:function(){return m},frontMatter:function(){return l},metadata:function(){return p},toc:function(){return d}});var r=n(3117),a=n(102),i=(n(7294),n(3905)),o=["components"],l={id:"dbcontext-batch",title:"9.9 \u6279\u91cf\u64cd\u4f5c",sidebar_label:"9.9 \u6279\u91cf\u64cd\u4f5c"},s=void 0,p={unversionedId:"dbcontext-batch",id:"dbcontext-batch",title:"9.9 \u6279\u91cf\u64cd\u4f5c",description:"9.9.1 \u5173\u4e8e\u6279\u91cf\u64cd\u4f5c",source:"@site/docs/dbcontext-batch.mdx",sourceDirName:".",slug:"/dbcontext-batch",permalink:"/furion/docs/dbcontext-batch",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-batch.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1658810232,formattedLastUpdatedAt:"Jul 26, 2022",frontMatter:{id:"dbcontext-batch",title:"9.9 \u6279\u91cf\u64cd\u4f5c",sidebar_label:"9.9 \u6279\u91cf\u64cd\u4f5c"},sidebar:"docs",previous:{title:"9.8 \u5220\u9664\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-delete"},next:{title:"9.10 \u67e5\u8be2\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-query"}},c={},d=[{value:"9.9.1 \u5173\u4e8e\u6279\u91cf\u64cd\u4f5c",id:"991-\u5173\u4e8e\u6279\u91cf\u64cd\u4f5c",level:2},{value:"9.9.2 Zack.EFCore.Batch \u4f7f\u7528",id:"992-zackefcorebatch-\u4f7f\u7528",level:2},{value:"9.9.2.1 \u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93 Nuget \u5305",id:"9921-\u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93-nuget-\u5305",level:3},{value:"9.9.2.2 \u6ce8\u518c\u5e76\u914d\u7f6e\u670d\u52a1",id:"9922-\u6ce8\u518c\u5e76\u914d\u7f6e\u670d\u52a1",level:3},{value:"9.9.2.3 \u57fa\u672c\u4f7f\u7528",id:"9923-\u57fa\u672c\u4f7f\u7528",level:3},{value:"9.9.3 EFCore.BulkExtensions \u4f7f\u7528",id:"993-efcorebulkextensions-\u4f7f\u7528",level:2},{value:"9.9.3.1 \u5e38\u89c1\u6279\u91cf\u64cd\u4f5c",id:"9931-\u5e38\u89c1\u6279\u91cf\u64cd\u4f5c",level:3},{value:"9.9.3.2 \u67e5\u8be2\u540e\u6279\u91cf\u64cd\u4f5c",id:"9932-\u67e5\u8be2\u540e\u6279\u91cf\u64cd\u4f5c",level:3},{value:"9.9.3.3 \u6279\u91cf\u64cd\u4f5c\u6027\u80fd",id:"9933-\u6279\u91cf\u64cd\u4f5c\u6027\u80fd",level:3},{value:"9.9.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"994-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],u={toc:d};function m(e){var t=e.components,n=(0,a.Z)(e,o);return(0,i.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"991-\u5173\u4e8e\u6279\u91cf\u64cd\u4f5c"},"9.9.1 \u5173\u4e8e\u6279\u91cf\u64cd\u4f5c"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u53ea\u63d0\u4f9b\u5c0f\u6570\u636e\uff08100 \u6761 \u4ee5\u5185\uff09\u6279\u91cf\u6570\u636e\u64cd\u4f5c\uff0c\u5982\u679c\u9700\u8981\u66f4\u5927\u7684\u6570\u636e\u6279\u91cf\u5904\u7406\uff0c\u63a8\u8350\u4f7f\u7528\u7b2c\u4e09\u65b9\u5305 ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/yangzhongke/Zack.EFCore.Batch"},"Zack.EFCore.Batch"),"\uff0c\u652f\u6301\u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u65e0\u7f1d\u8854\u63a5\u3002"),(0,i.kt)("h2",{id:"992-zackefcorebatch-\u4f7f\u7528"},"9.9.2 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Zack.EFCore.Batch")," \u4f7f\u7528"),(0,i.kt)("h3",{id:"9921-\u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93-nuget-\u5305"},"9.9.2.1 \u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Nuget")," \u5305"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"MSSQL"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Zack.EFCore.Batch.MSSQL")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"MySql"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Zack.EFCore.Batch.MySQL.Pomelo")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Npgsql"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Zack.EFCore.Batch.Npgsql")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Oracle"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Zack.EFCore.Batch.Oracle")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Sqlite"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Zack.EFCore.Batch.Sqlite"))),(0,i.kt)("h3",{id:"9922-\u6ce8\u518c\u5e76\u914d\u7f6e\u670d\u52a1"},"9.9.2.2 \u6ce8\u518c\u5e76\u914d\u7f6e\u670d\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5}",showLineNumbers:!0,"":!0,"{3,5}":!0},"services.AddDatabaseAccessor(options =>\n{\n options.AddDbPool(providerName: default, optionBuilder: (services, opt) => // \u5982\u679c\u662f v3.7.11 \u4e4b\u524d\uff0c\u4f7f\u7528 opt =>\n {\n opt.UseBatchEF_Sqlite(); // SQlite \u6570\u636e\u5e93\u5305\n });\n});\n")),(0,i.kt)("h3",{id:"9923-\u57fa\u672c\u4f7f\u7528"},"9.9.2.3 \u57fa\u672c\u4f7f\u7528"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u6279\u91cf\u66f4\u65b0\nawait repository.Context.BatchUpdate()\n .Set(b => b.Price, b => b.Price + 3)\n .Set(b => b.Title, b => s)\n .Set(b => b.AuthorName,b=>b.Title.Substring(3,2)+b.AuthorName.ToUpper())\n .Set(b => b.PubTime, b => DateTime.Now)\n .Where(b => b.Id > n || b.AuthorName.StartsWith("Zack"))\n .ExecuteAsync();\n\n// \u6279\u91cf\u5220\u9664\nawait repository.Context.DeleteRangeAsync(b => b.Price > n || b.AuthorName == "zack yang");\n')),(0,i.kt)("h2",{id:"993-efcorebulkextensions-\u4f7f\u7528"},"9.9.3 ",(0,i.kt)("inlineCode",{parentName:"h2"},"EFCore.BulkExtensions")," \u4f7f\u7528"),(0,i.kt)("p",null,"\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},"EFCore.BulkExtensions")," \u5305\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"9931-\u5e38\u89c1\u6279\u91cf\u64cd\u4f5c"},"9.9.3.1 \u5e38\u89c1\u6279\u91cf\u64cd\u4f5c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u6279\u91cf\u63d2\u5165\nrepository.Context.BulkInsert(entitiesList);\nrepository.Context.BulkInsertAsync(entitiesList);\n\n// \u6279\u91cf\u66f4\u65b0\nrepository.Context.BulkUpdate(entitiesList);\nrepository.Context.BulkUpdateAsync(entitiesList);\n\n// \u6279\u91cf\u5220\u9664\nrepository.Context.BulkDelete(entitiesList);\nrepository.Context.BulkDeleteAsync(entitiesList);\n\n// \u6279\u91cf\u63d2\u5165\u6216\u66f4\u65b0\nrepository.Context.BulkInsertOrUpdate(entitiesList);\nrepository.Context.BulkInsertOrUpdateAsync(entitiesList);\n\n// \u6279\u91cf\u63d2\u5165\u6216\u66f4\u65b0\u6216\u5220\u9664\nrepository.Context.BulkInsertOrUpdateOrDelete(entitiesList);\nrepository.Context.BulkInsertOrUpdateOrDeleteAsync(entitiesList);\n\n// \u6279\u91cf\u8bfb\u53d6\u591a\u4e2a\u5b9e\u4f53\nrepository.Context.BulkRead(entitiesList);\nrepository.Context.BulkReadAsync(entitiesList);\n\n// \u6279\u91cf\u6e05\u7a7a\u8868\uff08\u614e\u7528\uff01\uff01\uff01\uff01\uff01\uff09\nrepository.Context.Truncate();\nrepository.Context.TruncateAsync();\n")),(0,i.kt)("h3",{id:"9932-\u67e5\u8be2\u540e\u6279\u91cf\u64cd\u4f5c"},"9.9.3.2 \u67e5\u8be2\u540e\u6279\u91cf\u64cd\u4f5c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u6839\u636e\u6761\u4ef6\u6279\u91cf\u5220\u9664\nrepository.Where(a => a.ItemId > 500).BatchDelete();\nawait repository.Where(a => a.ItemId > 500).BatchDeleteAsync();\n\n// \u6839\u636e\u6761\u4ef6\u6279\u91cf\u66f4\u65b0\nrepository.Where(a => a.ItemId <= 500).BatchUpdate(a => new Item { Quantity = a.Quantity + 100 });\nrepository.Where(a => a.ItemId <= 500).BatchUpdate(new Item { Description = "Updated" });\nawait repository.Where(a => a.ItemId <= 500).BatchUpdateAsync(new Item { Description = "Updated" });\n\n// \u6279\u91cf\u66f4\u65b0\u6307\u5b9a\u5217\nvar updateColumns = new List { nameof(Item.Quantity) };\nvar q = repository.Where(a => a.ItemId <= 500);\nint affected = q.BatchUpdate(new Item { Description = "Updated" }, updateColumns);\n')),(0,i.kt)("h3",{id:"9933-\u6279\u91cf\u64cd\u4f5c\u6027\u80fd"},"9.9.3.3 \u6279\u91cf\u64cd\u4f5c\u6027\u80fd"),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"Operations\\Rows"),(0,i.kt)("th",{parentName:"tr",align:"right"},"100,000 EF"),(0,i.kt)("th",{parentName:"tr",align:"right"},"100,000 EFBulk"),(0,i.kt)("th",{parentName:"tr",align:"right"},"1,000,000 EFBulk"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"Insert"),(0,i.kt)("td",{parentName:"tr",align:"right"},"38.98 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"2.10 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"17.99 s")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"Update"),(0,i.kt)("td",{parentName:"tr",align:"right"},"109.25 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"3.96 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"31.45 s")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"Delete"),(0,i.kt)("td",{parentName:"tr",align:"right"},"7.26 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"2.04 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"12.18 s")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"-----------------"),(0,i.kt)("td",{parentName:"tr",align:"right"},"------------"),(0,i.kt)("td",{parentName:"tr",align:"right"},"----------------"),(0,i.kt)("td",{parentName:"tr",align:"right"},"------------------")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("strong",{parentName:"td"},"Together")),(0,i.kt)("td",{parentName:"tr",align:"right"},"70.70 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"5.88 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"56.84 s")))),(0,i.kt)("h2",{id:"994-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.9.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,i.kt)("hr",null),(0,i.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"p"},"EFCore.BulkExtensions")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/borisdj/EFCore.BulkExtensions"},"EFCore.BulkExtensions \u5f00\u6e90\u4ed3\u5e93"),"\u3002")))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return c},kt:function(){return m}});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),u=p(n),m=a,k=u["".concat(s,".").concat(m)]||u[m]||d[m]||i;return n?r.createElement(k,o(o({ref:t},c),{},{components:n})):r.createElement(k,o({ref:t},c))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,o=new Array(i);o[0]=u;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var p=2;p=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),u=p(n),m=a,k=u["".concat(s,".").concat(m)]||u[m]||d[m]||i;return n?r.createElement(k,o(o({ref:t},c),{},{components:n})):r.createElement(k,o({ref:t},c))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,o=new Array(i);o[0]=u;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var p=2;pZack.EFCore.Batch \u4f7f\u7528",id:"992-zackefcorebatch-\u4f7f\u7528",level:2},{value:"9.9.2.1 \u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93 Nuget \u5305",id:"9921-\u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93-nuget-\u5305",level:3},{value:"9.9.2.2 \u6ce8\u518c\u5e76\u914d\u7f6e\u670d\u52a1",id:"9922-\u6ce8\u518c\u5e76\u914d\u7f6e\u670d\u52a1",level:3},{value:"9.9.2.3 \u57fa\u672c\u4f7f\u7528",id:"9923-\u57fa\u672c\u4f7f\u7528",level:3},{value:"9.9.3 EFCore.BulkExtensions \u4f7f\u7528",id:"993-efcorebulkextensions-\u4f7f\u7528",level:2},{value:"9.9.3.1 \u5e38\u89c1\u6279\u91cf\u64cd\u4f5c",id:"9931-\u5e38\u89c1\u6279\u91cf\u64cd\u4f5c",level:3},{value:"9.9.3.2 \u67e5\u8be2\u540e\u6279\u91cf\u64cd\u4f5c",id:"9932-\u67e5\u8be2\u540e\u6279\u91cf\u64cd\u4f5c",level:3},{value:"9.9.3.3 \u6279\u91cf\u64cd\u4f5c\u6027\u80fd",id:"9933-\u6279\u91cf\u64cd\u4f5c\u6027\u80fd",level:3},{value:"9.9.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"994-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],u={toc:d};function m(e){var t=e.components,n=(0,a.Z)(e,o);return(0,i.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"991-\u5173\u4e8e\u6279\u91cf\u64cd\u4f5c"},"9.9.1 \u5173\u4e8e\u6279\u91cf\u64cd\u4f5c"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u53ea\u63d0\u4f9b\u5c0f\u6570\u636e\uff08100 \u6761 \u4ee5\u5185\uff09\u6279\u91cf\u6570\u636e\u64cd\u4f5c\uff0c\u5982\u679c\u9700\u8981\u66f4\u5927\u7684\u6570\u636e\u6279\u91cf\u5904\u7406\uff0c\u63a8\u8350\u4f7f\u7528\u7b2c\u4e09\u65b9\u5305 ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/yangzhongke/Zack.EFCore.Batch"},"Zack.EFCore.Batch"),"\uff0c\u652f\u6301\u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u65e0\u7f1d\u8854\u63a5\u3002"),(0,i.kt)("h2",{id:"992-zackefcorebatch-\u4f7f\u7528"},"9.9.2 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Zack.EFCore.Batch")," \u4f7f\u7528"),(0,i.kt)("h3",{id:"9921-\u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93-nuget-\u5305"},"9.9.2.1 \u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Nuget")," \u5305"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"MSSQL"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Zack.EFCore.Batch.MSSQL")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"MySql"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Zack.EFCore.Batch.MySQL.Pomelo")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Npgsql"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Zack.EFCore.Batch.Npgsql")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Oracle"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Zack.EFCore.Batch.Oracle")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Sqlite"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Zack.EFCore.Batch.Sqlite"))),(0,i.kt)("h3",{id:"9922-\u6ce8\u518c\u5e76\u914d\u7f6e\u670d\u52a1"},"9.9.2.2 \u6ce8\u518c\u5e76\u914d\u7f6e\u670d\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5}",showLineNumbers:!0,"":!0,"{3,5}":!0},"services.AddDatabaseAccessor(options =>\n{\n options.AddDbPool(providerName: default, optionBuilder: (services, opt) => // \u5982\u679c\u662f v3.7.11 \u4e4b\u524d\uff0c\u4f7f\u7528 opt =>\n {\n opt.UseBatchEF_Sqlite(); // SQlite \u6570\u636e\u5e93\u5305\n });\n});\n")),(0,i.kt)("h3",{id:"9923-\u57fa\u672c\u4f7f\u7528"},"9.9.2.3 \u57fa\u672c\u4f7f\u7528"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u6279\u91cf\u66f4\u65b0\nawait repository.Context.BatchUpdate()\n .Set(b => b.Price, b => b.Price + 3)\n .Set(b => b.Title, b => s)\n .Set(b => b.AuthorName,b=>b.Title.Substring(3,2)+b.AuthorName.ToUpper())\n .Set(b => b.PubTime, b => DateTime.Now)\n .Where(b => b.Id > n || b.AuthorName.StartsWith("Zack"))\n .ExecuteAsync();\n\n// \u6279\u91cf\u5220\u9664\nawait repository.Context.DeleteRangeAsync(b => b.Price > n || b.AuthorName == "zack yang");\n')),(0,i.kt)("h2",{id:"993-efcorebulkextensions-\u4f7f\u7528"},"9.9.3 ",(0,i.kt)("inlineCode",{parentName:"h2"},"EFCore.BulkExtensions")," \u4f7f\u7528"),(0,i.kt)("p",null,"\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},"EFCore.BulkExtensions")," \u5305\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"9931-\u5e38\u89c1\u6279\u91cf\u64cd\u4f5c"},"9.9.3.1 \u5e38\u89c1\u6279\u91cf\u64cd\u4f5c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u6279\u91cf\u63d2\u5165\nrepository.Context.BulkInsert(entitiesList);\nrepository.Context.BulkInsertAsync(entitiesList);\n\n// \u6279\u91cf\u66f4\u65b0\nrepository.Context.BulkUpdate(entitiesList);\nrepository.Context.BulkUpdateAsync(entitiesList);\n\n// \u6279\u91cf\u5220\u9664\nrepository.Context.BulkDelete(entitiesList);\nrepository.Context.BulkDeleteAsync(entitiesList);\n\n// \u6279\u91cf\u63d2\u5165\u6216\u66f4\u65b0\nrepository.Context.BulkInsertOrUpdate(entitiesList);\nrepository.Context.BulkInsertOrUpdateAsync(entitiesList);\n\n// \u6279\u91cf\u63d2\u5165\u6216\u66f4\u65b0\u6216\u5220\u9664\nrepository.Context.BulkInsertOrUpdateOrDelete(entitiesList);\nrepository.Context.BulkInsertOrUpdateOrDeleteAsync(entitiesList);\n\n// \u6279\u91cf\u8bfb\u53d6\u591a\u4e2a\u5b9e\u4f53\nrepository.Context.BulkRead(entitiesList);\nrepository.Context.BulkReadAsync(entitiesList);\n\n// \u6279\u91cf\u6e05\u7a7a\u8868\uff08\u614e\u7528\uff01\uff01\uff01\uff01\uff01\uff09\nrepository.Context.Truncate();\nrepository.Context.TruncateAsync();\n")),(0,i.kt)("h3",{id:"9932-\u67e5\u8be2\u540e\u6279\u91cf\u64cd\u4f5c"},"9.9.3.2 \u67e5\u8be2\u540e\u6279\u91cf\u64cd\u4f5c"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u6839\u636e\u6761\u4ef6\u6279\u91cf\u5220\u9664\nrepository.Where(a => a.ItemId > 500).BatchDelete();\nawait repository.Where(a => a.ItemId > 500).BatchDeleteAsync();\n\n// \u6839\u636e\u6761\u4ef6\u6279\u91cf\u66f4\u65b0\nrepository.Where(a => a.ItemId <= 500).BatchUpdate(a => new Item { Quantity = a.Quantity + 100 });\nrepository.Where(a => a.ItemId <= 500).BatchUpdate(new Item { Description = "Updated" });\nawait repository.Where(a => a.ItemId <= 500).BatchUpdateAsync(new Item { Description = "Updated" });\n\n// \u6279\u91cf\u66f4\u65b0\u6307\u5b9a\u5217\nvar updateColumns = new List { nameof(Item.Quantity) };\nvar q = repository.Where(a => a.ItemId <= 500);\nint affected = q.BatchUpdate(new Item { Description = "Updated" }, updateColumns);\n')),(0,i.kt)("h3",{id:"9933-\u6279\u91cf\u64cd\u4f5c\u6027\u80fd"},"9.9.3.3 \u6279\u91cf\u64cd\u4f5c\u6027\u80fd"),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"Operations\\Rows"),(0,i.kt)("th",{parentName:"tr",align:"right"},"100,000 EF"),(0,i.kt)("th",{parentName:"tr",align:"right"},"100,000 EFBulk"),(0,i.kt)("th",{parentName:"tr",align:"right"},"1,000,000 EFBulk"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"Insert"),(0,i.kt)("td",{parentName:"tr",align:"right"},"38.98 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"2.10 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"17.99 s")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"Update"),(0,i.kt)("td",{parentName:"tr",align:"right"},"109.25 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"3.96 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"31.45 s")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"Delete"),(0,i.kt)("td",{parentName:"tr",align:"right"},"7.26 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"2.04 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"12.18 s")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},"-----------------"),(0,i.kt)("td",{parentName:"tr",align:"right"},"------------"),(0,i.kt)("td",{parentName:"tr",align:"right"},"----------------"),(0,i.kt)("td",{parentName:"tr",align:"right"},"------------------")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("strong",{parentName:"td"},"Together")),(0,i.kt)("td",{parentName:"tr",align:"right"},"70.70 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"5.88 s"),(0,i.kt)("td",{parentName:"tr",align:"right"},"56.84 s")))),(0,i.kt)("h2",{id:"994-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.9.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,i.kt)("hr",null),(0,i.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"p"},"EFCore.BulkExtensions")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/borisdj/EFCore.BulkExtensions"},"EFCore.BulkExtensions \u5f00\u6e90\u4ed3\u5e93"),"\u3002")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/5edfff3a.4b55c402.js b/handbook/build/assets/js/5edfff3a.4b55c402.js deleted file mode 100644 index 50d08a4f6e..0000000000 --- a/handbook/build/assets/js/5edfff3a.4b55c402.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[318],{7709:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return d},default:function(){return k},frontMatter:function(){return l},metadata:function(){return c},toc:function(){return m}});var r=n(3117),i=n(102),a=(n(7294),n(3905)),o=n(1402),p=["components"],l={id:"get-start-net6",title:"2.1 ASP.NET 6 \u96c6\u6210",sidebar_label:"2.1 ASP.NET 6 \u96c6\u6210"},d=void 0,c={unversionedId:"get-start-net6",id:"get-start-net6",title:"2.1 ASP.NET 6 \u96c6\u6210",description:"Furion \u5b98\u65b9\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u65b9\u4fbf\u7684\u811a\u624b\u67b6\uff0c\u53ef\u4ee5\u5feb\u901f\u7684\u521b\u5efa\u591a\u5c42\u67b6\u6784\u9879\u76ee\u3002",source:"@site/docs/get-start-net6.mdx",sourceDirName:".",slug:"/get-start-net6",permalink:"/furion/docs/get-start-net6",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/get-start-net6.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1655479621,formattedLastUpdatedAt:"Jun 17, 2022",frontMatter:{id:"get-start-net6",title:"2.1 ASP.NET 6 \u96c6\u6210",sidebar_label:"2.1 ASP.NET 6 \u96c6\u6210"},sidebar:"docs",previous:{title:"2.1 ASP.NET 5 \u96c6\u6210",permalink:"/furion/docs/get-start"},next:{title:"2.2 \u5b98\u65b9\u811a\u624b\u67b6",permalink:"/furion/docs/template"}},u={},m=[{value:"2.1 \u521b\u5efa Web \u9879\u76ee",id:"21-\u521b\u5efa-web-\u9879\u76ee",level:2},{value:"2.1.1 \u521b\u5efa ASP.NET Core Web \u5e94\u7528\u7a0b\u5e8f",id:"211-\u521b\u5efa-aspnet-core-web-\u5e94\u7528\u7a0b\u5e8f",level:3},{value:"2.2 \u6dfb\u52a0 Furion \u4f9d\u8d56\u5305",id:"22-\u6dfb\u52a0-furion-\u4f9d\u8d56\u5305",level:2},{value:"2.3 Furion \u57fa\u672c\u914d\u7f6e",id:"23-furion-\u57fa\u672c\u914d\u7f6e",level:2},{value:"2.3.1 Program.cs \u6dfb\u52a0 Inject()",id:"231-programcs-\u6dfb\u52a0-inject",level:3},{value:"2.4 \u542f\u52a8\u6d4f\u89c8\u5668",id:"24-\u542f\u52a8\u6d4f\u89c8\u5668",level:2},{value:"2.5 WebApplication \u8bf4\u660e \ud83c\udf83",id:"25-webapplication-\u8bf4\u660e-",level:2}],s={toc:m};function k(e){var t=e.components,n=(0,i.Z)(e,p);return(0,a.kt)("wrapper",(0,r.Z)({},s,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{title:"\u63a8\u8350\u4f7f\u7528\u811a\u624b\u67b6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u5b98\u65b9\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u65b9\u4fbf\u7684\u811a\u624b\u67b6\uff0c\u53ef\u4ee5\u5feb\u901f\u7684\u521b\u5efa\u591a\u5c42\u67b6\u6784\u9879\u76ee\u3002"),(0,a.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u4f7f\u7528 \u300a",(0,a.kt)("a",{parentName:"p",href:"/furion/docs/template"},"2.2 \u5b98\u65b9\u811a\u624b\u67b6"),"\u300b\u4ee3\u66ff\u672c\u7ae0\u8282\u529f\u80fd\u3002")),(0,a.kt)("admonition",{title:"\u5165\u95e8\u6761\u4ef6",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u5bf9 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET Core/ASP.NET Core")," \u6709\u4e00\u5b9a\u57fa\u7840\u4e86\u89e3\uff0c\u8fd8\u672a\u63a5\u89e6\u7684\u53ef\u5148\u770b ",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/?view=aspnetcore-6.0&tabs=windows"},"\u3010ASP.NET Core \u57fa\u7840\u3011"))),(0,a.kt)("h2",{id:"21-\u521b\u5efa-web-\u9879\u76ee"},"2.1 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h2"},"Web")," \u9879\u76ee"),(0,a.kt)("admonition",{title:"\u73af\u5883\u8981\u6c42",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e4b\u524d\u5148\u786e\u4fdd\u5b89\u88c5\u4e86\u6700\u65b0\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET 6 SDK")," \u5e76\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio 2022")," \u6700\u65b0\u7248\u3002")),(0,a.kt)("h3",{id:"211-\u521b\u5efa-aspnet-core-web-\u5e94\u7528\u7a0b\u5e8f"},"2.1.1 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h3"},"ASP.NET Core Web \u5e94\u7528\u7a0b\u5e8f")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u6253\u5f00 ",(0,a.kt)("inlineCode",{parentName:"li"},"Visual Studio 2022")," \u5e76\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"li"},"Web")," \u9879\u76ee")),(0,a.kt)("img",{src:(0,o.Z)("img/rmn1.png")}),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u914d\u7f6e\u9879\u76ee\u540d\u79f0")),(0,a.kt)("img",{src:(0,o.Z)("img/rmn2.png")}),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"li"},"WebAPI")," \u9879\u76ee")),(0,a.kt)("img",{src:(0,o.Z)("img/rmn3.png")}),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u5df2\u7ecf\u5185\u7f6e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"Swagger")," \u89c4\u8303\u5316\u5e93\uff0c\u6240\u4ee5\u521b\u5efa\u65f6",(0,a.kt)("strong",{parentName:"p"},"\u65e0\u9700\u52fe\u9009")," ",(0,a.kt)("inlineCode",{parentName:"p"},"Enable OpenAPI support")," \u9009\u9879\u3002\u5426\u5219\u63d0\u793a\u7248\u672c\u4e0d\u4e00\u81f4\u4ea7\u751f\u51b2\u7a81\u3002")),(0,a.kt)("h2",{id:"22-\u6dfb\u52a0-furion-\u4f9d\u8d56\u5305"},"2.2 \u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Furion")," \u4f9d\u8d56\u5305"),(0,a.kt)("img",{src:(0,o.Z)("img/rmn4.png")}),(0,a.kt)("h2",{id:"23-furion-\u57fa\u672c\u914d\u7f6e"},"2.3 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Furion")," \u57fa\u672c\u914d\u7f6e"),(0,a.kt)("h3",{id:"231-programcs-\u6dfb\u52a0-inject"},"2.3.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Program.cs")," \u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Inject()")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,11}",showLineNumbers:!0,"":!0,"{1,3,11}":!0},"var builder = WebApplication.CreateBuilder(args).Inject();\n\nbuilder.Services.AddControllers().AddInject();\n\nvar app = builder.Build();\n\napp.UseHttpsRedirection();\n\napp.UseAuthorization();\n\napp.UseInject();\n\napp.MapControllers();\n\napp.Run();\n")),(0,a.kt)("admonition",{title:"\u5c0f\u63d0\u9192",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c ",(0,a.kt)("inlineCode",{parentName:"p"},"app.UseInject()")," \u4e0d\u8f93\u5165\u53c2\u6570\uff0c\u5219\u9ed8\u8ba4\u5730\u5740\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"/api"),"\uff0c\u5982\u679c\u8f93\u5165 ",(0,a.kt)("inlineCode",{parentName:"p"},"string.Empty")," \u5219\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"/")," \u76ee\u5f55\u3002\u5982\u679c\u8f93\u5165\u4efb\u610f\u5b57\u7b26\u4e32\uff0c\u5219\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"/\u4efb\u610f\u5b57\u7b26\u4e32")," \u76ee\u5f55\u3002")),(0,a.kt)("h2",{id:"24-\u542f\u52a8\u6d4f\u89c8\u5668"},"2.4 \u542f\u52a8\u6d4f\u89c8\u5668"),(0,a.kt)("p",null,"\u542f\u52a8\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u3002"),(0,a.kt)("img",{src:(0,o.Z)("img/rmn5.png")}),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio 2022")," \u521b\u5efa\u7684\u9879\u76ee\u4f1a\u81ea\u52a8\u914d\u7f6e\u4e86\u542f\u52a8\u9875\uff0c\u5982\u679c\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"F5")," \u8fd0\u884c\uff0c\u53ef\u80fd\u4e0d\u4f1a\u81ea\u52a8\u6253\u5f00\u9996\u9875\uff0c\u8fd9\u65f6\u5019\u6211\u4eec\u53ea\u9700\u8981\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"p"},"launchSettings.json")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"launchUrl")," \u5373\u53ef\uff1a"),(0,a.kt)("img",{src:(0,o.Z)("img/rmn6.png")})),(0,a.kt)("h2",{id:"25-webapplication-\u8bf4\u660e-"},"2.5 ",(0,a.kt)("inlineCode",{parentName:"h2"},"WebApplication")," \u8bf4\u660e \ud83c\udf83"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},".NET6")," \u7248\u672c\u65b0\u589e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"WebApplication")," \u5bf9\u8c61\uff0c\u5982\u679c\u6211\u4eec\u9700\u8981\u6ce8\u518c\u670d\u52a1\uff0c\u53ea\u9700\u8981\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"builder.Services.AddXXX()")," \u5373\u53ef\u3002\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"var builder = WebApplication.CreateBuilder(args).Inject();\n\nbuilder.Services.AddControllers().AddInject();\nbuilder.Services.AddRemoteRequest();\n")))}k.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return c},kt:function(){return s}});var r=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var l=r.createContext({}),d=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=d(e.components);return r.createElement(l.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,a=e.originalType,l=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),m=d(n),s=i,k=m["".concat(l,".").concat(s)]||m[s]||u[s]||a;return n?r.createElement(k,o(o({ref:t},c),{},{components:n})):r.createElement(k,o({ref:t},c))}));function s(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=n.length,o=new Array(a);o[0]=m;var p={};for(var l in t)hasOwnProperty.call(t,l)&&(p[l]=t[l]);p.originalType=e,p.mdxType="string"==typeof e?e:i,o[1]=p;for(var d=2;d=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var l=r.createContext({}),d=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=d(e.components);return r.createElement(l.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,a=e.originalType,l=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),m=d(n),s=i,k=m["".concat(l,".").concat(s)]||m[s]||u[s]||a;return n?r.createElement(k,o(o({ref:t},c),{},{components:n})):r.createElement(k,o({ref:t},c))}));function s(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=n.length,o=new Array(a);o[0]=m;var p={};for(var l in t)hasOwnProperty.call(t,l)&&(p[l]=t[l]);p.originalType=e,p.mdxType="string"==typeof e?e:i,o[1]=p;for(var d=2;dWeb \u9879\u76ee",id:"21-\u521b\u5efa-web-\u9879\u76ee",level:2},{value:"2.1.1 \u521b\u5efa ASP.NET Core Web \u5e94\u7528\u7a0b\u5e8f",id:"211-\u521b\u5efa-aspnet-core-web-\u5e94\u7528\u7a0b\u5e8f",level:3},{value:"2.2 \u6dfb\u52a0 Furion \u4f9d\u8d56\u5305",id:"22-\u6dfb\u52a0-furion-\u4f9d\u8d56\u5305",level:2},{value:"2.3 Furion \u57fa\u672c\u914d\u7f6e",id:"23-furion-\u57fa\u672c\u914d\u7f6e",level:2},{value:"2.3.1 Program.cs \u6dfb\u52a0 Inject()",id:"231-programcs-\u6dfb\u52a0-inject",level:3},{value:"2.4 \u542f\u52a8\u6d4f\u89c8\u5668",id:"24-\u542f\u52a8\u6d4f\u89c8\u5668",level:2},{value:"2.5 WebApplication \u8bf4\u660e \ud83c\udf83",id:"25-webapplication-\u8bf4\u660e-",level:2}],s={toc:m};function k(e){var t=e.components,n=(0,i.Z)(e,p);return(0,a.kt)("wrapper",(0,r.Z)({},s,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{title:"\u63a8\u8350\u4f7f\u7528\u811a\u624b\u67b6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u5b98\u65b9\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u65b9\u4fbf\u7684\u811a\u624b\u67b6\uff0c\u53ef\u4ee5\u5feb\u901f\u7684\u521b\u5efa\u591a\u5c42\u67b6\u6784\u9879\u76ee\u3002"),(0,a.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u4f7f\u7528 \u300a",(0,a.kt)("a",{parentName:"p",href:"/furion/docs/template"},"2.2 \u5b98\u65b9\u811a\u624b\u67b6"),"\u300b\u4ee3\u66ff\u672c\u7ae0\u8282\u529f\u80fd\u3002")),(0,a.kt)("admonition",{title:"\u5165\u95e8\u6761\u4ef6",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u5bf9 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET Core/ASP.NET Core")," \u6709\u4e00\u5b9a\u57fa\u7840\u4e86\u89e3\uff0c\u8fd8\u672a\u63a5\u89e6\u7684\u53ef\u5148\u770b ",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/?view=aspnetcore-6.0&tabs=windows"},"\u3010ASP.NET Core \u57fa\u7840\u3011"))),(0,a.kt)("h2",{id:"21-\u521b\u5efa-web-\u9879\u76ee"},"2.1 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h2"},"Web")," \u9879\u76ee"),(0,a.kt)("admonition",{title:"\u73af\u5883\u8981\u6c42",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e4b\u524d\u5148\u786e\u4fdd\u5b89\u88c5\u4e86\u6700\u65b0\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET 6 SDK")," \u5e76\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio 2022")," \u6700\u65b0\u7248\u3002")),(0,a.kt)("h3",{id:"211-\u521b\u5efa-aspnet-core-web-\u5e94\u7528\u7a0b\u5e8f"},"2.1.1 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h3"},"ASP.NET Core Web \u5e94\u7528\u7a0b\u5e8f")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u6253\u5f00 ",(0,a.kt)("inlineCode",{parentName:"li"},"Visual Studio 2022")," \u5e76\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"li"},"Web")," \u9879\u76ee")),(0,a.kt)("img",{src:(0,o.Z)("img/rmn1.png")}),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u914d\u7f6e\u9879\u76ee\u540d\u79f0")),(0,a.kt)("img",{src:(0,o.Z)("img/rmn2.png")}),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"li"},"WebAPI")," \u9879\u76ee")),(0,a.kt)("img",{src:(0,o.Z)("img/rmn3.png")}),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u5df2\u7ecf\u5185\u7f6e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"Swagger")," \u89c4\u8303\u5316\u5e93\uff0c\u6240\u4ee5\u521b\u5efa\u65f6",(0,a.kt)("strong",{parentName:"p"},"\u65e0\u9700\u52fe\u9009")," ",(0,a.kt)("inlineCode",{parentName:"p"},"Enable OpenAPI support")," \u9009\u9879\u3002\u5426\u5219\u63d0\u793a\u7248\u672c\u4e0d\u4e00\u81f4\u4ea7\u751f\u51b2\u7a81\u3002")),(0,a.kt)("h2",{id:"22-\u6dfb\u52a0-furion-\u4f9d\u8d56\u5305"},"2.2 \u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Furion")," \u4f9d\u8d56\u5305"),(0,a.kt)("img",{src:(0,o.Z)("img/rmn4.png")}),(0,a.kt)("h2",{id:"23-furion-\u57fa\u672c\u914d\u7f6e"},"2.3 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Furion")," \u57fa\u672c\u914d\u7f6e"),(0,a.kt)("h3",{id:"231-programcs-\u6dfb\u52a0-inject"},"2.3.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Program.cs")," \u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Inject()")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,11}",showLineNumbers:!0,"":!0,"{1,3,11}":!0},"var builder = WebApplication.CreateBuilder(args).Inject();\n\nbuilder.Services.AddControllers().AddInject();\n\nvar app = builder.Build();\n\napp.UseHttpsRedirection();\n\napp.UseAuthorization();\n\napp.UseInject();\n\napp.MapControllers();\n\napp.Run();\n")),(0,a.kt)("admonition",{title:"\u5c0f\u63d0\u9192",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c ",(0,a.kt)("inlineCode",{parentName:"p"},"app.UseInject()")," \u4e0d\u8f93\u5165\u53c2\u6570\uff0c\u5219\u9ed8\u8ba4\u5730\u5740\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"/api"),"\uff0c\u5982\u679c\u8f93\u5165 ",(0,a.kt)("inlineCode",{parentName:"p"},"string.Empty")," \u5219\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"/")," \u76ee\u5f55\u3002\u5982\u679c\u8f93\u5165\u4efb\u610f\u5b57\u7b26\u4e32\uff0c\u5219\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"/\u4efb\u610f\u5b57\u7b26\u4e32")," \u76ee\u5f55\u3002")),(0,a.kt)("h2",{id:"24-\u542f\u52a8\u6d4f\u89c8\u5668"},"2.4 \u542f\u52a8\u6d4f\u89c8\u5668"),(0,a.kt)("p",null,"\u542f\u52a8\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u3002"),(0,a.kt)("img",{src:(0,o.Z)("img/rmn5.png")}),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio 2022")," \u521b\u5efa\u7684\u9879\u76ee\u4f1a\u81ea\u52a8\u914d\u7f6e\u4e86\u542f\u52a8\u9875\uff0c\u5982\u679c\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"F5")," \u8fd0\u884c\uff0c\u53ef\u80fd\u4e0d\u4f1a\u81ea\u52a8\u6253\u5f00\u9996\u9875\uff0c\u8fd9\u65f6\u5019\u6211\u4eec\u53ea\u9700\u8981\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"p"},"launchSettings.json")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"launchUrl")," \u5373\u53ef\uff1a"),(0,a.kt)("img",{src:(0,o.Z)("img/rmn6.png")})),(0,a.kt)("h2",{id:"25-webapplication-\u8bf4\u660e-"},"2.5 ",(0,a.kt)("inlineCode",{parentName:"h2"},"WebApplication")," \u8bf4\u660e \ud83c\udf83"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},".NET6")," \u7248\u672c\u65b0\u589e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"WebApplication")," \u5bf9\u8c61\uff0c\u5982\u679c\u6211\u4eec\u9700\u8981\u6ce8\u518c\u670d\u52a1\uff0c\u53ea\u9700\u8981\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"builder.Services.AddXXX()")," \u5373\u53ef\u3002\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"var builder = WebApplication.CreateBuilder(args).Inject();\n\nbuilder.Services.AddControllers().AddInject();\nbuilder.Services.AddRemoteRequest();\n")))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/5f6c9278.c0cb49de.js b/handbook/build/assets/js/5f6c9278.c0cb49de.js deleted file mode 100644 index ef69e73f8c..0000000000 --- a/handbook/build/assets/js/5f6c9278.c0cb49de.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[732],{9243:function(e,n,t){t.r(n),t.d(n,{assets:function(){return m},contentTitle:function(){return s},default:function(){return c},frontMatter:function(){return o},metadata:function(){return u},toc:function(){return p}});var r=t(3117),i=t(102),a=(t(7294),t(3905)),l=["components"],o={id:"view-engine",title:"17. \u89c6\u56fe\u5f15\u64ce",sidebar_label:"17. \u89c6\u56fe\u5f15\u64ce"},s=void 0,u={unversionedId:"view-engine",id:"view-engine",title:"17. \u89c6\u56fe\u5f15\u64ce",description:"17.1 \u5173\u4e8e\u89c6\u56fe\u5f15\u64ce",source:"@site/docs/view-engine.mdx",sourceDirName:".",slug:"/view-engine",permalink:"/furion/docs/view-engine",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/view-engine.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"view-engine",title:"17. \u89c6\u56fe\u5f15\u64ce",sidebar_label:"17. \u89c6\u56fe\u5f15\u64ce"},sidebar:"docs",previous:{title:"16. CORS \u8de8\u57df",permalink:"/furion/docs/cors"},next:{title:"18. \u65e5\u5fd7\u8bb0\u5f55",permalink:"/furion/docs/logging"}},m={},p=[{value:"17.1 \u5173\u4e8e\u89c6\u56fe\u5f15\u64ce",id:"171-\u5173\u4e8e\u89c6\u56fe\u5f15\u64ce",level:2},{value:"17.2 \u89c6\u56fe\u5f15\u64ce\u4f5c\u7528",id:"172-\u89c6\u56fe\u5f15\u64ce\u4f5c\u7528",level:2},{value:"17.3 \u57fa\u7840\u4f7f\u7528",id:"173-\u57fa\u7840\u4f7f\u7528",level:2},{value:"17.3.1 \u6ce8\u518c\u670d\u52a1",id:"1731-\u6ce8\u518c\u670d\u52a1",level:3},{value:"17.3.2 \u4f7f\u7528\u65b9\u5f0f",id:"1732-\u4f7f\u7528\u65b9\u5f0f",level:3},{value:"17.3.3 \u5f31\u7c7b\u578b\u6a21\u677f",id:"1733-\u5f31\u7c7b\u578b\u6a21\u677f",level:3},{value:"17.3.4 \u5f3a\u7c7b\u578b\u6a21\u677f",id:"1734-\u5f3a\u7c7b\u578b\u6a21\u677f",level:3},{value:"17.3.5 \u9ad8\u6027\u80fd\u6a21\u677f\u7f13\u5b58 \ud83e\udd47",id:"1735-\u9ad8\u6027\u80fd\u6a21\u677f\u7f13\u5b58-",level:3},{value:"17.4 \u9ad8\u7ea7\u7528\u6cd5",id:"174-\u9ad8\u7ea7\u7528\u6cd5",level:2},{value:"17.4.1 \u6dfb\u52a0\u7a0b\u5e8f\u96c6",id:"1741-\u6dfb\u52a0\u7a0b\u5e8f\u96c6",level:3},{value:"17.4.2 \u6dfb\u52a0\u547d\u540d\u7a7a\u95f4",id:"1742-\u6dfb\u52a0\u547d\u540d\u7a7a\u95f4",level:3},{value:"17.4.3 \u5b9a\u4e49\u6a21\u677f\u65b9\u6cd5",id:"1743-\u5b9a\u4e49\u6a21\u677f\u65b9\u6cd5",level:3},{value:"17.4.4 \u8c03\u7528\u7c7b\u65b9\u6cd5",id:"1744-\u8c03\u7528\u7c7b\u65b9\u6cd5",level:3},{value:"17.5 IViewEngine \u63a5\u53e3",id:"175-iviewengine-\u63a5\u53e3",level:2},{value:"17.6 \u5b57\u7b26\u4e32\u6a21\u677f\u66ff\u6362\u5f15\u64ce",id:"176-\u5b57\u7b26\u4e32\u6a21\u677f\u66ff\u6362\u5f15\u64ce",level:2},{value:"17.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"177-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:p};function c(e){var n=e.components,t=(0,i.Z)(e,l);return(0,a.kt)("wrapper",(0,r.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"171-\u5173\u4e8e\u89c6\u56fe\u5f15\u64ce"},"17.1 \u5173\u4e8e\u89c6\u56fe\u5f15\u64ce"),(0,a.kt)("p",null,"\u89c6\u56fe\u5f15\u64ce\u8d1f\u8d23\u6839\u636e\u89c6\u56fe\u6a21\u677f\u521b\u5efa HTML\u3002\u89c6\u56fe\u901a\u5e38\u662f HTML \u548c\u7f16\u7a0b\u8bed\u8a00\u7684\u67d0\u79cd\u6df7\u5408\u3002\u652f\u6301\u53d8\u91cf\u5b9a\u4e49\u3001\u65b9\u6cd5\u8c03\u7528\u53ca\u903b\u8f91\u7f16\u5199\u3002"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5e95\u5c42\u96c6\u6210\u4e86\u5fae\u8f6f\u63d0\u4f9b\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Razor")," \u89c6\u56fe\u5f15\u64ce\u7ec4\u4ef6\u5e76\u63d0\u4f9b\u66f4\u52a0\u7075\u6d3b\u65b9\u4fbf\u7684\u8bed\u6cd5\u7cd6\u3002"),(0,a.kt)("h2",{id:"172-\u89c6\u56fe\u5f15\u64ce\u4f5c\u7528"},"17.2 \u89c6\u56fe\u5f15\u64ce\u4f5c\u7528"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"strong"},"ASP.NET Core")," \u5b8c\u6574\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"Razor")," \u8bed\u6cd5")),(0,a.kt)("li",{parentName:"ul"},"\u6839\u636e\u4e0d\u540c\u7684\u6570\u636e\u7f16\u8bd1\u6a21\u677f\u4ea7\u751f\u4e0d\u540c\u7684\u8f93\u51fa"),(0,a.kt)("li",{parentName:"ul"},"\u5b9e\u73b0\u5f3a\u5927\u7684\u63d2\u4ef6\u5316\u673a\u5236"),(0,a.kt)("li",{parentName:"ul"},"\u5b9e\u73b0\u5168\u7ad9\u9875\u9762\u9759\u6001\u5316"),(0,a.kt)("li",{parentName:"ul"},"\u53ef\u4ee5\u7528\u4f5c\u90ae\u4ef6\u6a21\u677f\u3001\u77ed\u4fe1\u6a21\u677f\u3001\u4f18\u60e0\u5238\u4fe1\u606f\u6a21\u677f\u7b49")),(0,a.kt)("h2",{id:"173-\u57fa\u7840\u4f7f\u7528"},"17.3 \u57fa\u7840\u4f7f\u7528"),(0,a.kt)("h3",{id:"1731-\u6ce8\u518c\u670d\u52a1"},"17.3.1 \u6ce8\u518c\u670d\u52a1"),(0,a.kt)("p",null,"\u4f7f\u7528\u4e4b\u524d\u9700\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c ",(0,a.kt)("inlineCode",{parentName:"p"},"\u89c6\u56fe\u5f15\u64ce\u670d\u52a1"),"\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public void ConfigureServices(IServiceCollection services)\n{\n services.AddViewEngine();\n}\n")),(0,a.kt)("h3",{id:"1732-\u4f7f\u7528\u65b9\u5f0f"},"17.3.2 \u4f7f\u7528\u65b9\u5f0f"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u6784\u9020\u51fd\u6570\u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"li"},"IViewEngine"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,9,12}",showLineNumbers:!0,"":!0,"{2,9,12}":!0},'using Furion.DynamicApiController;\nusing Furion.ViewEngine;\n\nnamespace Furion.Application\n{\n public class ViewEngineService : IDynamicApiController\n {\n private readonly IViewEngine _viewEngine;\n public ViewEngineService(IViewEngine viewEngine)\n {\n _viewEngine = viewEngine;\n var result = _viewEngine.RunCompile("Hello @Model.Name", new { Name = "Furion" });\n }\n }\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5b57\u7b26\u4e32\u65b9\u5f0f")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = "Hello @Model.Name".RunCompile(new { Name = "Furion" });\n')),(0,a.kt)("h3",{id:"1733-\u5f31\u7c7b\u578b\u6a21\u677f"},"17.3.3 \u5f31\u7c7b\u578b\u6a21\u677f"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = _viewEngine.RunCompile("Hello @Model.Name", new { Name = "Furion" });\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"Hello Furion\n")),(0,a.kt)("p",null,"\u652f\u6301\u5f02\u6b65 ",(0,a.kt)("inlineCode",{parentName:"p"},"RunCompileAsync")),(0,a.kt)("h3",{id:"1734-\u5f3a\u7c7b\u578b\u6a21\u677f"},"17.3.4 \u5f3a\u7c7b\u578b\u6a21\u677f"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = _viewEngine.RunCompile(@"\nHello @Model.Name\n@foreach(var item in Model.Items)\n{\n

@item

\n}\n", new TestModel\n{\n Name = "Furion",\n Items = new[] { 3, 1, 2 }\n});\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"Hello Furion\n

3

\n

1

\n

2

\n")),(0,a.kt)("p",null,"\u652f\u6301\u5f02\u6b65 ",(0,a.kt)("inlineCode",{parentName:"p"},"RunCompileAsync")),(0,a.kt)("h3",{id:"1735-\u9ad8\u6027\u80fd\u6a21\u677f\u7f13\u5b58-"},"17.3.5 \u9ad8\u6027\u80fd\u6a21\u677f\u7f13\u5b58 \ud83e\udd47"),(0,a.kt)("p",null,"\u7531\u4e8e\u6a21\u677f\u7f16\u8bd1\u9700\u8981\u6d88\u8017\u5927\u91cf\u7684\u6027\u80fd\uff0c\u6240\u4ee5\u5efa\u8bae\u4f7f\u7528\u5e26 ",(0,a.kt)("inlineCode",{parentName:"p"},"FromCached")," \u7ed3\u5c3e\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"RunCompileFromCached")," \u66ff\u4ee3\u3002\u8c03\u7528\u8be5\u65b9\u6cd5\u540e\u4f1a\u81ea\u52a8\u5c06\u6a21\u677f\u7f16\u8bd1\u6210 ",(0,a.kt)("inlineCode",{parentName:"p"},".dll")," \u4ee5\u4fbf\u4e0b\u6b21\u4f7f\u7528\u3002\u51cf\u5c11\u7b2c\u4e8c\u6b21\u4e4b\u540e\u4f7f\u7528\u6a21\u677f\u7684\u6027\u80fd\u635f\u8017\u3002"),(0,a.kt)("p",null,"\u5982\uff0c\u5f3a\u7c7b\u578b\u6a21\u677f\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = _viewEngine.RunCompileFromCached(@"\nHello @Model.Name\n@foreach(var item in Model.Items)\n{\n

@item

\n}\n", new TestModel\n{\n Name = "Furion",\n Items = new[] { 3, 1, 2 }\n});\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"Hello Furion\n

3

\n

1

\n

2

\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u8c03\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"RunCompileFromCached")," \u65b9\u6cd5\u4e4b\u540e\u5c06\u4f1a\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"MD5")," \u52a0\u5bc6\u6a21\u677f\u5e76\u751f\u6210 ",(0,a.kt)("inlineCode",{parentName:"strong"},"MD5"),"\u5b57\u7b26\u4e32\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},".dll")," \u5b58\u653e\u5728\u7f51\u7ad9\u6839\u76ee\u5f55\u4e0b\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"templates")," \u76ee\u5f55\u4e2d\u3002\u53ea\u8981\u6a21\u677f\u5185\u5bb9\u4e0d\u53d8\uff0c\u6570\u636e\u53d1\u751f\u6539\u53d8\u4e5f\u4e0d\u4f1a\u91cd\u65b0\u7f16\u8bd1\u6a21\u677f\u3002\u8fd9\u6837\u5927\u5927\u7684\u63d0\u9ad8\u4e86\u9996\u6b21\u4e4b\u540e\u7684\u6027\u80fd\u3002")),(0,a.kt)("p",null,"\u5982\uff0c\u4f20\u5165\u65b0\u7684\u6570\u636e\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {10}",showLineNumbers:!0,"":!0,"{10}":!0},'var result = _viewEngine.RunCompileFromCached(@"\nHello @Model.Name\n@foreach(var item in Model.Items)\n{\n

@item

\n}\n", new TestModel\n{\n Name = "Furion",\n Items = new[] { 5,6,7,8 }\n});\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"Hello Furion\n

5

\n

6

\n

7

\n

8

\n")),(0,a.kt)("p",null,"\u6a21\u677f\u4e0d\u518d\u91cd\u65b0\u7f16\u8bd1\uff0c\u53ea\u662f\u91cd\u65b0\u66ff\u6362\u6570\u636e\u3002"),(0,a.kt)("h2",{id:"174-\u9ad8\u7ea7\u7528\u6cd5"},"17.4 \u9ad8\u7ea7\u7528\u6cd5"),(0,a.kt)("p",null,"\u9ad8\u7ea7\u7528\u6cd5\u652f\u6301\u5c06\u7279\u5b9a\u7a0b\u5e8f\u96c6\u3001\u7279\u5b9a\u547d\u540d\u7a7a\u95f4\u3001\u7279\u5b9a\u7c7b\u578b\u5f15\u5165\u5230\u6a21\u677f\u4e2d\u4f7f\u7528\u3002"),(0,a.kt)("h3",{id:"1741-\u6dfb\u52a0\u7a0b\u5e8f\u96c6"},"17.4.1 \u6dfb\u52a0\u7a0b\u5e8f\u96c6"),(0,a.kt)("p",null,"\u6bd4\u5982\u8fd9\u91cc\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"System.IO")," \u7a0b\u5e8f\u96c6\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = _viewEngine.RunCompileFromCached(@"
@System.IO.Path.Combine(""Furion"", ""ViewEngine"")
", builderAction: builder =>\n {\n builder.AddAssemblyReferenceByName("System.IO");\n });\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"
Furion\\\\ViewEngine
\n")),(0,a.kt)("p",null,"\u53e6\u5916\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u591a\u79cd\u65b9\u5f0f\u52a0\u8f7d\u7a0b\u5e8f\u96c6\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'builder.AddAssemblyReferenceByName("System.Security"); // \u901a\u8fc7\u540d\u79f0\nbuilder.AddAssemblyReference(typeof(System.IO.File)); // \u901a\u8fc7\u7c7b\u578b\nbuilder.AddAssemblyReference(Assembly.Load("source")); // \u901a\u8fc7\u5143\u6570\u636e\u5f15\u7528\n')),(0,a.kt)("h3",{id:"1742-\u6dfb\u52a0\u547d\u540d\u7a7a\u95f4"},"17.4.2 \u6dfb\u52a0\u547d\u540d\u7a7a\u95f4"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = _viewEngine.RunCompileFromCached(@"
@Path.Combine(""Furion"", ""ViewEngine"")
", builderAction: builder =>\n {\n builder.AddUsing("System.IO");\n builder.AddAssemblyReferenceByName("System.IO");\n });\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"
Furion\\\\ViewEngine
\n")),(0,a.kt)("p",null,"\u4e5f\u652f\u6301\u52a0\u5165\u591a\u4e2a ",(0,a.kt)("inlineCode",{parentName:"p"},"using"),"\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'builder.AddUsing("System.IO");\nbuilder.AddUsing("Furion");\n')),(0,a.kt)("h3",{id:"1743-\u5b9a\u4e49\u6a21\u677f\u65b9\u6cd5"},"17.4.3 \u5b9a\u4e49\u6a21\u677f\u65b9\u6cd5"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = _viewEngine.RunCompileFromCached(@"\n\n @{ RecursionTest(3); }\n\n\n@{\n void RecursionTest(int level)\n {\n if (level <= 0)\n {\n return;\n }\n\n
LEVEL: @level
\n @{ RecursionTest(level - 1); }\n }\n}\n");\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"\n
LEVEL: 3
\n
LEVEL: 2
\n
LEVEL: 1
\n\n")),(0,a.kt)("h3",{id:"1744-\u8c03\u7528\u7c7b\u65b9\u6cd5"},"17.4.4 \u8c03\u7528\u7c7b\u65b9\u6cd5"),(0,a.kt)("p",null,"\u5b9a\u4e49 ",(0,a.kt)("inlineCode",{parentName:"p"},"CustomModel")," \u7c7b\u5e76\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"p"},"ViewEngineModel")," \u57fa\u7c7b"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'public class CustomModel : ViewEngineModel\n{\n public int A { get; set; }\n public string B { get; set; }\n public string Decorator(object value)\n {\n return "-=" + value + "=-";\n }\n}\n')),(0,a.kt)("p",null,"\u5728\u6a21\u677f\u4e2d\u8c03\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Decorator(value)")," \u65b9\u6cd5\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var content = @"Hello @A, @B, @Decorator(123)";\n\nvar template = _viewEngine.Compile(content);\n\nvar result = template.Run(instance =>\n{\n instance.A = 10;\n instance.B = "Alex";\n});\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"Hello 10, Alex, -=123=-\n")),(0,a.kt)("h2",{id:"175-iviewengine-\u63a5\u53e3"},"17.5 ",(0,a.kt)("inlineCode",{parentName:"h2"},"IViewEngine")," \u63a5\u53e3"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"IViewEngine")," \u63d0\u4f9b\u4e86\u7b80\u5355\u65b9\u4fbf\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"RunCompile")," \u65b9\u6cd5\uff0c\u4e5f\u63d0\u4f9b\u4e86\u6700\u539f\u59cb\u5316\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Compile")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"Run")," \u65b9\u6cd5\u3002"),(0,a.kt)("p",null,"\u901a\u8fc7\u539f\u59cb\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Compile")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"Run")," \u65b9\u6cd5\u53ef\u4ee5\u5b9e\u73b0\u5f88\u591a\u590d\u6742\u7684\u903b\u8f91\u548c\u81ea\u5b9a\u4e49\u6307\u4ee4\u96c6\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'/// \n/// \u7f16\u8bd1\u6a21\u677f\n/// \n/// \n/// \n/// \nIViewEngineTemplate Compile(string content, Action builderAction = null);\n/// \n/// \u7f16\u8bd1\u6a21\u677f\n/// \n/// \n/// \n/// \nTask CompileAsync(string content, Action builderAction = null);\n/// \n/// \u7f16\u8bd1\u6a21\u677f\n/// \n/// \n/// \n/// \n/// \nIViewEngineTemplate Compile(string content, Action builderAction = null)\n where T : IViewEngineModel;\n/// \n/// \u7f16\u8bd1\u6a21\u677f\n/// \n/// \n/// \n/// \n/// \nTask> CompileAsync(string content, Action builderAction = null)\n where T : IViewEngineModel;\n')),(0,a.kt)("h2",{id:"176-\u5b57\u7b26\u4e32\u6a21\u677f\u66ff\u6362\u5f15\u64ce"},"17.6 \u5b57\u7b26\u4e32\u6a21\u677f\u66ff\u6362\u5f15\u64ce"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u9664\u4e86\u5185\u7f6e\u89c6\u56fe\u5f15\u64ce\u4e4b\u5916\uff0c\u8fd8\u652f\u6301\u4ee5\u4e0b\u51e0\u79cd\u6a21\u677f\u66ff\u6362\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u63d0\u4f9b\u6570\u636e\u6a21\u677f\u65b9\u5f0f\nvar str = "\u6211\u53eb{name}".Render(new Dictionary{ {"name", "Furion"} });\nvar str = "\u6211\u53eb{Name}".Render(new { Name = "Furion" });\nvar str = "\u6211\u53eb{Detail.Name}".Render(new { Detail = new { Name = "Furoin" } });\n\n// \u4ece\u914d\u7f6e\u8bfb\u53d6\u65b9\u5f0f\nvar str = "\u6211\u53eb#(Furion:Address)".Render();\n')),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "Furion": {\n "Address": "https://www.furion.icu"\n }\n}\n')),(0,a.kt)("h2",{id:"177-\u53cd\u9988\u4e0e\u5efa\u8bae"},"17.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return m},kt:function(){return c}});var r=t(7294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function l(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var s=r.createContext({}),u=function(e){var n=r.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},m=function(e){var n=u(e.components);return r.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,m=o(e,["components","mdxType","originalType","parentName"]),d=u(t),c=i,g=d["".concat(s,".").concat(c)]||d[c]||p[c]||a;return t?r.createElement(g,l(l({ref:n},m),{},{components:t})):r.createElement(g,l({ref:n},m))}));function c(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var a=t.length,l=new Array(a);l[0]=d;var o={};for(var s in n)hasOwnProperty.call(n,s)&&(o[s]=n[s]);o.originalType=e,o.mdxType="string"==typeof e?e:i,l[1]=o;for(var u=2;u=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var s=r.createContext({}),u=function(e){var n=r.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},m=function(e){var n=u(e.components);return r.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,m=o(e,["components","mdxType","originalType","parentName"]),d=u(t),c=i,g=d["".concat(s,".").concat(c)]||d[c]||p[c]||a;return t?r.createElement(g,l(l({ref:n},m),{},{components:t})):r.createElement(g,l({ref:n},m))}));function c(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var a=t.length,l=new Array(a);l[0]=d;var o={};for(var s in n)hasOwnProperty.call(n,s)&&(o[s]=n[s]);o.originalType=e,o.mdxType="string"==typeof e?e:i,l[1]=o;for(var u=2;uIViewEngine \u63a5\u53e3",id:"175-iviewengine-\u63a5\u53e3",level:2},{value:"17.6 \u5b57\u7b26\u4e32\u6a21\u677f\u66ff\u6362\u5f15\u64ce",id:"176-\u5b57\u7b26\u4e32\u6a21\u677f\u66ff\u6362\u5f15\u64ce",level:2},{value:"17.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"177-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:p};function c(e){var n=e.components,t=(0,i.Z)(e,l);return(0,a.kt)("wrapper",(0,r.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"171-\u5173\u4e8e\u89c6\u56fe\u5f15\u64ce"},"17.1 \u5173\u4e8e\u89c6\u56fe\u5f15\u64ce"),(0,a.kt)("p",null,"\u89c6\u56fe\u5f15\u64ce\u8d1f\u8d23\u6839\u636e\u89c6\u56fe\u6a21\u677f\u521b\u5efa HTML\u3002\u89c6\u56fe\u901a\u5e38\u662f HTML \u548c\u7f16\u7a0b\u8bed\u8a00\u7684\u67d0\u79cd\u6df7\u5408\u3002\u652f\u6301\u53d8\u91cf\u5b9a\u4e49\u3001\u65b9\u6cd5\u8c03\u7528\u53ca\u903b\u8f91\u7f16\u5199\u3002"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5e95\u5c42\u96c6\u6210\u4e86\u5fae\u8f6f\u63d0\u4f9b\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Razor")," \u89c6\u56fe\u5f15\u64ce\u7ec4\u4ef6\u5e76\u63d0\u4f9b\u66f4\u52a0\u7075\u6d3b\u65b9\u4fbf\u7684\u8bed\u6cd5\u7cd6\u3002"),(0,a.kt)("h2",{id:"172-\u89c6\u56fe\u5f15\u64ce\u4f5c\u7528"},"17.2 \u89c6\u56fe\u5f15\u64ce\u4f5c\u7528"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"strong"},"ASP.NET Core")," \u5b8c\u6574\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"Razor")," \u8bed\u6cd5")),(0,a.kt)("li",{parentName:"ul"},"\u6839\u636e\u4e0d\u540c\u7684\u6570\u636e\u7f16\u8bd1\u6a21\u677f\u4ea7\u751f\u4e0d\u540c\u7684\u8f93\u51fa"),(0,a.kt)("li",{parentName:"ul"},"\u5b9e\u73b0\u5f3a\u5927\u7684\u63d2\u4ef6\u5316\u673a\u5236"),(0,a.kt)("li",{parentName:"ul"},"\u5b9e\u73b0\u5168\u7ad9\u9875\u9762\u9759\u6001\u5316"),(0,a.kt)("li",{parentName:"ul"},"\u53ef\u4ee5\u7528\u4f5c\u90ae\u4ef6\u6a21\u677f\u3001\u77ed\u4fe1\u6a21\u677f\u3001\u4f18\u60e0\u5238\u4fe1\u606f\u6a21\u677f\u7b49")),(0,a.kt)("h2",{id:"173-\u57fa\u7840\u4f7f\u7528"},"17.3 \u57fa\u7840\u4f7f\u7528"),(0,a.kt)("h3",{id:"1731-\u6ce8\u518c\u670d\u52a1"},"17.3.1 \u6ce8\u518c\u670d\u52a1"),(0,a.kt)("p",null,"\u4f7f\u7528\u4e4b\u524d\u9700\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c ",(0,a.kt)("inlineCode",{parentName:"p"},"\u89c6\u56fe\u5f15\u64ce\u670d\u52a1"),"\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public void ConfigureServices(IServiceCollection services)\n{\n services.AddViewEngine();\n}\n")),(0,a.kt)("h3",{id:"1732-\u4f7f\u7528\u65b9\u5f0f"},"17.3.2 \u4f7f\u7528\u65b9\u5f0f"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u6784\u9020\u51fd\u6570\u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"li"},"IViewEngine"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,9,12}",showLineNumbers:!0,"":!0,"{2,9,12}":!0},'using Furion.DynamicApiController;\nusing Furion.ViewEngine;\n\nnamespace Furion.Application\n{\n public class ViewEngineService : IDynamicApiController\n {\n private readonly IViewEngine _viewEngine;\n public ViewEngineService(IViewEngine viewEngine)\n {\n _viewEngine = viewEngine;\n var result = _viewEngine.RunCompile("Hello @Model.Name", new { Name = "Furion" });\n }\n }\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5b57\u7b26\u4e32\u65b9\u5f0f")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = "Hello @Model.Name".RunCompile(new { Name = "Furion" });\n')),(0,a.kt)("h3",{id:"1733-\u5f31\u7c7b\u578b\u6a21\u677f"},"17.3.3 \u5f31\u7c7b\u578b\u6a21\u677f"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = _viewEngine.RunCompile("Hello @Model.Name", new { Name = "Furion" });\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"Hello Furion\n")),(0,a.kt)("p",null,"\u652f\u6301\u5f02\u6b65 ",(0,a.kt)("inlineCode",{parentName:"p"},"RunCompileAsync")),(0,a.kt)("h3",{id:"1734-\u5f3a\u7c7b\u578b\u6a21\u677f"},"17.3.4 \u5f3a\u7c7b\u578b\u6a21\u677f"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = _viewEngine.RunCompile(@"\nHello @Model.Name\n@foreach(var item in Model.Items)\n{\n

@item

\n}\n", new TestModel\n{\n Name = "Furion",\n Items = new[] { 3, 1, 2 }\n});\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"Hello Furion\n

3

\n

1

\n

2

\n")),(0,a.kt)("p",null,"\u652f\u6301\u5f02\u6b65 ",(0,a.kt)("inlineCode",{parentName:"p"},"RunCompileAsync")),(0,a.kt)("h3",{id:"1735-\u9ad8\u6027\u80fd\u6a21\u677f\u7f13\u5b58-"},"17.3.5 \u9ad8\u6027\u80fd\u6a21\u677f\u7f13\u5b58 \ud83e\udd47"),(0,a.kt)("p",null,"\u7531\u4e8e\u6a21\u677f\u7f16\u8bd1\u9700\u8981\u6d88\u8017\u5927\u91cf\u7684\u6027\u80fd\uff0c\u6240\u4ee5\u5efa\u8bae\u4f7f\u7528\u5e26 ",(0,a.kt)("inlineCode",{parentName:"p"},"FromCached")," \u7ed3\u5c3e\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"RunCompileFromCached")," \u66ff\u4ee3\u3002\u8c03\u7528\u8be5\u65b9\u6cd5\u540e\u4f1a\u81ea\u52a8\u5c06\u6a21\u677f\u7f16\u8bd1\u6210 ",(0,a.kt)("inlineCode",{parentName:"p"},".dll")," \u4ee5\u4fbf\u4e0b\u6b21\u4f7f\u7528\u3002\u51cf\u5c11\u7b2c\u4e8c\u6b21\u4e4b\u540e\u4f7f\u7528\u6a21\u677f\u7684\u6027\u80fd\u635f\u8017\u3002"),(0,a.kt)("p",null,"\u5982\uff0c\u5f3a\u7c7b\u578b\u6a21\u677f\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = _viewEngine.RunCompileFromCached(@"\nHello @Model.Name\n@foreach(var item in Model.Items)\n{\n

@item

\n}\n", new TestModel\n{\n Name = "Furion",\n Items = new[] { 3, 1, 2 }\n});\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"Hello Furion\n

3

\n

1

\n

2

\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u8c03\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"RunCompileFromCached")," \u65b9\u6cd5\u4e4b\u540e\u5c06\u4f1a\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"MD5")," \u52a0\u5bc6\u6a21\u677f\u5e76\u751f\u6210 ",(0,a.kt)("inlineCode",{parentName:"strong"},"MD5"),"\u5b57\u7b26\u4e32\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},".dll")," \u5b58\u653e\u5728\u7f51\u7ad9\u6839\u76ee\u5f55\u4e0b\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"templates")," \u76ee\u5f55\u4e2d\u3002\u53ea\u8981\u6a21\u677f\u5185\u5bb9\u4e0d\u53d8\uff0c\u6570\u636e\u53d1\u751f\u6539\u53d8\u4e5f\u4e0d\u4f1a\u91cd\u65b0\u7f16\u8bd1\u6a21\u677f\u3002\u8fd9\u6837\u5927\u5927\u7684\u63d0\u9ad8\u4e86\u9996\u6b21\u4e4b\u540e\u7684\u6027\u80fd\u3002")),(0,a.kt)("p",null,"\u5982\uff0c\u4f20\u5165\u65b0\u7684\u6570\u636e\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {10}",showLineNumbers:!0,"":!0,"{10}":!0},'var result = _viewEngine.RunCompileFromCached(@"\nHello @Model.Name\n@foreach(var item in Model.Items)\n{\n

@item

\n}\n", new TestModel\n{\n Name = "Furion",\n Items = new[] { 5,6,7,8 }\n});\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"Hello Furion\n

5

\n

6

\n

7

\n

8

\n")),(0,a.kt)("p",null,"\u6a21\u677f\u4e0d\u518d\u91cd\u65b0\u7f16\u8bd1\uff0c\u53ea\u662f\u91cd\u65b0\u66ff\u6362\u6570\u636e\u3002"),(0,a.kt)("h2",{id:"174-\u9ad8\u7ea7\u7528\u6cd5"},"17.4 \u9ad8\u7ea7\u7528\u6cd5"),(0,a.kt)("p",null,"\u9ad8\u7ea7\u7528\u6cd5\u652f\u6301\u5c06\u7279\u5b9a\u7a0b\u5e8f\u96c6\u3001\u7279\u5b9a\u547d\u540d\u7a7a\u95f4\u3001\u7279\u5b9a\u7c7b\u578b\u5f15\u5165\u5230\u6a21\u677f\u4e2d\u4f7f\u7528\u3002"),(0,a.kt)("h3",{id:"1741-\u6dfb\u52a0\u7a0b\u5e8f\u96c6"},"17.4.1 \u6dfb\u52a0\u7a0b\u5e8f\u96c6"),(0,a.kt)("p",null,"\u6bd4\u5982\u8fd9\u91cc\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"System.IO")," \u7a0b\u5e8f\u96c6\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = _viewEngine.RunCompileFromCached(@"
@System.IO.Path.Combine(""Furion"", ""ViewEngine"")
", builderAction: builder =>\n {\n builder.AddAssemblyReferenceByName("System.IO");\n });\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"
Furion\\\\ViewEngine
\n")),(0,a.kt)("p",null,"\u53e6\u5916\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u591a\u79cd\u65b9\u5f0f\u52a0\u8f7d\u7a0b\u5e8f\u96c6\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'builder.AddAssemblyReferenceByName("System.Security"); // \u901a\u8fc7\u540d\u79f0\nbuilder.AddAssemblyReference(typeof(System.IO.File)); // \u901a\u8fc7\u7c7b\u578b\nbuilder.AddAssemblyReference(Assembly.Load("source")); // \u901a\u8fc7\u5143\u6570\u636e\u5f15\u7528\n')),(0,a.kt)("h3",{id:"1742-\u6dfb\u52a0\u547d\u540d\u7a7a\u95f4"},"17.4.2 \u6dfb\u52a0\u547d\u540d\u7a7a\u95f4"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = _viewEngine.RunCompileFromCached(@"
@Path.Combine(""Furion"", ""ViewEngine"")
", builderAction: builder =>\n {\n builder.AddUsing("System.IO");\n builder.AddAssemblyReferenceByName("System.IO");\n });\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"
Furion\\\\ViewEngine
\n")),(0,a.kt)("p",null,"\u4e5f\u652f\u6301\u52a0\u5165\u591a\u4e2a ",(0,a.kt)("inlineCode",{parentName:"p"},"using"),"\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'builder.AddUsing("System.IO");\nbuilder.AddUsing("Furion");\n')),(0,a.kt)("h3",{id:"1743-\u5b9a\u4e49\u6a21\u677f\u65b9\u6cd5"},"17.4.3 \u5b9a\u4e49\u6a21\u677f\u65b9\u6cd5"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = _viewEngine.RunCompileFromCached(@"\n\n @{ RecursionTest(3); }\n\n\n@{\n void RecursionTest(int level)\n {\n if (level <= 0)\n {\n return;\n }\n\n
LEVEL: @level
\n @{ RecursionTest(level - 1); }\n }\n}\n");\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"\n
LEVEL: 3
\n
LEVEL: 2
\n
LEVEL: 1
\n\n")),(0,a.kt)("h3",{id:"1744-\u8c03\u7528\u7c7b\u65b9\u6cd5"},"17.4.4 \u8c03\u7528\u7c7b\u65b9\u6cd5"),(0,a.kt)("p",null,"\u5b9a\u4e49 ",(0,a.kt)("inlineCode",{parentName:"p"},"CustomModel")," \u7c7b\u5e76\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"p"},"ViewEngineModel")," \u57fa\u7c7b"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'public class CustomModel : ViewEngineModel\n{\n public int A { get; set; }\n public string B { get; set; }\n public string Decorator(object value)\n {\n return "-=" + value + "=-";\n }\n}\n')),(0,a.kt)("p",null,"\u5728\u6a21\u677f\u4e2d\u8c03\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Decorator(value)")," \u65b9\u6cd5\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var content = @"Hello @A, @B, @Decorator(123)";\n\nvar template = _viewEngine.Compile(content);\n\nvar result = template.Run(instance =>\n{\n instance.A = 10;\n instance.B = "Alex";\n});\n')),(0,a.kt)("p",null,"\u7ed3\u679c\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-html",metastring:"showLineNumbers",showLineNumbers:!0},"Hello 10, Alex, -=123=-\n")),(0,a.kt)("h2",{id:"175-iviewengine-\u63a5\u53e3"},"17.5 ",(0,a.kt)("inlineCode",{parentName:"h2"},"IViewEngine")," \u63a5\u53e3"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"IViewEngine")," \u63d0\u4f9b\u4e86\u7b80\u5355\u65b9\u4fbf\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"RunCompile")," \u65b9\u6cd5\uff0c\u4e5f\u63d0\u4f9b\u4e86\u6700\u539f\u59cb\u5316\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Compile")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"Run")," \u65b9\u6cd5\u3002"),(0,a.kt)("p",null,"\u901a\u8fc7\u539f\u59cb\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Compile")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"Run")," \u65b9\u6cd5\u53ef\u4ee5\u5b9e\u73b0\u5f88\u591a\u590d\u6742\u7684\u903b\u8f91\u548c\u81ea\u5b9a\u4e49\u6307\u4ee4\u96c6\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'/// \n/// \u7f16\u8bd1\u6a21\u677f\n/// \n/// \n/// \n/// \nIViewEngineTemplate Compile(string content, Action builderAction = null);\n/// \n/// \u7f16\u8bd1\u6a21\u677f\n/// \n/// \n/// \n/// \nTask CompileAsync(string content, Action builderAction = null);\n/// \n/// \u7f16\u8bd1\u6a21\u677f\n/// \n/// \n/// \n/// \n/// \nIViewEngineTemplate Compile(string content, Action builderAction = null)\n where T : IViewEngineModel;\n/// \n/// \u7f16\u8bd1\u6a21\u677f\n/// \n/// \n/// \n/// \n/// \nTask> CompileAsync(string content, Action builderAction = null)\n where T : IViewEngineModel;\n')),(0,a.kt)("h2",{id:"176-\u5b57\u7b26\u4e32\u6a21\u677f\u66ff\u6362\u5f15\u64ce"},"17.6 \u5b57\u7b26\u4e32\u6a21\u677f\u66ff\u6362\u5f15\u64ce"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u9664\u4e86\u5185\u7f6e\u89c6\u56fe\u5f15\u64ce\u4e4b\u5916\uff0c\u8fd8\u652f\u6301\u4ee5\u4e0b\u51e0\u79cd\u6a21\u677f\u66ff\u6362\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u63d0\u4f9b\u6570\u636e\u6a21\u677f\u65b9\u5f0f\nvar str = "\u6211\u53eb{name}".Render(new Dictionary{ {"name", "Furion"} });\nvar str = "\u6211\u53eb{Name}".Render(new { Name = "Furion" });\nvar str = "\u6211\u53eb{Detail.Name}".Render(new { Detail = new { Name = "Furoin" } });\n\n// \u4ece\u914d\u7f6e\u8bfb\u53d6\u65b9\u5f0f\nvar str = "\u6211\u53eb#(Furion:Address)".Render();\n')),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "Furion": {\n "Address": "https://www.furion.icu"\n }\n}\n')),(0,a.kt)("h2",{id:"177-\u53cd\u9988\u4e0e\u5efa\u8bae"},"17.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/612f2d9e.5cb6d11d.js b/handbook/build/assets/js/612f2d9e.5cb6d11d.js new file mode 100644 index 0000000000..797dbcd6a0 --- /dev/null +++ b/handbook/build/assets/js/612f2d9e.5cb6d11d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[2114],{3905:function(t,e,n){n.d(e,{Zo:function(){return c},kt:function(){return h}});var i=n(7294);function o(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function r(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,i)}return n}function a(t){for(var e=1;e=0||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}var p=i.createContext({}),m=function(t){var e=i.useContext(p),n=e;return t&&(n="function"==typeof t?t(e):a(a({},e),t)),n},c=function(t){var e=m(t.components);return i.createElement(p.Provider,{value:e},t.children)},u={inlineCode:"code",wrapper:function(t){var e=t.children;return i.createElement(i.Fragment,{},e)}},s=i.forwardRef((function(t,e){var n=t.components,o=t.mdxType,r=t.originalType,p=t.parentName,c=l(t,["components","mdxType","originalType","parentName"]),s=m(n),h=o,w=s["".concat(p,".").concat(h)]||s[h]||u[h]||r;return n?i.createElement(w,a(a({ref:e},c),{},{components:n})):i.createElement(w,a({ref:e},c))}));function h(t,e){var n=arguments,o=e&&e.mdxType;if("string"==typeof t||o){var r=n.length,a=new Array(r);a[0]=s;var l={};for(var p in e)hasOwnProperty.call(e,p)&&(l[p]=e[p]);l.originalType=t,l.mdxType="string"==typeof t?t:o,a[1]=l;for(var m=2;m=0||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}var p=i.createContext({}),m=function(t){var e=i.useContext(p),n=e;return t&&(n="function"==typeof t?t(e):a(a({},e),t)),n},c=function(t){var e=m(t.components);return i.createElement(p.Provider,{value:e},t.children)},u={inlineCode:"code",wrapper:function(t){var e=t.children;return i.createElement(i.Fragment,{},e)}},s=i.forwardRef((function(t,e){var n=t.components,o=t.mdxType,r=t.originalType,p=t.parentName,c=l(t,["components","mdxType","originalType","parentName"]),s=m(n),h=o,w=s["".concat(p,".").concat(h)]||s[h]||u[h]||r;return n?i.createElement(w,a(a({ref:e},c),{},{components:n})):i.createElement(w,a({ref:e},c))}));function h(t,e){var n=arguments,o=e&&e.mdxType;if("string"==typeof t||o){var r=n.length,a=new Array(r);a[0]=s;var l={};for(var p in e)hasOwnProperty.call(e,p)&&(l[p]=e[p]);l.originalType=t,l.mdxType="string"==typeof t?t:o,a[1]=l;for(var m=2;m0})).map((function(e){return[e-1,[i]]}));return{lineClassNames:Object.fromEntries(c),code:n}}if(void 0===r)return{lineClassNames:{},code:n};for(var s=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return E(["js","jsBlock"],t);case"jsx":case"tsx":return E(["js","jsBlock","jsx"],t);case"html":return E(["js","jsBlock","html"],t);case"python":case"py":case"bash":return E(["bash"],t);case"markdown":case"md":return E(["html","jsx","bash"],t);default:return E(Object.keys(b),t)}}(r,a),u=n.split("\n"),m=Object.fromEntries(a.map((function(e){return[e.className,{start:0,range:""}]}))),d=Object.fromEntries(a.filter((function(e){return e.line})).map((function(e){var t=e.className;return[e.line,t]}))),p=Object.fromEntries(a.filter((function(e){return e.block})).map((function(e){var t=e.className;return[e.block.start,t]}))),f=Object.fromEntries(a.filter((function(e){return e.block})).map((function(e){var t=e.className;return[e.block.end,t]}))),h=0;h0&&e[n-1]===t?e:e.concat(t)},M=function(e,t){var n=e.plain,r=Object.create(null),a=e.styles.reduce((function(e,n){var r=n.languages,a=n.style;return r&&!r.includes(t)||n.types.forEach((function(t){var n=z({},e[t],a);e[t]=n})),e}),r);return a.root=n,a.plain=z({},n,{backgroundColor:null}),a};function H(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&-1===t.indexOf(r)&&(n[r]=e[r]);return n}var P=function(e){function t(){for(var t=this,n=[],r=arguments.length;r--;)n[r]=arguments[r];e.apply(this,n),S(this,"getThemeDict",(function(e){if(void 0!==t.themeDict&&e.theme===t.prevTheme&&e.language===t.prevLanguage)return t.themeDict;t.prevTheme=e.theme,t.prevLanguage=e.language;var n=e.theme?M(e.theme,e.language):void 0;return t.themeDict=n})),S(this,"getLineProps",(function(e){var n=e.key,r=e.className,a=e.style,o=z({},H(e,["key","className","style","line"]),{className:"token-line",style:void 0,key:void 0}),l=t.getThemeDict(t.props);return void 0!==l&&(o.style=l.plain),void 0!==a&&(o.style=void 0!==o.style?z({},o.style,a):a),void 0!==n&&(o.key=n),r&&(o.className+=" "+r),o})),S(this,"getStyleForToken",(function(e){var n=e.types,r=e.empty,a=n.length,o=t.getThemeDict(t.props);if(void 0!==o){if(1===a&&"plain"===n[0])return r?{display:"inline-block"}:void 0;if(1===a&&!r)return o[n[0]];var l=r?{display:"inline-block"}:{},i=n.map((function(e){return o[e]}));return Object.assign.apply(Object,[l].concat(i))}})),S(this,"getTokenProps",(function(e){var n=e.key,r=e.className,a=e.style,o=e.token,l=z({},H(e,["key","className","style","token"]),{className:"token "+o.types.join(" "),children:o.content,style:t.getStyleForToken(o),key:void 0});return void 0!==a&&(l.style=void 0!==l.style?z({},l.style,a):a),void 0!==n&&(l.key=n),r&&(l.className+=" "+r),l})),S(this,"tokenize",(function(e,t,n,r){var a={code:t,grammar:n,language:r,tokens:[]};e.hooks.run("before-tokenize",a);var o=a.tokens=e.tokenize(a.code,a.grammar,a.language);return e.hooks.run("after-tokenize",a),o}))}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.render=function(){var e=this.props,t=e.Prism,n=e.language,r=e.code,a=e.children,o=this.getThemeDict(this.props),l=t.languages[n];return a({tokens:function(e){for(var t=[[]],n=[e],r=[0],a=[e.length],o=0,l=0,i=[],c=[i];l>-1;){for(;(o=r[l]++)0?u:["plain"],s=m):(u=O(u,m.type),m.alias&&(u=O(u,m.alias)),s=m.content),"string"==typeof s){var d=s.split(A),p=d.length;i.push({types:u,content:d[0]});for(var f=1;f0&&(o=a.getRangeAt(0)),t.append(n),n.select(),n.selectionStart=0,n.selectionEnd=e.length;let l=!1;try{l=document.execCommand("copy")}catch{}n.remove(),o&&(a.removeAllRanges(),a.addRange(o)),r&&r.focus()}(t),l(!0),i.current=window.setTimeout((function(){l(!1)}),1e3)}),[t]);return(0,a.useEffect)((function(){return function(){return window.clearTimeout(i.current)}}),[]),a.createElement("button",{type:"button","aria-label":o?(0,q.I)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,q.I)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,q.I)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,s.Z)("clean-btn",n,G.copyButton,o&&G.copyButtonCopied),onClick:c},a.createElement("span",{className:G.copyButtonIcons,"aria-hidden":"true"},a.createElement("svg",{className:G.copyButtonIcon,viewBox:"0 0 24 24"},a.createElement("path",{d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"})),a.createElement("svg",{className:G.copyButtonSuccessIcon,viewBox:"0 0 24 24"},a.createElement("path",{d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"}))))}var $="wordWrapButtonIcon_Bwma",Y="wordWrapButtonEnabled_EoeP";function Q(e){var t=e.className,n=e.onClick,r=e.isEnabled,o=(0,q.I)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return a.createElement("button",{type:"button",onClick:n,className:(0,s.Z)("clean-btn",t,r&&Y),"aria-label":o,title:o},a.createElement("svg",{className:$,viewBox:"0 0 24 24","aria-hidden":"true"},a.createElement("path",{fill:"currentColor",d:"M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3l3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"})))}function J(e){var t,n,o,l,i,c,u,p,f,h,v,y=e.children,b=e.className,E=void 0===b?"":b,N=e.metastring,C=e.title,Z=e.showLineNumbers,w=e.language,L=(0,m.L)().prism,x=L.defaultLanguage,S=L.magicComments,z=null!=(t=null!=w?w:null==(n=E.split(" ").find((function(e){return e.startsWith("language-")})))?void 0:n.replace(/language-/,""))?t:x,A=d(),I=(o=(0,a.useState)(!1),l=o[0],i=o[1],c=(0,a.useState)(!1),u=c[0],p=c[1],f=(0,a.useRef)(null),h=(0,a.useCallback)((function(){var e=f.current.querySelector("code");l?e.removeAttribute("style"):(e.style.whiteSpace="pre-wrap",e.style.overflowWrap="anywhere"),i((function(e){return!e}))}),[f,l]),v=(0,a.useCallback)((function(){var e=f.current,t=e.scrollWidth>e.clientWidth||f.current.querySelector("code").hasAttribute("style");p(t)}),[f]),j(f,v),(0,a.useEffect)((function(){v()}),[l,v]),(0,a.useEffect)((function(){return window.addEventListener("resize",v,{passive:!0}),function(){window.removeEventListener("resize",v)}}),[v]),{codeBlockRef:f,isEnabled:l,isCodeScrollable:u,toggle:h}),O=function(e){var t,n;return null!=(t=null==e||null==(n=e.match(g))?void 0:n.groups.title)?t:""}(N)||C,M=k(y,{metastring:N,language:z,magicComments:S}),H=M.lineClassNames,P=M.code,D=null!=Z?Z:function(e){return Boolean(null==e?void 0:e.includes("showLineNumbers"))}(N);return a.createElement(B,{as:"div",className:(0,s.Z)(E,z&&!E.includes("language-"+z)&&"language-"+z)},O&&a.createElement("div",{className:T.codeBlockTitle},O),a.createElement("div",{className:T.codeBlockContent},a.createElement(V,(0,r.Z)({},_,{theme:A,code:P,language:null!=z?z:"text"}),(function(e){var t=e.className,n=e.tokens,r=e.getLineProps,o=e.getTokenProps;return a.createElement("pre",{tabIndex:0,ref:I.codeBlockRef,className:(0,s.Z)(t,T.codeBlock,"thin-scrollbar")},a.createElement("code",{className:(0,s.Z)(T.codeBlockLines,D&&T.codeBlockLinesWithNumbering)},n.map((function(e,t){return a.createElement(F,{key:t,line:e,getLineProps:r,getTokenProps:o,classNames:H[t],showLineNumbers:D})}))))})),a.createElement("div",{className:T.buttonGroup},(I.isEnabled||I.isCodeScrollable)&&a.createElement(Q,{className:T.codeButton,onClick:function(){return I.toggle()},isEnabled:I.isEnabled}),a.createElement(U,{className:T.codeButton,code:P}))))}var K=["children"];function X(e){var t=e.children,n=(0,o.Z)(e,K),l=(0,c.Z)(),i=function(e){return a.Children.toArray(e).some((function(e){return(0,a.isValidElement)(e)}))?e:Array.isArray(e)?e.join(""):e}(t),s="string"==typeof i?J:Z;return a.createElement(s,(0,r.Z)({key:String(l)},n),i)}var ee=n(8746);var te=n(7459),ne=n(7940),re="details_lb9f",ae="isBrowser_bmU9",oe="collapsibleContent_i85q",le=["summary","children"];function ie(e){return!!e&&("SUMMARY"===e.tagName||ie(e.parentElement))}function ce(e,t){return!!e&&(e===t||ce(e.parentElement,t))}function se(e){var t=e.summary,n=e.children,l=(0,o.Z)(e,le),i=(0,c.Z)(),s=(0,a.useRef)(null),u=(0,ne.u)({initialState:!l.open}),m=u.collapsed,d=u.setCollapsed,p=(0,a.useState)(l.open),f=p[0],h=p[1];return a.createElement("details",(0,r.Z)({},l,{ref:s,open:f,"data-collapsed":m,className:(0,te.Z)(re,i&&ae,l.className),onMouseDown:function(e){ie(e.target)&&e.detail>1&&e.preventDefault()},onClick:function(e){e.stopPropagation();var t=e.target;ie(t)&&ce(t,s.current)&&(e.preventDefault(),m?(d(!1),h(!0)):d(!0))}}),null!=t?t:a.createElement("summary",null,"Details"),a.createElement(ne.z,{lazy:!1,collapsed:m,disableSSRStyle:!0,onCollapseTransitionEnd:function(e){d(e),h(!e)}},a.createElement("div",{className:oe},n)))}var ue="details_b_Ee";function me(e){var t=Object.assign({},e);return a.createElement(se,(0,r.Z)({},t,{className:(0,s.Z)("alert alert--info",ue,t.className)}))}var de=n(4055);function pe(e){return a.createElement(de.Z,e)}var fe="containsTaskList_mC6p";var he="img_ev3q";var ve="admonition_LlT9",ge="admonitionHeading_tbUL",ye="admonitionIcon_kALy",be="admonitionContent_S0QG";var Ee={note:{infimaClassName:"secondary",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 14 16"},a.createElement("path",{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))},label:a.createElement(q.Z,{id:"theme.admonition.note",description:"The default label used for the Note admonition (:::note)"},"note")},tip:{infimaClassName:"success",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 12 16"},a.createElement("path",{fillRule:"evenodd",d:"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"}))},label:a.createElement(q.Z,{id:"theme.admonition.tip",description:"The default label used for the Tip admonition (:::tip)"},"tip")},danger:{infimaClassName:"danger",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 12 16"},a.createElement("path",{fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"}))},label:a.createElement(q.Z,{id:"theme.admonition.danger",description:"The default label used for the Danger admonition (:::danger)"},"danger")},info:{infimaClassName:"info",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 14 16"},a.createElement("path",{fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"}))},label:a.createElement(q.Z,{id:"theme.admonition.info",description:"The default label used for the Info admonition (:::info)"},"info")},caution:{infimaClassName:"warning",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 16 16"},a.createElement("path",{fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"}))},label:a.createElement(q.Z,{id:"theme.admonition.caution",description:"The default label used for the Caution admonition (:::caution)"},"caution")}},ke={secondary:"note",important:"info",success:"tip",warning:"danger"};function Ne(e){var t,n=function(e){var t=a.Children.toArray(e),n=t.find((function(e){var t;return a.isValidElement(e)&&"mdxAdmonitionTitle"===(null==(t=e.props)?void 0:t.mdxType)})),r=a.createElement(a.Fragment,null,t.filter((function(e){return e!==n})));return{mdxAdmonitionTitle:n,rest:r}}(e.children),r=n.mdxAdmonitionTitle,o=n.rest;return Object.assign({},e,{title:null!=(t=e.title)?t:r,children:o})}var Ce={head:function(e){var t=a.Children.map(e.children,(function(e){return a.isValidElement(e)?function(e){var t;if(null!=(t=e.props)&&t.mdxType&&e.props.originalType){var n=e.props,r=(n.mdxType,n.originalType,(0,o.Z)(n,i));return a.createElement(e.props.originalType,r)}return e}(e):e}));return a.createElement(l.Z,e,t)},code:function(e){var t=["a","b","big","i","span","em","strong","sup","sub","small"];return a.Children.toArray(e.children).every((function(e){var n;return"string"==typeof e&&!e.includes("\n")||(0,a.isValidElement)(e)&&t.includes(null==(n=e.props)?void 0:n.mdxType)}))?a.createElement("code",e):a.createElement(X,e)},a:function(e){return a.createElement(ee.Z,e)},pre:function(e){var t;return a.createElement(X,(0,a.isValidElement)(e.children)&&"code"===(null==(t=e.children.props)?void 0:t.originalType)?e.children.props:Object.assign({},e))},details:function(e){var t=a.Children.toArray(e.children),n=t.find((function(e){var t;return a.isValidElement(e)&&"summary"===(null==(t=e.props)?void 0:t.mdxType)})),o=a.createElement(a.Fragment,null,t.filter((function(e){return e!==n})));return a.createElement(me,(0,r.Z)({},e,{summary:n}),o)},ul:function(e){return a.createElement("ul",(0,r.Z)({},e,{className:(t=e.className,(0,s.Z)(t,(null==t?void 0:t.includes("contains-task-list"))&&fe))}));var t},img:function(e){return a.createElement("img",(0,r.Z)({loading:"lazy"},e,{className:(t=e.className,(0,s.Z)(t,he))}));var t},h1:function(e){return a.createElement(pe,(0,r.Z)({as:"h1"},e))},h2:function(e){return a.createElement(pe,(0,r.Z)({as:"h2"},e))},h3:function(e){return a.createElement(pe,(0,r.Z)({as:"h3"},e))},h4:function(e){return a.createElement(pe,(0,r.Z)({as:"h4"},e))},h5:function(e){return a.createElement(pe,(0,r.Z)({as:"h5"},e))},h6:function(e){return a.createElement(pe,(0,r.Z)({as:"h6"},e))},admonition:function(e){var t=Ne(e),n=t.children,r=t.type,o=t.title,l=t.icon,i=function(e){var t,n=null!=(t=ke[e])?t:e;return Ee[n]||(console.warn('No admonition config found for admonition type "'+n+'". Using Info as fallback.'),Ee.info)}(r),c=null!=o?o:i.label,u=i.iconComponent,m=null!=l?l:a.createElement(u,null);return a.createElement("div",{className:(0,s.Z)(p.k.common.admonition,p.k.common.admonitionType(e.type),"alert","alert--"+i.infimaClassName,ve)},a.createElement("div",{className:ge},a.createElement("span",{className:ye},m),c),a.createElement("div",{className:be},n))}}},7594:function(e,t){function n(e){let t,n=[];for(let r of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(r))n.push(parseInt(r,10));else if(t=r.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,r,a,o]=t;if(r&&o){r=parseInt(r),o=parseInt(o);const e=r0})).map((function(e){return[e-1,[i]]}));return{lineClassNames:Object.fromEntries(c),code:n}}if(void 0===r)return{lineClassNames:{},code:n};for(var s=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return E(["js","jsBlock"],t);case"jsx":case"tsx":return E(["js","jsBlock","jsx"],t);case"html":return E(["js","jsBlock","html"],t);case"python":case"py":case"bash":return E(["bash"],t);case"markdown":case"md":return E(["html","jsx","bash"],t);default:return E(Object.keys(b),t)}}(r,a),u=n.split("\n"),m=Object.fromEntries(a.map((function(e){return[e.className,{start:0,range:""}]}))),d=Object.fromEntries(a.filter((function(e){return e.line})).map((function(e){var t=e.className;return[e.line,t]}))),p=Object.fromEntries(a.filter((function(e){return e.block})).map((function(e){var t=e.className;return[e.block.start,t]}))),f=Object.fromEntries(a.filter((function(e){return e.block})).map((function(e){var t=e.className;return[e.block.end,t]}))),h=0;h0&&e[n-1]===t?e:e.concat(t)},M=function(e,t){var n=e.plain,r=Object.create(null),a=e.styles.reduce((function(e,n){var r=n.languages,a=n.style;return r&&!r.includes(t)||n.types.forEach((function(t){var n=z({},e[t],a);e[t]=n})),e}),r);return a.root=n,a.plain=z({},n,{backgroundColor:null}),a};function H(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&-1===t.indexOf(r)&&(n[r]=e[r]);return n}var P=function(e){function t(){for(var t=this,n=[],r=arguments.length;r--;)n[r]=arguments[r];e.apply(this,n),S(this,"getThemeDict",(function(e){if(void 0!==t.themeDict&&e.theme===t.prevTheme&&e.language===t.prevLanguage)return t.themeDict;t.prevTheme=e.theme,t.prevLanguage=e.language;var n=e.theme?M(e.theme,e.language):void 0;return t.themeDict=n})),S(this,"getLineProps",(function(e){var n=e.key,r=e.className,a=e.style,o=z({},H(e,["key","className","style","line"]),{className:"token-line",style:void 0,key:void 0}),l=t.getThemeDict(t.props);return void 0!==l&&(o.style=l.plain),void 0!==a&&(o.style=void 0!==o.style?z({},o.style,a):a),void 0!==n&&(o.key=n),r&&(o.className+=" "+r),o})),S(this,"getStyleForToken",(function(e){var n=e.types,r=e.empty,a=n.length,o=t.getThemeDict(t.props);if(void 0!==o){if(1===a&&"plain"===n[0])return r?{display:"inline-block"}:void 0;if(1===a&&!r)return o[n[0]];var l=r?{display:"inline-block"}:{},i=n.map((function(e){return o[e]}));return Object.assign.apply(Object,[l].concat(i))}})),S(this,"getTokenProps",(function(e){var n=e.key,r=e.className,a=e.style,o=e.token,l=z({},H(e,["key","className","style","token"]),{className:"token "+o.types.join(" "),children:o.content,style:t.getStyleForToken(o),key:void 0});return void 0!==a&&(l.style=void 0!==l.style?z({},l.style,a):a),void 0!==n&&(l.key=n),r&&(l.className+=" "+r),l})),S(this,"tokenize",(function(e,t,n,r){var a={code:t,grammar:n,language:r,tokens:[]};e.hooks.run("before-tokenize",a);var o=a.tokens=e.tokenize(a.code,a.grammar,a.language);return e.hooks.run("after-tokenize",a),o}))}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.render=function(){var e=this.props,t=e.Prism,n=e.language,r=e.code,a=e.children,o=this.getThemeDict(this.props),l=t.languages[n];return a({tokens:function(e){for(var t=[[]],n=[e],r=[0],a=[e.length],o=0,l=0,i=[],c=[i];l>-1;){for(;(o=r[l]++)0?u:["plain"],s=m):(u=O(u,m.type),m.alias&&(u=O(u,m.alias)),s=m.content),"string"==typeof s){var d=s.split(A),p=d.length;i.push({types:u,content:d[0]});for(var f=1;f0&&(o=a.getRangeAt(0)),t.append(n),n.select(),n.selectionStart=0,n.selectionEnd=e.length;let l=!1;try{l=document.execCommand("copy")}catch{}n.remove(),o&&(a.removeAllRanges(),a.addRange(o)),r&&r.focus()}(t),l(!0),i.current=window.setTimeout((function(){l(!1)}),1e3)}),[t]);return(0,a.useEffect)((function(){return function(){return window.clearTimeout(i.current)}}),[]),a.createElement("button",{type:"button","aria-label":o?(0,q.I)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,q.I)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,q.I)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,s.Z)("clean-btn",n,G.copyButton,o&&G.copyButtonCopied),onClick:c},a.createElement("span",{className:G.copyButtonIcons,"aria-hidden":"true"},a.createElement("svg",{className:G.copyButtonIcon,viewBox:"0 0 24 24"},a.createElement("path",{d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"})),a.createElement("svg",{className:G.copyButtonSuccessIcon,viewBox:"0 0 24 24"},a.createElement("path",{d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"}))))}var $="wordWrapButtonIcon_Bwma",Y="wordWrapButtonEnabled_EoeP";function Q(e){var t=e.className,n=e.onClick,r=e.isEnabled,o=(0,q.I)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return a.createElement("button",{type:"button",onClick:n,className:(0,s.Z)("clean-btn",t,r&&Y),"aria-label":o,title:o},a.createElement("svg",{className:$,viewBox:"0 0 24 24","aria-hidden":"true"},a.createElement("path",{fill:"currentColor",d:"M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3l3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"})))}function J(e){var t,n,o,l,i,c,u,p,f,h,v,y=e.children,b=e.className,E=void 0===b?"":b,N=e.metastring,C=e.title,Z=e.showLineNumbers,w=e.language,L=(0,m.L)().prism,x=L.defaultLanguage,S=L.magicComments,z=null!=(t=null!=w?w:null==(n=E.split(" ").find((function(e){return e.startsWith("language-")})))?void 0:n.replace(/language-/,""))?t:x,A=d(),I=(o=(0,a.useState)(!1),l=o[0],i=o[1],c=(0,a.useState)(!1),u=c[0],p=c[1],f=(0,a.useRef)(null),h=(0,a.useCallback)((function(){var e=f.current.querySelector("code");l?e.removeAttribute("style"):(e.style.whiteSpace="pre-wrap",e.style.overflowWrap="anywhere"),i((function(e){return!e}))}),[f,l]),v=(0,a.useCallback)((function(){var e=f.current,t=e.scrollWidth>e.clientWidth||f.current.querySelector("code").hasAttribute("style");p(t)}),[f]),j(f,v),(0,a.useEffect)((function(){v()}),[l,v]),(0,a.useEffect)((function(){return window.addEventListener("resize",v,{passive:!0}),function(){window.removeEventListener("resize",v)}}),[v]),{codeBlockRef:f,isEnabled:l,isCodeScrollable:u,toggle:h}),O=function(e){var t,n;return null!=(t=null==e||null==(n=e.match(g))?void 0:n.groups.title)?t:""}(N)||C,M=k(y,{metastring:N,language:z,magicComments:S}),H=M.lineClassNames,P=M.code,D=null!=Z?Z:function(e){return Boolean(null==e?void 0:e.includes("showLineNumbers"))}(N);return a.createElement(B,{as:"div",className:(0,s.Z)(E,z&&!E.includes("language-"+z)&&"language-"+z)},O&&a.createElement("div",{className:T.codeBlockTitle},O),a.createElement("div",{className:T.codeBlockContent},a.createElement(V,(0,r.Z)({},_,{theme:A,code:P,language:null!=z?z:"text"}),(function(e){var t=e.className,n=e.tokens,r=e.getLineProps,o=e.getTokenProps;return a.createElement("pre",{tabIndex:0,ref:I.codeBlockRef,className:(0,s.Z)(t,T.codeBlock,"thin-scrollbar")},a.createElement("code",{className:(0,s.Z)(T.codeBlockLines,D&&T.codeBlockLinesWithNumbering)},n.map((function(e,t){return a.createElement(F,{key:t,line:e,getLineProps:r,getTokenProps:o,classNames:H[t],showLineNumbers:D})}))))})),a.createElement("div",{className:T.buttonGroup},(I.isEnabled||I.isCodeScrollable)&&a.createElement(Q,{className:T.codeButton,onClick:function(){return I.toggle()},isEnabled:I.isEnabled}),a.createElement(U,{className:T.codeButton,code:P}))))}var K=["children"];function X(e){var t=e.children,n=(0,o.Z)(e,K),l=(0,c.Z)(),i=function(e){return a.Children.toArray(e).some((function(e){return(0,a.isValidElement)(e)}))?e:Array.isArray(e)?e.join(""):e}(t),s="string"==typeof i?J:Z;return a.createElement(s,(0,r.Z)({key:String(l)},n),i)}var ee=n(9960);var te=n(7459),ne=n(6043),re="details_lb9f",ae="isBrowser_bmU9",oe="collapsibleContent_i85q",le=["summary","children"];function ie(e){return!!e&&("SUMMARY"===e.tagName||ie(e.parentElement))}function ce(e,t){return!!e&&(e===t||ce(e.parentElement,t))}function se(e){var t=e.summary,n=e.children,l=(0,o.Z)(e,le),i=(0,c.Z)(),s=(0,a.useRef)(null),u=(0,ne.u)({initialState:!l.open}),m=u.collapsed,d=u.setCollapsed,p=(0,a.useState)(l.open),f=p[0],h=p[1];return a.createElement("details",(0,r.Z)({},l,{ref:s,open:f,"data-collapsed":m,className:(0,te.Z)(re,i&&ae,l.className),onMouseDown:function(e){ie(e.target)&&e.detail>1&&e.preventDefault()},onClick:function(e){e.stopPropagation();var t=e.target;ie(t)&&ce(t,s.current)&&(e.preventDefault(),m?(d(!1),h(!0)):d(!0))}}),null!=t?t:a.createElement("summary",null,"Details"),a.createElement(ne.z,{lazy:!1,collapsed:m,disableSSRStyle:!0,onCollapseTransitionEnd:function(e){d(e),h(!e)}},a.createElement("div",{className:oe},n)))}var ue="details_b_Ee";function me(e){var t=Object.assign({},e);return a.createElement(se,(0,r.Z)({},t,{className:(0,s.Z)("alert alert--info",ue,t.className)}))}var de=n(2503);function pe(e){return a.createElement(de.Z,e)}var fe="containsTaskList_mC6p";var he="img_ev3q";var ve="admonition_LlT9",ge="admonitionHeading_tbUL",ye="admonitionIcon_kALy",be="admonitionContent_S0QG";var Ee={note:{infimaClassName:"secondary",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 14 16"},a.createElement("path",{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))},label:a.createElement(q.Z,{id:"theme.admonition.note",description:"The default label used for the Note admonition (:::note)"},"note")},tip:{infimaClassName:"success",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 12 16"},a.createElement("path",{fillRule:"evenodd",d:"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"}))},label:a.createElement(q.Z,{id:"theme.admonition.tip",description:"The default label used for the Tip admonition (:::tip)"},"tip")},danger:{infimaClassName:"danger",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 12 16"},a.createElement("path",{fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"}))},label:a.createElement(q.Z,{id:"theme.admonition.danger",description:"The default label used for the Danger admonition (:::danger)"},"danger")},info:{infimaClassName:"info",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 14 16"},a.createElement("path",{fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"}))},label:a.createElement(q.Z,{id:"theme.admonition.info",description:"The default label used for the Info admonition (:::info)"},"info")},caution:{infimaClassName:"warning",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 16 16"},a.createElement("path",{fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"}))},label:a.createElement(q.Z,{id:"theme.admonition.caution",description:"The default label used for the Caution admonition (:::caution)"},"caution")}},ke={secondary:"note",important:"info",success:"tip",warning:"danger"};function Ne(e){var t,n=function(e){var t=a.Children.toArray(e),n=t.find((function(e){var t;return a.isValidElement(e)&&"mdxAdmonitionTitle"===(null==(t=e.props)?void 0:t.mdxType)})),r=a.createElement(a.Fragment,null,t.filter((function(e){return e!==n})));return{mdxAdmonitionTitle:n,rest:r}}(e.children),r=n.mdxAdmonitionTitle,o=n.rest;return Object.assign({},e,{title:null!=(t=e.title)?t:r,children:o})}var Ce={head:function(e){var t=a.Children.map(e.children,(function(e){return a.isValidElement(e)?function(e){var t;if(null!=(t=e.props)&&t.mdxType&&e.props.originalType){var n=e.props,r=(n.mdxType,n.originalType,(0,o.Z)(n,i));return a.createElement(e.props.originalType,r)}return e}(e):e}));return a.createElement(l.Z,e,t)},code:function(e){var t=["a","b","big","i","span","em","strong","sup","sub","small"];return a.Children.toArray(e.children).every((function(e){var n;return"string"==typeof e&&!e.includes("\n")||(0,a.isValidElement)(e)&&t.includes(null==(n=e.props)?void 0:n.mdxType)}))?a.createElement("code",e):a.createElement(X,e)},a:function(e){return a.createElement(ee.Z,e)},pre:function(e){var t;return a.createElement(X,(0,a.isValidElement)(e.children)&&"code"===(null==(t=e.children.props)?void 0:t.originalType)?e.children.props:Object.assign({},e))},details:function(e){var t=a.Children.toArray(e.children),n=t.find((function(e){var t;return a.isValidElement(e)&&"summary"===(null==(t=e.props)?void 0:t.mdxType)})),o=a.createElement(a.Fragment,null,t.filter((function(e){return e!==n})));return a.createElement(me,(0,r.Z)({},e,{summary:n}),o)},ul:function(e){return a.createElement("ul",(0,r.Z)({},e,{className:(t=e.className,(0,s.Z)(t,(null==t?void 0:t.includes("contains-task-list"))&&fe))}));var t},img:function(e){return a.createElement("img",(0,r.Z)({loading:"lazy"},e,{className:(t=e.className,(0,s.Z)(t,he))}));var t},h1:function(e){return a.createElement(pe,(0,r.Z)({as:"h1"},e))},h2:function(e){return a.createElement(pe,(0,r.Z)({as:"h2"},e))},h3:function(e){return a.createElement(pe,(0,r.Z)({as:"h3"},e))},h4:function(e){return a.createElement(pe,(0,r.Z)({as:"h4"},e))},h5:function(e){return a.createElement(pe,(0,r.Z)({as:"h5"},e))},h6:function(e){return a.createElement(pe,(0,r.Z)({as:"h6"},e))},admonition:function(e){var t=Ne(e),n=t.children,r=t.type,o=t.title,l=t.icon,i=function(e){var t,n=null!=(t=ke[e])?t:e;return Ee[n]||(console.warn('No admonition config found for admonition type "'+n+'". Using Info as fallback.'),Ee.info)}(r),c=null!=o?o:i.label,u=i.iconComponent,m=null!=l?l:a.createElement(u,null);return a.createElement("div",{className:(0,s.Z)(p.k.common.admonition,p.k.common.admonitionType(e.type),"alert","alert--"+i.infimaClassName,ve)},a.createElement("div",{className:ge},a.createElement("span",{className:ye},m),c),a.createElement("div",{className:be},n))}}},7594:function(e,t){function n(e){let t,n=[];for(let r of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(r))n.push(parseInt(r,10));else if(t=r.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,r,a,o]=t;if(r&&o){r=parseInt(r),o=parseInt(o);const e=r=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var p=n.createContext({}),u=function(e){var t=n.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},l=function(e){var t=u(e.components);return n.createElement(p.Provider,{value:t},e.children)},f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},s=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,p=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),s=u(r),m=o,d=s["".concat(p,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(d,i(i({ref:t},l),{},{components:r})):n.createElement(d,i({ref:t},l))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=s;var c={};for(var p in t)hasOwnProperty.call(t,p)&&(c[p]=t[p]);c.originalType=e,c.mdxType="string"==typeof e?e:o,i[1]=c;for(var u=2;u=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var p=n.createContext({}),u=function(e){var t=n.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},l=function(e){var t=u(e.components);return n.createElement(p.Provider,{value:t},e.children)},f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},s=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,p=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),s=u(r),m=o,d=s["".concat(p,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(d,i(i({ref:t},l),{},{components:r})):n.createElement(d,i({ref:t},l))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=s;var c={};for(var p in t)hasOwnProperty.call(t,p)&&(c[p]=t[p]);c.originalType=e,c.mdxType="string"==typeof e?e:o,i[1]=c;for(var u=2;u=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var o=i.createContext({}),u=function(e){var n=i.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},p=function(e){var n=u(e.components);return i.createElement(o.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},m=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,o=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),m=u(t),k=r,d=m["".concat(o,".").concat(k)]||m[k]||c[k]||a;return t?i.createElement(d,l(l({ref:n},p),{},{components:t})):i.createElement(d,l({ref:n},p))}));function k(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,l=new Array(a);l[0]=m;var s={};for(var o in n)hasOwnProperty.call(n,o)&&(s[o]=n[o]);s.originalType=e,s.mdxType="string"==typeof e?e:r,l[1]=s;for(var u=2;uxUnit \u5355\u5143\u6d4b\u8bd5\u9879\u76ee",id:"36151-\u521b\u5efa-xunit-\u5355\u5143\u6d4b\u8bd5\u9879\u76ee",level:3},{value:"36.1.5.2 \u7b2c\u4e00\u4e2a\u6d4b\u8bd5\u65b9\u6cd5",id:"36152-\u7b2c\u4e00\u4e2a\u6d4b\u8bd5\u65b9\u6cd5",level:3},{value:"36.1.5.3 \u8fd0\u884c\u6d4b\u8bd5",id:"36153-\u8fd0\u884c\u6d4b\u8bd5",level:3},{value:"36.1.5.4 \u591a\u4e2a\u6d4b\u8bd5\u65b9\u6cd5\u6d4b\u8bd5",id:"36154-\u591a\u4e2a\u6d4b\u8bd5\u65b9\u6cd5\u6d4b\u8bd5",level:3},{value:"36.1.5.5 \u91cd\u590d/\u56de\u5f52\u6d4b\u8bd5",id:"36155-\u91cd\u590d\u56de\u5f52\u6d4b\u8bd5",level:3},{value:"36.1.6 \u96c6\u6210 Furion \u5f3a\u5927\u529f\u80fd",id:"3616-\u96c6\u6210-furion-\u5f3a\u5927\u529f\u80fd",level:2},{value:"36.1.6.1 \u5b89\u88c5 Furion.Xunit \u5305",id:"36161-\u5b89\u88c5-furionxunit-\u5305",level:3},{value:"36.1.6.2 \u6dfb\u52a0\u521d\u59cb\u914d\u7f6e\u7c7b",id:"36162-\u6dfb\u52a0\u521d\u59cb\u914d\u7f6e\u7c7b",level:3},{value:"36.1.6.3 \u4f7f\u7528 Furion \u5b8c\u6574\u529f\u80fd",id:"36163-\u4f7f\u7528-furion-\u5b8c\u6574\u529f\u80fd",level:3},{value:"36.1.7 \u5e26\u53c2\u6570\u7684\u6d4b\u8bd5\u65b9\u6cd5",id:"3617-\u5e26\u53c2\u6570\u7684\u6d4b\u8bd5\u65b9\u6cd5",level:2},{value:"36.1.8 \u5982\u4f55\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165",id:"3618-\u5982\u4f55\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165",level:2},{value:"36.1.8.1 \u7f16\u5199\u4e00\u4e2a ICalcService \u63a5\u53e3\u53ca\u5b9e\u73b0\u7c7b",id:"36181-\u7f16\u5199\u4e00\u4e2a-icalcservice-\u63a5\u53e3\u53ca\u5b9e\u73b0\u7c7b",level:3},{value:"36.1.8.2 \u5728\u6d4b\u8bd5\u7c7b\u4e2d\u8c03\u7528",id:"36182-\u5728\u6d4b\u8bd5\u7c7b\u4e2d\u8c03\u7528",level:3},{value:"36.1.8.3 \u8f93\u51fa\u65e5\u5fd7",id:"36183-\u8f93\u51fa\u65e5\u5fd7",level:3},{value:"36.1.8.4 \u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165\u4f5c\u7528\u57df\u91ca\u653e",id:"36184-\u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165\u4f5c\u7528\u57df\u91ca\u653e",level:3},{value:"36.1.8.5 \u6d4b\u8bd5\u91ca\u653e\u8d44\u6e90",id:"36185-\u6d4b\u8bd5\u91ca\u653e\u8d44\u6e90",level:3},{value:"36.1.8.6 [AssemblyFixture] \u7279\u6027",id:"36186-assemblyfixture-\u7279\u6027",level:3},{value:"36.1.8.7 IClassFixture<> \u5355\u4e2a\u6ce8\u5165",id:"36187-iclassfixture-\u5355\u4e2a\u6ce8\u5165",level:3},{value:"36.1.8.8 ICollectionFixture<> \u591a\u4e2a\u6ce8\u5165",id:"36188-icollectionfixture-\u591a\u4e2a\u6ce8\u5165",level:3},{value:"36.1.9 Web \u96c6\u6210\u6d4b\u8bd5",id:"3619-web-\u96c6\u6210\u6d4b\u8bd5",level:2},{value:"36.1.9.1 \u5bf9\u73b0\u6709\u9879\u76ee\u8fdb\u884c\u96c6\u6210\u6d4b\u8bd5",id:"36191-\u5bf9\u73b0\u6709\u9879\u76ee\u8fdb\u884c\u96c6\u6210\u6d4b\u8bd5",level:3},{value:"36.1.9.2 \u72ec\u7acb\u4e3b\u673a\u65b9\u5f0f\u6d4b\u8bd5",id:"36192-\u72ec\u7acb\u4e3b\u673a\u65b9\u5f0f\u6d4b\u8bd5",level:3},{value:"36.1.9.3 \u7cfb\u7edf\u96c6\u6210/\u73af\u5883/\u914d\u7f6e\u90e8\u7f72\u6d4b\u8bd5",id:"36193-\u7cfb\u7edf\u96c6\u6210\u73af\u5883\u914d\u7f6e\u90e8\u7f72\u6d4b\u8bd5",level:3},{value:"36.1.9.4 \u96c6\u6210 Furion.Xunit \u62d3\u5c55",id:"36194-\u96c6\u6210-furionxunit-\u62d3\u5c55",level:3},{value:"36.1.10 Assert \u65ad\u8a00",id:"36110-assert-\u65ad\u8a00",level:2},{value:"36.1.11 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"36111-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],k={toc:m};function d(e){var n=e.components,t=(0,r.Z)(e,s);return(0,a.kt)("wrapper",(0,i.Z)({},k,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"3611-\u5173\u4e8e\u5355\u5143\u6d4b\u8bd5"},"36.1.1 \u5173\u4e8e\u5355\u5143\u6d4b\u8bd5"),(0,a.kt)("p",null,"\u5f15\u7528\u81ea\u767e\u5ea6\u767e\u79d1\uff1a"),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},"\u5355\u5143\u6d4b\u8bd5\uff08unit testing\uff09\uff0c\u662f\u6307\u5bf9\u8f6f\u4ef6\u4e2d\u7684\u6700\u5c0f\u53ef\u6d4b\u8bd5\u5355\u5143\u8fdb\u884c\u68c0\u67e5\u548c\u9a8c\u8bc1\u3002\u5bf9\u4e8e\u5355\u5143\u6d4b\u8bd5\u4e2d\u5355\u5143\u7684\u542b\u4e49\uff0c\u4e00\u822c\u6765\u8bf4\uff0c\u8981\u6839\u636e\u5b9e\u9645\u60c5\u51b5\u53bb\u5224\u5b9a\u5176\u5177\u4f53\u542b\u4e49\uff0c\u5982 C \u8bed\u8a00\u4e2d\u5355\u5143\u6307\u4e00\u4e2a\u51fd\u6570\uff0cJava \u91cc\u5355\u5143\u6307\u4e00\u4e2a\u7c7b\uff0c\u56fe\u5f62\u5316\u7684\u8f6f\u4ef6\u4e2d\u53ef\u4ee5\u6307\u4e00\u4e2a\u7a97\u53e3\u6216\u4e00\u4e2a\u83dc\u5355\u7b49\u3002\u603b\u7684\u6765\u8bf4\uff0c\u5355\u5143\u5c31\u662f\u4eba\u4e3a\u89c4\u5b9a\u7684\u6700\u5c0f\u7684\u88ab\u6d4b\u529f\u80fd\u6a21\u5757\u3002\u5355\u5143\u6d4b\u8bd5\u662f\u5728\u8f6f\u4ef6\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u8981\u8fdb\u884c\u7684\u6700\u4f4e\u7ea7\u522b\u7684\u6d4b\u8bd5\u6d3b\u52a8\uff0c\u8f6f\u4ef6\u7684\u72ec\u7acb\u5355\u5143\u5c06\u5728\u4e0e\u7a0b\u5e8f\u7684\u5176\u4ed6\u90e8\u5206\u76f8\u9694\u79bb\u7684\u60c5\u51b5\u4e0b\u8fdb\u884c\u6d4b\u8bd5\u3002")),(0,a.kt)("h2",{id:"3612-\u5355\u5143\u6d4b\u8bd5\u597d\u5904"},"36.1.2 \u5355\u5143\u6d4b\u8bd5\u597d\u5904"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u6d88\u706d\u4f4e\u7ea7\u9519\u8bef"))),(0,a.kt)("p",null,"\u57fa\u672c\u7684\u5355\u5143\u6d4b\u8bd5\uff0c\u53ef\u4ee5\u5728\u7cfb\u7edf\u6d4b\u8bd5\u4e4b\u524d\uff0c\u628a\u5927\u90e8\u5206\u6bd4\u8f83\u4f4e\u7ea7\u7684\u9519\u8bef\u90fd\u6d88\u706d\u6389\uff0c\u51cf\u5c11\u7cfb\u7edf\u6d4b\u8bd5\u8fc7\u7a0b\u4e2d\u7684\u95ee\u9898\uff0c\u8fd9\u6837\u4e5f\u5c31\u51cf\u5c11\u4e86\u7cfb\u7edf\u6d4b\u8bd5\u4e2d\u5b9a\u4f4d\u548c\u89e3\u51b3\u95ee\u9898\u7684\u65f6\u95f4\u6210\u672c\u4e86\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u627e\u51fa\u6f5c\u5728\u7684 bug"))),(0,a.kt)("p",null,"\u67d0\u4e9b\u7c7b\u578b\u7684 bug\uff0c\u9760\u7cfb\u7edf\u6d4b\u8bd5\u662f\u5f88\u96be\u627e\u5230\u7684\u3002\u4f8b\u5982\u4e00\u4e9b\u4ee3\u7801\u5206\u652f\uff0c\u5e73\u65f6 99%\u7684\u573a\u666f\u57fa\u672c\u4e0a\u90fd\u8d70\u4e0d\u5230\uff0c\u4f46\u4e00\u65e6\u8d70\u5230\u4e86\uff0c\u5982\u679c\u6ca1\u6709\u63d0\u524d\u6d4b\u8bd5\u597d\uff0c\u90a3\u4e48\u53ef\u80fd\u5c31\u662f\u4e00\u4e2a\u707e\u96be\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u4e0a\u7ebf\u524d\u7684\u4fdd\u8bc1"))),(0,a.kt)("p",null,"\u52a0\u4e86\u65b0\u4ee3\u7801\uff0c\u4e0a\u7ebf\u524d\u8dd1\u4e00\u628a\u5355\u5143\u6d4b\u8bd5\uff0c\u90fd\u901a\u8fc7\uff0c\u8bf4\u660e\u4ee3\u7801\u53ef\u80fd\u6ca1\u6709\u5f71\u54cd\u5230\u4e4b\u524d\u7684\u903b\u8f91\uff0c\u8fd9\u6837\u4e0a\u7ebf\u4e5f\u6bd4\u8f83\u653e\u5fc3\u3002\u5982\u679c\u4e4b\u524d\u7684\u5355\u5143\u6d4b\u8bd5\u8dd1\u4e0d\u8fc7\uff0c\u90a3\u4e48\u5f88\u6709\u53ef\u80fd\u65b0\u7684\u4ee3\u7801\u6709\u6f5c\u5728\u7684\u95ee\u9898\uff0c\u8d76\u7d27\u4fee\u590d\u53bb\u5427\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u91cd\u6784\u4ee3\u7801\u7684\u673a\u4f1a"))),(0,a.kt)("p",null,"\u5199\u5355\u5143\u6d4b\u8bd5\u7684\u8fc7\u7a0b\u4e2d\uff0c\u4f60\u53ef\u80fd\u4f1a\u987a\u624b\u628a\u4e00\u4e9b code \u91cd\u6784\u4e86\uff0c\u4e3a\u4ec0\u4e48\uff1f\u4e3e\u4f8b\uff0c\u4e00\u4e9b\u957f\u5f97\u975e\u5e38\u50cf\u7684\u4ee3\u7801\uff0c\u5982\u679c\u6bcf\u6b21\u90fd\u8981\u5199\u4e00\u5806\u6d4b\u8bd5\u4ee3\u7801\u53bb\u6d4b\u540c\u6837\u7684 code\uff0c\u4f60\u4f1a\u4e0d\u4f1a\u6293\u72c2\uff1f\u4e0d\u6d4b\u5427\uff0c\u8986\u76d6\u7387\u53c8\u4e0a\u4e0d\u53bb\uff0c\u4e8e\u662f\u6211\u5c31\u4f1a\u60f3\u65b9\u8bbe\u6cd5\u628a\u5f85\u6d4b\u8bd5\u7684 code \u6539\u5f97\u5c3d\u91cf\u7684\u7cbe\u7b80\uff0c\u91cd\u590d\u4ee3\u7801\u51cf\u5c11\uff0c\u8fd9\u6837\u8986\u76d6\u7387\u4e0a\u53bb\u4e86\uff0c\u6d4b\u8bd5\u4e5f\u597d\u6d4b\u4e86\uff0c\u4ee3\u7801\u4e5f\u7b80\u6d01\u4e86\u3002\u5982\u679c\u6ca1\u6709\u5355\u5143\u6d4b\u8bd5\u548c\u8986\u76d6\u7387\u7684\u8981\u6c42\u7684\u8bdd\uff0c\u5766\u767d\u8bf4\u53ef\u80fd\u4e00\u6765\u81ea\u5df1\u4e0d\u4f1a\u53d1\u73b0\u8fd9\u4e9b\u91cd\u590d\u7684 code\uff0c\u53e6\u4e00\u65b9\u9762\u5373\u4f7f\u53d1\u73b0\u4e86\uff0c\u53ef\u80fd\u4e5f\u6ca1\u6709\u592a\u5927\u7684\u52a8\u529b\u53bb\u6539\u8fdb\u3002"),(0,a.kt)("p",null,"\u53e6\u5916\uff0c\u7531\u4e8e\u5355\u5143\u6d4b\u8bd5\u4e2d\uff0c\u4f60\u9700\u8981\u5c1d\u8bd5\u53bb\u8986\u76d6\u4e00\u4e9b\u5f02\u5e38\u5206\u652f\uff0c\u8fd9\u662f\u7cfb\u7edf\u6d4b\u8bd5\u5e38\u5e38\u8d70\u4e0d\u5230\u7684\u5730\u65b9\uff0c\u4e8e\u662f\u5c31\u4f1a\u5f15\u8d77\u4f60\u7684\u4e00\u4e9b\u601d\u8003\uff0c\u4f8b\u5982\u8fd9\u4e2a\u5f02\u5e38\u5206\u652f\u662f\u5426\u771f\u7684\u9700\u8981\uff1f\u662f\u5426\u771f\u7684\u4f1a\u53d1\u751f\uff1f\u5bf9\u4e8e\u4e00\u4e9b\u5b9e\u9645\u4e0a\u7edd\u5bf9\u4e0d\u4f1a\u51fa\u9519\u7684\u51fd\u6570\uff0c\u90a3\u4e48\u6211\u89c9\u5f97\u53ef\u80fd\u5f02\u5e38\u5206\u652f\u662f\u6ca1\u5fc5\u8981\u5b58\u5728\u7684\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u91cd\u65b0 review \u4ee3\u7801\u7684\u673a\u4f1a"))),(0,a.kt)("p",null,"\u5199 UT \u7684\u8fc7\u7a0b\u4e2d\uff0c\u6211\u603b\u662f\u4f1a\u597d\u597d\u770b\u54ea\u4e9b\u4ee3\u7801\u6267\u884c\u5230\u4e86\uff0c\u54ea\u4e9b\u4ee3\u7801\u6ca1\u6709\u6267\u884c\u5230\uff0c\u8fd9\u5176\u5b9e\u4e5f\u662f\u4e00\u4e2a review \u81ea\u5df1\u4ee3\u7801\u7684\u673a\u4f1a\uff0c\u6709\u4e9b\u65f6\u5019\uff0c\u5e76\u4e0d\u662f UT \u672c\u8eab\u5e2e\u6211\u627e\u5230 bug\uff0c\u800c\u662f\u56de\u5934 review \u81ea\u5df1\u4ee3\u7801\u7684\u65f6\u5019\u53d1\u73b0\u7684\u3002"),(0,a.kt)("h2",{id:"3613-\u5355\u5143\u6d4b\u8bd5\u7c7b\u578b"},"36.1.3 \u5355\u5143\u6d4b\u8bd5\u7c7b\u578b"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u57fa\u4e8e API \u63a5\u53e3\u6d4b\u8bd5\uff08\u767d\u76d2 + \u6d45\u5ea6\u9ed1\u76d2\u6d4b\u8bd5\uff09"),(0,a.kt)("li",{parentName:"ul"},"\u57fa\u4e8e\u9879\u76ee\u4ee3\u7801\u6d4b\u8bd5\uff08\u6df1\u5ea6\u9ed1\u76d2\u6d4b\u8bd5\uff09")),(0,a.kt)("h2",{id:"3614-\u4e3b\u6d41\u7684\u5355\u5143\u6d4b\u8bd5\u5e93"},"36.1.4 \u4e3b\u6d41\u7684\u5355\u5143\u6d4b\u8bd5\u5e93"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"xUnit"),"\uff08",(0,a.kt)("strong",{parentName:"li"},"\u6700\u6d41\u884c\u7684\u5e93\uff0c\u63a8\u8350"),"\uff09"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"NUnit")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"MSTest"))),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u5728\u672c\u7ae0\u8282\uff0c",(0,a.kt)("inlineCode",{parentName:"strong"},"Furion")," \u6846\u67b6\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"xUnit")," \u5e93\u8fdb\u884c\u5355\u5143\u6d4b\u8bd5\u3002")),(0,a.kt)("h2",{id:"3615-\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"36.1.5 \u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,a.kt)("h3",{id:"36151-\u521b\u5efa-xunit-\u5355\u5143\u6d4b\u8bd5\u9879\u76ee"},"36.1.5.1 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h3"},"xUnit")," \u5355\u5143\u6d4b\u8bd5\u9879\u76ee"),(0,a.kt)("img",{src:(0,l.Z)("img/ut1.png")}),(0,a.kt)("h3",{id:"36152-\u7b2c\u4e00\u4e2a\u6d4b\u8bd5\u65b9\u6cd5"},"36.1.5.2 \u7b2c\u4e00\u4e2a\u6d4b\u8bd5\u65b9\u6cd5"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,7,10}",showLineNumbers:!0,"":!0,"{1,7,10}":!0},"using Xunit;\n\nnamespace TestProject1\n{\n public class UnitTest1\n {\n [Fact]\n public void Test1()\n {\n Assert.Equal(2, 1 + 1);\n }\n }\n}\n")),(0,a.kt)("p",null,"\u5355\u5143\u6d4b\u8bd5\u5b9e\u9645\u4e0a\u662f\u901a\u8fc7\u666e\u901a\u7684\u7c7b\u7684\u65b9\u6cd5\u8fdb\u884c\u6a21\u5757\u529f\u80fd\u6d4b\u8bd5\uff0c\u5177\u4f53\u6d4b\u8bd5\u5219\u662f\u6807\u8bb0\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"[Fact]")," \u7279\u6027\u7684\u65b9\u6cd5\uff0c\u5728\u65b9\u6cd5\u4e2d\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Assert")," \u7c7b\u63d0\u4f9b\u7684\u9759\u6001\u65b9\u6cd5\u8fdb\u884c ",(0,a.kt)("inlineCode",{parentName:"p"},"\u65ad\u8a00"),"\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"\u65ad\u8a00")," \u6210\u529f\uff0c\u5219\u6d4b\u8bd5\u901a\u8fc7\uff0c\u5426\u5219\u6d4b\u8bd5\u4e0d\u901a\u8fc7\u3002"),(0,a.kt)("h3",{id:"36153-\u8fd0\u884c\u6d4b\u8bd5"},"36.1.5.3 \u8fd0\u884c\u6d4b\u8bd5"),(0,a.kt)("p",null,"\u5728\u5355\u5143\u6d4b\u8bd5\u9879\u76ee\u4e2d ",(0,a.kt)("inlineCode",{parentName:"p"},"\u53f3\u952e")," \u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u8fd0\u884c\u6d4b\u8bd5")," \u5e76\u6253\u5f00 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6d4b\u8bd5\u8d44\u6e90\u7ba1\u7406\u5668")," \u5373\u53ef\u67e5\u770b\u6d4b\u8bd5\u7ed3\u679c\u3002"),(0,a.kt)("img",{src:(0,l.Z)("img/ut2.png")}),(0,a.kt)("img",{src:(0,l.Z)("img/ut3.png")}),(0,a.kt)("h3",{id:"36154-\u591a\u4e2a\u6d4b\u8bd5\u65b9\u6cd5\u6d4b\u8bd5"},"36.1.5.4 \u591a\u4e2a\u6d4b\u8bd5\u65b9\u6cd5\u6d4b\u8bd5"),(0,a.kt)("img",{src:(0,l.Z)("img/ut4.png")}),(0,a.kt)("h3",{id:"36155-\u91cd\u590d\u56de\u5f52\u6d4b\u8bd5"},"36.1.5.5 \u91cd\u590d/\u56de\u5f52\u6d4b\u8bd5"),(0,a.kt)("p",null,"\u540e\u7eed\u6dfb\u52a0\u66f4\u591a\u6d4b\u8bd5\u65b9\u6cd5\u53ea\u9700\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6d4b\u8bd5\u8d44\u6e90\u7ba1\u7406\u5668")," \u70b9\u51fb ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5728\u89c6\u56fe\u4e2d\u8fd0\u884c\u6240\u6709\u6d4b\u8bd5")," \u64ad\u653e\u6309\u94ae\u5373\u53ef\uff0c\u5982\u4e0b\u56fe"),(0,a.kt)("img",{src:(0,l.Z)("img/ut5.png")}),(0,a.kt)("h2",{id:"3616-\u96c6\u6210-furion-\u5f3a\u5927\u529f\u80fd"},"36.1.6 \u96c6\u6210 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Furion")," \u5f3a\u5927\u529f\u80fd"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u662f\u8de8\u5e73\u53f0\u3001\u8de8\u9879\u76ee\u7684\u5f00\u53d1\u6846\u67b6\uff0c\u652f\u6301\u4efb\u610f\u9879\u76ee\u7c7b\u578b\uff0c\u5305\u62ec\u5355\u5143\u6d4b\u8bd5\u9879\u76ee\u3002"),(0,a.kt)("h3",{id:"36161-\u5b89\u88c5-furionxunit-\u5305"},"36.1.6.1 \u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Furion.Xunit")," \u5305"),(0,a.kt)("admonition",{type:"note"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Furion")," \u7eaf\u51c0\u7248"),(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528\u7684\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Pure")," \u5219\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Pure.Xunit")," \u8fd9\u4e2a\u62d3\u5c55\u5305\u3002")),(0,a.kt)("p",null,"\u6253\u5f00 ",(0,a.kt)("inlineCode",{parentName:"p"},"Nuget")," \u7a0b\u5e8f\u5305\u63a7\u5236\u53f0\uff0c\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Xunit")," \u5305"),(0,a.kt)("img",{src:(0,l.Z)("img/ut6.png")}),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Xunit")," \u5df2\u7ecf\u5305\u542b ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u65e0\u9700\u518d\u6b21\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion"),"\u3002")),(0,a.kt)("h3",{id:"36162-\u6dfb\u52a0\u521d\u59cb\u914d\u7f6e\u7c7b"},"36.1.6.2 \u6dfb\u52a0\u521d\u59cb\u914d\u7f6e\u7c7b"),(0,a.kt)("p",null,"\u5728\u5355\u5143\u6d4b\u8bd5\u9879\u76ee\u6839\u76ee\u5f55\u4e0b\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"TestProgram.cs")," \u7c7b\uff0c\u5e76\u5199\u4e0b\u4ee5\u4e0b\u4ee3\u7801\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {6,13,18} title="TestProgram.cs"',showLineNumbers:!0,"{6,13,18}":!0,title:'"TestProgram.cs"'},'using Furion.Xunit;\nusing Xunit.Abstractions;\nusing Xunit.Sdk;\n\n// \u914d\u7f6e\u542f\u52a8\u7c7b\u7c7b\u578b\uff0c\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f TestProgram \u7c7b\u5b8c\u6574\u9650\u5b9a\u540d\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f\u5f53\u524d\u9879\u76ee\u7a0b\u5e8f\u96c6\u540d\u79f0\n[assembly: TestFramework("TestProject1.TestProgram", "TestProject1")]\n\nnamespace TestProject1;\n\n/// \n/// \u5355\u5143\u6d4b\u8bd5\u542f\u52a8\u7c7b\n/// \npublic class TestProgram : TestStartup\n{\n public TestProgram(IMessageSink messageSink) : base(messageSink)\n {\n // \u521d\u59cb\u5316 Furion\n Serve.Run(silence: true);\n }\n}\n')),(0,a.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"TestProgram.cs")," \u540d\u79f0\u53ef\u968f\u610f\uff0c\u53ea\u9700\u8981\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"p"},"TestStartup")," \u7c7b\u5373\u53ef\u3002")),(0,a.kt)("h3",{id:"36163-\u4f7f\u7528-furion-\u5b8c\u6574\u529f\u80fd"},"36.1.6.3 \u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Furion")," \u5b8c\u6574\u529f\u80fd"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u662f\u8de8\u5e73\u53f0\u3001\u8de8\u9879\u76ee\u7684\u5f00\u53d1\u6846\u67b6\uff0c\u4e0b\u9762\u5728\u5355\u5143\u6d4b\u8bd5\u4e2d\u6f14\u793a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u8fdc\u7a0b\u8bf7\u6c42")," \u5e76\u8bf7\u6c42 ",(0,a.kt)("inlineCode",{parentName:"p"},"https://www.baidu.com")," \u6570\u636e\uff0c\u5e76\u6d4b\u8bd5\u662f\u5426\u8bf7\u6c42\u6210\u529f\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5728\u6839\u76ee\u5f55\u4e0b\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u542f\u52a8\u7c7b\uff0c\u5e76\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"li"},"AppStartup"),":")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {8,13} title="Startup.cs"',showLineNumbers:!0,"{8,13}":!0,title:'"Startup.cs"'},"using Furion;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace TestProject1;\n\npublic class Startup : AppStartup\n{\n public void ConfigureServices(IServiceCollection services)\n {\n // \u6ce8\u518c\u8fdc\u7a0b\u670d\u52a1\n services.AddRemoteRequest();\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n }\n}\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u7f16\u5199\u6d4b\u8bd5\u65b9\u6cd5")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[Fact]\npublic async Task \u6d4b\u8bd5\u8bf7\u6c42\u767e\u5ea6()\n{\n var rep = await "https://www.baidu.com".GetAsync();\n Assert.True(rep.IsSuccessStatusCode);\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u67e5\u770b\u6d4b\u8bd5\u7ed3\u679c")),(0,a.kt)("img",{src:(0,l.Z)("img/ut7.png")}),(0,a.kt)("p",null,"\u5f88\u795e\u5947\u5427\uff01",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u652f\u6301\u4efb\u4f55\u9879\u76ee\u7c7b\u578b\uff0c\u4efb\u4f55\u5e73\u53f0\u4f7f\u7528\u3002"),(0,a.kt)("h2",{id:"3617-\u5e26\u53c2\u6570\u7684\u6d4b\u8bd5\u65b9\u6cd5"},"36.1.7 \u5e26\u53c2\u6570\u7684\u6d4b\u8bd5\u65b9\u6cd5"),(0,a.kt)("p",null,"\u4e0a\u9762\u4f8b\u5b50\u4e2d\uff0c\u6d4b\u8bd5\u65b9\u6cd5\u90fd\u662f\u6ca1\u6709\u53c2\u6570\u7684\uff0c\u6709\u65f6\u5019\u9700\u8981\u540c\u4e00\u4e2a\u65b9\u6cd5\u8f93\u5165\u591a\u4e2a\u4e0d\u540c\u7684\u503c\u8fdb\u884c\u6d4b\u8bd5\uff0c\u8fd9\u65f6\u5019\u5c31\u9700\u8981\u7528\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"[Theory]")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"[InlineData]")," \u7279\u6027\u4e86\u3002"),(0,a.kt)("p",null,"\u5982\uff0c\u4e0b\u9762\u6d4b\u8bd5\u4e24\u4e2a\u6570\u7684\u548c\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5947\u6570"),"\uff0c\u6d4b\u8bd5\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-4}",showLineNumbers:!0,"":!0,"{1-4}":!0},"[Theory]\n[InlineData(1, 2)]\n[InlineData(3, 4)]\n[InlineData(5, 7)]\npublic void \u5e26\u53c2\u6570\u6d4b\u8bd5(int i, int j)\n{\n Assert.NotEqual(0, (i + j) % 2);\n}\n")),(0,a.kt)("p",null,"\u6d4b\u8bd5\u7ed3\u679c\uff1a"),(0,a.kt)("img",{src:(0,l.Z)("img/ut8.png")}),(0,a.kt)("h2",{id:"3618-\u5982\u4f55\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165"},"36.1.8 \u5982\u4f55\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165"),(0,a.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u9700\u8981\u6d4b\u8bd5\u67d0\u63a5\u53e3\uff0c\u6216\u8005\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f\u89e3\u6790\u670d\u52a1\u5e76\u8c03\u7528\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Xunit")," \u63d0\u4f9b\u5b8c\u6574\u7684\u6784\u9020\u51fd\u6570\u6ce8\u5165\u3002"),(0,a.kt)("h3",{id:"36181-\u7f16\u5199\u4e00\u4e2a-icalcservice-\u63a5\u53e3\u53ca\u5b9e\u73b0\u7c7b"},"36.1.8.1 \u7f16\u5199\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"h3"},"ICalcService")," \u63a5\u53e3\u53ca\u5b9e\u73b0\u7c7b"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,10}",showLineNumbers:!0,"":!0,"{5,10}":!0},"using Furion.DependencyInjection;\n\nnamespace TestProject1.Services;\n\npublic interface ICalcService\n{\n int Plus(int i, int j);\n}\n\npublic class CalcService : ICalcService, ITransient // \u652f\u6301\u4efb\u4f55\u751f\u547d\u5468\u671f\n{\n public int Plus(int i, int j)\n {\n return i + j;\n }\n}\n")),(0,a.kt)("h3",{id:"36182-\u5728\u6d4b\u8bd5\u7c7b\u4e2d\u8c03\u7528"},"36.1.8.2 \u5728\u6d4b\u8bd5\u7c7b\u4e2d\u8c03\u7528"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,15,17}",showLineNumbers:!0,"":!0,"{9,15,17}":!0},"using TestProject1.Services;\nusing Xunit;\n\nnamespace TestProject1;\n\npublic class UnitTest1\n{\n private readonly ICalcService _calcService;\n public UnitTest1(ICalcService calcService)\n {\n _calcService = calcService;\n }\n\n [Fact]\n public void \u6d4b\u8bd5\u4e24\u4e2a\u6570\u7684\u548c()\n {\n Assert.Equal(3, _calcService.Plus(1, 2));\n }\n}\n")),(0,a.kt)("img",{src:(0,l.Z)("img/ut9.png")}),(0,a.kt)("h3",{id:"36183-\u8f93\u51fa\u65e5\u5fd7"},"36.1.8.3 \u8f93\u51fa\u65e5\u5fd7"),(0,a.kt)("p",null,"\u5982\u679c\u5728\u5355\u5143\u6d4b\u8bd5\u4e2d\u60f3\u8f93\u51fa\u65e5\u5fd7\uff0c\u53ea\u9700\u8981\u5728\u6784\u9020\u51fd\u6570\u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"p"},"ITestOutputHelper")," \u5373\u53ef\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,10,12,18}",showLineNumbers:!0,"":!0,"{2,10,12,18}":!0},'using Xunit;\nusing Xunit.Abstractions;\n\nnamespace TestProject1\n{\n public class UnitTest1\n {\n private readonly ITestOutputHelper Output;\n\n public UnitTest1(ITestOutputHelper tempOutput)\n {\n Output = tempOutput;\n }\n\n [Fact]\n public void Test_String_Equal()\n {\n Output.WriteLine("\u54c8\u54c8\u54c8\u54c8\uff0c\u6211\u662f Furion");\n Assert.NotEqual("Furion", "Fur");\n }\n }\n}\n')),(0,a.kt)("img",{src:(0,l.Z)("img/un3.png")}),(0,a.kt)("h3",{id:"36184-\u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165\u4f5c\u7528\u57df\u91ca\u653e"},"36.1.8.4 \u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165\u4f5c\u7528\u57df\u91ca\u653e"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u4f1a\u5728\u521b\u5efa\u5355\u5143\u6d4b\u8bd5\u5b9e\u4f8b\u65f6\u521b\u5efa\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"p"},"IServiceScope")," \u5bf9\u8c61\uff0c\u7b49\u8be5\u5b9e\u4f8b\u6240\u6709\u6d4b\u8bd5\u6848\u4f8b\u6267\u884c\u5b8c\u6bd5\u81ea\u52a8\u8c03\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Dispose"),"\uff0c\u7f16\u5199\u6d4b\u8bd5\u7684\u5f00\u53d1\u8005\u65e0\u9700\u5173\u6ce8\u3002"),(0,a.kt)("h3",{id:"36185-\u6d4b\u8bd5\u91ca\u653e\u8d44\u6e90"},"36.1.8.5 \u6d4b\u8bd5\u91ca\u653e\u8d44\u6e90"),(0,a.kt)("p",null,"\u6709\u65f6\u5019\uff0c\u6211\u4eec\u9700\u8981\u6d4b\u8bd5\u6210\u529f\u540e\u91ca\u653e\u4e00\u4e9b\u4e0d\u80fd\u53ca\u65f6\u91ca\u653e\u7684\u5bf9\u8c61\uff0c\u8fd9\u65f6\uff0c\u53ea\u9700\u8981\u5b9e\u73b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"IDisposable")," \u63a5\u53e3\u5373\u53ef\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,14-17}",showLineNumbers:!0,"":!0,"{6,14-17}":!0},'using System;\nusing Xunit;\n\nnamespace TestProject1\n{\n public class UnitTest1 : IDisposable\n {\n [Fact]\n public void Test_String_Equal()\n {\n Assert.NotEqual("Furion", "Fur");\n }\n\n public void Dispose()\n {\n // \u91ca\u653e\u4f60\u7684\u5bf9\u8c61\n }\n }\n}\n')),(0,a.kt)("h3",{id:"36186-assemblyfixture-\u7279\u6027"},"36.1.8.6 ",(0,a.kt)("inlineCode",{parentName:"h3"},"[AssemblyFixture]")," \u7279\u6027"),(0,a.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u53ef\u80fd\u4e0d\u9700\u8981\u5bf9\u7c7b\u8fdb\u884c\u4f9d\u8d56\u6ce8\u518c\uff0c\u6216\u8005\u65e0\u6cd5\u901a\u8fc7\u5916\u90e8\u8fdb\u884c\u6ce8\u518c\uff0c\u8fd9\u65f6\u5019\u53ef\u4ee5\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"[AssemblyFixture]")," \u7279\u6027\u5b9e\u73b0\u6784\u9020\u51fd\u6570\u6ce8\u5165\u4efb\u4f55\u7c7b\uff0c\u5982\uff1a"),(0,a.kt)("admonition",{title:"\u6709\u6548\u8303\u56f4\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"[AssemblyFixture]")," \u65b9\u5f0f\u5bf9\u6574\u4e2a\u5355\u5143\u6d4b\u8bd5\u7c7b\u6784\u9020\u51fd\u6570\u90fd\u6709\u6548\uff0c\u5982\u9700\u4e2a\u522b\u5355\u5143\u6d4b\u8bd5\u7c7b\u6709\u6548\u53ef\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IClassFixture<>")," \u6216 ",(0,a.kt)("inlineCode",{parentName:"p"},"ICollectionFixture<>")," + ",(0,a.kt)("inlineCode",{parentName:"p"},"[Collection]")," \u7ec4\u5408\u65b9\u5f0f\u3002")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5b9a\u4e49\u9700\u8981\u6ce8\u5165\u8fdb\u5355\u5143\u6d4b\u8bd5\u6784\u9020\u51fd\u6570\u4e2d\u7684\u7c7b"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},"public class MyAssemblyFixture : IDisposable\n{\n public static int InstantiationCount;\n\n public MyAssemblyFixture()\n {\n InstantiationCount++;\n }\n\n public void Dispose()\n {\n // \u505a\u4e00\u4e9b\u91ca\u653e\u5de5\u4f5c\n }\n}\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"strong"},"TestProgram.cs")," \u9876\u90e8\u5168\u5c40\u6ce8\u518c"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {11} title="TestProgram.cs"',showLineNumbers:!0,"{11}":!0,title:'"TestProgram.cs"'},'using Furion.Xunit;\nusing TestProject1;\nusing Xunit;\nusing Xunit.Abstractions;\nusing Xunit.Sdk;\n\n// \u914d\u7f6e\u542f\u52a8\u7c7b\u7c7b\u578b\uff0c\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f TestProgram \u7c7b\u5b8c\u6574\u9650\u5b9a\u540d\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f\u5f53\u524d\u9879\u76ee\u7a0b\u5e8f\u96c6\u540d\u79f0\n[assembly: TestFramework("TestProject1.TestProgram", "TestProject1")]\n\n// \u652f\u6301\u591a\u4e2a\n[assembly: AssemblyFixture(typeof(MyAssemblyFixture))]\n// [assembly: AssemblyFixture(typeof(XXXXFixture))]\n\nnamespace TestProject1;\n\n/// \n/// \u5355\u5143\u6d4b\u8bd5\u542f\u52a8\u7c7b\n/// \npublic class TestProgram : TestStartup\n{\n public TestProgram(IMessageSink messageSink) : base(messageSink)\n {\n Serve.Run(silence: true);\n }\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5728\u6d4b\u8bd5\u7c7b\u6784\u9020\u51fd\u6570\u6ce8\u5165"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {12,27}",showLineNumbers:!0,"{12,27}":!0},"using TestProject1.Services;\nusing Xunit;\n\nnamespace TestProject1;\n\npublic class UnitTest1\n{\n private readonly ICalcService _calcService;\n private readonly MyAssemblyFixture _fixture;\n\n public UnitTest1(ICalcService calcService\n , MyAssemblyFixture fixture)\n {\n _calcService = calcService;\n _fixture = fixture;\n }\n\n [Fact]\n public void \u6d4b\u8bd5\u4e24\u4e2a\u6570\u7684\u548c()\n {\n Assert.Equal(3, _calcService.Plus(1, 2));\n }\n\n [Fact]\n public void EnsureSingleton()\n {\n Assert.Equal(1, MyAssemblyFixture.InstantiationCount);\n }\n}\n")),(0,a.kt)("img",{src:(0,l.Z)("img/ut10.png")}),(0,a.kt)("h3",{id:"36187-iclassfixture-\u5355\u4e2a\u6ce8\u5165"},"36.1.8.7 ",(0,a.kt)("inlineCode",{parentName:"h3"},"IClassFixture<>")," \u5355\u4e2a\u6ce8\u5165"),(0,a.kt)("p",null,"\u901a\u8fc7\u4e0a\u9762 ",(0,a.kt)("inlineCode",{parentName:"p"},"[AssemblyFixture]")," \u65b9\u5f0f\u6211\u4eec\u77e5\u9053\u6b64\u65b9\u5f0f\u5bf9\u5168\u5c40\u7684\u5355\u5143\u6d4b\u8bd5\u7c7b\u90fd\u6709\u6548\uff0c\u4f46\u6709\u65f6\u5019\u6211\u4eec\u53ea\u9700\u8981\u7279\u5b9a\u5355\u5143\u6d4b\u8bd5\u7c7b\u6709\u6548\uff0c\u5219\u53ef\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"IClassFixture<>")," \u65b9\u5f0f\uff0c\u5982\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5b9a\u4e49\u9700\u8981\u6ce8\u5165\u8fdb\u5355\u5143\u6d4b\u8bd5\u6784\u9020\u51fd\u6570\u4e2d\u7684\u7c7b"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},"public class MyClassFixture : IDisposable\n{\n public static int InstantiationCount;\n\n public MyClassFixture()\n {\n InstantiationCount++;\n }\n\n public void Dispose()\n {\n // \u505a\u4e00\u4e9b\u91ca\u653e\u5de5\u4f5c\n }\n}\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5728\u6d4b\u8bd5\u7c7b\u6784\u9020\u51fd\u6570\u6ce8\u5165"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,14,34}",showLineNumbers:!0,"{6,14,34}":!0},"using TestProject1.Services;\nusing Xunit;\n\nnamespace TestProject1;\n\npublic class UnitTest1 : IClassFixture\n{\n private readonly ICalcService _calcService;\n private readonly MyAssemblyFixture _fixture;\n private readonly MyClassFixture _classFixture;\n\n public UnitTest1(ICalcService calcService\n , MyAssemblyFixture fixture\n , MyClassFixture classFixture)\n {\n _calcService = calcService;\n _fixture = fixture;\n _classFixture = classFixture;\n }\n\n [Fact]\n public void \u6d4b\u8bd5\u4e24\u4e2a\u6570\u7684\u548c()\n {\n Assert.Equal(3, _calcService.Plus(1, 2));\n }\n\n [Fact]\n public void EnsureSingleton()\n {\n Assert.Equal(1, MyAssemblyFixture.InstantiationCount);\n }\n\n [Fact]\n public void EnsureClassSingleton()\n {\n Assert.Equal(1, MyClassFixture.InstantiationCount);\n }\n}\n")),(0,a.kt)("img",{src:(0,l.Z)("img/ut11.png")}),(0,a.kt)("h3",{id:"36188-icollectionfixture-\u591a\u4e2a\u6ce8\u5165"},"36.1.8.8 ",(0,a.kt)("inlineCode",{parentName:"h3"},"ICollectionFixture<>")," \u591a\u4e2a\u6ce8\u5165"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"ICollectionFixture<>")," \u65b9\u5f0f\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"IClassFixture<>")," \u65b9\u5f0f\u6700\u5927\u7684\u4e0d\u540c\u5c31\u662f\u540e\u8005\u53ea\u80fd\u914d\u7f6e\u4e3a\u5355\u4e2a\u6d4b\u8bd5\u7c7b\u4f7f\u7528\uff0c\u800c ",(0,a.kt)("inlineCode",{parentName:"p"},"ICollectionFixture<>")," \u5219\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"[Collection]")," \u65b9\u5f0f\u914d\u7f6e\u591a\u4e2a\u6d4b\u8bd5\u7c7b\u6709\u6548\uff0c\u5982\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5b9a\u4e49\u9700\u8981\u6ce8\u5165\u8fdb\u5355\u5143\u6d4b\u8bd5\u6784\u9020\u51fd\u6570\u4e2d\u7684\u7c7b"))),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u8fd9\u91cc\u533a\u522b\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"IClassFixture<>")," \u65b9\u5f0f\uff0c\u9700\u5b9a\u4e49\u914d\u7f6e\u5668\u5e76\u5b9e\u73b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"ICollectionFixture<>")," \u63a5\u53e3\u3002")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,20-21}",showLineNumbers:!0,"{5,20-21}":!0},'using Xunit;\n\nnamespace TestProject1;\n\npublic class MyCollectionFixture : IDisposable\n{\n public static int InstantiationCount;\n\n public MyCollectionFixture()\n {\n InstantiationCount++;\n }\n\n public void Dispose()\n {\n // \u505a\u4e00\u4e9b\u91ca\u653e\u5de5\u4f5c\n }\n}\n\n[CollectionDefinition("MyCollection")]\npublic class MyCollection : ICollectionFixture\n{\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5728\u6d4b\u8bd5\u7c7b\u6784\u9020\u51fd\u6570\u6ce8\u5165"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,17,44}",showLineNumbers:!0,"{6,17,44}":!0},'using TestProject1.Services;\nusing Xunit;\n\nnamespace TestProject1;\n\n[Collection("MyCollection")]\npublic class UnitTest1 : IClassFixture\n{\n private readonly ICalcService _calcService;\n private readonly MyAssemblyFixture _fixture;\n private readonly MyClassFixture _classFixture;\n private readonly MyCollectionFixture _collectionFixture;\n\n public UnitTest1(ICalcService calcService\n , MyAssemblyFixture fixture\n , MyClassFixture classFixture\n , MyCollectionFixture collectionFixture)\n {\n _calcService = calcService;\n _fixture = fixture;\n _classFixture = classFixture;\n _collectionFixture = collectionFixture;\n }\n\n [Fact]\n public void \u6d4b\u8bd5\u4e24\u4e2a\u6570\u7684\u548c()\n {\n Assert.Equal(3, _calcService.Plus(1, 2));\n }\n\n [Fact]\n public void EnsureSingleton()\n {\n Assert.Equal(1, MyAssemblyFixture.InstantiationCount);\n }\n\n [Fact]\n public void EnsureClassSingleton()\n {\n Assert.Equal(1, MyClassFixture.InstantiationCount);\n }\n\n [Fact]\n public void EnsureCollectionSingleton()\n {\n Assert.Equal(1, MyCollectionFixture.InstantiationCount);\n }\n}\n')),(0,a.kt)("img",{src:(0,l.Z)("img/ut12.png")}),(0,a.kt)("h2",{id:"3619-web-\u96c6\u6210\u6d4b\u8bd5"},"36.1.9 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Web")," \u96c6\u6210\u6d4b\u8bd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u96c6\u6210\u6d4b\u8bd5\u6709\u4e09\u79cd\u65b9\u5f0f\uff0c\u901a\u8fc7\u8fd9\u4e09\u79cd\u65b9\u5f0f\u53ef\u4ee5\u5bf9\u9879\u76ee\u8fdb\u884c\u5168\u65b9\u4f4d\u7684\u6d4b\u8bd5\uff0c\u4fdd\u8bc1\u90e8\u7f72\u4e0a\u7ebf\u662f\u6d4b\u8bd5\u671f\u76fc\u6548\u679c\u3002"),(0,a.kt)("h3",{id:"36191-\u5bf9\u73b0\u6709\u9879\u76ee\u8fdb\u884c\u96c6\u6210\u6d4b\u8bd5"},"36.1.9.1 \u5bf9\u73b0\u6709\u9879\u76ee\u8fdb\u884c\u96c6\u6210\u6d4b\u8bd5"),(0,a.kt)("p",null,"\u8fd9\u79cd\u65b9\u5f0f\u6bd4\u8f83\u7b80\u5355\uff0c\u4e5f\u662f\u6700\u5e38\u7528\u7684\u65b9\u5f0f\uff0c\u65e0\u9700\u90e8\u7f72\u5230\u670d\u52a1\u5668\u76f4\u63a5\u5728\u672c\u5730\u5373\u53ef\u6d4b\u8bd5\uff0c\u5982\uff1a"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"li"},"Xunit")," \u5355\u5143\u6d4b\u8bd5\u9879\u76ee")),(0,a.kt)("img",{src:(0,l.Z)("img/ut1.png")}),(0,a.kt)("ol",{start:2},(0,a.kt)("li",{parentName:"ol"},"\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"li"},"Microsoft.AspNetCore.Mvc.Testing")," \u5fae\u8f6f\u63d0\u4f9b\u7684\u96c6\u6210\u6d4b\u8bd5\u62d3\u5c55")),(0,a.kt)("img",{src:(0,l.Z)("img/ut13.png")}),(0,a.kt)("ol",{start:3},(0,a.kt)("li",{parentName:"ol"},"\u6dfb\u52a0\u6d4b\u8bd5\u9879\u76ee\u6216\u4f7f\u7528\u5df2\u6709\u7684\u6d4b\u8bd5\u9879\u76ee",(0,a.kt)("strong",{parentName:"li"},"\u5f15\u7528"))),(0,a.kt)("img",{src:(0,l.Z)("img/ut14.png")}),(0,a.kt)("ol",{start:4},(0,a.kt)("li",{parentName:"ol"},"\u5728\u9700\u8981\u6d4b\u8bd5\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"Web")," \u9879\u76ee\u542f\u52a8\u5c42\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"li"},"FakeStarup.cs")," \u7c7b")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="FakeStarup.cs"',showLineNumbers:!0,title:'"FakeStarup.cs"'},"namespace WebApplication1;\n\n/// \n/// \u4f9b\u96c6\u6210\u6d4b\u8bd5\u4f7f\u7528\n/// \npublic class FakeStartup\n{\n}\n")),(0,a.kt)("ol",{start:5},(0,a.kt)("li",{parentName:"ol"},"\u7f16\u5199\u6d4b\u8bd5 ",(0,a.kt)("inlineCode",{parentName:"li"},"Web")," \u9879\u76ee\u63a5\u53e3\u6d4b\u8bd5\u6848\u4f8b")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,8-12,15,16}",showLineNumbers:!0,"{6,8-12,15,16}":!0},'using Microsoft.AspNetCore.Mvc.Testing;\nusing Xunit;\n\nnamespace TestProject2;\n\npublic class UnitTest1 : IClassFixture>\n{\n private readonly WebApplicationFactory _factory;\n public UnitTest1(WebApplicationFactory factory)\n {\n _factory = factory;\n }\n\n [Theory]\n [InlineData("/default")]\n public async Task TestEnsureSuccessStatusCode(string url)\n {\n using var client = _factory.CreateClient();\n using var response = await client.GetAsync(url);\n response.EnsureSuccessStatusCode();\n }\n}\n')),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"/default")," \u63a5\u53e3\u5bf9\u5e94\u63a7\u5236\u5668\u5b9a\u4e49\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {10,12}",showLineNumbers:!0,"{10,12}":!0},'using Microsoft.AspNetCore.Mvc;\n\nnamespace WebApplication1.Controllers\n{\n [ApiController]\n [Route("[controller]")]\n public class DefaultController : ControllerBase\n {\n [HttpGet]\n public string Get()\n {\n return "Furion \u96c6\u6210\u6d4b\u8bd5";\n }\n }\n}\n')),(0,a.kt)("img",{src:(0,l.Z)("img/ut15.png")}),(0,a.kt)("ol",{start:6},(0,a.kt)("li",{parentName:"ol"},"\u5141\u8bb8\u6d4b\u8bd5")),(0,a.kt)("img",{src:(0,l.Z)("img/ut16.png")}),(0,a.kt)("h3",{id:"36192-\u72ec\u7acb\u4e3b\u673a\u65b9\u5f0f\u6d4b\u8bd5"},"36.1.9.2 \u72ec\u7acb\u4e3b\u673a\u65b9\u5f0f\u6d4b\u8bd5"),(0,a.kt)("p",null,"\u72ec\u7acb\u4e3b\u673a\u7684\u65b9\u5f0f\u5c31\u662f\u5229\u7528\u5355\u5143\u6d4b\u8bd5\u7684\u6bcf\u4e00\u4e2a\u6d4b\u8bd5\u6848\u4f8b\u6784\u5efa\u4e3b\u673a\u8fdb\u884c\u6d4b\u8bd5\u3002"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"li"},"Xunit")," \u5355\u5143\u6d4b\u8bd5\u9879\u76ee")),(0,a.kt)("img",{src:(0,l.Z)("img/ut1.png")}),(0,a.kt)("ol",{start:2},(0,a.kt)("li",{parentName:"ol"},"\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"li"},"Microsoft.AspNetCore.Mvc.Testing")," \u5fae\u8f6f\u63d0\u4f9b\u7684\u96c6\u6210\u6d4b\u8bd5\u62d3\u5c55")),(0,a.kt)("img",{src:(0,l.Z)("img/ut13.png")}),(0,a.kt)("ol",{start:3},(0,a.kt)("li",{parentName:"ol"},"\u5404\u79cd\u521b\u5efa\u4e3b\u673a\u65b9\u5f0f\u793a\u4f8b")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {15,33}",showLineNumbers:!0,"{15,33}":!0},'using Microsoft.AspNetCore.Builder;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\nusing Xunit;\n\nnamespace TestProject3;\n\npublic class UnitTest1\n{\n /// \n /// \u521b\u5efa\u4e3b\u673a\u5e76\u6ce8\u518c\u670d\u52a1\n /// \n /// \u53ef\u7528\u6765\u5224\u65ad\u670d\u52a1\u662f\u5426\u6ce8\u518c\n [Fact]\n public void Test1()\n {\n var builder = WebApplication.CreateBuilder();\n\n // \u6ce8\u518c\u670d\u52a1\n builder.Services.AddScoped();\n\n using var app = builder.Build();\n var services = app.Services;\n\n services.GetRequiredService();\n }\n\n /// \n /// \u6d4b\u8bd5\u914d\u7f6e\n /// \n /// \u6bd4\u5982\u6dfb\u52a0 JSON \u6587\u4ef6\u914d\u7f6e\u540e\u8bfb\u53d6\n [Fact]\n public void Test2()\n {\n var builder = WebApplication.CreateBuilder();\n var host = builder.Host;\n host.ConfigureAppConfiguration(builder =>\n {\n builder.Sources.Clear();\n });\n\n var config = builder.Configuration["\u914d\u7f6e"];\n\n // \u5224\u65ad\u4e0d\u4e3a\u7a7a\n }\n}\n')),(0,a.kt)("h3",{id:"36193-\u7cfb\u7edf\u96c6\u6210\u73af\u5883\u914d\u7f6e\u90e8\u7f72\u6d4b\u8bd5"},"36.1.9.3 \u7cfb\u7edf\u96c6\u6210/\u73af\u5883/\u914d\u7f6e\u90e8\u7f72\u6d4b\u8bd5"),(0,a.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u6d4b\u8bd5 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u4e3b\u673a\u5404\u79cd\u60c5\u51b5\uff0c\u6bd4\u5982\u7aef\u53e3\u662f\u5426\u6709\u6548\uff0c\u73af\u5883\u914d\u7f6e\u662f\u5426\u6709\u6548\uff0c\u7cfb\u7edf\u96c6\u6210\u60c5\u51b5\u7b49\u7b49\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"Microsoft.AspNetCore.TestHost")," \u62d3\u5c55\uff0c\u7136\u540e\u5728\u6d4b\u8bd5\u7c7b\u9876\u90e8\u8d34\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"[assembly: HostingStartup(typeof(WebApplicationTests.TestHostingStartup))]\n")),(0,a.kt)("p",null,"\u5fae\u8f6f\u5df2\u7ecf\u63d0\u4f9b\u4e86\u975e\u5e38\u8be6\u7ec6\u7684\u4f8b\u5b50\uff0c\u8fd9\u91cc\u76f4\u63a5\u653e\u94fe\u63a5 ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/dotnet/aspnetcore/tree/main/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests"},"https://github.com/dotnet/aspnetcore/tree/main/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"WebApplicationTests.TestHostingStartup")," \u4e3a\u60a8\u8981\u6d4b\u8bd5\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u9879\u76ee\u542f\u52a8\u7c7b\u3002"),(0,a.kt)("h3",{id:"36194-\u96c6\u6210-furionxunit-\u62d3\u5c55"},"36.1.9.4 \u96c6\u6210 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Furion.Xunit")," \u62d3\u5c55"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u96c6\u6210\u6d4b\u8bd5\u652f\u6301\u5b8c\u6574\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u7279\u6027\uff0c\u53c2\u8003\u4e0a\u9762\u5355\u5143\u6d4b\u8bd5\u96c6\u6210 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u7ae0\u8282\u3002"),(0,a.kt)("admonition",{type:"note"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Furion")," \u7eaf\u51c0\u7248"),(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528\u7684\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Pure")," \u5219\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Pure.Xunit")," \u8fd9\u4e2a\u62d3\u5c55\u5305\u3002")),(0,a.kt)("h2",{id:"36110-assert-\u65ad\u8a00"},"36.1.10 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Assert")," \u65ad\u8a00"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Assert")," \u662f\u5355\u5143\u6d4b\u8bd5\u5224\u5b9a\u6210\u529f\u7684\u4f9d\u636e\uff0c\u901a\u5e38\u7b2c\u4e00\u4e2a\u53c2\u6570\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u671f\u671b\u503c"),"\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5b9e\u9645\u503c"),"\uff0c\u5bf9\u6bd4\u8fd9\u4e24\u4e2a\u503c\u662f\u5426\u4e00\u81f4\u5373\u53ef\u5224\u65ad\u6210\u529f\u4e0e\u5426\u3002\u8be6\u7ec6\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Assert")," \u9759\u6001\u65b9\u6cd5\u53ef\u67e5\u9605\u5b98\u65b9\u5e93 ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/xunit/assert.xunit"},"Assert \u65b9\u6cd5")),(0,a.kt)("h2",{id:"36111-\u53cd\u9988\u4e0e\u5efa\u8bae"},"36.1.11 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,a.kt)("hr",null),(0,a.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5355\u5143\u6d4b\u8bd5")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/dotnet/core/testing/"},"\u5728 .NET \u4e2d\u6d4b\u8bd5")," \u7ae0\u8282\u3002")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/633e39ed.f316c012.js b/handbook/build/assets/js/633e39ed.f316c012.js deleted file mode 100644 index 97e266106a..0000000000 --- a/handbook/build/assets/js/633e39ed.f316c012.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[519],{9726:function(e,n,t){t.r(n),t.d(n,{assets:function(){return c},contentTitle:function(){return u},default:function(){return d},frontMatter:function(){return o},metadata:function(){return p},toc:function(){return m}});var i=t(3117),r=t(102),a=(t(7294),t(3905)),l=t(1402),s=["components"],o={id:"unittest",title:"36.1 \u5355\u5143/\u96c6\u6210\u6d4b\u8bd5",sidebar_label:"36.1 \u5355\u5143/\u96c6\u6210\u6d4b\u8bd5"},u=void 0,p={unversionedId:"unittest",id:"unittest",title:"36.1 \u5355\u5143/\u96c6\u6210\u6d4b\u8bd5",description:"",source:"@site/docs/unittest.mdx",sourceDirName:".",slug:"/unittest",permalink:"/furion/docs/unittest",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/unittest.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1661755829,formattedLastUpdatedAt:"Aug 29, 2022",frontMatter:{id:"unittest",title:"36.1 \u5355\u5143/\u96c6\u6210\u6d4b\u8bd5",sidebar_label:"36.1 \u5355\u5143/\u96c6\u6210\u6d4b\u8bd5"},sidebar:"docs",previous:{title:"35.2 \u6301\u7eed\u90e8\u7f72\u96c6\u6210",permalink:"/furion/docs/devops"},next:{title:"36.2 \u8d1f\u8f7d\u538b\u6d4b",permalink:"/furion/docs/performance"}},c={},m=[{value:"36.1.1 \u5173\u4e8e\u5355\u5143\u6d4b\u8bd5",id:"3611-\u5173\u4e8e\u5355\u5143\u6d4b\u8bd5",level:2},{value:"36.1.2 \u5355\u5143\u6d4b\u8bd5\u597d\u5904",id:"3612-\u5355\u5143\u6d4b\u8bd5\u597d\u5904",level:2},{value:"36.1.3 \u5355\u5143\u6d4b\u8bd5\u7c7b\u578b",id:"3613-\u5355\u5143\u6d4b\u8bd5\u7c7b\u578b",level:2},{value:"36.1.4 \u4e3b\u6d41\u7684\u5355\u5143\u6d4b\u8bd5\u5e93",id:"3614-\u4e3b\u6d41\u7684\u5355\u5143\u6d4b\u8bd5\u5e93",level:2},{value:"36.1.5 \u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"3615-\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:2},{value:"36.1.5.1 \u521b\u5efa xUnit \u5355\u5143\u6d4b\u8bd5\u9879\u76ee",id:"36151-\u521b\u5efa-xunit-\u5355\u5143\u6d4b\u8bd5\u9879\u76ee",level:3},{value:"36.1.5.2 \u7b2c\u4e00\u4e2a\u6d4b\u8bd5\u65b9\u6cd5",id:"36152-\u7b2c\u4e00\u4e2a\u6d4b\u8bd5\u65b9\u6cd5",level:3},{value:"36.1.5.3 \u8fd0\u884c\u6d4b\u8bd5",id:"36153-\u8fd0\u884c\u6d4b\u8bd5",level:3},{value:"36.1.5.4 \u591a\u4e2a\u6d4b\u8bd5\u65b9\u6cd5\u6d4b\u8bd5",id:"36154-\u591a\u4e2a\u6d4b\u8bd5\u65b9\u6cd5\u6d4b\u8bd5",level:3},{value:"36.1.5.5 \u91cd\u590d/\u56de\u5f52\u6d4b\u8bd5",id:"36155-\u91cd\u590d\u56de\u5f52\u6d4b\u8bd5",level:3},{value:"36.1.6 \u96c6\u6210 Furion \u5f3a\u5927\u529f\u80fd",id:"3616-\u96c6\u6210-furion-\u5f3a\u5927\u529f\u80fd",level:2},{value:"36.1.6.1 \u5b89\u88c5 Furion.Xunit \u5305",id:"36161-\u5b89\u88c5-furionxunit-\u5305",level:3},{value:"36.1.6.2 \u6dfb\u52a0\u521d\u59cb\u914d\u7f6e\u7c7b",id:"36162-\u6dfb\u52a0\u521d\u59cb\u914d\u7f6e\u7c7b",level:3},{value:"36.1.6.3 \u4f7f\u7528 Furion \u5b8c\u6574\u529f\u80fd",id:"36163-\u4f7f\u7528-furion-\u5b8c\u6574\u529f\u80fd",level:3},{value:"36.1.7 \u5e26\u53c2\u6570\u7684\u6d4b\u8bd5\u65b9\u6cd5",id:"3617-\u5e26\u53c2\u6570\u7684\u6d4b\u8bd5\u65b9\u6cd5",level:2},{value:"36.1.8 \u5982\u4f55\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165",id:"3618-\u5982\u4f55\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165",level:2},{value:"36.1.8.1 \u7f16\u5199\u4e00\u4e2a ICalcService \u63a5\u53e3\u53ca\u5b9e\u73b0\u7c7b",id:"36181-\u7f16\u5199\u4e00\u4e2a-icalcservice-\u63a5\u53e3\u53ca\u5b9e\u73b0\u7c7b",level:3},{value:"36.1.8.2 \u5728\u6d4b\u8bd5\u7c7b\u4e2d\u8c03\u7528",id:"36182-\u5728\u6d4b\u8bd5\u7c7b\u4e2d\u8c03\u7528",level:3},{value:"36.1.8.3 \u8f93\u51fa\u65e5\u5fd7",id:"36183-\u8f93\u51fa\u65e5\u5fd7",level:3},{value:"36.1.8.4 \u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165\u4f5c\u7528\u57df\u91ca\u653e",id:"36184-\u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165\u4f5c\u7528\u57df\u91ca\u653e",level:3},{value:"36.1.8.5 \u6d4b\u8bd5\u91ca\u653e\u8d44\u6e90",id:"36185-\u6d4b\u8bd5\u91ca\u653e\u8d44\u6e90",level:3},{value:"36.1.8.6 [AssemblyFixture] \u7279\u6027",id:"36186-assemblyfixture-\u7279\u6027",level:3},{value:"36.1.8.7 IClassFixture<> \u5355\u4e2a\u6ce8\u5165",id:"36187-iclassfixture-\u5355\u4e2a\u6ce8\u5165",level:3},{value:"36.1.8.8 ICollectionFixture<> \u591a\u4e2a\u6ce8\u5165",id:"36188-icollectionfixture-\u591a\u4e2a\u6ce8\u5165",level:3},{value:"36.1.9 Web \u96c6\u6210\u6d4b\u8bd5",id:"3619-web-\u96c6\u6210\u6d4b\u8bd5",level:2},{value:"36.1.9.1 \u5bf9\u73b0\u6709\u9879\u76ee\u8fdb\u884c\u96c6\u6210\u6d4b\u8bd5",id:"36191-\u5bf9\u73b0\u6709\u9879\u76ee\u8fdb\u884c\u96c6\u6210\u6d4b\u8bd5",level:3},{value:"36.1.9.2 \u72ec\u7acb\u4e3b\u673a\u65b9\u5f0f\u6d4b\u8bd5",id:"36192-\u72ec\u7acb\u4e3b\u673a\u65b9\u5f0f\u6d4b\u8bd5",level:3},{value:"36.1.9.3 \u7cfb\u7edf\u96c6\u6210/\u73af\u5883/\u914d\u7f6e\u90e8\u7f72\u6d4b\u8bd5",id:"36193-\u7cfb\u7edf\u96c6\u6210\u73af\u5883\u914d\u7f6e\u90e8\u7f72\u6d4b\u8bd5",level:3},{value:"36.1.9.4 \u96c6\u6210 Furion.Xunit \u62d3\u5c55",id:"36194-\u96c6\u6210-furionxunit-\u62d3\u5c55",level:3},{value:"36.1.10 Assert \u65ad\u8a00",id:"36110-assert-\u65ad\u8a00",level:2},{value:"36.1.11 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"36111-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],k={toc:m};function d(e){var n=e.components,t=(0,r.Z)(e,s);return(0,a.kt)("wrapper",(0,i.Z)({},k,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"3611-\u5173\u4e8e\u5355\u5143\u6d4b\u8bd5"},"36.1.1 \u5173\u4e8e\u5355\u5143\u6d4b\u8bd5"),(0,a.kt)("p",null,"\u5f15\u7528\u81ea\u767e\u5ea6\u767e\u79d1\uff1a"),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},"\u5355\u5143\u6d4b\u8bd5\uff08unit testing\uff09\uff0c\u662f\u6307\u5bf9\u8f6f\u4ef6\u4e2d\u7684\u6700\u5c0f\u53ef\u6d4b\u8bd5\u5355\u5143\u8fdb\u884c\u68c0\u67e5\u548c\u9a8c\u8bc1\u3002\u5bf9\u4e8e\u5355\u5143\u6d4b\u8bd5\u4e2d\u5355\u5143\u7684\u542b\u4e49\uff0c\u4e00\u822c\u6765\u8bf4\uff0c\u8981\u6839\u636e\u5b9e\u9645\u60c5\u51b5\u53bb\u5224\u5b9a\u5176\u5177\u4f53\u542b\u4e49\uff0c\u5982 C \u8bed\u8a00\u4e2d\u5355\u5143\u6307\u4e00\u4e2a\u51fd\u6570\uff0cJava \u91cc\u5355\u5143\u6307\u4e00\u4e2a\u7c7b\uff0c\u56fe\u5f62\u5316\u7684\u8f6f\u4ef6\u4e2d\u53ef\u4ee5\u6307\u4e00\u4e2a\u7a97\u53e3\u6216\u4e00\u4e2a\u83dc\u5355\u7b49\u3002\u603b\u7684\u6765\u8bf4\uff0c\u5355\u5143\u5c31\u662f\u4eba\u4e3a\u89c4\u5b9a\u7684\u6700\u5c0f\u7684\u88ab\u6d4b\u529f\u80fd\u6a21\u5757\u3002\u5355\u5143\u6d4b\u8bd5\u662f\u5728\u8f6f\u4ef6\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u8981\u8fdb\u884c\u7684\u6700\u4f4e\u7ea7\u522b\u7684\u6d4b\u8bd5\u6d3b\u52a8\uff0c\u8f6f\u4ef6\u7684\u72ec\u7acb\u5355\u5143\u5c06\u5728\u4e0e\u7a0b\u5e8f\u7684\u5176\u4ed6\u90e8\u5206\u76f8\u9694\u79bb\u7684\u60c5\u51b5\u4e0b\u8fdb\u884c\u6d4b\u8bd5\u3002")),(0,a.kt)("h2",{id:"3612-\u5355\u5143\u6d4b\u8bd5\u597d\u5904"},"36.1.2 \u5355\u5143\u6d4b\u8bd5\u597d\u5904"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u6d88\u706d\u4f4e\u7ea7\u9519\u8bef"))),(0,a.kt)("p",null,"\u57fa\u672c\u7684\u5355\u5143\u6d4b\u8bd5\uff0c\u53ef\u4ee5\u5728\u7cfb\u7edf\u6d4b\u8bd5\u4e4b\u524d\uff0c\u628a\u5927\u90e8\u5206\u6bd4\u8f83\u4f4e\u7ea7\u7684\u9519\u8bef\u90fd\u6d88\u706d\u6389\uff0c\u51cf\u5c11\u7cfb\u7edf\u6d4b\u8bd5\u8fc7\u7a0b\u4e2d\u7684\u95ee\u9898\uff0c\u8fd9\u6837\u4e5f\u5c31\u51cf\u5c11\u4e86\u7cfb\u7edf\u6d4b\u8bd5\u4e2d\u5b9a\u4f4d\u548c\u89e3\u51b3\u95ee\u9898\u7684\u65f6\u95f4\u6210\u672c\u4e86\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u627e\u51fa\u6f5c\u5728\u7684 bug"))),(0,a.kt)("p",null,"\u67d0\u4e9b\u7c7b\u578b\u7684 bug\uff0c\u9760\u7cfb\u7edf\u6d4b\u8bd5\u662f\u5f88\u96be\u627e\u5230\u7684\u3002\u4f8b\u5982\u4e00\u4e9b\u4ee3\u7801\u5206\u652f\uff0c\u5e73\u65f6 99%\u7684\u573a\u666f\u57fa\u672c\u4e0a\u90fd\u8d70\u4e0d\u5230\uff0c\u4f46\u4e00\u65e6\u8d70\u5230\u4e86\uff0c\u5982\u679c\u6ca1\u6709\u63d0\u524d\u6d4b\u8bd5\u597d\uff0c\u90a3\u4e48\u53ef\u80fd\u5c31\u662f\u4e00\u4e2a\u707e\u96be\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u4e0a\u7ebf\u524d\u7684\u4fdd\u8bc1"))),(0,a.kt)("p",null,"\u52a0\u4e86\u65b0\u4ee3\u7801\uff0c\u4e0a\u7ebf\u524d\u8dd1\u4e00\u628a\u5355\u5143\u6d4b\u8bd5\uff0c\u90fd\u901a\u8fc7\uff0c\u8bf4\u660e\u4ee3\u7801\u53ef\u80fd\u6ca1\u6709\u5f71\u54cd\u5230\u4e4b\u524d\u7684\u903b\u8f91\uff0c\u8fd9\u6837\u4e0a\u7ebf\u4e5f\u6bd4\u8f83\u653e\u5fc3\u3002\u5982\u679c\u4e4b\u524d\u7684\u5355\u5143\u6d4b\u8bd5\u8dd1\u4e0d\u8fc7\uff0c\u90a3\u4e48\u5f88\u6709\u53ef\u80fd\u65b0\u7684\u4ee3\u7801\u6709\u6f5c\u5728\u7684\u95ee\u9898\uff0c\u8d76\u7d27\u4fee\u590d\u53bb\u5427\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u91cd\u6784\u4ee3\u7801\u7684\u673a\u4f1a"))),(0,a.kt)("p",null,"\u5199\u5355\u5143\u6d4b\u8bd5\u7684\u8fc7\u7a0b\u4e2d\uff0c\u4f60\u53ef\u80fd\u4f1a\u987a\u624b\u628a\u4e00\u4e9b code \u91cd\u6784\u4e86\uff0c\u4e3a\u4ec0\u4e48\uff1f\u4e3e\u4f8b\uff0c\u4e00\u4e9b\u957f\u5f97\u975e\u5e38\u50cf\u7684\u4ee3\u7801\uff0c\u5982\u679c\u6bcf\u6b21\u90fd\u8981\u5199\u4e00\u5806\u6d4b\u8bd5\u4ee3\u7801\u53bb\u6d4b\u540c\u6837\u7684 code\uff0c\u4f60\u4f1a\u4e0d\u4f1a\u6293\u72c2\uff1f\u4e0d\u6d4b\u5427\uff0c\u8986\u76d6\u7387\u53c8\u4e0a\u4e0d\u53bb\uff0c\u4e8e\u662f\u6211\u5c31\u4f1a\u60f3\u65b9\u8bbe\u6cd5\u628a\u5f85\u6d4b\u8bd5\u7684 code \u6539\u5f97\u5c3d\u91cf\u7684\u7cbe\u7b80\uff0c\u91cd\u590d\u4ee3\u7801\u51cf\u5c11\uff0c\u8fd9\u6837\u8986\u76d6\u7387\u4e0a\u53bb\u4e86\uff0c\u6d4b\u8bd5\u4e5f\u597d\u6d4b\u4e86\uff0c\u4ee3\u7801\u4e5f\u7b80\u6d01\u4e86\u3002\u5982\u679c\u6ca1\u6709\u5355\u5143\u6d4b\u8bd5\u548c\u8986\u76d6\u7387\u7684\u8981\u6c42\u7684\u8bdd\uff0c\u5766\u767d\u8bf4\u53ef\u80fd\u4e00\u6765\u81ea\u5df1\u4e0d\u4f1a\u53d1\u73b0\u8fd9\u4e9b\u91cd\u590d\u7684 code\uff0c\u53e6\u4e00\u65b9\u9762\u5373\u4f7f\u53d1\u73b0\u4e86\uff0c\u53ef\u80fd\u4e5f\u6ca1\u6709\u592a\u5927\u7684\u52a8\u529b\u53bb\u6539\u8fdb\u3002"),(0,a.kt)("p",null,"\u53e6\u5916\uff0c\u7531\u4e8e\u5355\u5143\u6d4b\u8bd5\u4e2d\uff0c\u4f60\u9700\u8981\u5c1d\u8bd5\u53bb\u8986\u76d6\u4e00\u4e9b\u5f02\u5e38\u5206\u652f\uff0c\u8fd9\u662f\u7cfb\u7edf\u6d4b\u8bd5\u5e38\u5e38\u8d70\u4e0d\u5230\u7684\u5730\u65b9\uff0c\u4e8e\u662f\u5c31\u4f1a\u5f15\u8d77\u4f60\u7684\u4e00\u4e9b\u601d\u8003\uff0c\u4f8b\u5982\u8fd9\u4e2a\u5f02\u5e38\u5206\u652f\u662f\u5426\u771f\u7684\u9700\u8981\uff1f\u662f\u5426\u771f\u7684\u4f1a\u53d1\u751f\uff1f\u5bf9\u4e8e\u4e00\u4e9b\u5b9e\u9645\u4e0a\u7edd\u5bf9\u4e0d\u4f1a\u51fa\u9519\u7684\u51fd\u6570\uff0c\u90a3\u4e48\u6211\u89c9\u5f97\u53ef\u80fd\u5f02\u5e38\u5206\u652f\u662f\u6ca1\u5fc5\u8981\u5b58\u5728\u7684\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u91cd\u65b0 review \u4ee3\u7801\u7684\u673a\u4f1a"))),(0,a.kt)("p",null,"\u5199 UT \u7684\u8fc7\u7a0b\u4e2d\uff0c\u6211\u603b\u662f\u4f1a\u597d\u597d\u770b\u54ea\u4e9b\u4ee3\u7801\u6267\u884c\u5230\u4e86\uff0c\u54ea\u4e9b\u4ee3\u7801\u6ca1\u6709\u6267\u884c\u5230\uff0c\u8fd9\u5176\u5b9e\u4e5f\u662f\u4e00\u4e2a review \u81ea\u5df1\u4ee3\u7801\u7684\u673a\u4f1a\uff0c\u6709\u4e9b\u65f6\u5019\uff0c\u5e76\u4e0d\u662f UT \u672c\u8eab\u5e2e\u6211\u627e\u5230 bug\uff0c\u800c\u662f\u56de\u5934 review \u81ea\u5df1\u4ee3\u7801\u7684\u65f6\u5019\u53d1\u73b0\u7684\u3002"),(0,a.kt)("h2",{id:"3613-\u5355\u5143\u6d4b\u8bd5\u7c7b\u578b"},"36.1.3 \u5355\u5143\u6d4b\u8bd5\u7c7b\u578b"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u57fa\u4e8e API \u63a5\u53e3\u6d4b\u8bd5\uff08\u767d\u76d2 + \u6d45\u5ea6\u9ed1\u76d2\u6d4b\u8bd5\uff09"),(0,a.kt)("li",{parentName:"ul"},"\u57fa\u4e8e\u9879\u76ee\u4ee3\u7801\u6d4b\u8bd5\uff08\u6df1\u5ea6\u9ed1\u76d2\u6d4b\u8bd5\uff09")),(0,a.kt)("h2",{id:"3614-\u4e3b\u6d41\u7684\u5355\u5143\u6d4b\u8bd5\u5e93"},"36.1.4 \u4e3b\u6d41\u7684\u5355\u5143\u6d4b\u8bd5\u5e93"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"xUnit"),"\uff08",(0,a.kt)("strong",{parentName:"li"},"\u6700\u6d41\u884c\u7684\u5e93\uff0c\u63a8\u8350"),"\uff09"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"NUnit")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"MSTest"))),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u5728\u672c\u7ae0\u8282\uff0c",(0,a.kt)("inlineCode",{parentName:"strong"},"Furion")," \u6846\u67b6\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"xUnit")," \u5e93\u8fdb\u884c\u5355\u5143\u6d4b\u8bd5\u3002")),(0,a.kt)("h2",{id:"3615-\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"36.1.5 \u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,a.kt)("h3",{id:"36151-\u521b\u5efa-xunit-\u5355\u5143\u6d4b\u8bd5\u9879\u76ee"},"36.1.5.1 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h3"},"xUnit")," \u5355\u5143\u6d4b\u8bd5\u9879\u76ee"),(0,a.kt)("img",{src:(0,l.Z)("img/ut1.png")}),(0,a.kt)("h3",{id:"36152-\u7b2c\u4e00\u4e2a\u6d4b\u8bd5\u65b9\u6cd5"},"36.1.5.2 \u7b2c\u4e00\u4e2a\u6d4b\u8bd5\u65b9\u6cd5"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,7,10}",showLineNumbers:!0,"":!0,"{1,7,10}":!0},"using Xunit;\n\nnamespace TestProject1\n{\n public class UnitTest1\n {\n [Fact]\n public void Test1()\n {\n Assert.Equal(2, 1 + 1);\n }\n }\n}\n")),(0,a.kt)("p",null,"\u5355\u5143\u6d4b\u8bd5\u5b9e\u9645\u4e0a\u662f\u901a\u8fc7\u666e\u901a\u7684\u7c7b\u7684\u65b9\u6cd5\u8fdb\u884c\u6a21\u5757\u529f\u80fd\u6d4b\u8bd5\uff0c\u5177\u4f53\u6d4b\u8bd5\u5219\u662f\u6807\u8bb0\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"[Fact]")," \u7279\u6027\u7684\u65b9\u6cd5\uff0c\u5728\u65b9\u6cd5\u4e2d\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Assert")," \u7c7b\u63d0\u4f9b\u7684\u9759\u6001\u65b9\u6cd5\u8fdb\u884c ",(0,a.kt)("inlineCode",{parentName:"p"},"\u65ad\u8a00"),"\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"\u65ad\u8a00")," \u6210\u529f\uff0c\u5219\u6d4b\u8bd5\u901a\u8fc7\uff0c\u5426\u5219\u6d4b\u8bd5\u4e0d\u901a\u8fc7\u3002"),(0,a.kt)("h3",{id:"36153-\u8fd0\u884c\u6d4b\u8bd5"},"36.1.5.3 \u8fd0\u884c\u6d4b\u8bd5"),(0,a.kt)("p",null,"\u5728\u5355\u5143\u6d4b\u8bd5\u9879\u76ee\u4e2d ",(0,a.kt)("inlineCode",{parentName:"p"},"\u53f3\u952e")," \u9009\u62e9 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u8fd0\u884c\u6d4b\u8bd5")," \u5e76\u6253\u5f00 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6d4b\u8bd5\u8d44\u6e90\u7ba1\u7406\u5668")," \u5373\u53ef\u67e5\u770b\u6d4b\u8bd5\u7ed3\u679c\u3002"),(0,a.kt)("img",{src:(0,l.Z)("img/ut2.png")}),(0,a.kt)("img",{src:(0,l.Z)("img/ut3.png")}),(0,a.kt)("h3",{id:"36154-\u591a\u4e2a\u6d4b\u8bd5\u65b9\u6cd5\u6d4b\u8bd5"},"36.1.5.4 \u591a\u4e2a\u6d4b\u8bd5\u65b9\u6cd5\u6d4b\u8bd5"),(0,a.kt)("img",{src:(0,l.Z)("img/ut4.png")}),(0,a.kt)("h3",{id:"36155-\u91cd\u590d\u56de\u5f52\u6d4b\u8bd5"},"36.1.5.5 \u91cd\u590d/\u56de\u5f52\u6d4b\u8bd5"),(0,a.kt)("p",null,"\u540e\u7eed\u6dfb\u52a0\u66f4\u591a\u6d4b\u8bd5\u65b9\u6cd5\u53ea\u9700\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6d4b\u8bd5\u8d44\u6e90\u7ba1\u7406\u5668")," \u70b9\u51fb ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5728\u89c6\u56fe\u4e2d\u8fd0\u884c\u6240\u6709\u6d4b\u8bd5")," \u64ad\u653e\u6309\u94ae\u5373\u53ef\uff0c\u5982\u4e0b\u56fe"),(0,a.kt)("img",{src:(0,l.Z)("img/ut5.png")}),(0,a.kt)("h2",{id:"3616-\u96c6\u6210-furion-\u5f3a\u5927\u529f\u80fd"},"36.1.6 \u96c6\u6210 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Furion")," \u5f3a\u5927\u529f\u80fd"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u662f\u8de8\u5e73\u53f0\u3001\u8de8\u9879\u76ee\u7684\u5f00\u53d1\u6846\u67b6\uff0c\u652f\u6301\u4efb\u610f\u9879\u76ee\u7c7b\u578b\uff0c\u5305\u62ec\u5355\u5143\u6d4b\u8bd5\u9879\u76ee\u3002"),(0,a.kt)("h3",{id:"36161-\u5b89\u88c5-furionxunit-\u5305"},"36.1.6.1 \u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Furion.Xunit")," \u5305"),(0,a.kt)("admonition",{type:"note"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Furion")," \u7eaf\u51c0\u7248"),(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528\u7684\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Pure")," \u5219\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Pure.Xunit")," \u8fd9\u4e2a\u62d3\u5c55\u5305\u3002")),(0,a.kt)("p",null,"\u6253\u5f00 ",(0,a.kt)("inlineCode",{parentName:"p"},"Nuget")," \u7a0b\u5e8f\u5305\u63a7\u5236\u53f0\uff0c\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Xunit")," \u5305"),(0,a.kt)("img",{src:(0,l.Z)("img/ut6.png")}),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Xunit")," \u5df2\u7ecf\u5305\u542b ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u65e0\u9700\u518d\u6b21\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion"),"\u3002")),(0,a.kt)("h3",{id:"36162-\u6dfb\u52a0\u521d\u59cb\u914d\u7f6e\u7c7b"},"36.1.6.2 \u6dfb\u52a0\u521d\u59cb\u914d\u7f6e\u7c7b"),(0,a.kt)("p",null,"\u5728\u5355\u5143\u6d4b\u8bd5\u9879\u76ee\u6839\u76ee\u5f55\u4e0b\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"TestProgram.cs")," \u7c7b\uff0c\u5e76\u5199\u4e0b\u4ee5\u4e0b\u4ee3\u7801\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {6,13,18} title="TestProgram.cs"',showLineNumbers:!0,"{6,13,18}":!0,title:'"TestProgram.cs"'},'using Furion.Xunit;\nusing Xunit.Abstractions;\nusing Xunit.Sdk;\n\n// \u914d\u7f6e\u542f\u52a8\u7c7b\u7c7b\u578b\uff0c\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f TestProgram \u7c7b\u5b8c\u6574\u9650\u5b9a\u540d\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f\u5f53\u524d\u9879\u76ee\u7a0b\u5e8f\u96c6\u540d\u79f0\n[assembly: TestFramework("TestProject1.TestProgram", "TestProject1")]\n\nnamespace TestProject1;\n\n/// \n/// \u5355\u5143\u6d4b\u8bd5\u542f\u52a8\u7c7b\n/// \npublic class TestProgram : TestStartup\n{\n public TestProgram(IMessageSink messageSink) : base(messageSink)\n {\n // \u521d\u59cb\u5316 Furion\n Serve.Run(silence: true);\n }\n}\n')),(0,a.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"TestProgram.cs")," \u540d\u79f0\u53ef\u968f\u610f\uff0c\u53ea\u9700\u8981\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"p"},"TestStartup")," \u7c7b\u5373\u53ef\u3002")),(0,a.kt)("h3",{id:"36163-\u4f7f\u7528-furion-\u5b8c\u6574\u529f\u80fd"},"36.1.6.3 \u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Furion")," \u5b8c\u6574\u529f\u80fd"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u662f\u8de8\u5e73\u53f0\u3001\u8de8\u9879\u76ee\u7684\u5f00\u53d1\u6846\u67b6\uff0c\u4e0b\u9762\u5728\u5355\u5143\u6d4b\u8bd5\u4e2d\u6f14\u793a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u8fdc\u7a0b\u8bf7\u6c42")," \u5e76\u8bf7\u6c42 ",(0,a.kt)("inlineCode",{parentName:"p"},"https://www.baidu.com")," \u6570\u636e\uff0c\u5e76\u6d4b\u8bd5\u662f\u5426\u8bf7\u6c42\u6210\u529f\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5728\u6839\u76ee\u5f55\u4e0b\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u542f\u52a8\u7c7b\uff0c\u5e76\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"li"},"AppStartup"),":")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {8,13} title="Startup.cs"',showLineNumbers:!0,"{8,13}":!0,title:'"Startup.cs"'},"using Furion;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace TestProject1;\n\npublic class Startup : AppStartup\n{\n public void ConfigureServices(IServiceCollection services)\n {\n // \u6ce8\u518c\u8fdc\u7a0b\u670d\u52a1\n services.AddRemoteRequest();\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n }\n}\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u7f16\u5199\u6d4b\u8bd5\u65b9\u6cd5")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[Fact]\npublic async Task \u6d4b\u8bd5\u8bf7\u6c42\u767e\u5ea6()\n{\n var rep = await "https://www.baidu.com".GetAsync();\n Assert.True(rep.IsSuccessStatusCode);\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u67e5\u770b\u6d4b\u8bd5\u7ed3\u679c")),(0,a.kt)("img",{src:(0,l.Z)("img/ut7.png")}),(0,a.kt)("p",null,"\u5f88\u795e\u5947\u5427\uff01",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u652f\u6301\u4efb\u4f55\u9879\u76ee\u7c7b\u578b\uff0c\u4efb\u4f55\u5e73\u53f0\u4f7f\u7528\u3002"),(0,a.kt)("h2",{id:"3617-\u5e26\u53c2\u6570\u7684\u6d4b\u8bd5\u65b9\u6cd5"},"36.1.7 \u5e26\u53c2\u6570\u7684\u6d4b\u8bd5\u65b9\u6cd5"),(0,a.kt)("p",null,"\u4e0a\u9762\u4f8b\u5b50\u4e2d\uff0c\u6d4b\u8bd5\u65b9\u6cd5\u90fd\u662f\u6ca1\u6709\u53c2\u6570\u7684\uff0c\u6709\u65f6\u5019\u9700\u8981\u540c\u4e00\u4e2a\u65b9\u6cd5\u8f93\u5165\u591a\u4e2a\u4e0d\u540c\u7684\u503c\u8fdb\u884c\u6d4b\u8bd5\uff0c\u8fd9\u65f6\u5019\u5c31\u9700\u8981\u7528\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"[Theory]")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"[InlineData]")," \u7279\u6027\u4e86\u3002"),(0,a.kt)("p",null,"\u5982\uff0c\u4e0b\u9762\u6d4b\u8bd5\u4e24\u4e2a\u6570\u7684\u548c\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5947\u6570"),"\uff0c\u6d4b\u8bd5\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-4}",showLineNumbers:!0,"":!0,"{1-4}":!0},"[Theory]\n[InlineData(1, 2)]\n[InlineData(3, 4)]\n[InlineData(5, 7)]\npublic void \u5e26\u53c2\u6570\u6d4b\u8bd5(int i, int j)\n{\n Assert.NotEqual(0, (i + j) % 2);\n}\n")),(0,a.kt)("p",null,"\u6d4b\u8bd5\u7ed3\u679c\uff1a"),(0,a.kt)("img",{src:(0,l.Z)("img/ut8.png")}),(0,a.kt)("h2",{id:"3618-\u5982\u4f55\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165"},"36.1.8 \u5982\u4f55\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165"),(0,a.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u9700\u8981\u6d4b\u8bd5\u67d0\u63a5\u53e3\uff0c\u6216\u8005\u8fdb\u884c\u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f\u89e3\u6790\u670d\u52a1\u5e76\u8c03\u7528\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Xunit")," \u63d0\u4f9b\u5b8c\u6574\u7684\u6784\u9020\u51fd\u6570\u6ce8\u5165\u3002"),(0,a.kt)("h3",{id:"36181-\u7f16\u5199\u4e00\u4e2a-icalcservice-\u63a5\u53e3\u53ca\u5b9e\u73b0\u7c7b"},"36.1.8.1 \u7f16\u5199\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"h3"},"ICalcService")," \u63a5\u53e3\u53ca\u5b9e\u73b0\u7c7b"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,10}",showLineNumbers:!0,"":!0,"{5,10}":!0},"using Furion.DependencyInjection;\n\nnamespace TestProject1.Services;\n\npublic interface ICalcService\n{\n int Plus(int i, int j);\n}\n\npublic class CalcService : ICalcService, ITransient // \u652f\u6301\u4efb\u4f55\u751f\u547d\u5468\u671f\n{\n public int Plus(int i, int j)\n {\n return i + j;\n }\n}\n")),(0,a.kt)("h3",{id:"36182-\u5728\u6d4b\u8bd5\u7c7b\u4e2d\u8c03\u7528"},"36.1.8.2 \u5728\u6d4b\u8bd5\u7c7b\u4e2d\u8c03\u7528"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,15,17}",showLineNumbers:!0,"":!0,"{9,15,17}":!0},"using TestProject1.Services;\nusing Xunit;\n\nnamespace TestProject1;\n\npublic class UnitTest1\n{\n private readonly ICalcService _calcService;\n public UnitTest1(ICalcService calcService)\n {\n _calcService = calcService;\n }\n\n [Fact]\n public void \u6d4b\u8bd5\u4e24\u4e2a\u6570\u7684\u548c()\n {\n Assert.Equal(3, _calcService.Plus(1, 2));\n }\n}\n")),(0,a.kt)("img",{src:(0,l.Z)("img/ut9.png")}),(0,a.kt)("h3",{id:"36183-\u8f93\u51fa\u65e5\u5fd7"},"36.1.8.3 \u8f93\u51fa\u65e5\u5fd7"),(0,a.kt)("p",null,"\u5982\u679c\u5728\u5355\u5143\u6d4b\u8bd5\u4e2d\u60f3\u8f93\u51fa\u65e5\u5fd7\uff0c\u53ea\u9700\u8981\u5728\u6784\u9020\u51fd\u6570\u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"p"},"ITestOutputHelper")," \u5373\u53ef\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,10,12,18}",showLineNumbers:!0,"":!0,"{2,10,12,18}":!0},'using Xunit;\nusing Xunit.Abstractions;\n\nnamespace TestProject1\n{\n public class UnitTest1\n {\n private readonly ITestOutputHelper Output;\n\n public UnitTest1(ITestOutputHelper tempOutput)\n {\n Output = tempOutput;\n }\n\n [Fact]\n public void Test_String_Equal()\n {\n Output.WriteLine("\u54c8\u54c8\u54c8\u54c8\uff0c\u6211\u662f Furion");\n Assert.NotEqual("Furion", "Fur");\n }\n }\n}\n')),(0,a.kt)("img",{src:(0,l.Z)("img/un3.png")}),(0,a.kt)("h3",{id:"36184-\u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165\u4f5c\u7528\u57df\u91ca\u653e"},"36.1.8.4 \u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165\u4f5c\u7528\u57df\u91ca\u653e"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u4f1a\u5728\u521b\u5efa\u5355\u5143\u6d4b\u8bd5\u5b9e\u4f8b\u65f6\u521b\u5efa\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"p"},"IServiceScope")," \u5bf9\u8c61\uff0c\u7b49\u8be5\u5b9e\u4f8b\u6240\u6709\u6d4b\u8bd5\u6848\u4f8b\u6267\u884c\u5b8c\u6bd5\u81ea\u52a8\u8c03\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Dispose"),"\uff0c\u7f16\u5199\u6d4b\u8bd5\u7684\u5f00\u53d1\u8005\u65e0\u9700\u5173\u6ce8\u3002"),(0,a.kt)("h3",{id:"36185-\u6d4b\u8bd5\u91ca\u653e\u8d44\u6e90"},"36.1.8.5 \u6d4b\u8bd5\u91ca\u653e\u8d44\u6e90"),(0,a.kt)("p",null,"\u6709\u65f6\u5019\uff0c\u6211\u4eec\u9700\u8981\u6d4b\u8bd5\u6210\u529f\u540e\u91ca\u653e\u4e00\u4e9b\u4e0d\u80fd\u53ca\u65f6\u91ca\u653e\u7684\u5bf9\u8c61\uff0c\u8fd9\u65f6\uff0c\u53ea\u9700\u8981\u5b9e\u73b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"IDisposable")," \u63a5\u53e3\u5373\u53ef\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,14-17}",showLineNumbers:!0,"":!0,"{6,14-17}":!0},'using System;\nusing Xunit;\n\nnamespace TestProject1\n{\n public class UnitTest1 : IDisposable\n {\n [Fact]\n public void Test_String_Equal()\n {\n Assert.NotEqual("Furion", "Fur");\n }\n\n public void Dispose()\n {\n // \u91ca\u653e\u4f60\u7684\u5bf9\u8c61\n }\n }\n}\n')),(0,a.kt)("h3",{id:"36186-assemblyfixture-\u7279\u6027"},"36.1.8.6 ",(0,a.kt)("inlineCode",{parentName:"h3"},"[AssemblyFixture]")," \u7279\u6027"),(0,a.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u53ef\u80fd\u4e0d\u9700\u8981\u5bf9\u7c7b\u8fdb\u884c\u4f9d\u8d56\u6ce8\u518c\uff0c\u6216\u8005\u65e0\u6cd5\u901a\u8fc7\u5916\u90e8\u8fdb\u884c\u6ce8\u518c\uff0c\u8fd9\u65f6\u5019\u53ef\u4ee5\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"[AssemblyFixture]")," \u7279\u6027\u5b9e\u73b0\u6784\u9020\u51fd\u6570\u6ce8\u5165\u4efb\u4f55\u7c7b\uff0c\u5982\uff1a"),(0,a.kt)("admonition",{title:"\u6709\u6548\u8303\u56f4\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"[AssemblyFixture]")," \u65b9\u5f0f\u5bf9\u6574\u4e2a\u5355\u5143\u6d4b\u8bd5\u7c7b\u6784\u9020\u51fd\u6570\u90fd\u6709\u6548\uff0c\u5982\u9700\u4e2a\u522b\u5355\u5143\u6d4b\u8bd5\u7c7b\u6709\u6548\u53ef\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IClassFixture<>")," \u6216 ",(0,a.kt)("inlineCode",{parentName:"p"},"ICollectionFixture<>")," + ",(0,a.kt)("inlineCode",{parentName:"p"},"[Collection]")," \u7ec4\u5408\u65b9\u5f0f\u3002")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5b9a\u4e49\u9700\u8981\u6ce8\u5165\u8fdb\u5355\u5143\u6d4b\u8bd5\u6784\u9020\u51fd\u6570\u4e2d\u7684\u7c7b"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},"public class MyAssemblyFixture : IDisposable\n{\n public static int InstantiationCount;\n\n public MyAssemblyFixture()\n {\n InstantiationCount++;\n }\n\n public void Dispose()\n {\n // \u505a\u4e00\u4e9b\u91ca\u653e\u5de5\u4f5c\n }\n}\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"strong"},"TestProgram.cs")," \u9876\u90e8\u5168\u5c40\u6ce8\u518c"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {11} title="TestProgram.cs"',showLineNumbers:!0,"{11}":!0,title:'"TestProgram.cs"'},'using Furion.Xunit;\nusing TestProject1;\nusing Xunit;\nusing Xunit.Abstractions;\nusing Xunit.Sdk;\n\n// \u914d\u7f6e\u542f\u52a8\u7c7b\u7c7b\u578b\uff0c\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f TestProgram \u7c7b\u5b8c\u6574\u9650\u5b9a\u540d\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f\u5f53\u524d\u9879\u76ee\u7a0b\u5e8f\u96c6\u540d\u79f0\n[assembly: TestFramework("TestProject1.TestProgram", "TestProject1")]\n\n// \u652f\u6301\u591a\u4e2a\n[assembly: AssemblyFixture(typeof(MyAssemblyFixture))]\n// [assembly: AssemblyFixture(typeof(XXXXFixture))]\n\nnamespace TestProject1;\n\n/// \n/// \u5355\u5143\u6d4b\u8bd5\u542f\u52a8\u7c7b\n/// \npublic class TestProgram : TestStartup\n{\n public TestProgram(IMessageSink messageSink) : base(messageSink)\n {\n Serve.Run(silence: true);\n }\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5728\u6d4b\u8bd5\u7c7b\u6784\u9020\u51fd\u6570\u6ce8\u5165"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {12,27}",showLineNumbers:!0,"{12,27}":!0},"using TestProject1.Services;\nusing Xunit;\n\nnamespace TestProject1;\n\npublic class UnitTest1\n{\n private readonly ICalcService _calcService;\n private readonly MyAssemblyFixture _fixture;\n\n public UnitTest1(ICalcService calcService\n , MyAssemblyFixture fixture)\n {\n _calcService = calcService;\n _fixture = fixture;\n }\n\n [Fact]\n public void \u6d4b\u8bd5\u4e24\u4e2a\u6570\u7684\u548c()\n {\n Assert.Equal(3, _calcService.Plus(1, 2));\n }\n\n [Fact]\n public void EnsureSingleton()\n {\n Assert.Equal(1, MyAssemblyFixture.InstantiationCount);\n }\n}\n")),(0,a.kt)("img",{src:(0,l.Z)("img/ut10.png")}),(0,a.kt)("h3",{id:"36187-iclassfixture-\u5355\u4e2a\u6ce8\u5165"},"36.1.8.7 ",(0,a.kt)("inlineCode",{parentName:"h3"},"IClassFixture<>")," \u5355\u4e2a\u6ce8\u5165"),(0,a.kt)("p",null,"\u901a\u8fc7\u4e0a\u9762 ",(0,a.kt)("inlineCode",{parentName:"p"},"[AssemblyFixture]")," \u65b9\u5f0f\u6211\u4eec\u77e5\u9053\u6b64\u65b9\u5f0f\u5bf9\u5168\u5c40\u7684\u5355\u5143\u6d4b\u8bd5\u7c7b\u90fd\u6709\u6548\uff0c\u4f46\u6709\u65f6\u5019\u6211\u4eec\u53ea\u9700\u8981\u7279\u5b9a\u5355\u5143\u6d4b\u8bd5\u7c7b\u6709\u6548\uff0c\u5219\u53ef\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"IClassFixture<>")," \u65b9\u5f0f\uff0c\u5982\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5b9a\u4e49\u9700\u8981\u6ce8\u5165\u8fdb\u5355\u5143\u6d4b\u8bd5\u6784\u9020\u51fd\u6570\u4e2d\u7684\u7c7b"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},"public class MyClassFixture : IDisposable\n{\n public static int InstantiationCount;\n\n public MyClassFixture()\n {\n InstantiationCount++;\n }\n\n public void Dispose()\n {\n // \u505a\u4e00\u4e9b\u91ca\u653e\u5de5\u4f5c\n }\n}\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5728\u6d4b\u8bd5\u7c7b\u6784\u9020\u51fd\u6570\u6ce8\u5165"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,14,34}",showLineNumbers:!0,"{6,14,34}":!0},"using TestProject1.Services;\nusing Xunit;\n\nnamespace TestProject1;\n\npublic class UnitTest1 : IClassFixture\n{\n private readonly ICalcService _calcService;\n private readonly MyAssemblyFixture _fixture;\n private readonly MyClassFixture _classFixture;\n\n public UnitTest1(ICalcService calcService\n , MyAssemblyFixture fixture\n , MyClassFixture classFixture)\n {\n _calcService = calcService;\n _fixture = fixture;\n _classFixture = classFixture;\n }\n\n [Fact]\n public void \u6d4b\u8bd5\u4e24\u4e2a\u6570\u7684\u548c()\n {\n Assert.Equal(3, _calcService.Plus(1, 2));\n }\n\n [Fact]\n public void EnsureSingleton()\n {\n Assert.Equal(1, MyAssemblyFixture.InstantiationCount);\n }\n\n [Fact]\n public void EnsureClassSingleton()\n {\n Assert.Equal(1, MyClassFixture.InstantiationCount);\n }\n}\n")),(0,a.kt)("img",{src:(0,l.Z)("img/ut11.png")}),(0,a.kt)("h3",{id:"36188-icollectionfixture-\u591a\u4e2a\u6ce8\u5165"},"36.1.8.8 ",(0,a.kt)("inlineCode",{parentName:"h3"},"ICollectionFixture<>")," \u591a\u4e2a\u6ce8\u5165"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"ICollectionFixture<>")," \u65b9\u5f0f\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"IClassFixture<>")," \u65b9\u5f0f\u6700\u5927\u7684\u4e0d\u540c\u5c31\u662f\u540e\u8005\u53ea\u80fd\u914d\u7f6e\u4e3a\u5355\u4e2a\u6d4b\u8bd5\u7c7b\u4f7f\u7528\uff0c\u800c ",(0,a.kt)("inlineCode",{parentName:"p"},"ICollectionFixture<>")," \u5219\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"[Collection]")," \u65b9\u5f0f\u914d\u7f6e\u591a\u4e2a\u6d4b\u8bd5\u7c7b\u6709\u6548\uff0c\u5982\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5b9a\u4e49\u9700\u8981\u6ce8\u5165\u8fdb\u5355\u5143\u6d4b\u8bd5\u6784\u9020\u51fd\u6570\u4e2d\u7684\u7c7b"))),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u8fd9\u91cc\u533a\u522b\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"IClassFixture<>")," \u65b9\u5f0f\uff0c\u9700\u5b9a\u4e49\u914d\u7f6e\u5668\u5e76\u5b9e\u73b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"ICollectionFixture<>")," \u63a5\u53e3\u3002")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,20-21}",showLineNumbers:!0,"{5,20-21}":!0},'using Xunit;\n\nnamespace TestProject1;\n\npublic class MyCollectionFixture : IDisposable\n{\n public static int InstantiationCount;\n\n public MyCollectionFixture()\n {\n InstantiationCount++;\n }\n\n public void Dispose()\n {\n // \u505a\u4e00\u4e9b\u91ca\u653e\u5de5\u4f5c\n }\n}\n\n[CollectionDefinition("MyCollection")]\npublic class MyCollection : ICollectionFixture\n{\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5728\u6d4b\u8bd5\u7c7b\u6784\u9020\u51fd\u6570\u6ce8\u5165"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,17,44}",showLineNumbers:!0,"{6,17,44}":!0},'using TestProject1.Services;\nusing Xunit;\n\nnamespace TestProject1;\n\n[Collection("MyCollection")]\npublic class UnitTest1 : IClassFixture\n{\n private readonly ICalcService _calcService;\n private readonly MyAssemblyFixture _fixture;\n private readonly MyClassFixture _classFixture;\n private readonly MyCollectionFixture _collectionFixture;\n\n public UnitTest1(ICalcService calcService\n , MyAssemblyFixture fixture\n , MyClassFixture classFixture\n , MyCollectionFixture collectionFixture)\n {\n _calcService = calcService;\n _fixture = fixture;\n _classFixture = classFixture;\n _collectionFixture = collectionFixture;\n }\n\n [Fact]\n public void \u6d4b\u8bd5\u4e24\u4e2a\u6570\u7684\u548c()\n {\n Assert.Equal(3, _calcService.Plus(1, 2));\n }\n\n [Fact]\n public void EnsureSingleton()\n {\n Assert.Equal(1, MyAssemblyFixture.InstantiationCount);\n }\n\n [Fact]\n public void EnsureClassSingleton()\n {\n Assert.Equal(1, MyClassFixture.InstantiationCount);\n }\n\n [Fact]\n public void EnsureCollectionSingleton()\n {\n Assert.Equal(1, MyCollectionFixture.InstantiationCount);\n }\n}\n')),(0,a.kt)("img",{src:(0,l.Z)("img/ut12.png")}),(0,a.kt)("h2",{id:"3619-web-\u96c6\u6210\u6d4b\u8bd5"},"36.1.9 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Web")," \u96c6\u6210\u6d4b\u8bd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u96c6\u6210\u6d4b\u8bd5\u6709\u4e09\u79cd\u65b9\u5f0f\uff0c\u901a\u8fc7\u8fd9\u4e09\u79cd\u65b9\u5f0f\u53ef\u4ee5\u5bf9\u9879\u76ee\u8fdb\u884c\u5168\u65b9\u4f4d\u7684\u6d4b\u8bd5\uff0c\u4fdd\u8bc1\u90e8\u7f72\u4e0a\u7ebf\u662f\u6d4b\u8bd5\u671f\u76fc\u6548\u679c\u3002"),(0,a.kt)("h3",{id:"36191-\u5bf9\u73b0\u6709\u9879\u76ee\u8fdb\u884c\u96c6\u6210\u6d4b\u8bd5"},"36.1.9.1 \u5bf9\u73b0\u6709\u9879\u76ee\u8fdb\u884c\u96c6\u6210\u6d4b\u8bd5"),(0,a.kt)("p",null,"\u8fd9\u79cd\u65b9\u5f0f\u6bd4\u8f83\u7b80\u5355\uff0c\u4e5f\u662f\u6700\u5e38\u7528\u7684\u65b9\u5f0f\uff0c\u65e0\u9700\u90e8\u7f72\u5230\u670d\u52a1\u5668\u76f4\u63a5\u5728\u672c\u5730\u5373\u53ef\u6d4b\u8bd5\uff0c\u5982\uff1a"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"li"},"Xunit")," \u5355\u5143\u6d4b\u8bd5\u9879\u76ee")),(0,a.kt)("img",{src:(0,l.Z)("img/ut1.png")}),(0,a.kt)("ol",{start:2},(0,a.kt)("li",{parentName:"ol"},"\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"li"},"Microsoft.AspNetCore.Mvc.Testing")," \u5fae\u8f6f\u63d0\u4f9b\u7684\u96c6\u6210\u6d4b\u8bd5\u62d3\u5c55")),(0,a.kt)("img",{src:(0,l.Z)("img/ut13.png")}),(0,a.kt)("ol",{start:3},(0,a.kt)("li",{parentName:"ol"},"\u6dfb\u52a0\u6d4b\u8bd5\u9879\u76ee\u6216\u4f7f\u7528\u5df2\u6709\u7684\u6d4b\u8bd5\u9879\u76ee",(0,a.kt)("strong",{parentName:"li"},"\u5f15\u7528"))),(0,a.kt)("img",{src:(0,l.Z)("img/ut14.png")}),(0,a.kt)("ol",{start:4},(0,a.kt)("li",{parentName:"ol"},"\u5728\u9700\u8981\u6d4b\u8bd5\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"Web")," \u9879\u76ee\u542f\u52a8\u5c42\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"li"},"FakeStarup.cs")," \u7c7b")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="FakeStarup.cs"',showLineNumbers:!0,title:'"FakeStarup.cs"'},"namespace WebApplication1;\n\n/// \n/// \u4f9b\u96c6\u6210\u6d4b\u8bd5\u4f7f\u7528\n/// \npublic class FakeStartup\n{\n}\n")),(0,a.kt)("ol",{start:5},(0,a.kt)("li",{parentName:"ol"},"\u7f16\u5199\u6d4b\u8bd5 ",(0,a.kt)("inlineCode",{parentName:"li"},"Web")," \u9879\u76ee\u63a5\u53e3\u6d4b\u8bd5\u6848\u4f8b")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,8-12,15,16}",showLineNumbers:!0,"{6,8-12,15,16}":!0},'using Microsoft.AspNetCore.Mvc.Testing;\nusing Xunit;\n\nnamespace TestProject2;\n\npublic class UnitTest1 : IClassFixture>\n{\n private readonly WebApplicationFactory _factory;\n public UnitTest1(WebApplicationFactory factory)\n {\n _factory = factory;\n }\n\n [Theory]\n [InlineData("/default")]\n public async Task TestEnsureSuccessStatusCode(string url)\n {\n using var client = _factory.CreateClient();\n using var response = await client.GetAsync(url);\n response.EnsureSuccessStatusCode();\n }\n}\n')),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"/default")," \u63a5\u53e3\u5bf9\u5e94\u63a7\u5236\u5668\u5b9a\u4e49\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {10,12}",showLineNumbers:!0,"{10,12}":!0},'using Microsoft.AspNetCore.Mvc;\n\nnamespace WebApplication1.Controllers\n{\n [ApiController]\n [Route("[controller]")]\n public class DefaultController : ControllerBase\n {\n [HttpGet]\n public string Get()\n {\n return "Furion \u96c6\u6210\u6d4b\u8bd5";\n }\n }\n}\n')),(0,a.kt)("img",{src:(0,l.Z)("img/ut15.png")}),(0,a.kt)("ol",{start:6},(0,a.kt)("li",{parentName:"ol"},"\u5141\u8bb8\u6d4b\u8bd5")),(0,a.kt)("img",{src:(0,l.Z)("img/ut16.png")}),(0,a.kt)("h3",{id:"36192-\u72ec\u7acb\u4e3b\u673a\u65b9\u5f0f\u6d4b\u8bd5"},"36.1.9.2 \u72ec\u7acb\u4e3b\u673a\u65b9\u5f0f\u6d4b\u8bd5"),(0,a.kt)("p",null,"\u72ec\u7acb\u4e3b\u673a\u7684\u65b9\u5f0f\u5c31\u662f\u5229\u7528\u5355\u5143\u6d4b\u8bd5\u7684\u6bcf\u4e00\u4e2a\u6d4b\u8bd5\u6848\u4f8b\u6784\u5efa\u4e3b\u673a\u8fdb\u884c\u6d4b\u8bd5\u3002"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"li"},"Xunit")," \u5355\u5143\u6d4b\u8bd5\u9879\u76ee")),(0,a.kt)("img",{src:(0,l.Z)("img/ut1.png")}),(0,a.kt)("ol",{start:2},(0,a.kt)("li",{parentName:"ol"},"\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"li"},"Microsoft.AspNetCore.Mvc.Testing")," \u5fae\u8f6f\u63d0\u4f9b\u7684\u96c6\u6210\u6d4b\u8bd5\u62d3\u5c55")),(0,a.kt)("img",{src:(0,l.Z)("img/ut13.png")}),(0,a.kt)("ol",{start:3},(0,a.kt)("li",{parentName:"ol"},"\u5404\u79cd\u521b\u5efa\u4e3b\u673a\u65b9\u5f0f\u793a\u4f8b")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {15,33}",showLineNumbers:!0,"{15,33}":!0},'using Microsoft.AspNetCore.Builder;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\nusing Xunit;\n\nnamespace TestProject3;\n\npublic class UnitTest1\n{\n /// \n /// \u521b\u5efa\u4e3b\u673a\u5e76\u6ce8\u518c\u670d\u52a1\n /// \n /// \u53ef\u7528\u6765\u5224\u65ad\u670d\u52a1\u662f\u5426\u6ce8\u518c\n [Fact]\n public void Test1()\n {\n var builder = WebApplication.CreateBuilder();\n\n // \u6ce8\u518c\u670d\u52a1\n builder.Services.AddScoped();\n\n using var app = builder.Build();\n var services = app.Services;\n\n services.GetRequiredService();\n }\n\n /// \n /// \u6d4b\u8bd5\u914d\u7f6e\n /// \n /// \u6bd4\u5982\u6dfb\u52a0 JSON \u6587\u4ef6\u914d\u7f6e\u540e\u8bfb\u53d6\n [Fact]\n public void Test2()\n {\n var builder = WebApplication.CreateBuilder();\n var host = builder.Host;\n host.ConfigureAppConfiguration(builder =>\n {\n builder.Sources.Clear();\n });\n\n var config = builder.Configuration["\u914d\u7f6e"];\n\n // \u5224\u65ad\u4e0d\u4e3a\u7a7a\n }\n}\n')),(0,a.kt)("h3",{id:"36193-\u7cfb\u7edf\u96c6\u6210\u73af\u5883\u914d\u7f6e\u90e8\u7f72\u6d4b\u8bd5"},"36.1.9.3 \u7cfb\u7edf\u96c6\u6210/\u73af\u5883/\u914d\u7f6e\u90e8\u7f72\u6d4b\u8bd5"),(0,a.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u6d4b\u8bd5 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u4e3b\u673a\u5404\u79cd\u60c5\u51b5\uff0c\u6bd4\u5982\u7aef\u53e3\u662f\u5426\u6709\u6548\uff0c\u73af\u5883\u914d\u7f6e\u662f\u5426\u6709\u6548\uff0c\u7cfb\u7edf\u96c6\u6210\u60c5\u51b5\u7b49\u7b49\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"Microsoft.AspNetCore.TestHost")," \u62d3\u5c55\uff0c\u7136\u540e\u5728\u6d4b\u8bd5\u7c7b\u9876\u90e8\u8d34\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"[assembly: HostingStartup(typeof(WebApplicationTests.TestHostingStartup))]\n")),(0,a.kt)("p",null,"\u5fae\u8f6f\u5df2\u7ecf\u63d0\u4f9b\u4e86\u975e\u5e38\u8be6\u7ec6\u7684\u4f8b\u5b50\uff0c\u8fd9\u91cc\u76f4\u63a5\u653e\u94fe\u63a5 ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/dotnet/aspnetcore/tree/main/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests"},"https://github.com/dotnet/aspnetcore/tree/main/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"WebApplicationTests.TestHostingStartup")," \u4e3a\u60a8\u8981\u6d4b\u8bd5\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u9879\u76ee\u542f\u52a8\u7c7b\u3002"),(0,a.kt)("h3",{id:"36194-\u96c6\u6210-furionxunit-\u62d3\u5c55"},"36.1.9.4 \u96c6\u6210 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Furion.Xunit")," \u62d3\u5c55"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u96c6\u6210\u6d4b\u8bd5\u652f\u6301\u5b8c\u6574\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u7279\u6027\uff0c\u53c2\u8003\u4e0a\u9762\u5355\u5143\u6d4b\u8bd5\u96c6\u6210 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u7ae0\u8282\u3002"),(0,a.kt)("admonition",{type:"note"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Furion")," \u7eaf\u51c0\u7248"),(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528\u7684\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Pure")," \u5219\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Pure.Xunit")," \u8fd9\u4e2a\u62d3\u5c55\u5305\u3002")),(0,a.kt)("h2",{id:"36110-assert-\u65ad\u8a00"},"36.1.10 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Assert")," \u65ad\u8a00"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Assert")," \u662f\u5355\u5143\u6d4b\u8bd5\u5224\u5b9a\u6210\u529f\u7684\u4f9d\u636e\uff0c\u901a\u5e38\u7b2c\u4e00\u4e2a\u53c2\u6570\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u671f\u671b\u503c"),"\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5b9e\u9645\u503c"),"\uff0c\u5bf9\u6bd4\u8fd9\u4e24\u4e2a\u503c\u662f\u5426\u4e00\u81f4\u5373\u53ef\u5224\u65ad\u6210\u529f\u4e0e\u5426\u3002\u8be6\u7ec6\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Assert")," \u9759\u6001\u65b9\u6cd5\u53ef\u67e5\u9605\u5b98\u65b9\u5e93 ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/xunit/assert.xunit"},"Assert \u65b9\u6cd5")),(0,a.kt)("h2",{id:"36111-\u53cd\u9988\u4e0e\u5efa\u8bae"},"36.1.11 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,a.kt)("hr",null),(0,a.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5355\u5143\u6d4b\u8bd5")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/dotnet/core/testing/"},"\u5728 .NET \u4e2d\u6d4b\u8bd5")," \u7ae0\u8282\u3002")))}d.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return p},kt:function(){return k}});var i=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function l(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var o=i.createContext({}),u=function(e){var n=i.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},p=function(e){var n=u(e.components);return i.createElement(o.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},m=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,o=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),m=u(t),k=r,d=m["".concat(o,".").concat(k)]||m[k]||c[k]||a;return t?i.createElement(d,l(l({ref:n},p),{},{components:t})):i.createElement(d,l({ref:n},p))}));function k(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,l=new Array(a);l[0]=m;var s={};for(var o in n)hasOwnProperty.call(n,o)&&(s[o]=n[o]);s.originalType=e,s.mdxType="string"==typeof e?e:r,l[1]=s;for(var u=2;u=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var p=i.createContext({}),m=function(e){var n=i.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):r(r({},n),e)),t},u=function(e){var n=m(e.components);return i.createElement(p.Provider,{value:n},e.children)},s={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},d=i.forwardRef((function(e,n){var t=e.components,a=e.mdxType,l=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),d=m(t),k=a,c=d["".concat(p,".").concat(k)]||d[k]||s[k]||l;return t?i.createElement(c,r(r({ref:n},u),{},{components:t})):i.createElement(c,r({ref:n},u))}));function k(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var l=t.length,r=new Array(l);r[0]=d;var o={};for(var p in n)hasOwnProperty.call(n,p)&&(o[p]=n[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,r[1]=o;for(var m=2;m child <"+("string"==typeof e.type?e.type:e.type.name)+'>: all children of the component should be , and every should have a unique "value" prop.')})),b=null!=c?c:g.map((function(e){var n=e.props;return{value:n.value,label:n.label,attributes:n.attributes}})),A=(0,o.l)(b,(function(e,n){return e.value===n.value}));if(A.length>0)throw new Error('Docusaurus error: Duplicate values "'+A.map((function(e){return e.value})).join(", ")+'" found in . Every value needs to be unique.');var v=null===k?k:null!=(n=null!=k?k:null==(t=g.find((function(e){return e.props.default})))?void 0:t.props.value)?n:g[0].props.value;if(null!==v&&!b.some((function(e){return e.value===v})))throw new Error('Docusaurus error: The has a defaultValue "'+v+'" but none of its children has the corresponding value. Available values are: '+b.map((function(e){return e.value})).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");var h=(0,p.U)(),y=h.tabGroupChoices,f=h.setTabGroupChoices,F=(0,a.useState)(v),S=F[0],D=F[1],w=[],T=(0,m.o5)().blockElementScrollPositionUntilNextRender;if(null!=N){var P=y[N];null!=P&&P!==S&&b.some((function(e){return e.value===P}))&&D(P)}var E=function(e){var n=e.currentTarget,t=w.indexOf(n),i=b[t].value;i!==S&&(T(n),D(i),null!=N&&f(N,String(i)))},L=function(e){var n,t=null;switch(e.key){case"ArrowRight":var i,a=w.indexOf(e.currentTarget)+1;t=null!=(i=w[a])?i:w[0];break;case"ArrowLeft":var l,r=w.indexOf(e.currentTarget)-1;t=null!=(l=w[r])?l:w[w.length-1]}null==(n=t)||n.focus()};return a.createElement("div",{className:(0,l.Z)("tabs-container",u)},a.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,l.Z)("tabs",{"tabs--block":d},C)},b.map((function(e){var n=e.value,t=e.label,r=e.attributes;return a.createElement("li",(0,i.Z)({role:"tab",tabIndex:S===n?0:-1,"aria-selected":S===n,key:n,ref:function(e){return w.push(e)},onKeyDown:L,onFocus:E,onClick:E},r,{className:(0,l.Z)("tabs__item",s,null==r?void 0:r.className,{"tabs__item--active":S===n})}),null!=t?t:n)}))),r?(0,a.cloneElement)(g.filter((function(e){return e.props.value===S}))[0],{className:"margin-top--md"}):a.createElement("div",{className:"margin-top--md"},g.map((function(e,n){return(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==S})}))))}function k(e){var n=(0,r.Z)();return a.createElement(d,(0,i.Z)({key:String(n)},e))}},8211:function(e,n,t){t.r(n),t.d(n,{assets:function(){return k},contentTitle:function(){return s},default:function(){return C},frontMatter:function(){return u},metadata:function(){return d},toc:function(){return c}});var i=t(3117),a=t(102),l=(t(7294),t(3905)),r=t(4996),o=t(5488),p=t(5162),m=["components"],u={id:"dynamic-api-controller",title:"5.1 \u52a8\u6001 WebAPI",sidebar_label:"5.1 \u52a8\u6001 WebAPI"},s=void 0,d={unversionedId:"dynamic-api-controller",id:"dynamic-api-controller",title:"5.1 \u52a8\u6001 WebAPI",description:"",source:"@site/docs/dynamic-api-controller.mdx",sourceDirName:".",slug:"/dynamic-api-controller",permalink:"/furion/docs/dynamic-api-controller",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dynamic-api-controller.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1655430671,formattedLastUpdatedAt:"Jun 17, 2022",frontMatter:{id:"dynamic-api-controller",title:"5.1 \u52a8\u6001 WebAPI",sidebar_label:"5.1 \u52a8\u6001 WebAPI"},sidebar:"docs",previous:{title:"4.2 \u9009\u9879",permalink:"/furion/docs/options"},next:{title:"5.2 HttpContext",permalink:"/furion/docs/httpcontext"}},k={},c=[{value:"5.1.1 \u4ec0\u4e48\u662f\u63a7\u5236\u5668",id:"511-\u4ec0\u4e48\u662f\u63a7\u5236\u5668",level:2},{value:"5.1.2 Mvc \u63a7\u5236\u5668 \u7ea6\u5b9a\u548c\u7f3a\u70b9",id:"512-mvc-\u63a7\u5236\u5668-\u7ea6\u5b9a\u548c\u7f3a\u70b9",level:2},{value:"5.1.2.1 WebAPI \u7ea6\u5b9a",id:"5121-webapi-\u7ea6\u5b9a",level:3},{value:"5.1.2.2 .NET Core WebAPI \u7f3a\u70b9",id:"5122-net-core-webapi-\u7f3a\u70b9",level:3},{value:"5.1.3 \u52a8\u6001 WebAPI \u63a7\u5236\u5668",id:"513-\u52a8\u6001-webapi-\u63a7\u5236\u5668",level:2},{value:"5.1.4 \u6ce8\u518c\u52a8\u6001 WebAPI \u670d\u52a1",id:"514-\u6ce8\u518c\u52a8\u6001-webapi-\u670d\u52a1",level:2},{value:"5.1.5 \u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"515-\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:2},{value:"5.1.6 \u52a8\u6001 WebAPI \u539f\u7406\u89e3\u6790",id:"516-\u52a8\u6001-webapi-\u539f\u7406\u89e3\u6790",level:2},{value:"5.1.6.1 \u63a7\u5236\u5668\u7279\u6027\u63d0\u4f9b\u5668",id:"5161-\u63a7\u5236\u5668\u7279\u6027\u63d0\u4f9b\u5668",level:3},{value:"5.1.6.2 \u5e94\u7528\u6a21\u578b\u8f6c\u6362\u5668",id:"5162-\u5e94\u7528\u6a21\u578b\u8f6c\u6362\u5668",level:3},{value:"5.1.7 \u52a8\u6001 WebAPI \u914d\u7f6e\u7ea6\u5b9a",id:"517-\u52a8\u6001-webapi-\u914d\u7f6e\u7ea6\u5b9a",level:2},{value:"5.1.7.1 \u63a7\u5236\u5668\u9ed8\u8ba4\u7ea6\u5b9a",id:"5171-\u63a7\u5236\u5668\u9ed8\u8ba4\u7ea6\u5b9a",level:3},{value:"5.1.7.2 \u52a8\u4f5c\u65b9\u6cd5\u9ed8\u8ba4\u7ea6\u5b9a",id:"5172-\u52a8\u4f5c\u65b9\u6cd5\u9ed8\u8ba4\u7ea6\u5b9a",level:3},{value:"5.1.7.3 \u8bf7\u6c42\u8c13\u8bcd\u9ed8\u8ba4\u7ea6\u5b9a",id:"5173-\u8bf7\u6c42\u8c13\u8bcd\u9ed8\u8ba4\u7ea6\u5b9a",level:3},{value:"5.1.7.4 \u8def\u7531\u5730\u5740\u9ed8\u8ba4\u7ea6\u5b9a",id:"5174-\u8def\u7531\u5730\u5740\u9ed8\u8ba4\u7ea6\u5b9a",level:3},{value:"5.1.7.5 \u5176\u4ed6\u7ea6\u5b9a",id:"5175-\u5176\u4ed6\u7ea6\u5b9a",level:3},{value:"5.1.8 \u66f4\u591a\u4f8b\u5b50",id:"518-\u66f4\u591a\u4f8b\u5b50",level:2},{value:"5.1.8.1 \u591a\u79cd\u8bf7\u6c42\u8c13\u8bcd\u65b9\u6cd5",id:"5181-\u591a\u79cd\u8bf7\u6c42\u8c13\u8bcd\u65b9\u6cd5",level:3},{value:"5.1.8.2 \u591a\u4e2a\u81ea\u5b9a\u4e49\u52a8\u4f5c\u65b9\u6cd5",id:"5182-\u591a\u4e2a\u81ea\u5b9a\u4e49\u52a8\u4f5c\u65b9\u6cd5",level:3},{value:"5.1.8.3 \u5e26\u53c2\u6570\u52a8\u4f5c\u65b9\u6cd5",id:"5183-\u5e26\u53c2\u6570\u52a8\u4f5c\u65b9\u6cd5",level:3},{value:"5.1.8.4 GET/HEAD \u7c7b\u7c7b\u578b\u53c2\u6570",id:"5184-gethead-\u7c7b\u7c7b\u578b\u53c2\u6570",level:3},{value:"5.1.8.5 \u81ea\u5b9a\u4e49\u53c2\u6570\u4f4d\u7f6e",id:"5185-\u81ea\u5b9a\u4e49\u53c2\u6570\u4f4d\u7f6e",level:3},{value:"5.1.8.6 \u81ea\u5b9a\u4e49\u8bf7\u6c42\u8c13\u8bcd",id:"5186-\u81ea\u5b9a\u4e49\u8bf7\u6c42\u8c13\u8bcd",level:3},{value:"5.1.8.7 \u652f\u6301\u591a\u4e2a\u8c13\u8bcd",id:"5187-\u652f\u6301\u591a\u4e2a\u8c13\u8bcd",level:3},{value:"5.1.8.8 \u652f\u6301\u81ea\u5b9a\u4e49\u8def\u7531",id:"5188-\u652f\u6301\u81ea\u5b9a\u4e49\u8def\u7531",level:3},{value:"5.1.8.9 \u591a\u8def\u7531\u968f\u610f\u7ec4\u5408",id:"5189-\u591a\u8def\u7531\u968f\u610f\u7ec4\u5408",level:3},{value:"5.1.8.10 \u652f\u6301\u7248\u672c\u63a7\u5236",id:"51810-\u652f\u6301\u7248\u672c\u63a7\u5236",level:3},{value:"5.1.8.11 \u4e0d\u516c\u5f00\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5",id:"51811-\u4e0d\u516c\u5f00\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5",level:3},{value:"5.1.8.12 \u4fdd\u6301\u63a7\u5236\u5668\u548c\u65b9\u6cd5\u547d\u540d",id:"51812-\u4fdd\u6301\u63a7\u5236\u5668\u548c\u65b9\u6cd5\u547d\u540d",level:3},{value:"5.1.8.13 \u65b9\u6cd5\u53c2\u6570 [FromQuery] \u5316/\u53c2\u6570\u975e\u5fc5\u586b/\u53c2\u6570\u53ef\u9009",id:"51813-\u65b9\u6cd5\u53c2\u6570-fromquery-\u5316\u53c2\u6570\u975e\u5fc5\u586b\u53c2\u6570\u53ef\u9009",level:3},{value:"5.1.8.14 \u53c2\u6570\u7ed1\u5b9a\u914d\u7f6e",id:"51814-\u53c2\u6570\u7ed1\u5b9a\u914d\u7f6e",level:3},{value:"5.1.8.15 \u81ea\u5b9a\u4e49\u6839\u636e\u65b9\u6cd5\u540d\u751f\u6210 [HttpMethod] \u89c4\u5219",id:"51815-\u81ea\u5b9a\u4e49\u6839\u636e\u65b9\u6cd5\u540d\u751f\u6210-httpmethod-\u89c4\u5219",level:3},{value:"5.1.8.16 \u8def\u7531\u53c2\u6570\u975e\u5fc5\u586b/\u9009\u586b",id:"51816-\u8def\u7531\u53c2\u6570\u975e\u5fc5\u586b\u9009\u586b",level:3},{value:"5.1.8.17 [FormRoute] \u8def\u7531\u7ea6\u675f",id:"51817-formroute-\u8def\u7531\u7ea6\u675f",level:3},{value:"5.1.8.18 \u5c0f\u9a7c\u5cf0 \u8def\u7531\u8def\u5f84",id:"51818-\u5c0f\u9a7c\u5cf0-\u8def\u7531\u8def\u5f84",level:3},{value:"5.1.9 [ApiDescriptionSettings]",id:"519-apidescriptionsettings",level:2},{value:"5.1.9.1 \u5185\u7f6e\u914d\u7f6e",id:"5191-\u5185\u7f6e\u914d\u7f6e",level:3},{value:"5.1.9.2 Name \u914d\u7f6e",id:"5192-name-\u914d\u7f6e",level:3},{value:"5.1.9.3 KeepName \u914d\u7f6e",id:"5193-keepname-\u914d\u7f6e",level:3},{value:"5.1.9.4 SplitCamelCase \u914d\u7f6e",id:"5194-splitcamelcase-\u914d\u7f6e",level:3},{value:"5.1.9.5 KeepVerb \u914d\u7f6e",id:"5195-keepverb-\u914d\u7f6e",level:3},{value:"5.1.9.6 Enabled \u914d\u7f6e",id:"5196-enabled-\u914d\u7f6e",level:3},{value:"5.1.9.7 Module \u914d\u7f6e",id:"5197-module-\u914d\u7f6e",level:3},{value:"5.1.9.8 Version \u914d\u7f6e",id:"5198-version-\u914d\u7f6e",level:3},{value:"5.1.9.9 Groups \u914d\u7f6e",id:"5199-groups-\u914d\u7f6e",level:3},{value:"5.1.9.10 Tag \u914d\u7f6e",id:"51910-tag-\u914d\u7f6e",level:3},{value:"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d",id:"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d",level:4},{value:"\u8d34\u6807\u7b7e\u4e4b\u540e",id:"\u8d34\u6807\u7b7e\u4e4b\u540e",level:4},{value:"5.1.10 DynamicApiControllerSettings \u914d\u7f6e",id:"5110-dynamicapicontrollersettings-\u914d\u7f6e",level:2},{value:"5.1.10.1 \u652f\u6301 Mvc \u63a7\u5236\u5668 \u52a8\u6001\u914d\u7f6e",id:"51101-\u652f\u6301-mvc-\u63a7\u5236\u5668-\u52a8\u6001\u914d\u7f6e",level:3},{value:"5.1.11 \u5173\u4e8e AOP \u62e6\u622a",id:"5111-\u5173\u4e8e-aop-\u62e6\u622a",level:2},{value:"5.1.12 \u8bbe\u7f6e api \u8d85\u65f6\u8bf7\u6c42\u65f6\u95f4",id:"5112-\u8bbe\u7f6e-api-\u8d85\u65f6\u8bf7\u6c42\u65f6\u95f4",level:2},{value:"5.1.13 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"5113-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],N={toc:c};function C(e){var n=e.components,t=(0,a.Z)(e,m);return(0,l.kt)("wrapper",(0,i.Z)({},N,t,{components:n,mdxType:"MDXLayout"}),(0,l.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"p"},"\u52a8\u6001WebAPI")," \u5b9e\u9645\u4e0a\u5c31\u662f\u5c06\u666e\u901a\u7684\u7c7b\u53d8\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"Controller"),"\uff0c\u4e5f\u5c31\u662f ",(0,l.kt)("inlineCode",{parentName:"p"},"\u52a8\u6001WebAPI")," \u5c31\u662f\u63a7\u5236\u5668\uff0c\u652f\u6301\u63a7\u5236\u5668\u4e00\u5207\u529f\u80fd\u3002")),(0,l.kt)("h2",{id:"511-\u4ec0\u4e48\u662f\u63a7\u5236\u5668"},"5.1.1 \u4ec0\u4e48\u662f\u63a7\u5236\u5668"),(0,l.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u63a7\u5236\u5668\u662f\u4e00\u4e2a\u627f\u4e0a\u542f\u4e0b\u7684\u4f5c\u7528\uff0c\u6839\u636e\u7528\u6237\u8f93\u5165\uff0c\u6267\u884c\u54cd\u5e94\u884c\u4e3a\uff08\u52a8\u4f5c\u65b9\u6cd5\uff09\uff0c\u540c\u65f6\u5728\u884c\u4e3a\u4e2d\u8c03\u7528\u6a21\u578b\u7684\u4e1a\u52a1\u903b\u8f91\uff0c\u8fd4\u56de\u7ed9\u7528\u6237\u7ed3\u679c\uff08\u89c6\u56fe\uff09\u3002"),(0,l.kt)("img",{src:(0,r.Z)("img/kzq.png")}),(0,l.kt)("p",null),(0,l.kt)("p",null,"\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u4e2d\uff0c\u63a7\u5236\u5668\u6709\u4e24\u79cd\u8868\u73b0\u5f62\u5f0f\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Mvc"),"\uff08\u5e26\u89c6\u56fe\uff09"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"WebAPI"),"\uff08RESTful API\uff09")),(0,l.kt)(o.Z,{defaultValue:"mvc",values:[{label:"Mvc \u63a7\u5236\u5668",value:"mvc"},{label:"WebAPI \u63a7\u5236\u5668",value:"webapi"}],mdxType:"Tabs"},(0,l.kt)(p.Z,{value:"mvc",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,7}",showLineNumbers:!0,"":!0,"{1,5,7}":!0},"using Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n public class MvcController : Controller\n {\n public IActionResult Index()\n {\n return View();\n }\n }\n}\n"))),(0,l.kt)(p.Z,{value:"webapi",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,6,8,9}",showLineNumbers:!0,"":!0,"{1,5,6,8,9}":!0},'using Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n public class WebApiController : ControllerBase\n {\n [HttpGet]\n public IActionResult Get()\n {\n return Content(nameof(Furion));\n }\n }\n}\n')))),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Mvc")," \u63a7\u5236\u5668\u548c ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a7\u5236\u5668\u6700\u5927\u7684\u533a\u522b\u662f ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a7\u5236\u5668\u4e0d\u5e26 ",(0,l.kt)("strong",{parentName:"p"},"\u89c6\u56fe")," \u548c\u901a\u8fc7 ",(0,l.kt)("strong",{parentName:"p"},"\u8bf7\u6c42\u8c13\u8bcd\u548c\u8def\u7531\u5730\u5740\u54cd\u5e94\u884c\u4e3a"),"\u3002"),(0,l.kt)("h2",{id:"512-mvc-\u63a7\u5236\u5668-\u7ea6\u5b9a\u548c\u7f3a\u70b9"},"5.1.2 ",(0,l.kt)("inlineCode",{parentName:"h2"},"Mvc \u63a7\u5236\u5668")," \u7ea6\u5b9a\u548c\u7f3a\u70b9"),(0,l.kt)("p",null,"\u5728\u5b66\u4e60\u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a7\u5236\u5668\u4e4b\u524d\uff0c\u9996\u5148\u4e86\u89e3 ",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u4e2d ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u7684\u4e00\u4e9b\u7ea6\u5b9a\u548c\u6ce8\u610f\u4e8b\u9879\u3002"),(0,l.kt)("h3",{id:"5121-webapi-\u7ea6\u5b9a"},"5.1.2.1 ",(0,l.kt)("inlineCode",{parentName:"h3"},"WebAPI")," \u7ea6\u5b9a"),(0,l.kt)("p",null,"\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u4e2d\uff0c\u4e00\u4e2a ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a7\u5236\u5668\u9700\u9075\u5faa\u4ee5\u4e0b\u7ea6\u5b9a\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u63a7\u5236\u5668\u7c7b",(0,l.kt)("strong",{parentName:"li"},"\u5fc5\u987b\u7ee7\u627f ",(0,l.kt)("inlineCode",{parentName:"strong"},"ControllerBase")," \u6216\u95f4\u63a5\u7ee7\u627f")),(0,l.kt)("li",{parentName:"ul"},"\u52a8\u4f5c\u65b9\u6cd5",(0,l.kt)("strong",{parentName:"li"},"\u5fc5\u987b\u8d34\u6709 ",(0,l.kt)("inlineCode",{parentName:"strong"},"[HttpMethod]")," \u7279\u6027\uff0c\u5982\uff1a",(0,l.kt)("inlineCode",{parentName:"strong"},"[HttpGet]"))),(0,l.kt)("li",{parentName:"ul"},"\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5",(0,l.kt)("strong",{parentName:"li"},"\u81f3\u5c11\u6709\u4e00\u4e2a\u914d\u7f6e ",(0,l.kt)("inlineCode",{parentName:"strong"},"[Route]")," \u7279\u6027")),(0,l.kt)("li",{parentName:"ul"},"\u751f\u6210 ",(0,l.kt)("inlineCode",{parentName:"li"},"WebAPI")," \u8def\u7531\u5730\u5740\u65f6\u4f1a\u81ea\u52a8\u53bb\u6389\u63a7\u5236\u5668\u540d\u79f0 ",(0,l.kt)("inlineCode",{parentName:"li"},"Controller")," \u540e\u7f00\uff0c\u540c\u65f6\u4e5f\u4f1a\u53bb\u6389\u52a8\u4f5c\u65b9\u6cd5\u5339\u914d\u7684 ",(0,l.kt)("inlineCode",{parentName:"li"},"HttpVerb")," \u8c13\u8bcd\uff0c\u5982 ",(0,l.kt)("inlineCode",{parentName:"li"},"GET\uff0cPOST\uff0cDELETE\uff0cPUT")," \u7b49"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u4e0d\u652f\u6301\u8fd4\u56de\u975e ",(0,l.kt)("inlineCode",{parentName:"strong"},"IEnumerable")," \u6cdb\u578b\u5bf9\u8c61")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u4e0d\u652f\u6301\u7c7b\u7c7b\u578b\u53c2\u6570\u5728 ",(0,l.kt)("inlineCode",{parentName:"strong"},"GET\uff0cHEAD")," \u8bf7\u6c42\u4e0b\u751f\u6210 ",(0,l.kt)("inlineCode",{parentName:"strong"},"Query")," \u53c2\u6570"))),(0,l.kt)("p",null,"\u9664\u4e86\u4e0a\u8ff0\u7ea6\u5b9a\u5916\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u8def\u7531\u5730\u5740",(0,l.kt)("strong",{parentName:"p"},"\u57fa\u672c\u9760\u624b\u5de5\u5b8c\u6210"),"\uff0c\u4e0d\u5229\u4e8e\u4e66\u5199\uff0c\u4e0d\u5229\u4e8e\u7ef4\u62a4\uff0c\u518d\u8005\uff0c\u5728\u79fb\u52a8\u5e94\u7528\u5bf9\u63a5\u4e2d\u96be\u4ee5\u8fdb\u884c\u591a\u7248\u672c\u63a7\u5236\u3002"),(0,l.kt)("h3",{id:"5122-net-core-webapi-\u7f3a\u70b9"},"5.1.2.2 ",(0,l.kt)("inlineCode",{parentName:"h3"},".NET Core WebAPI")," \u7f3a\u70b9"),(0,l.kt)("p",null,"\u901a\u8fc7\u4e0a\u4e00\u7ae0\u8282\u53ef\u4ee5\u770b\u51fa\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u5b9e\u73b0 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u9700\u8981\u9075\u5faa\u79cd\u79cd\u7ea6\u5b9a\uff0c\u800c\u4e14\u5bb9\u6613\u51fa\u9519\u3002"),(0,l.kt)("p",null,"\u9664\u4e86\u8fd9\u4e9b\u7ea6\u5b9a\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},".NET Core WebAPI")," \u6709\u4ee5\u4e0b\u7f3a\u70b9\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u8def\u7531\u5730\u5740\u57fa\u672c\u9760\u624b\u5de5\u5b8c\u6210"),(0,l.kt)("li",{parentName:"ul"},"\u5728\u73b0\u5728\u79fb\u52a8\u4e3a\u738b\u7684\u65f6\u4ee3\uff0c\u4e0d\u5229\u4e8e\u8fdb\u884c\u591a\u7248\u672c\u63a7\u5236"),(0,l.kt)("li",{parentName:"ul"},"\u5bf9\u63a5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Swagger")," \u6587\u6863\u5206\u7ec4\u6bd4\u8f83\u590d\u6742"),(0,l.kt)("li",{parentName:"ul"},"\u5b9e\u73b0 ",(0,l.kt)("inlineCode",{parentName:"li"},"Policy")," \u7b56\u7565\u6388\u6743\u4e5f\u6bd4\u8f83\u590d\u6742"),(0,l.kt)("li",{parentName:"ul"},"\u4e0d\u652f\u6301\u63a7\u5236\u5668\u70ed\u63d2\u62d4\u63d2\u4ef6\u5316"),(0,l.kt)("li",{parentName:"ul"},"\u96be\u4ee5\u5b9e\u73b0\u590d\u6742\u81ea\u5b9a\u4e49\u7684 ",(0,l.kt)("inlineCode",{parentName:"li"},"RESTful API")," \u98ce\u683c")),(0,l.kt)("h2",{id:"513-\u52a8\u6001-webapi-\u63a7\u5236\u5668"},"5.1.3 \u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"h2"},"WebAPI")," \u63a7\u5236\u5668"),(0,l.kt)("p",null,"\u9488\u5bf9\u4ee5\u4e0a ",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u63d0\u4f9b\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u5fc5\u987b\u9075\u5faa\u7684\u7ea6\u5b9a\u548c\u4e0d\u53ef\u907f\u514d\u7684\u7f3a\u70b9\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u521b\u9020\u51fa\u4e00\u79cd\u66f4\u52a0\u7075\u6d3b\u521b\u5efa ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a7\u5236\u5668\u7684\u65b9\u5f0f\u3002"),(0,l.kt)("p",null,"\u8fd9\u4e2a\u65b9\u5f0f\u5728\u7ee7\u627f\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core WebAPI")," \u6240\u6709\u4f18\u70b9\uff0c\u540c\u65f6\u8fdb\u884c\u4e86\u5927\u91cf\u62d3\u5c55\u548c\u4f18\u5316\u3002\u4f18\u5316\u540e\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u5177\u6709\u4ee5\u4e0b\u4f18\u70b9\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u5177\u5907\u539f\u6709\u7684 ",(0,l.kt)("inlineCode",{parentName:"li"},"ControllerBase")," \u6240\u6709\u529f\u80fd"),(0,l.kt)("li",{parentName:"ul"},"\u652f\u6301",(0,l.kt)("strong",{parentName:"li"},"\u4efb\u610f\u516c\u5f00 \u975e\u9759\u6001 \u975e\u62bd\u8c61 \u975e\u6cdb\u578b\u7c7b"),"\u8f6c\u63a7\u5236\u5668"),(0,l.kt)("li",{parentName:"ul"},"\u63d0\u4f9b\u66f4\u52a0\u7075\u6d3b\u65b9\u4fbf\u7684 ",(0,l.kt)("inlineCode",{parentName:"li"},"IDynamicApiController")," \u7a7a\u63a5\u53e3\u6216 ",(0,l.kt)("inlineCode",{parentName:"li"},"[DynamicApiController]")," \u7279\u6027\u66ff\u4ee3 ",(0,l.kt)("inlineCode",{parentName:"li"},"ControllerBase")," \u62bd\u8c61\u7c7b"),(0,l.kt)("li",{parentName:"ul"},"\u65e0\u9700\u624b\u52a8\u914d\u7f6e ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpMethod]")," \u7279\u6027\uff0c\u540c\u65f6\u652f\u6301\u4e00\u4e2a\u52a8\u4f5c\u65b9\u6cd5\u591a\u4e2a ",(0,l.kt)("inlineCode",{parentName:"li"},"HttpVerb")),(0,l.kt)("li",{parentName:"ul"},"\u65e0\u9700\u624b\u52a8\u914d\u7f6e ",(0,l.kt)("inlineCode",{parentName:"li"},"[Route]")," \u7279\u6027\uff0c\u652f\u6301\u66f4\u52a0\u7075\u6d3b\u7684\u914d\u7f6e\u53ca\u81ea\u52a8\u8def\u7531\u751f\u6210"),(0,l.kt)("li",{parentName:"ul"},"\u652f\u6301\u8fd4\u56de\u6cdb\u578b\u63a5\u53e3\uff0c\u6cdb\u578b\u7c7b"),(0,l.kt)("li",{parentName:"ul"},"\u548c ",(0,l.kt)("inlineCode",{parentName:"li"},"Swagger")," \u6df1\u5ea6\u7ed3\u5408\uff0c\u63d0\u4f9b\u6781\u5176\u65b9\u4fbf\u7684\u521b\u5efa ",(0,l.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5206\u7ec4\u914d\u7f6e"),(0,l.kt)("li",{parentName:"ul"},"\u652f\u6301 ",(0,l.kt)("inlineCode",{parentName:"li"},"Basic Auth\uff0cJwt\uff0cApiKey")," \u7b49\u591a\u79cd\u6743\u9650\u7075\u6d3b\u914d\u7f6e"),(0,l.kt)("li",{parentName:"ul"},"\u652f\u6301\u63a7\u5236\u5668\u3001\u52a8\u4f5c\u65b9\u6cd5",(0,l.kt)("strong",{parentName:"li"},"\u7248\u672c\u63a7\u5236"),"\u529f\u80fd"),(0,l.kt)("li",{parentName:"ul"},"\u652f\u6301 ",(0,l.kt)("inlineCode",{parentName:"li"},"GET\u3001HEAD")," \u8bf7\u6c42\u81ea\u52a8\u8f6c\u6362 ",(0,l.kt)("inlineCode",{parentName:"li"},"\u7c7b\u7c7b\u578b\u53c2\u6570")),(0,l.kt)("li",{parentName:"ul"},"\u652f\u6301\u751f\u6210 ",(0,l.kt)("inlineCode",{parentName:"li"},"OAS3")," \u63a5\u53e3\u89c4\u8303")),(0,l.kt)("h2",{id:"514-\u6ce8\u518c\u52a8\u6001-webapi-\u670d\u52a1"},"5.1.4 \u6ce8\u518c\u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"h2"},"WebAPI")," \u670d\u52a1"),(0,l.kt)("admonition",{title:"\u5907\u6ce8",type:"important"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"p"},".AddDynamicApiControllers()")," \u9ed8\u8ba4\u5df2\u7ecf\u96c6\u6210\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"AddInject()")," \u4e2d\u4e86\uff0c\u65e0\u9700\u518d\u6b21\u6ce8\u518c\u3002\u4e5f\u5c31\u662f\u4e0b\u5217\u4ee3\u7801\u53ef\u4e0d\u914d\u7f6e\u3002")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {11} title="Furion.Web.Core\\FurWebCoreStartup.cs"',showLineNumbers:!0,"":!0,"{11}":!0,title:'"Furion.Web.Core\\FurWebCoreStartup.cs"'},"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.Web.Core\n{\n [AppStartup(800)]\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddControllers()\n .AddDynamicApiControllers();\n }\n }\n}\n")),(0,l.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"p"},".AddDynamicApiControllers()")," \u5fc5\u987b\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"services.AddControllers()")," \u4e4b\u540e\u6ce8\u518c\u3002")),(0,l.kt)("h2",{id:"515-\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"5.1.5 \u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,l.kt)("p",null,"\u521b\u5efa\u4e00\u4e2a ",(0,l.kt)("inlineCode",{parentName:"p"},"FurionAppService")," \u7c7b\u7ee7\u627f ",(0,l.kt)("inlineCode",{parentName:"p"},"IDynamicApiController")," \u63a5\u53e3 \u6216 \u8d34 ",(0,l.kt)("inlineCode",{parentName:"p"},"[DynamicApiController]")," \u7279\u6027\uff0c\u5e76\u5728\u8fd9\u4e2a\u7c7b\u4e2d\u7f16\u5199\u4e00\u4e2a ",(0,l.kt)("inlineCode",{parentName:"p"},"Get")," \u65b9\u6cd5\u3002"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},(0,l.kt)("inlineCode",{parentName:"strong"},"IDynamicApiController")," \u65b9\u5f0f"))),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,7}",showLineNumbers:!0,"":!0,"{1,5,7}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return $"Hello {nameof(Furion)}";\n }\n }\n}\n')),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},(0,l.kt)("inlineCode",{parentName:"strong"},"[DynamicApiController]")," \u65b9\u5f0f"))),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,8}",showLineNumbers:!0,"":!0,"{1,5,8}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [DynamicApiController]\n public class FurionAppService\n {\n public string Get()\n {\n return $"Hello {nameof(Furion)}";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff0c\u4e00\u4e2a ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a5\u53e3\u5c31\u8fd9\u4e48\u751f\u6210\u4e86\u3002"),(0,l.kt)("img",{src:(0,r.Z)("img/dyglz.gif")}),(0,l.kt)("h2",{id:"516-\u52a8\u6001-webapi-\u539f\u7406\u89e3\u6790"},"5.1.6 \u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"h2"},"WebAPI")," \u539f\u7406\u89e3\u6790"),(0,l.kt)("h3",{id:"5161-\u63a7\u5236\u5668\u7279\u6027\u63d0\u4f9b\u5668"},"5.1.6.1 \u63a7\u5236\u5668\u7279\u6027\u63d0\u4f9b\u5668"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4f1a\u5728\u5e94\u7528\u542f\u52a8\u65f6\u6ce8\u518c ",(0,l.kt)("inlineCode",{parentName:"p"},"DynamicApiControllerFeatureProvider")," \u63a7\u5236\u5668\u7279\u6027\u63d0\u4f9b\u5668\uff0c\u8be5\u63d0\u4f9b\u5668\u7ee7\u627f\u81ea ",(0,l.kt)("inlineCode",{parentName:"p"},"ControllerFeatureProvider")," \u7c7b\u3002"),(0,l.kt)("p",null,"\u63a5\u7740\u91cd\u5199 ",(0,l.kt)("inlineCode",{parentName:"p"},"bool IsController(TypeInfo typeInfo)")," \u65b9\u6cd5\uff0c\u7528\u6765\u6807\u8bc6\u63a7\u5236\u5668\u7c7b\u578b\u3002\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c",(0,l.kt)("strong",{parentName:"p"},"\u7ee7\u627f\u81ea ",(0,l.kt)("inlineCode",{parentName:"strong"},"ControllerBase")," \u7c7b\u6216 ",(0,l.kt)("inlineCode",{parentName:"strong"},"IDynamicApiController")," \u63a5\u53e3\u6216 ",(0,l.kt)("inlineCode",{parentName:"strong"},"[DynamicApiController]")," \u7279\u6027\u90fd\u4f1a\u88ab\u6807\u8bb0\u4e3a\u63a7\u5236\u5668\u7c7b\u578b\u3002")),(0,l.kt)("h3",{id:"5162-\u5e94\u7528\u6a21\u578b\u8f6c\u6362\u5668"},"5.1.6.2 \u5e94\u7528\u6a21\u578b\u8f6c\u6362\u5668"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u540c\u65f6\u5728\u5e94\u7528\u542f\u52a8\u65f6\u6ce8\u518c ",(0,l.kt)("inlineCode",{parentName:"p"},"DynamicApiControllerApplicationModelConvention")," \u5e94\u7528\u6a21\u578b\u8f6c\u6362\u5668\uff0c\u8be5\u8f6c\u6362\u5668\u7ee7\u627f\u81ea ",(0,l.kt)("inlineCode",{parentName:"p"},"IApplicationModelConvention")," \u63a5\u53e3\u3002"),(0,l.kt)("p",null,"\u63a5\u7740\u5b9e\u73b0 ",(0,l.kt)("inlineCode",{parentName:"p"},"void Apply(ApplicationModel application)")," \u63a5\u53e3\u65b9\u6cd5\u3002\u5728\u8be5\u65b9\u6cd5\u4e2d\u914d\u7f6e\u63a7\u5236\u5668\u540d\u79f0\u3001\u8def\u7531\u3001\u5bfc\u51fa\u53ef\u89c1\u6027\u53ca\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u3001\u8def\u7531\u3001\u5bfc\u51fa\u53ef\u89c1\u6027\u7b49\u3002"),(0,l.kt)("p",null,"\u5b9e\u9645\u4e0a\u8be5\u65b9\u6cd5\u505a\u7684\u5c31\u662f\u6309\u7167 ",(0,l.kt)("strong",{parentName:"p"},(0,l.kt)("a",{parentName:"strong",href:"#521-webapi-%E7%BA%A6%E5%AE%9A"},"WebAPI \u7ea6\u5b9a"))," \u63d0\u524d\u5e2e\u6211\u4eec\u914d\u7f6e\u597d\u8def\u7531\u3001\u8bf7\u6c42\u8c13\u8bcd\u7b49\u4fe1\u606f\u3002\u907f\u514d\u4e86\u624b\u52a8\u914d\u7f6e\u7684\u540c\u65f6\u8fd8\u589e\u52a0\u4e86\u8bb8\u591a\u65b0\u7279\u6027\uff0c\u5982",(0,l.kt)("strong",{parentName:"p"},"\u7248\u672c\u63a7\u5236\u3002")),(0,l.kt)("h2",{id:"517-\u52a8\u6001-webapi-\u914d\u7f6e\u7ea6\u5b9a"},"5.1.7 \u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"h2"},"WebAPI")," \u914d\u7f6e\u7ea6\u5b9a"),(0,l.kt)("h3",{id:"5171-\u63a7\u5236\u5668\u9ed8\u8ba4\u7ea6\u5b9a"},"5.1.7.1 \u63a7\u5236\u5668\u9ed8\u8ba4\u7ea6\u5b9a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u751f\u6210\u63a7\u5236\u5668\u540d\u79f0\u9ed8\u8ba4\u53bb\u9664\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"AppServices\uff0cAppService\uff0cApiController\uff0cController\uff0cServices\uff0cService")," \u4f5c\u4e3a\u524d\u540e\u7f00\u7684\u5b57\u7b26\u4e32\u3002\u89c1\u7b2c\u4e00\u4e2a\u4f8b\u5b50\u4e2d\u7684 ",(0,l.kt)("inlineCode",{parentName:"li"},"FurionAppService -> Furion")," ",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u63a7\u5236\u5668\u540d\u79f0\u5e26 ",(0,l.kt)("inlineCode",{parentName:"li"},"V[0-9_]")," \u7ed3\u5c3e\u7684\uff0c\u4f1a\u81ea\u52a8\u751f\u6210\u63a7\u5236\u5668\u7248\u672c\u53f7\uff0c\u5982 ",(0,l.kt)("inlineCode",{parentName:"li"},"FurionAppServiceV2 -> Furion@2"),"\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"FurionAppServiceV1_1_0 -> Furion@1.1.0"),"\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u7248\u672c\u5206\u9694\u7b26\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u63a7\u5236\u540d\u79f0\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"\u9a86\u9a7c\u547d\u540d\uff08CamelCase\uff09")," \u4f1a\u81ea\u52a8\u5207\u5272\u6210\u591a\u4e2a\u5355\u8bcd ",(0,l.kt)("inlineCode",{parentName:"li"},"-")," \u8fde\u63a5\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"))),(0,l.kt)("h3",{id:"5172-\u52a8\u4f5c\u65b9\u6cd5\u9ed8\u8ba4\u7ea6\u5b9a"},"5.1.7.2 \u52a8\u4f5c\u65b9\u6cd5\u9ed8\u8ba4\u7ea6\u5b9a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u751f\u6210\u7684\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u9ed8\u8ba4\u53bb\u9664\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Post/Add/Create/Insert/Submit\uff0cGetAll/GetList/Get/Find/Fetch/Query/Search\uff0cPut/Update\uff0cDelete/Remove/Clear\uff0cPatch")," \u5f00\u5934\u7684\u5b57\u7b26\u4e32\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u751f\u6210\u7684\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u9ed8\u8ba4\u53bb\u9664\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Async")," \u4f5c\u4e3a\u524d\u540e\u7f00\u7684\u5b57\u7b26\u4e32\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u5e26 ",(0,l.kt)("inlineCode",{parentName:"li"},"V[0-9_]")," \u7ed3\u5c3e\u7684\uff0c\u4f1a\u81ea\u52a8\u751f\u6210\u52a8\u4f5c\u65b9\u6cd5\u7248\u672c\u53f7\uff0c\u5982 ",(0,l.kt)("inlineCode",{parentName:"li"},"ChangePasswordV2 -> ChangePassword@2"),"\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"ChangePasswordV1_1_0 -> ChangePassword@1.1.0"),"\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u7248\u672c\u5206\u9694\u7b26\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"\u9a86\u9a7c(\u9a7c\u5cf0)/\u5e15\u65af\u5361\u547d\u540d\uff08CamelCase/Pascal\uff09")," \u4f1a\u81ea\u52a8\u5207\u5272\u6210\u591a\u4e2a\u5355\u8bcd ",(0,l.kt)("inlineCode",{parentName:"li"},"-")," \u8fde\u63a5\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u52a8\u4f5c\u65b9\u6cd5\u53c2\u6570\u5c06\u81ea\u52a8\u8f6c\u4e3a\u5c0f\u5199\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"))),(0,l.kt)("h3",{id:"5173-\u8bf7\u6c42\u8c13\u8bcd\u9ed8\u8ba4\u7ea6\u5b9a"},"5.1.7.3 \u8bf7\u6c42\u8c13\u8bcd\u9ed8\u8ba4\u7ea6\u5b9a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u52a8\u4f5c\u65b9\u6cd5\u540d",(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Post/Add/Create/Insert/Submit/Change")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPost]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"GetAll/GetList/Get/Find/Fetch/Query")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpGet]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Put/Update")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPut]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Delete/Remove/Clear")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpDelete]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Patch")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPatch]")," \u7279\u6027"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")))),(0,l.kt)("li",{parentName:"ul"},"\u5982\u679c\u4e0d\u5728\u4e0a\u9762\u7ea6\u5b9a\u4e2d\uff0c\u5219\u9ed8\u8ba4\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPost]")," \u7279\u6027\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"))),(0,l.kt)("h3",{id:"5174-\u8def\u7531\u5730\u5740\u9ed8\u8ba4\u7ea6\u5b9a"},"5.1.7.4 \u8def\u7531\u5730\u5740\u9ed8\u8ba4\u7ea6\u5b9a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u9ed8\u8ba4\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"api")," \u5f00\u5934\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u9ed8\u8ba4\u8f6c\u6362\u4e3a\u5c0f\u5199\u8def\u7531\u5730\u5740\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u751f\u6210\u63a7\u5236\u5668\u8def\u7531\u6a21\u677f\u683c\u5f0f\u4e3a\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"api/\u524d\u7f6e\u53c2\u6570\u5217\u8868/\u6a21\u5757\u540d\u6216\u9ed8\u8ba4\u533a\u57df\u540d/[controller@\u7248\u672c\u53f7]/\u540e\u7f6e\u53c2\u6570\u5217\u8868")),(0,l.kt)("li",{parentName:"ul"},"\u751f\u6210\u52a8\u4f5c\u65b9\u6cd5\u8def\u7531\u6a21\u677f\u683c\u5f0f\u4e3a\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"\u524d\u7f6e\u53c2\u6570\u5217\u8868/\u6a21\u5757\u540d/[action@\u7248\u672c\u53f7]/\u540e\u7f6e\u53c2\u6570\u5217\u8868"))),(0,l.kt)("h3",{id:"5175-\u5176\u4ed6\u7ea6\u5b9a"},"5.1.7.5 \u5176\u4ed6\u7ea6\u5b9a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u9ed8\u8ba4\u4e0d\u5904\u7406 ",(0,l.kt)("inlineCode",{parentName:"li"},"ControllerBase")," \u63a7\u5236\u5668\u7c7b\u578b\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u9ed8\u8ba4\u4e0d\u5904\u7406 ",(0,l.kt)("inlineCode",{parentName:"li"},"GET\uff0cHEAD")," \u8bf7\u6c42\u7684\u5f15\u7528\u7c7b\u578b\u53c2\u6570\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"))),(0,l.kt)("h2",{id:"518-\u66f4\u591a\u4f8b\u5b50"},"5.1.8 \u66f4\u591a\u4f8b\u5b50"),(0,l.kt)("h3",{id:"5181-\u591a\u79cd\u8bf7\u6c42\u8c13\u8bcd\u65b9\u6cd5"},"5.1.8.1 \u591a\u79cd\u8bf7\u6c42\u8c13\u8bcd\u65b9\u6cd5"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,12,17,22,27}",showLineNumbers:!0,"":!0,"{7,12,17,22,27}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return $"GET \u8bf7\u6c42";\n }\n\n public string Post()\n {\n return $"POST \u8bf7\u6c42";\n }\n\n public string Delete()\n {\n return $"DELETE \u8bf7\u6c42";\n }\n\n public string Put()\n {\n return $"PUT \u8bf7\u6c42";\n }\n\n public string Patch()\n {\n return $"PATCH \u8bf7\u6c42";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dgqqwc.png")}),(0,l.kt)("h3",{id:"5182-\u591a\u4e2a\u81ea\u5b9a\u4e49\u52a8\u4f5c\u65b9\u6cd5"},"5.1.8.2 \u591a\u4e2a\u81ea\u5b9a\u4e49\u52a8\u4f5c\u65b9\u6cd5"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,12,17}",showLineNumbers:!0,"":!0,"{7,12,17}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string GetVersion()\n {\n return $"v1.0.0";\n }\n\n public string ChangeProfile()\n {\n return "\u4fee\u6539\u6210\u529f";\n }\n\n public string DeleteUser()\n {\n return "\u5220\u9664\u6210\u529f";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dzmc.png")}),(0,l.kt)("h3",{id:"5183-\u5e26\u53c2\u6570\u52a8\u4f5c\u65b9\u6cd5"},"5.1.8.3 \u5e26\u53c2\u6570\u52a8\u4f5c\u65b9\u6cd5"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,12,17}",showLineNumbers:!0,"":!0,"{7,12,17}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string GetUser(int id)\n {\n return $"{id}";\n }\n\n public string GetUser(int id, string name)\n {\n return $"{id} {name}";\n }\n\n public TestDto Add(TestDto testDto)\n {\n return testDto;\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dcsff.gif")}),(0,l.kt)("h3",{id:"5184-gethead-\u7c7b\u7c7b\u578b\u53c2\u6570"},"5.1.8.4 ",(0,l.kt)("inlineCode",{parentName:"h3"},"GET/HEAD")," \u7c7b\u7c7b\u578b\u53c2\u6570"),(0,l.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u4f1a\u5c06 ",(0,l.kt)("inlineCode",{parentName:"p"},"GET/HEAD")," \u8bf7\u6c42\u4e2d\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"\u7c7b\u7c7b\u578b\u53c2\u6570")," \u8bbe\u7f6e\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"[FromBody]")," \u7ed1\u5b9a\uff0c\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7}",showLineNumbers:!0,"":!0,"{7}":!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public TestDto GetTest(TestDto testDto)\n {\n return testDto;\n }\n }\n}\n")),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/getyycs.png")}),(0,l.kt)("p",null,"\u4f46\u662f\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"GET\u3001HEAD")," \u8bf7\u6c42\u4e0d\u652f\u6301 ",(0,l.kt)("inlineCode",{parentName:"p"},"From Body")," \u7ed1\u5b9a\u3002\u6240\u4ee5\u6211\u4eec\u9700\u8981\u8f6c\u6362\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"Query")," \u67e5\u8be2\u53c2\u6570\u3002"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u652f\u6301\u4ee5\u4e0b\u4e24\u79cd\u65b9\u5f0f\u914d\u7f6e\uff1a"),(0,l.kt)(o.Z,{defaultValue:"fromquery",values:[{label:"[FromQuery] \u7279\u6027",value:"fromquery"},{label:"\u914d\u7f6e DynamicApiControllerSettings",value:"DynamicApiControllerSettings"}],mdxType:"Tabs"},(0,l.kt)(p.Z,{value:"fromquery",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,8}",showLineNumbers:!0,"":!0,"{2,8}":!0},"using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public TestDto GetTest([FromQuery] TestDto testDto)\n {\n return testDto;\n }\n }\n}\n"))),(0,l.kt)(p.Z,{value:"DynamicApiControllerSettings",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers {2-4} title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,"{2-4}":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "DynamicApiControllerSettings": {\n "ModelToQuery": true\n }\n}\n')))),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/modeltoquery.png")}),(0,l.kt)("h3",{id:"5185-\u81ea\u5b9a\u4e49\u53c2\u6570\u4f4d\u7f6e"},"5.1.8.5 \u81ea\u5b9a\u4e49\u53c2\u6570\u4f4d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u975e\u5e38\u65b9\u4fbf\u7684\u81ea\u5b9a\u4e49\u53c2\u6570\u4f4d\u7f6e\u7684\u7279\u6027 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiSeat]"),"\uff0c\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiSeat]")," \u53ef\u914d\u7f6e\u53c2\u6570\u4f4d\u7f6e\uff0c\u652f\u6301\u4ee5\u4e0b\u56db\u79cd\u4f4d\u7f6e\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ApiSeats.ControllerStart"),"\uff1a\u63a7\u5236\u5668\u4e4b\u524d"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ApiSeats.ControllerEnd"),"\uff1a\u63a7\u5236\u5668\u4e4b\u540e"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ApiSeats.ActionStart"),"\uff1a\u52a8\u4f5c\u65b9\u6cd5\u4e4b\u524d"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ApiSeats.ActionEnd"),"\uff1a\u52a8\u4f5c\u65b9\u6cd5\u4e4b\u540e\u3002",(0,l.kt)("strong",{parentName:"li"},"\u9ed8\u8ba4\u503c"))),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8-9,15-20}",showLineNumbers:!0,"":!0,"{8-9,15-20}":!0},'using Furion.DynamicApiController;\nusing System;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n // \u53c2\u6570\u9ed8\u8ba4\u4e3a ApiSeats.ActionEnd\n public string RouteSeat(int id, string name)\n {\n return "\u914d\u7f6e\u8def\u7531\u53c2\u6570\u4f4d\u7f6e";\n }\n\n public string RouteSeat(\n [ApiSeat(ApiSeats.ControllerStart)] int id, // \u63a7\u5236\u5668\u540d\u79f0\u4e4b\u524d\n [ApiSeat(ApiSeats.ControllerEnd)] string name, // \u63a7\u5236\u5668\u540d\u79f0\u4e4b\u540e\n [ApiSeat(ApiSeats.ControllerEnd)] int age, // \u63a7\u5236\u5668\u540d\u79f0\u4e4b\u540e\n [ApiSeat(ApiSeats.ActionStart)] decimal weight, // \u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u4e4b\u524d\n [ApiSeat(ApiSeats.ActionStart)] float height, // \u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u4e4b\u524d\n [ApiSeat(ApiSeats.ActionEnd)] DateTime birthday) // \u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u4e4b\u540e\uff08\u9ed8\u8ba4\u503c\uff09\n {\n return "\u914d\u7f6e\u8def\u7531\u53c2\u6570\u4f4d\u7f6e";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/cswz.png")}),(0,l.kt)("admonition",{title:"\u6e29\u99a8\u63d0\u793a",type:"note"},(0,l.kt)("p",{parentName:"admonition"},"\u591a\u4e2a ",(0,l.kt)("strong",{parentName:"p"},(0,l.kt)("inlineCode",{parentName:"strong"},"\u540c\u4f4d\u7f6e"))," \u914d\u7f6e\u7684\u53c2\u6570\u5c06\u6309\u7167 ",(0,l.kt)("strong",{parentName:"p"},(0,l.kt)("inlineCode",{parentName:"strong"},"\u5b9a\u4e49\u53c2\u6570\u987a\u5e8f"))," \u8fdb\u884c\u6392\u5e8f\u3002")),(0,l.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"p"},"[ApiSeat]")," \u53ea\u80fd\u5e94\u7528\u4e8e\u8d34\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},"[FromRoute]")," \u7279\u6027\u7684\u53c2\u6570\u6216 ",(0,l.kt)("inlineCode",{parentName:"p"},"\u57fa\u5143\u7c7b\u578b\u3001\u503c\u7c7b\u578b\u3001\u53ef\u7a7a\u57fa\u5143\u7c7b\u578b\u548c\u53ef\u7a7a\u503c\u7c7b\u578b"),"\u3002")),(0,l.kt)("h3",{id:"5186-\u81ea\u5b9a\u4e49\u8bf7\u6c42\u8c13\u8bcd"},"5.1.8.6 \u81ea\u5b9a\u4e49\u8bf7\u6c42\u8c13\u8bcd"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,8}",showLineNumbers:!0,"":!0,"{2,8}":!0},'using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n [HttpPost]\n public string GetVersion()\n {\n return "1.0.0";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/zdywc.png")}),(0,l.kt)("h3",{id:"5187-\u652f\u6301\u591a\u4e2a\u8c13\u8bcd"},"5.1.8.7 \u652f\u6301\u591a\u4e2a\u8c13\u8bcd"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,8}",showLineNumbers:!0,"":!0,"{2,8}":!0},'using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n [HttpPost, HttpGet, AcceptVerbs("PUT", "DELETE")]\n public string GetVersion()\n {\n return "1.0.0";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dgwc.png")}),(0,l.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,l.kt)("p",{parentName:"admonition"},"\u5982\u679c\u52a8\u4f5c\u65b9\u6cd5\u4e2d\u542b\u6709 ",(0,l.kt)("inlineCode",{parentName:"p"},"\u7c7b\u7c7b\u578b\u53c2\u6570"),"\uff0c\u4e14\u542b\u6709 ",(0,l.kt)("inlineCode",{parentName:"p"},"POST/PUT/DELETE")," \u4efb\u610f\u8bf7\u6c42\u8c13\u8bcd\uff0c\u90a3\u4e48\u8be5\u53c2\u6570\u4f1a\u81ea\u52a8\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"p"},"[FromBody]")," \u53c2\u6570\uff0c\u5373\u4f7f\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"GET/HEAD")," \u8bf7\u6c42\u4e2d\u4e0d\u652f\u6301\u3002")),(0,l.kt)("h3",{id:"5188-\u652f\u6301\u81ea\u5b9a\u4e49\u8def\u7531"},"5.1.8.8 \u652f\u6301\u81ea\u5b9a\u4e49\u8def\u7531"),(0,l.kt)("p",null,"\u652f\u6301\u63a7\u5236\u5668\u548c\u52a8\u4f5c\u65b9\u6cd5\u81ea\u5b9a\u4e49\u8def\u7531\uff1a"),(0,l.kt)(o.Z,{defaultValue:"kzqrl",values:[{label:"\u81ea\u5b9a\u4e49\u63a7\u5236\u5668\u8def\u7531",value:"kzqrl"},{label:"\u81ea\u5b9a\u4e49\u52a8\u4f5c\u65b9\u6cd5\u8def\u7531",value:"dzffrl"},{label:"\u540c\u65f6\u81ea\u5b9a\u4e49\u8def\u7531",value:"allrl"},{label:"\u8c13\u8bcd\u81ea\u5b9a\u4e49\u8def\u7531",value:"vcrl"}],mdxType:"Tabs"},(0,l.kt)(p.Z,{value:"kzqrl",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6}",showLineNumbers:!0,"":!0,"{2,6}":!0},'using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n [Route("customapi/mobile/[controller]")]\n public class FurionAppService : IDynamicApiController\n {\n public string GetVersion()\n {\n return "1.0.0";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/kzqrl.png")})),(0,l.kt)(p.Z,{value:"dzffrl",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,8}",showLineNumbers:!0,"":!0,"{2,8}":!0},'using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n [Route("customapi/[action]")]\n public string GetVersion()\n {\n return "1.0.0";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dzffrl.png")})),(0,l.kt)(p.Z,{value:"allrl",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6,9}",showLineNumbers:!0,"":!0,"{2,6,9}":!0},'using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n [Route("customapi/mobile/[controller]")]\n public class FurionAppService : IDynamicApiController\n {\n [Route("get/[action]")]\n public string GetVersion()\n {\n return "1.0.0";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/allrl.png")})),(0,l.kt)(p.Z,{value:"vcrl",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9}",showLineNumbers:!0,"":!0,"{9}":!0},'using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n [Route("api/[controller]")]\n public class FurionAppService : IDynamicApiController\n {\n [HttpGet("get/[action]")]\n public string GetVersion()\n {\n return "1.0.0";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/wcrl.png")}))),(0,l.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"important"},(0,l.kt)("p",{parentName:"admonition"},"\u52a8\u4f5c\u65b9\u6cd5\u81ea\u5b9a\u4e49\u8def\u7531\u5982\u679c\u4ee5 ",(0,l.kt)("strong",{parentName:"p"},(0,l.kt)("inlineCode",{parentName:"strong"},"/"))," \u5f00\u5934\uff0c\u5219\u4e0d\u4f1a\u5408\u5e76\u63a7\u5236\u5668\u8def\u7531\u3002")),(0,l.kt)("admonition",{title:"\u63a8\u8350\u914d\u7f6e",type:"tip"},(0,l.kt)("p",{parentName:"admonition"},"\u81ea\u5b9a\u4e49\u8def\u7531\u5982\u679c\u9700\u8981\u7528\u5230 ",(0,l.kt)("strong",{parentName:"p"},"\u63a7\u5236\u5668/\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0"),"\uff0c\u63a8\u8350\u4f7f\u7528 ",(0,l.kt)("inlineCode",{parentName:"p"},"[controller]")," \u6216 ",(0,l.kt)("inlineCode",{parentName:"p"},"[action]")," \u5360\u4f4d\u7b26\uff0c\u56e0\u4e3a\u8be5\u5360\u4f4d\u7b26\u5df2\u7ecf\u81ea\u52a8\u5904\u7406\u4e86 ",(0,l.kt)("strong",{parentName:"p"},"\u524d\u540e\u7f00\u3001\u7248\u672c\u53f7\u3001\u6a21\u5757\u540d\u79f0"),"\u7b49\u3002")),(0,l.kt)("h3",{id:"5189-\u591a\u8def\u7531\u968f\u610f\u7ec4\u5408"},"5.1.8.9 \u591a\u8def\u7531\u968f\u610f\u7ec4\u5408"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u7684\u5404\u79cd\u8def\u7531\u7ec4\u5408\u65b9\u5f0f\uff0c\u652f\u6301\u4e00\u5bf9\u591a\uff0c\u591a\u5bf9\u591a\u8def\u7531\u7ec4\u5408\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6-8,11-14}",showLineNumbers:!0,"":!0,"{6-8,11-14}":!0},'using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n [Route("api/[controller]")]\n [Route("api/[controller]/second")]\n [Route("api/[controller]/three")]\n public class FurionAppService : IDynamicApiController\n {\n [HttpGet]\n [HttpGet("get/[action]")]\n [HttpPost]\n [HttpPost("post/cus-version")]\n public string GetVersion()\n {\n return "1.0.0";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dlrzh.gif")}),(0,l.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,l.kt)("p",{parentName:"admonition"},"\u52a8\u4f5c\u65b9\u6cd5\u4e0d\u80fd\u540c\u65f6\u8d34 ",(0,l.kt)("inlineCode",{parentName:"p"},"[Route]")," \u548c ",(0,l.kt)("inlineCode",{parentName:"p"},"[HttpMethod]")," \u7279\u6027\uff0c\u53ea\u80fd\u4e8c\u53d6\u4e00\u3002")),(0,l.kt)("h3",{id:"51810-\u652f\u6301\u7248\u672c\u63a7\u5236"},"5.1.8.10 \u652f\u6301\u7248\u672c\u63a7\u5236"),(0,l.kt)(o.Z,{defaultValue:"kzqbb",values:[{label:"\u63a7\u5236\u5668\u7248\u672c",value:"kzqbb"},{label:"\u52a8\u4f5c\u65b9\u6cd5\u7248\u672c",value:"dzffbb"}],mdxType:"Tabs"},(0,l.kt)(p.Z,{value:"kzqbb",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,13,21}",showLineNumbers:!0,"":!0,"{5,13,21}":!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppServiceV1 : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n }\n\n public class FurionAppServiceV1_2 : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n }\n\n public class FurionAppServiceV1_2_1 : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n }\n}\n")),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/kzqbb.png")})),(0,l.kt)(p.Z,{value:"dzffbb",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,12,16}",showLineNumbers:!0,"":!0,"{7,12,16}":!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public string GetV1()\n {\n return nameof(Furion);\n }\n public string GetV2_1()\n {\n return nameof(Furion);\n }\n }\n}\n")),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dzffbb.png")}))),(0,l.kt)("admonition",{title:"\u7248\u672c\u751f\u6210\u539f\u7406",type:"note"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("strong",{parentName:"p"},(0,l.kt)("inlineCode",{parentName:"strong"},"V[0-9_]"))," \u7ed3\u5c3e\u7684\u547d\u540d\u81ea\u52a8\u89e3\u6790\u6210\u7248\u672c\u53f7\uff0c\u5982 ",(0,l.kt)("strong",{parentName:"p"},(0,l.kt)("inlineCode",{parentName:"strong"},"FurionAppServiceV2 -> Furion@2")),"\u3002")),(0,l.kt)("admonition",{title:"\u7248\u672c\u590d\u5199",type:"tip"},(0,l.kt)("p",{parentName:"admonition"},"\u9664\u4e86\u901a\u8fc7\u7279\u5b9a\u540e\u7f00\u65b9\u5f0f\u4ee5\u5916\uff0c\u7248\u672c\u8fd8\u76f4\u63a5\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiDescriptionSettings]")," \u8fdb\u884c\u590d\u5199\u3002\u5982\uff1a"),(0,l.kt)("pre",{parentName:"admonition"},(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,2}",showLineNumbers:!0,"":!0,"{1,2}":!0},'[ApiDescriptionSettings(Version = "4.0")]\npublic string GetV1()\n{\n return nameof(Furion);\n}\n')),(0,l.kt)("p",{parentName:"admonition"},"\u8fd9\u65f6\uff0c\u751f\u6210\u7248\u672c\u5c06\u91c7\u7528 ",(0,l.kt)("inlineCode",{parentName:"p"},"4.0")," \u66ff\u4ee3 ",(0,l.kt)("inlineCode",{parentName:"p"},"1"))),(0,l.kt)("h3",{id:"51811-\u4e0d\u516c\u5f00\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5"},"5.1.8.11 \u4e0d\u516c\u5f00\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5"),(0,l.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u65e0\u9700\u5bfc\u51fa\u67d0\u4e2a\u52a8\u4f5c\u65b9\u6cd5\u6216\u63a7\u5236\u5668\uff08",(0,l.kt)("strong",{parentName:"p"},"\u4e0d\u663e\u793a\u5230 Swagger"),"\uff09\uff0c\u53ea\u9700\u8981\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiDescriptionSettings(false)]")," \u6216 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiExplorerSettings(IgnoreApi = true)]"),"\u5373\u53ef\u3002"),(0,l.kt)("p",null,"\u53e6\u5916\u52a8\u4f5c\u65b9\u6cd5\u8fd8\u652f\u6301 ",(0,l.kt)("inlineCode",{parentName:"p"},"[NonAction]")," \u6807\u8bb0\u4e0d\u662f\u4e00\u4e2a\u6709\u6548\u7684\u63a7\u5236\u5668\u6216 Action\u3002"),(0,l.kt)("admonition",{title:"\u63a8\u8350\u4f7f\u7528",type:"tip"},(0,l.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5\u8bbe\u7f6e\u4e0d\u5bfc\u51fa\u4f7f\u7528 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiDescriptionSettings(false)]")," \u7279\u6027\u3002\u8be5\u7279\u6027\u9ed8\u8ba4\u7ee7\u627f\u81ea ",(0,l.kt)("inlineCode",{parentName:"p"},"ApiExplorerSettingsAttribute")," \u7c7b\u3002")),(0,l.kt)("h3",{id:"51812-\u4fdd\u6301\u63a7\u5236\u5668\u548c\u65b9\u6cd5\u547d\u540d"},"5.1.8.12 \u4fdd\u6301\u63a7\u5236\u5668\u548c\u65b9\u6cd5\u547d\u540d"),(0,l.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u52a8\u6001 API \u4f1a\u5c06\u63a7\u5236\u5668\u548c\u65b9\u6cd5\u540d\u8f93\u51fa\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"RESTFul")," \u98ce\u683c\u7684\u8def\u7531\uff0c\u5982\u9700\u4fdd\u7559\u539f\u6709\u8bbe\u8ba1\uff0c\u53ea\u9700\u914d\u7f6e\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "DynamicApiControllerSettings": {\n "KeepName": true,\n "KeepVerb": true,\n "LowercaseRoute": false\n }\n}\n')),(0,l.kt)("h3",{id:"51813-\u65b9\u6cd5\u53c2\u6570-fromquery-\u5316\u53c2\u6570\u975e\u5fc5\u586b\u53c2\u6570\u53ef\u9009"},"5.1.8.13 \u65b9\u6cd5\u53c2\u6570 ",(0,l.kt)("inlineCode",{parentName:"h3"},"[FromQuery]")," \u5316/\u53c2\u6570\u975e\u5fc5\u586b/\u53c2\u6570\u53ef\u9009"),(0,l.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u6240\u6709\u7684\u57fa\u5143\u7c7b\u578b\u53c2\u6570\u90fd\u4f1a\u8d34\u4e0a ",(0,l.kt)("inlineCode",{parentName:"p"},"[FromRoute]")," \u7279\u6027\uff0c\u5982\u679c\u9700\u8981\u5c06\u53c2\u6570\u8c03\u6574\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"[FromQuery]")," \u4fee\u9970\uff0c\u53ea\u9700\u8981\u5728\u65b9\u6cd5\u4e0a\u9762\u8d34 ",(0,l.kt)("inlineCode",{parentName:"p"},"[QueryParameters]")," \u7279\u6027\u5373\u53ef\uff0c\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[QueryParameters]\npublic string Get(int id, string name)\n{\n return nameof($"{id} {name}");\n}\n')),(0,l.kt)("p",null,"\u751f\u6210\u7684\u8def\u7531\u4e3a\uff1a",(0,l.kt)("inlineCode",{parentName:"p"},"https://xxx.com?id=1&name=Furion")),(0,l.kt)("p",null,"\u5982\u679c\u4e0d\u559c\u6b22\u6bcf\u4e2a\u90fd\u914d\u7f6e\uff0c\u4e5f\u53ef\u4ee5\u5168\u5c40\u914d\u7f6e\uff08",(0,l.kt)("strong",{parentName:"p"},"\u53ea\u4f1a\u5f71\u54cd\u57fa\u5143\u7c7b\u578b\u7684\u53c2\u6570"),"\uff09\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "DynamicApiControllerSettings": {\n "UrlParameterization": true\n }\n}\n')),(0,l.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,l.kt)("p",{parentName:"admonition"},"\u8d34\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},"[QueryParameters]")," \u4e4b\u540e\uff0c\u4f1a\u5bf9\u6240\u6709\u53c2\u6570\u5f71\u54cd\uff0c\u5305\u62ec\u7c7b\u7c7b\u578b\u53c2\u6570\uff0c\u5982\u679c\u4e0d\u9700\u8981\u5904\u7406\u67d0\u4e2a\u53c2\u6570\uff0c\u53ea\u9700\u8981\u8d34 ",(0,l.kt)("inlineCode",{parentName:"p"},"[FromXXX]")," \u7279\u6027\u5373\u53ef\u3002")),(0,l.kt)("h3",{id:"51814-\u53c2\u6570\u7ed1\u5b9a\u914d\u7f6e"},"5.1.8.14 \u53c2\u6570\u7ed1\u5b9a\u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u591a\u79cd\u53c2\u6570\u7279\u6027\u914d\u7f6e\u53c2\u6570\u7ed1\u5b9a\u89c4\u5219\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[FromRoute]"),"\uff1a\u901a\u8fc7\u8def\u7531\u53c2\u6570\u7ed1\u5b9a\u503c"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[FromQuery]"),"\uff1a\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"li"},"Url")," \u5730\u5740\u53c2\u6570\u7ed1\u5b9a\u503c"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[FromBody]"),"\uff1a\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"li"},"Request Body")," \u53c2\u6570\u7ed1\u5b9a\u503c"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[FromForm]"),"\uff1a\u901a\u8fc7\u8868\u5355\u63d0\u4ea4\u7ed1\u5b9a\u503c"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[FromHeader]"),"\uff1a\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"li"},"Request Header")," \u53c2\u6570\u7ed1\u5b9a\u503c")),(0,l.kt)("h3",{id:"51815-\u81ea\u5b9a\u4e49\u6839\u636e\u65b9\u6cd5\u540d\u751f\u6210-httpmethod-\u89c4\u5219"},"5.1.8.15 \u81ea\u5b9a\u4e49\u6839\u636e\u65b9\u6cd5\u540d\u751f\u6210 ",(0,l.kt)("inlineCode",{parentName:"h3"},"[HttpMethod]")," \u89c4\u5219"),(0,l.kt)("p",null,"\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5728\u6ca1\u6709\u914d\u7f6e ",(0,l.kt)("inlineCode",{parentName:"p"},"[HttpMethod]")," \u7279\u6027\u7684\u60c5\u51b5\u4e0b\uff0c\u4f1a\u81ea\u52a8\u6839\u636e\u65b9\u6cd5\u540d\u7b2c\u4e00\u4e2a\u53c2\u6570\u8fdb\u884c\u5206\u6790\uff0c\u5e76\u751f\u6210\u5bf9\u5e94\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"[HttpMethod]")," \u7279\u6027\uff0c\u89c4\u5219\u5982\u4e0b\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u52a8\u4f5c\u65b9\u6cd5\u540d",(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Post/Add/Create/Insert/Submit")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPost]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"GetAll/GetList/Get/Find/Fetch/Query")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpGet]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Put/Update")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPut]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Delete/Remove/Clear")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpDelete]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Patch")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPatch]")," \u7279\u6027"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Head")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpHead]")," \u7279\u6027"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")))),(0,l.kt)("li",{parentName:"ul"},"\u5982\u679c\u4e0d\u5728\u4e0a\u9762\u7ea6\u5b9a\u4e2d\uff0c\u5219\u9ed8\u8ba4\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPost]")," \u7279\u6027\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"))),(0,l.kt)("p",null,(0,l.kt)("strong",{parentName:"p"},"\u4f46\u662f\uff0c\u6709\u4e9b\u65f6\u5019\u8fd9\u4e0d\u662f\u6211\u4eec\u60f3\u8981\u7684\u89c4\u5219"),"\uff0c\u8fd9\u65f6\u6211\u4eec\u53ea\u9700\u8981\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u4e2d\u914d\u7f6e\u5373\u53ef\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2,3}",showLineNumbers:!0,"":!0,"{2,3}":!0},'{\n "DynamicApiControllerSettings": {\n "VerbToHttpMethods": [\n ["getall", "HEAD"], // => getall \u4f1a\u88ab\u590d\u5199\u4e3a `[HttpHead]`\n ["other", "PUT"] // => \u65b0\u589e\u4e00\u6761\u65b0\u89c4\u5219\uff0c\u6bd4\u5982\uff0c\u4e00 `[other]` \u5f00\u5934\u4f1a\u8f6c\u6362\u4e3a `[HttpPut]` \u8bf7\u6c42\n ]\n }\n}\n')),(0,l.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,l.kt)("p",{parentName:"admonition"},"\u4e8c\u7ef4\u6570\u7ec4\u4e2d\u7684\u6bcf\u4e00\u4e2a\u5143\u7d20\u7684\u7b2c\u4e00\u4e2a\u5143\u7d20",(0,l.kt)("strong",{parentName:"p"},"\u5fc5\u987b\u662f\u5168\u5c0f\u5199"),"\uff0c\u7b2c\u4e8c\u4e2a\u5143\u7d20",(0,l.kt)("strong",{parentName:"p"},"\u5fc5\u987b\u662f\u5168\u5927\u5199\u5927\u5199"),"\uff0c\u7b2c\u4e8c\u4e2a\u5143\u7d20\u53d6\u503c\u6709\uff1a",(0,l.kt)("inlineCode",{parentName:"p"},"HEAD, GET, PUT, POST, PATCH, DELETE"))),(0,l.kt)("h3",{id:"51816-\u8def\u7531\u53c2\u6570\u975e\u5fc5\u586b\u9009\u586b"},"5.1.8.16 \u8def\u7531\u53c2\u6570\u975e\u5fc5\u586b/\u9009\u586b"),(0,l.kt)("p",null,"\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"Furion v2.8.6")," \u7248\u672c\u4e2d\u5b9e\u73b0\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},"[FromRoute]")," \u53c2\u6570\u975e\u5fc5\u586b\u529f\u80fd\uff0c\u652f\u6301\u4ee5\u4e0b\u51e0\u79cd\u65b9\u5f0f\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6,11,16}",showLineNumbers:!0,"":!0,"{2,6,11,16}":!0},"// \u65b9\u5f0f\u4e00\uff0c\u901a\u8fc7\u53ef\u7a7a ?\npublic object Method1(int id, Datetime? dateTime)\n{\n}\n\n// \u65b9\u5f0f\u4e8c\uff0c\u901a\u8fc7\u9ed8\u8ba4\u503c\npublic object Method1(int id, int age = 10)\n{\n}\n\n// \u65b9\u5f0f\u4e09\uff0c\u9ed8\u8ba4\u503c + \u53ef\u7a7a ?\npublic object Method1(int id, int? age = 10)\n{\n}\n\n// \u65b9\u5f0f\u56db\uff0c[FromQuery] \u4fee\u9970\npublic object Method1(int id, [FromQuery]string keyword)\n{\n}\n")),(0,l.kt)("h3",{id:"51817-formroute-\u8def\u7531\u7ea6\u675f"},"5.1.8.17 ",(0,l.kt)("inlineCode",{parentName:"h3"},"[FormRoute]")," \u8def\u7531\u7ea6\u675f"),(0,l.kt)("p",null,"\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"Furion v2.8.6")," \u7248\u672c\u4e2d\uff0c\u6dfb\u52a0\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},"[RouteConstraint]")," \u7279\u6027\uff0c\u53ef\u914d\u7f6e\u8def\u7531\u7ea6\u675f\uff0c\u5982\uff1a",(0,l.kt)("inlineCode",{parentName:"p"},'[RouteConstraint(":min(10)")]')),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},'// \u6700\u5c0f\u503c 10\npublic object Method1([RouteConstraint(":min(10)")] int id)\n{\n}\n')),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"[RouteConstraint]")," \u652f\u6301\u8def\u7531\u7ea6\u675f\u7b26\u53f7\u5982\u4e0b\uff1a"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"\u7b26\u53f7"),(0,l.kt)("th",{parentName:"tr",align:null},"\u63cf\u8ff0"),(0,l.kt)("th",{parentName:"tr",align:null},"\u4f8b\u5b50"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"alpha")),(0,l.kt)("td",{parentName:"tr",align:null},"\u5339\u914d\u5927\u5199\u6216\u5c0f\u5199\u62c9\u4e01\u5b57\u6bcd\u5b57\u7b26\uff08a-z\u3001A-Z\uff09"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":alpha"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"bool")),(0,l.kt)("td",{parentName:"tr",align:null},"bool \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":bool"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"datetime")),(0,l.kt)("td",{parentName:"tr",align:null},"DateTime \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":datetime"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"decimal")),(0,l.kt)("td",{parentName:"tr",align:null},"decimal \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":decimal"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"double")),(0,l.kt)("td",{parentName:"tr",align:null},"double \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":double"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"float")),(0,l.kt)("td",{parentName:"tr",align:null},"float \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":float"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"guid")),(0,l.kt)("td",{parentName:"tr",align:null},"guid \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":guid"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"int")),(0,l.kt)("td",{parentName:"tr",align:null},"int \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":int"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"long")),(0,l.kt)("td",{parentName:"tr",align:null},"long \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":long"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"length")),(0,l.kt)("td",{parentName:"tr",align:null},"\u5339\u914d\u957f\u5ea6\uff08\u5b57\u7b26\u4e32\uff09"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":length(6)")," \u6216 ",(0,l.kt)("inlineCode",{parentName:"td"},":length(1,20)"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"max")),(0,l.kt)("td",{parentName:"tr",align:null},"\u6700\u5927\u503c"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":max(10)"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"maxlength")),(0,l.kt)("td",{parentName:"tr",align:null},"\u6700\u5927\u957f\u5ea6\uff08\u5b57\u7b26\u4e32\uff09"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":maxlength(10)"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"min")),(0,l.kt)("td",{parentName:"tr",align:null},"\u6700\u5c0f\u503c"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":min(10)"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"minlength")),(0,l.kt)("td",{parentName:"tr",align:null},"\u6700\u5c0f\u957f\u5ea6\uff08\u5b57\u7b26\u4e32\uff09"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":minlength(10)"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"range")),(0,l.kt)("td",{parentName:"tr",align:null},"\u53d6\u503c\u8303\u56f4"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":range(10,50)"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"regex")),(0,l.kt)("td",{parentName:"tr",align:null},"\u6b63\u5219\u8868\u8fbe\u5f0f"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":regex(^\\d{3}-\\d{3}-\\d{4}$)"))))),(0,l.kt)("h3",{id:"51818-\u5c0f\u9a7c\u5cf0-\u8def\u7531\u8def\u5f84"},"5.1.8.18 ",(0,l.kt)("inlineCode",{parentName:"h3"},"\u5c0f\u9a7c\u5cf0")," \u8def\u7531\u8def\u5f84"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "DynamicApiControllerSettings": {\n "LowercaseRoute": false,\n "KeepName": true,\n "AsLowerCamelCase": true\n }\n}\n')),(0,l.kt)("h2",{id:"519-apidescriptionsettings"},"5.1.9 ",(0,l.kt)("inlineCode",{parentName:"h2"},"[ApiDescriptionSettings]")),(0,l.kt)("p",null,"\u9664\u4e86\u4e0a\u8ff0 ",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u63d0\u4f9b\u7684\u914d\u7f6e\u5916\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u8fd8\u63d0\u4f9b\u4e86\u975e\u5e38\u5f3a\u5927\u4e14\u7075\u6d3b\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiDescriptionSettings]")," \u7279\u6027\u3002"),(0,l.kt)("h3",{id:"5191-\u5185\u7f6e\u914d\u7f6e"},"5.1.9.1 \u5185\u7f6e\u914d\u7f6e"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Name"),"\uff1a\u81ea\u5b9a\u4e49\u63a7\u5236\u5668/\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"null")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"KeepName"),"\uff1a\u662f\u5426\u4fdd\u6301\u539f\u6709\u540d\u79f0\u4e0d\u5904\u7406\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"false")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"SplitCamelCase"),"\uff1a\u5207\u5272\u9a86\u9a7c(\u9a7c\u5cf0)/\u5e15\u65af\u5361\u547d\u540d\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"true")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"KeepVerb"),"\uff1a\u662f\u5426\u4fdd\u7559\u52a8\u4f5c\u65b9\u6cd5\u8bf7\u6c42\u8c13\u8bcd\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"false")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Enabled"),"\uff1a\u662f\u5426\u5bfc\u51fa\u63a5\u53e3\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"true")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Module"),"\uff1a\u6a21\u5757\u540d\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"null")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Version"),"\uff1a\u7248\u672c\u53f7\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"null")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Groups"),"\uff1a\u63a5\u53e3\u5206\u7ec4\uff0c\u53ef\u7ed3\u5408 ",(0,l.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e00\u8d77\u4f7f\u7528\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string[]"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"null")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Tags"),"\uff1a\u63a5\u53e3\u6807\u7b7e\uff0c\u53ef\u7ed3\u5408 ",(0,l.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e00\u8d77\u4f7f\u7528\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string[]"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"null")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Order"),"\uff1a\u914d\u7f6e\u63a7\u5236\u5668/\u52a8\u4f5c\u65b9\u6cd5\u6392\u5e8f"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"LowercaseRoute"),"\uff1a\u662f\u5426\u91c7\u7528\u5c0f\u5199\u8def\u7531\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"true")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"AsLowerCamelCase"),"\uff1a\u542f\u7528\u5c0f\u9a7c\u5cf0\u547d\u540d\uff08\u9996\u5b57\u6bcd\u5c0f\u5199\uff09\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"false")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Area"),"\uff1a\u914d\u7f6e\u533a\u57df\u540d\u79f0\uff0c\u9ed8\u8ba4\u7a7a\uff0c",(0,l.kt)("strong",{parentName:"li"},"\u53ea\u4f5c\u7528\u4e8e\u7c7b\u4e2d\u8d34")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Description"),"\uff1a\u914d\u7f6e\u5355\u4e00\u63a5\u53e3\u66f4\u591a\u63cf\u8ff0\u529f\u80fd\uff0c\u53ea\u5728 ",(0,l.kt)("inlineCode",{parentName:"li"},"\u65b9\u6cd5")," \u4e2d\u6709\u6548\uff0c",(0,l.kt)("strong",{parentName:"li"},"\u4ec5\u9650 v3.3.5+\u7248\u672c\u6709\u6548")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ForceWithRoutePrefix"),"\uff1a\u914d\u7f6e\u662f\u5426\u5f3a\u5236\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"DefaultRoutePrefix"),"\uff0c\u5f53\u63a7\u5236\u5668\u81ea\u5b9a\u4e49\u4e86 ",(0,l.kt)("inlineCode",{parentName:"li"},"[Route]")," \u6709\u6548\uff0c",(0,l.kt)("strong",{parentName:"li"},"\u4ec5\u9650 v3.4.1+\u7248\u672c\u6709\u6548"))),(0,l.kt)("h3",{id:"5192-name-\u914d\u7f6e"},"5.1.9.2 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Name")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Name")," \u53c2\u6570\u53ef\u4ee5\u8986\u76d6\u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u81ea\u52a8\u751f\u6210\u7684\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u3002\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8}",showLineNumbers:!0,"":!0,"{5,8}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(Name = "MyFur")]\n public class FurionAppService : IDynamicApiController\n {\n [ApiDescriptionSettings(Name = "MyGet")]\n public string Get()\n {\n return nameof(Furion);\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/namepz.png")}),(0,l.kt)("h3",{id:"5193-keepname-\u914d\u7f6e"},"5.1.9.3 ",(0,l.kt)("inlineCode",{parentName:"h3"},"KeepName")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"KeepName")," \u53c2\u6570\u53ef\u4ee5\u4fdd\u7559\u539f\u6709\u7684\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u3002\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8}",showLineNumbers:!0,"":!0,"{5,8}":!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(KeepName = true)]\n public class FurionAppService : IDynamicApiController\n {\n [ApiDescriptionSettings(KeepName = true)]\n public string Get()\n {\n return nameof(Furion);\n }\n }\n}\n")),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/keepnamepz.png")}),(0,l.kt)("h3",{id:"5194-splitcamelcase-\u914d\u7f6e"},"5.1.9.4 ",(0,l.kt)("inlineCode",{parentName:"h3"},"SplitCamelCase")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"SplitCamelCase")," \u53c2\u6570\u9ed8\u8ba4\u5c06\u9a86\u9a7c(\u9a7c\u5cf0)\u547d\u540d\u5207\u5272\u6210\u591a\u4e2a\u5355\u8bcd\u5e76\u901a\u8fc7\u6307\u5b9a ",(0,l.kt)("inlineCode",{parentName:"p"},"\u5360\u4f4d\u7b26")," \u8fde\u63a5\u8d77\u6765\u3002\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"p"},"\u5360\u4f4d\u7b26")," \u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"-"),"\u3002\u9ed8\u8ba4\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"true"),"\u3002\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8}",showLineNumbers:!0,"":!0,"{5,8}":!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(SplitCamelCase = false)]\n public class MyFurionAppService : IDynamicApiController\n {\n [ApiDescriptionSettings(SplitCamelCase = true)]\n public string ChangeUserName()\n {\n return nameof(Furion);\n }\n }\n}\n")),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/splitnamepz.png")}),(0,l.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"p"},"KeepName")," \u4f18\u5148\u7ea7\u9ad8\u4e8e ",(0,l.kt)("inlineCode",{parentName:"p"},"SplitCamelCase"),"\uff0c\u4e5f\u5c31\u662f ",(0,l.kt)("inlineCode",{parentName:"p"},"KeepName")," \u8bbe\u7f6e\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"true"),"\uff0c\u5219\u4e0d\u4f1a\u5904\u7406 ",(0,l.kt)("inlineCode",{parentName:"p"},"SplitCamelCase")," \u53c2\u6570\u3002")),(0,l.kt)("h3",{id:"5195-keepverb-\u914d\u7f6e"},"5.1.9.5 ",(0,l.kt)("inlineCode",{parentName:"h3"},"KeepVerb")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"KeepVerb")," \u53c2\u6570\u4f5c\u7528\u4e8e\u52a8\u4f5c\u65b9\u6cd5\uff0c\u6807\u8bc6\u662f\u5426\u4fdd\u7559\u52a8\u4f5c\u8c13\u8bcd\u3002\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7}",showLineNumbers:!0,"":!0,"{7}":!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n [ApiDescriptionSettings(KeepVerb = true)]\n public string GetVersion()\n {\n return nameof(Furion);\n }\n }\n}\n")),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/keepverbpz.png")}),(0,l.kt)("h3",{id:"5196-enabled-\u914d\u7f6e"},"5.1.9.6 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Enabled")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Enabled")," \u53c2\u6570\u914d\u7f6e\u63a5\u53e3\u662f\u5426\u5bfc\u51fa\u3002\u901a\u5e38\u7528\u4e8e\u52a8\u4f5c\u65b9\u6cd5\uff0c\u5982\u679c\u7528\u4e8e\u63a7\u5236\u5668\u5b9e\u9645\u4f5c\u7528\u4e0d\u5927\u3002"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {12}",showLineNumbers:!0,"":!0,"{12}":!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string GetVersion()\n {\n return nameof(Furion);\n }\n\n [ApiDescriptionSettings(false)]\n public string NoExport()\n {\n return nameof(Furion);\n }\n }\n}\n")),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/enablepz.png")}),(0,l.kt)("h3",{id:"5197-module-\u914d\u7f6e"},"5.1.9.7 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Module")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Module")," \u53c2\u6570\u53ef\u4ee5\u914d\u7f6e\u8def\u7531\u5206\u79bb\uff0c\u7c7b\u4f3c\u4e8e ",(0,l.kt)("inlineCode",{parentName:"p"},"Mvc \u533a\u57df")," \u7684\u4f5c\u7528\u3002"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8}",showLineNumbers:!0,"":!0,"{5,8}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(Module = "mobile")]\n public class FurionAppService : IDynamicApiController\n {\n [ApiDescriptionSettings(Module = "user")]\n public string GetVersion()\n {\n return nameof(Furion);\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/modulepz.png")}),(0,l.kt)("h3",{id:"5198-version-\u914d\u7f6e"},"5.1.9.8 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Version")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Version")," \u53c2\u6570\u53ef\u4ee5\u914d\u7f6e\u63a5\u53e3\u7248\u672c\uff0c\u540c\u65f6\u53c8\u53ef\u4ee5\u590d\u5199\u7279\u6b8a\u7248\u672c\u547d\u540d\u914d\u7f6e\u3002\u9ed8\u8ba4\u7248\u672c\u5206\u9694\u7b26\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"@"),"\u3002\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,9-10}",showLineNumbers:!0,"":!0,"{5,9-10}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(Version = "1.0")]\n public class FurionAppService : IDynamicApiController\n {\n // V2.0.0 \u88ab\u590d\u5199\u6210 V2.1.1\n [ApiDescriptionSettings(Version = "2.1.1")]\n public string GetVersionV2_0_0()\n {\n return nameof(Furion);\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/versionpz.png")}),(0,l.kt)("h3",{id:"5199-groups-\u914d\u7f6e"},"5.1.9.9 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Groups")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Groups")," \u914d\u7f6e\u4e3b\u8981\u7528\u4e8e\u914d\u7f6e ",(0,l.kt)("inlineCode",{parentName:"p"},"Swagger")," \u5206\u7ec4\u4fe1\u606f\u3002"),(0,l.kt)("p",null,"\u901a\u8fc7\u914d\u7f6e ",(0,l.kt)("inlineCode",{parentName:"p"},"Groups")," \u53c2\u6570\u53ef\u4ee5\u5c06",(0,l.kt)("inlineCode",{parentName:"p"},"\u63a7\u5236\u5668\u548c\u52a8\u4f5c\u65b9\u6cd5")," \u8fdb\u884c\u5f52\u7c7b\u548c\u591a\u4e2a\u5206\u7ec4\u76f4\u63a5\u5171\u4eab\u3002\u53ef\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiDescriptionSettings(params Groups)]")," \u6784\u9020\u51fd\u6570\u4f20\u5165\u6216\u6307\u5b9a ",(0,l.kt)("inlineCode",{parentName:"p"},"Groups")," \u53c2\u6570\u914d\u7f6e\u63a5\u53e3\u662f\u5426\u5bfc\u51fa\u3002\u901a\u5e38\u7528\u4e8e\u52a8\u4f5c\u65b9\u6cd5\uff0c\u5982\u679c\u7528\u4e8e\u63a7\u5236\u5668\u5b9e\u9645\u4f5c\u7528\u4e0d\u5927\u3002"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,13}",showLineNumbers:!0,"":!0,"{5,13}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings("Default", "Common")]\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n [ApiDescriptionSettings("Custom")]\n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dfz.gif")}),(0,l.kt)("h3",{id:"51910-tag-\u914d\u7f6e"},"5.1.9.10 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Tag")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Tag")," \u914d\u7f6e\u4e3b\u8981\u7528\u4e8e\u914d\u7f6e ",(0,l.kt)("inlineCode",{parentName:"p"},"Swagger")," \u6807\u7b7e\u5206\u7ec4\u4fe1\u606f\u53ca\u5408\u5e76\u6807\u7b7e\u3002\u4e5f\u5c31\u662f ",(0,l.kt)("inlineCode",{parentName:"p"},"\u7ec4\u4e2d\u7ec4"),":"),(0,l.kt)(o.Z,{defaultValue:"tag1",values:[{label:"\u6807\u7b7e\u547d\u540d",value:"tag1"},{label:"\u5408\u5e76\u6807\u7b7e",value:"tag2"}],mdxType:"Tabs"},(0,l.kt)(p.Z,{value:"tag1",mdxType:"TabItem"},(0,l.kt)("h4",{id:"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d"},"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n\n public class TestAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n}\n")),(0,l.kt)("h4",{id:"\u8d34\u6807\u7b7e\u4e4b\u540e"},"\u8d34\u6807\u7b7e\u4e4b\u540e"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,19}",showLineNumbers:!0,"":!0,"{5,19}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(Tag = "\u5206\u7ec4\u4e00")]\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n\n [ApiDescriptionSettings(Tag = "\u5206\u7ec4\u4e8c")]\n public class TestAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/tag1.png")})),(0,l.kt)(p.Z,{value:"tag2",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,19}",showLineNumbers:!0,"":!0,"{5,19}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(Tag = "\u5408\u5e76\u6240\u6709\u6807\u7b7e")]\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n\n [ApiDescriptionSettings(Tag = "\u5408\u5e76\u6240\u6709\u6807\u7b7e")]\n public class TestAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/tag2.png")}))),(0,l.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,l.kt)("p",{parentName:"admonition"},"\u5982\u679c ",(0,l.kt)("inlineCode",{parentName:"p"},"Tag")," \u540d\u5b57\u4e00\u6837\uff0c\u5219\u4f1a\u81ea\u52a8\u5408\u5e76\uff0c\u5426\u5219\u53ea\u662f\u547d\u540d\u3002")),(0,l.kt)("h2",{id:"5110-dynamicapicontrollersettings-\u914d\u7f6e"},"5.1.10 ",(0,l.kt)("inlineCode",{parentName:"h2"},"DynamicApiControllerSettings")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fd8\u63d0\u4f9b\u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a5\u53e3\u4e00\u4e9b\u5168\u5c40\u914d\u7f6e\u9009\u9879\uff0c\u5982\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"DefaultRoutePrefix"),"\uff1a\u9ed8\u8ba4\u8def\u7531\u524d\u7f00\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"api")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"DefaultHttpMethod"),"\uff1a\u9ed8\u8ba4\u8bf7\u6c42\u8c13\u8bcd\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"POST")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"DefaultModule"),"\uff1a\u9ed8\u8ba4\u6a21\u5757\u540d\u79f0\uff08\u533a\u57df\uff09\uff0c\u53ef\u7528\u4f5c\u63a5\u53e3\u7248\u672c\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"v1")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"LowercaseRoute"),"\uff1a\u5c0f\u5199\u8def\u7531\u683c\u5f0f\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"true")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"AsLowerCamelCase"),"\uff1a\u542f\u7528\u5c0f\u9a7c\u5cf0\u547d\u540d\uff08\u9996\u5b57\u6bcd\u5c0f\u5199\uff09\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"false")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"KeepVerb"),"\uff1a\u662f\u5426\u4fdd\u7559\u52a8\u4f5c\u8c13\u8bcd\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"false")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"KeepName"),"\uff1a\u662f\u5426\u4fdd\u7559\u9ed8\u8ba4\u540d\u79f0\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"fasle")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"CamelCaseSeparator"),"\uff1a\u9a86\u9a7c(\u9a7c\u5cf0)/\u5e15\u65af\u5361\u547d\u540d\u5206\u9694\u7b26\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"-")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"VersionSeparator"),"\uff1a\u7248\u672c\u5206\u9694\u7b26\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"@")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ModelToQuery"),"\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"GET/HEAD")," \u8bf7\u6c42\u5c06 ",(0,l.kt)("inlineCode",{parentName:"li"},"\u7c7b\u7c7b\u578b\u53c2\u6570\u8f6c\u67e5\u8be2\u53c2\u6570"),"\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"false")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"SupportedMvcController"),"\uff1a\u662f\u5426\u652f\u6301 ",(0,l.kt)("inlineCode",{parentName:"li"},"Mvc Controller")," \u52a8\u6001\u914d\u7f6e\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"false")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"UrlParameterization"),"\uff1a\u8def\u7531\u53c2\u6570\u91c7\u7528 ",(0,l.kt)("inlineCode",{parentName:"li"},"[FromQuery]")," \u5316\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"false"),"\uff08",(0,l.kt)("inlineCode",{parentName:"li"},"[FromRoute]")," \u65b9\u5f0f\uff09"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"DefaultArea"),"\uff1a\u914d\u7f6e\u9ed8\u8ba4\u533a\u57df\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"null")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ForceWithRoutePrefix"),"\uff1a\u914d\u7f6e\u662f\u5426\u5f3a\u5236\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"DefaultRoutePrefix"),"\uff0c\u5f53\u63a7\u5236\u5668\u81ea\u5b9a\u4e49\u4e86 ",(0,l.kt)("inlineCode",{parentName:"li"},"[Route]")," \u6709\u6548\uff0c",(0,l.kt)("strong",{parentName:"li"},"\u4ec5\u9650 v3.4.1+\u7248\u672c\u6709\u6548")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"AbandonControllerAffixes"),"\uff1a\u9ed8\u8ba4\u53bb\u9664\u63a7\u5236\u5668\u540d\u79f0\u524d\u540e\u7f00\u5217\u8868\u540d\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string[]"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"AppServices")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"AppService")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ApiController")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Controller")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Services")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Service")))),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"AbandonActionAffixes"),"\uff1a\u9ed8\u8ba4\u53bb\u9664\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u524d\u540e\u7f00\u5217\u8868\u540d\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string[]"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Async")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"VerbToHttpMethods"),"\uff1a\u590d\u5199\u9ed8\u8ba4\u65b9\u6cd5\u540d\u8f6c ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpMethod]")," \u89c4\u5219\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string[][]")," \u4e8c\u7ef4\u6570\u7ec4\u7c7b\u578b\uff0c\u5185\u7f6e\u5339\u914d\u89c4\u5219\u4e3a\uff1a",(0,l.kt)("pre",{parentName:"li"},(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'["post"] = "POST",\n["add"] = "POST",\n["create"] = "POST",\n["insert"] = "POST",\n["submit"] = "POST",\n["get"] = "GET",\n["find"] = "GET",\n["fetch"] = "GET",\n["query"] = "GET",\n["getlist"] = "GET",\n["getall"] = "GET",\n["put"] = "PUT",\n["update"] = "PUT",\n["delete"] = "DELETE",\n["remove"] = "DELETE",\n["clear"] = "DELETE",\n["patch"] = "PATCH"\n')),(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},"\u590d\u5199\u793a\u4f8b")),(0,l.kt)("pre",{parentName:"li"},(0,l.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'"DynamicApiControllerSettings": {\n "VerbToHttpMethods": [\n [ "getall", "HEAD" ], // => getall \u4f1a\u88ab\u590d\u5199\u4e3a `[HttpHead]`\n [ "other", "PUT" ] // => \u65b0\u589e\u4e00\u6761\u65b0\u89c4\u5219\uff0c\u6bd4\u5982\uff0c\u4e00 `[other]` \u5f00\u5934\u4f1a\u8f6c\u6362\u4e3a `[HttpPut]` \u8bf7\u6c42\n ]\n }\n')))))),(0,l.kt)("h3",{id:"51101-\u652f\u6301-mvc-\u63a7\u5236\u5668-\u52a8\u6001\u914d\u7f6e"},"5.1.10.1 \u652f\u6301 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Mvc \u63a7\u5236\u5668")," \u52a8\u6001\u914d\u7f6e"),(0,l.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a5\u53e3\u4e0d\u5bf9 ",(0,l.kt)("inlineCode",{parentName:"p"},"ControllerBase")," \u7c7b\u578b\u8fdb\u884c\u4efb\u4f55\u5904\u7406\u3002\u5f53\u7136\uff0c\u6211\u4eec\u4e5f\u53ef\u4ee5\u624b\u52a8\u542f\u7528 ",(0,l.kt)("inlineCode",{parentName:"p"},"ControllerBase")," \u652f\u6301\u3002"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers {2-4} title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,"{2-4}":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "DynamicApiControllerSettings": {\n "SupportedMvcController": true\n }\n}\n')),(0,l.kt)("p",null,"\u8bbe\u7f6e ",(0,l.kt)("inlineCode",{parentName:"p"},"SupportedMvcController: true")," \u540e\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"Mvc ControllerBase")," \u7c7b\u578b\u4e5f\u80fd\u548c\u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u4e00\u6837\u7684\u7075\u6d3b\u4e86\u3002\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},"using Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n public class MvcController : ControllerBase\n {\n public string Get()\n {\n return nameof(Furion);\n }\n }\n}\n\n")),(0,l.kt)("admonition",{title:"\u6ce8\u610f\u4e8b\u9879",type:"warning"},(0,l.kt)("p",{parentName:"admonition"},"\u542f\u7528\u8be5\u914d\u7f6e\u540e\uff0c\u5982\u679c ",(0,l.kt)("inlineCode",{parentName:"p"},"Mvc \u63a7\u5236\u5668")," \u6ca1\u6709\u4efb\u4f55 ",(0,l.kt)("inlineCode",{parentName:"p"},"[Route]")," \u7279\u6027\uff0c\u4f46\u662f\u8d34\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiController]")," \u7279\u6027\u5c06\u4f1a\u62a5\u9519\u3002\u539f\u56e0\u662f ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiController]")," \u7279\u6027\u5185\u90e8\u505a\u4e86\u8def\u7531\u7279\u6027\u68c0\u6d4b\u3002\u6240\u4ee5\u5efa\u8bae\u4f7f\u7528 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiDataValidation]")," \u4ee3\u66ff\u3002"),(0,l.kt)("p",{parentName:"admonition"},"\u67e5\u770b ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/dotnet/aspnetcore/blob/c565386a3ed135560bc2e9017aa54a950b4e35dd/src/Mvc/Mvc.Core/src/ApplicationModels/ApiBehaviorApplicationModelProvider.cs#L90"},"ASP.NET Core - ApiBehaviorApplicationModelProvider \u6e90\u7801"))),(0,l.kt)("h2",{id:"5111-\u5173\u4e8e-aop-\u62e6\u622a"},"5.1.11 \u5173\u4e8e AOP \u62e6\u622a"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"\u52a8\u6001WebAPI")," \u652f\u6301 ",(0,l.kt)("inlineCode",{parentName:"p"},"Controller")," \u7684\u6240\u6709\u8fc7\u6ee4\u5668/\u7b5b\u9009\u5668\u62e6\u622a\uff0c\u4e5f\u5c31\u662f\u53ef\u4ee5\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"ActionFilter"),"\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"ResultFilter")," \u8fdb\u884c\u62e6\u622a\u64cd\u4f5c\u3002\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3}",showLineNumbers:!0,"":!0,"{1,3}":!0},"public class SampleAsyncActionFilter : IAsyncActionFilter\n{\n public async Task OnActionExecutionAsync(ActionExecutingContext context,ActionExecutionDelegate next)\n {\n // \u62e6\u622a\u4e4b\u524d\n\n var resultContext = await next();\n\n // \u62e6\u622a\u4e4b\u540e\n\n // \u5f02\u5e38\u62e6\u622a\n if(resultContext.Exception != null)\n {\n\n }\n }\n}\n")),(0,l.kt)("p",null,"\u8be6\u7ec6\u7528\u6cd5\u53ef\u53c2\u89c1 ",(0,l.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/mvc/controllers/filters?view=aspnetcore-5.0"},"ASP.NET Core 5.0 - \u7b5b\u9009\u5668")),(0,l.kt)("h2",{id:"5112-\u8bbe\u7f6e-api-\u8d85\u65f6\u8bf7\u6c42\u65f6\u95f4"},"5.1.12 \u8bbe\u7f6e ",(0,l.kt)("inlineCode",{parentName:"h2"},"api")," \u8d85\u65f6\u8bf7\u6c42\u65f6\u95f4"),(0,l.kt)("p",null,"\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"p"},".UseKestrel")," \u914d\u7f6e\u5373\u53ef\uff0c\u5982\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},".NET5 \u7248\u672c"))),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8-12}",showLineNumbers:!0,"":!0,"{8-12}":!0},"public static IHostBuilder CreateHostBuilder(string[] args)\n{\n return Host.CreateDefaultBuilder(args)\n .ConfigureWebHostDefaults(webBuilder =>\n {\n webBuilder.Inject()\n .UseStartup()\n .UseKestrel(option =>\n {\n option.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(20);\n option.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(20);\n });\n });\n}\n")),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},".NET6 \u7248\u672c"))),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-7}",showLineNumbers:!0,"":!0,"{3-7}":!0},"var app = builder.Build();\n\napp.Configuration.Get().ConfigureKestrel(x =>\n{\n x.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(20);\n x.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(20);\n});\n")),(0,l.kt)("h2",{id:"5113-\u53cd\u9988\u4e0e\u5efa\u8bae"},"5.1.13 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,l.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,l.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,l.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}C.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/64e66f0d.d611c4b2.js b/handbook/build/assets/js/64e66f0d.d611c4b2.js deleted file mode 100644 index b603afa65d..0000000000 --- a/handbook/build/assets/js/64e66f0d.d611c4b2.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[8475],{433:function(e,n,t){t.d(n,{Z:function(){return r}});var i=t(7294),a=t(4334),l="tabItem_Ymn6";function r(e){var n=e.children,t=e.hidden,r=e.className;return i.createElement("div",{role:"tabpanel",className:(0,a.Z)(l,r),hidden:t},n)}},5559:function(e,n,t){t.d(n,{Z:function(){return k}});var i=t(3117),a=t(7294),l=t(4334),r=t(5730),o=t(636),p=t(6602),m=t(3735),u="tabList__CuJ",s="tabItem_LNqP";function d(e){var n,t,r=e.lazy,d=e.block,k=e.defaultValue,c=e.values,N=e.groupId,C=e.className,g=a.Children.map(e.children,(function(e){if((0,a.isValidElement)(e)&&"value"in e.props)return e;throw new Error("Docusaurus error: Bad child <"+("string"==typeof e.type?e.type:e.type.name)+'>: all children of the component should be , and every should have a unique "value" prop.')})),b=null!=c?c:g.map((function(e){var n=e.props;return{value:n.value,label:n.label,attributes:n.attributes}})),A=(0,o.l)(b,(function(e,n){return e.value===n.value}));if(A.length>0)throw new Error('Docusaurus error: Duplicate values "'+A.map((function(e){return e.value})).join(", ")+'" found in . Every value needs to be unique.');var v=null===k?k:null!=(n=null!=k?k:null==(t=g.find((function(e){return e.props.default})))?void 0:t.props.value)?n:g[0].props.value;if(null!==v&&!b.some((function(e){return e.value===v})))throw new Error('Docusaurus error: The has a defaultValue "'+v+'" but none of its children has the corresponding value. Available values are: '+b.map((function(e){return e.value})).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");var h=(0,p.U)(),y=h.tabGroupChoices,f=h.setTabGroupChoices,F=(0,a.useState)(v),S=F[0],D=F[1],w=[],T=(0,m.o5)().blockElementScrollPositionUntilNextRender;if(null!=N){var P=y[N];null!=P&&P!==S&&b.some((function(e){return e.value===P}))&&D(P)}var E=function(e){var n=e.currentTarget,t=w.indexOf(n),i=b[t].value;i!==S&&(T(n),D(i),null!=N&&f(N,String(i)))},L=function(e){var n,t=null;switch(e.key){case"ArrowRight":var i,a=w.indexOf(e.currentTarget)+1;t=null!=(i=w[a])?i:w[0];break;case"ArrowLeft":var l,r=w.indexOf(e.currentTarget)-1;t=null!=(l=w[r])?l:w[w.length-1]}null==(n=t)||n.focus()};return a.createElement("div",{className:(0,l.Z)("tabs-container",u)},a.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,l.Z)("tabs",{"tabs--block":d},C)},b.map((function(e){var n=e.value,t=e.label,r=e.attributes;return a.createElement("li",(0,i.Z)({role:"tab",tabIndex:S===n?0:-1,"aria-selected":S===n,key:n,ref:function(e){return w.push(e)},onKeyDown:L,onFocus:E,onClick:E},r,{className:(0,l.Z)("tabs__item",s,null==r?void 0:r.className,{"tabs__item--active":S===n})}),null!=t?t:n)}))),r?(0,a.cloneElement)(g.filter((function(e){return e.props.value===S}))[0],{className:"margin-top--md"}):a.createElement("div",{className:"margin-top--md"},g.map((function(e,n){return(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==S})}))))}function k(e){var n=(0,r.Z)();return a.createElement(d,(0,i.Z)({key:String(n)},e))}},9665:function(e,n,t){t.r(n),t.d(n,{assets:function(){return k},contentTitle:function(){return s},default:function(){return C},frontMatter:function(){return u},metadata:function(){return d},toc:function(){return c}});var i=t(3117),a=t(102),l=(t(7294),t(3905)),r=t(1402),o=t(5559),p=t(433),m=["components"],u={id:"dynamic-api-controller",title:"5.1 \u52a8\u6001 WebAPI",sidebar_label:"5.1 \u52a8\u6001 WebAPI"},s=void 0,d={unversionedId:"dynamic-api-controller",id:"dynamic-api-controller",title:"5.1 \u52a8\u6001 WebAPI",description:"",source:"@site/docs/dynamic-api-controller.mdx",sourceDirName:".",slug:"/dynamic-api-controller",permalink:"/furion/docs/dynamic-api-controller",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dynamic-api-controller.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1655430671,formattedLastUpdatedAt:"Jun 17, 2022",frontMatter:{id:"dynamic-api-controller",title:"5.1 \u52a8\u6001 WebAPI",sidebar_label:"5.1 \u52a8\u6001 WebAPI"},sidebar:"docs",previous:{title:"4.2 \u9009\u9879",permalink:"/furion/docs/options"},next:{title:"5.2 HttpContext",permalink:"/furion/docs/httpcontext"}},k={},c=[{value:"5.1.1 \u4ec0\u4e48\u662f\u63a7\u5236\u5668",id:"511-\u4ec0\u4e48\u662f\u63a7\u5236\u5668",level:2},{value:"5.1.2 Mvc \u63a7\u5236\u5668 \u7ea6\u5b9a\u548c\u7f3a\u70b9",id:"512-mvc-\u63a7\u5236\u5668-\u7ea6\u5b9a\u548c\u7f3a\u70b9",level:2},{value:"5.1.2.1 WebAPI \u7ea6\u5b9a",id:"5121-webapi-\u7ea6\u5b9a",level:3},{value:"5.1.2.2 .NET Core WebAPI \u7f3a\u70b9",id:"5122-net-core-webapi-\u7f3a\u70b9",level:3},{value:"5.1.3 \u52a8\u6001 WebAPI \u63a7\u5236\u5668",id:"513-\u52a8\u6001-webapi-\u63a7\u5236\u5668",level:2},{value:"5.1.4 \u6ce8\u518c\u52a8\u6001 WebAPI \u670d\u52a1",id:"514-\u6ce8\u518c\u52a8\u6001-webapi-\u670d\u52a1",level:2},{value:"5.1.5 \u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"515-\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:2},{value:"5.1.6 \u52a8\u6001 WebAPI \u539f\u7406\u89e3\u6790",id:"516-\u52a8\u6001-webapi-\u539f\u7406\u89e3\u6790",level:2},{value:"5.1.6.1 \u63a7\u5236\u5668\u7279\u6027\u63d0\u4f9b\u5668",id:"5161-\u63a7\u5236\u5668\u7279\u6027\u63d0\u4f9b\u5668",level:3},{value:"5.1.6.2 \u5e94\u7528\u6a21\u578b\u8f6c\u6362\u5668",id:"5162-\u5e94\u7528\u6a21\u578b\u8f6c\u6362\u5668",level:3},{value:"5.1.7 \u52a8\u6001 WebAPI \u914d\u7f6e\u7ea6\u5b9a",id:"517-\u52a8\u6001-webapi-\u914d\u7f6e\u7ea6\u5b9a",level:2},{value:"5.1.7.1 \u63a7\u5236\u5668\u9ed8\u8ba4\u7ea6\u5b9a",id:"5171-\u63a7\u5236\u5668\u9ed8\u8ba4\u7ea6\u5b9a",level:3},{value:"5.1.7.2 \u52a8\u4f5c\u65b9\u6cd5\u9ed8\u8ba4\u7ea6\u5b9a",id:"5172-\u52a8\u4f5c\u65b9\u6cd5\u9ed8\u8ba4\u7ea6\u5b9a",level:3},{value:"5.1.7.3 \u8bf7\u6c42\u8c13\u8bcd\u9ed8\u8ba4\u7ea6\u5b9a",id:"5173-\u8bf7\u6c42\u8c13\u8bcd\u9ed8\u8ba4\u7ea6\u5b9a",level:3},{value:"5.1.7.4 \u8def\u7531\u5730\u5740\u9ed8\u8ba4\u7ea6\u5b9a",id:"5174-\u8def\u7531\u5730\u5740\u9ed8\u8ba4\u7ea6\u5b9a",level:3},{value:"5.1.7.5 \u5176\u4ed6\u7ea6\u5b9a",id:"5175-\u5176\u4ed6\u7ea6\u5b9a",level:3},{value:"5.1.8 \u66f4\u591a\u4f8b\u5b50",id:"518-\u66f4\u591a\u4f8b\u5b50",level:2},{value:"5.1.8.1 \u591a\u79cd\u8bf7\u6c42\u8c13\u8bcd\u65b9\u6cd5",id:"5181-\u591a\u79cd\u8bf7\u6c42\u8c13\u8bcd\u65b9\u6cd5",level:3},{value:"5.1.8.2 \u591a\u4e2a\u81ea\u5b9a\u4e49\u52a8\u4f5c\u65b9\u6cd5",id:"5182-\u591a\u4e2a\u81ea\u5b9a\u4e49\u52a8\u4f5c\u65b9\u6cd5",level:3},{value:"5.1.8.3 \u5e26\u53c2\u6570\u52a8\u4f5c\u65b9\u6cd5",id:"5183-\u5e26\u53c2\u6570\u52a8\u4f5c\u65b9\u6cd5",level:3},{value:"5.1.8.4 GET/HEAD \u7c7b\u7c7b\u578b\u53c2\u6570",id:"5184-gethead-\u7c7b\u7c7b\u578b\u53c2\u6570",level:3},{value:"5.1.8.5 \u81ea\u5b9a\u4e49\u53c2\u6570\u4f4d\u7f6e",id:"5185-\u81ea\u5b9a\u4e49\u53c2\u6570\u4f4d\u7f6e",level:3},{value:"5.1.8.6 \u81ea\u5b9a\u4e49\u8bf7\u6c42\u8c13\u8bcd",id:"5186-\u81ea\u5b9a\u4e49\u8bf7\u6c42\u8c13\u8bcd",level:3},{value:"5.1.8.7 \u652f\u6301\u591a\u4e2a\u8c13\u8bcd",id:"5187-\u652f\u6301\u591a\u4e2a\u8c13\u8bcd",level:3},{value:"5.1.8.8 \u652f\u6301\u81ea\u5b9a\u4e49\u8def\u7531",id:"5188-\u652f\u6301\u81ea\u5b9a\u4e49\u8def\u7531",level:3},{value:"5.1.8.9 \u591a\u8def\u7531\u968f\u610f\u7ec4\u5408",id:"5189-\u591a\u8def\u7531\u968f\u610f\u7ec4\u5408",level:3},{value:"5.1.8.10 \u652f\u6301\u7248\u672c\u63a7\u5236",id:"51810-\u652f\u6301\u7248\u672c\u63a7\u5236",level:3},{value:"5.1.8.11 \u4e0d\u516c\u5f00\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5",id:"51811-\u4e0d\u516c\u5f00\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5",level:3},{value:"5.1.8.12 \u4fdd\u6301\u63a7\u5236\u5668\u548c\u65b9\u6cd5\u547d\u540d",id:"51812-\u4fdd\u6301\u63a7\u5236\u5668\u548c\u65b9\u6cd5\u547d\u540d",level:3},{value:"5.1.8.13 \u65b9\u6cd5\u53c2\u6570 [FromQuery] \u5316/\u53c2\u6570\u975e\u5fc5\u586b/\u53c2\u6570\u53ef\u9009",id:"51813-\u65b9\u6cd5\u53c2\u6570-fromquery-\u5316\u53c2\u6570\u975e\u5fc5\u586b\u53c2\u6570\u53ef\u9009",level:3},{value:"5.1.8.14 \u53c2\u6570\u7ed1\u5b9a\u914d\u7f6e",id:"51814-\u53c2\u6570\u7ed1\u5b9a\u914d\u7f6e",level:3},{value:"5.1.8.15 \u81ea\u5b9a\u4e49\u6839\u636e\u65b9\u6cd5\u540d\u751f\u6210 [HttpMethod] \u89c4\u5219",id:"51815-\u81ea\u5b9a\u4e49\u6839\u636e\u65b9\u6cd5\u540d\u751f\u6210-httpmethod-\u89c4\u5219",level:3},{value:"5.1.8.16 \u8def\u7531\u53c2\u6570\u975e\u5fc5\u586b/\u9009\u586b",id:"51816-\u8def\u7531\u53c2\u6570\u975e\u5fc5\u586b\u9009\u586b",level:3},{value:"5.1.8.17 [FormRoute] \u8def\u7531\u7ea6\u675f",id:"51817-formroute-\u8def\u7531\u7ea6\u675f",level:3},{value:"5.1.8.18 \u5c0f\u9a7c\u5cf0 \u8def\u7531\u8def\u5f84",id:"51818-\u5c0f\u9a7c\u5cf0-\u8def\u7531\u8def\u5f84",level:3},{value:"5.1.9 [ApiDescriptionSettings]",id:"519-apidescriptionsettings",level:2},{value:"5.1.9.1 \u5185\u7f6e\u914d\u7f6e",id:"5191-\u5185\u7f6e\u914d\u7f6e",level:3},{value:"5.1.9.2 Name \u914d\u7f6e",id:"5192-name-\u914d\u7f6e",level:3},{value:"5.1.9.3 KeepName \u914d\u7f6e",id:"5193-keepname-\u914d\u7f6e",level:3},{value:"5.1.9.4 SplitCamelCase \u914d\u7f6e",id:"5194-splitcamelcase-\u914d\u7f6e",level:3},{value:"5.1.9.5 KeepVerb \u914d\u7f6e",id:"5195-keepverb-\u914d\u7f6e",level:3},{value:"5.1.9.6 Enabled \u914d\u7f6e",id:"5196-enabled-\u914d\u7f6e",level:3},{value:"5.1.9.7 Module \u914d\u7f6e",id:"5197-module-\u914d\u7f6e",level:3},{value:"5.1.9.8 Version \u914d\u7f6e",id:"5198-version-\u914d\u7f6e",level:3},{value:"5.1.9.9 Groups \u914d\u7f6e",id:"5199-groups-\u914d\u7f6e",level:3},{value:"5.1.9.10 Tag \u914d\u7f6e",id:"51910-tag-\u914d\u7f6e",level:3},{value:"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d",id:"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d",level:4},{value:"\u8d34\u6807\u7b7e\u4e4b\u540e",id:"\u8d34\u6807\u7b7e\u4e4b\u540e",level:4},{value:"5.1.10 DynamicApiControllerSettings \u914d\u7f6e",id:"5110-dynamicapicontrollersettings-\u914d\u7f6e",level:2},{value:"5.1.10.1 \u652f\u6301 Mvc \u63a7\u5236\u5668 \u52a8\u6001\u914d\u7f6e",id:"51101-\u652f\u6301-mvc-\u63a7\u5236\u5668-\u52a8\u6001\u914d\u7f6e",level:3},{value:"5.1.11 \u5173\u4e8e AOP \u62e6\u622a",id:"5111-\u5173\u4e8e-aop-\u62e6\u622a",level:2},{value:"5.1.12 \u8bbe\u7f6e api \u8d85\u65f6\u8bf7\u6c42\u65f6\u95f4",id:"5112-\u8bbe\u7f6e-api-\u8d85\u65f6\u8bf7\u6c42\u65f6\u95f4",level:2},{value:"5.1.13 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"5113-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],N={toc:c};function C(e){var n=e.components,t=(0,a.Z)(e,m);return(0,l.kt)("wrapper",(0,i.Z)({},N,t,{components:n,mdxType:"MDXLayout"}),(0,l.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"p"},"\u52a8\u6001WebAPI")," \u5b9e\u9645\u4e0a\u5c31\u662f\u5c06\u666e\u901a\u7684\u7c7b\u53d8\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"Controller"),"\uff0c\u4e5f\u5c31\u662f ",(0,l.kt)("inlineCode",{parentName:"p"},"\u52a8\u6001WebAPI")," \u5c31\u662f\u63a7\u5236\u5668\uff0c\u652f\u6301\u63a7\u5236\u5668\u4e00\u5207\u529f\u80fd\u3002")),(0,l.kt)("h2",{id:"511-\u4ec0\u4e48\u662f\u63a7\u5236\u5668"},"5.1.1 \u4ec0\u4e48\u662f\u63a7\u5236\u5668"),(0,l.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u63a7\u5236\u5668\u662f\u4e00\u4e2a\u627f\u4e0a\u542f\u4e0b\u7684\u4f5c\u7528\uff0c\u6839\u636e\u7528\u6237\u8f93\u5165\uff0c\u6267\u884c\u54cd\u5e94\u884c\u4e3a\uff08\u52a8\u4f5c\u65b9\u6cd5\uff09\uff0c\u540c\u65f6\u5728\u884c\u4e3a\u4e2d\u8c03\u7528\u6a21\u578b\u7684\u4e1a\u52a1\u903b\u8f91\uff0c\u8fd4\u56de\u7ed9\u7528\u6237\u7ed3\u679c\uff08\u89c6\u56fe\uff09\u3002"),(0,l.kt)("img",{src:(0,r.Z)("img/kzq.png")}),(0,l.kt)("p",null),(0,l.kt)("p",null,"\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u4e2d\uff0c\u63a7\u5236\u5668\u6709\u4e24\u79cd\u8868\u73b0\u5f62\u5f0f\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Mvc"),"\uff08\u5e26\u89c6\u56fe\uff09"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"WebAPI"),"\uff08RESTful API\uff09")),(0,l.kt)(o.Z,{defaultValue:"mvc",values:[{label:"Mvc \u63a7\u5236\u5668",value:"mvc"},{label:"WebAPI \u63a7\u5236\u5668",value:"webapi"}],mdxType:"Tabs"},(0,l.kt)(p.Z,{value:"mvc",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,7}",showLineNumbers:!0,"":!0,"{1,5,7}":!0},"using Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n public class MvcController : Controller\n {\n public IActionResult Index()\n {\n return View();\n }\n }\n}\n"))),(0,l.kt)(p.Z,{value:"webapi",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,6,8,9}",showLineNumbers:!0,"":!0,"{1,5,6,8,9}":!0},'using Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n public class WebApiController : ControllerBase\n {\n [HttpGet]\n public IActionResult Get()\n {\n return Content(nameof(Furion));\n }\n }\n}\n')))),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Mvc")," \u63a7\u5236\u5668\u548c ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a7\u5236\u5668\u6700\u5927\u7684\u533a\u522b\u662f ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a7\u5236\u5668\u4e0d\u5e26 ",(0,l.kt)("strong",{parentName:"p"},"\u89c6\u56fe")," \u548c\u901a\u8fc7 ",(0,l.kt)("strong",{parentName:"p"},"\u8bf7\u6c42\u8c13\u8bcd\u548c\u8def\u7531\u5730\u5740\u54cd\u5e94\u884c\u4e3a"),"\u3002"),(0,l.kt)("h2",{id:"512-mvc-\u63a7\u5236\u5668-\u7ea6\u5b9a\u548c\u7f3a\u70b9"},"5.1.2 ",(0,l.kt)("inlineCode",{parentName:"h2"},"Mvc \u63a7\u5236\u5668")," \u7ea6\u5b9a\u548c\u7f3a\u70b9"),(0,l.kt)("p",null,"\u5728\u5b66\u4e60\u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a7\u5236\u5668\u4e4b\u524d\uff0c\u9996\u5148\u4e86\u89e3 ",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u4e2d ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u7684\u4e00\u4e9b\u7ea6\u5b9a\u548c\u6ce8\u610f\u4e8b\u9879\u3002"),(0,l.kt)("h3",{id:"5121-webapi-\u7ea6\u5b9a"},"5.1.2.1 ",(0,l.kt)("inlineCode",{parentName:"h3"},"WebAPI")," \u7ea6\u5b9a"),(0,l.kt)("p",null,"\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u4e2d\uff0c\u4e00\u4e2a ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a7\u5236\u5668\u9700\u9075\u5faa\u4ee5\u4e0b\u7ea6\u5b9a\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u63a7\u5236\u5668\u7c7b",(0,l.kt)("strong",{parentName:"li"},"\u5fc5\u987b\u7ee7\u627f ",(0,l.kt)("inlineCode",{parentName:"strong"},"ControllerBase")," \u6216\u95f4\u63a5\u7ee7\u627f")),(0,l.kt)("li",{parentName:"ul"},"\u52a8\u4f5c\u65b9\u6cd5",(0,l.kt)("strong",{parentName:"li"},"\u5fc5\u987b\u8d34\u6709 ",(0,l.kt)("inlineCode",{parentName:"strong"},"[HttpMethod]")," \u7279\u6027\uff0c\u5982\uff1a",(0,l.kt)("inlineCode",{parentName:"strong"},"[HttpGet]"))),(0,l.kt)("li",{parentName:"ul"},"\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5",(0,l.kt)("strong",{parentName:"li"},"\u81f3\u5c11\u6709\u4e00\u4e2a\u914d\u7f6e ",(0,l.kt)("inlineCode",{parentName:"strong"},"[Route]")," \u7279\u6027")),(0,l.kt)("li",{parentName:"ul"},"\u751f\u6210 ",(0,l.kt)("inlineCode",{parentName:"li"},"WebAPI")," \u8def\u7531\u5730\u5740\u65f6\u4f1a\u81ea\u52a8\u53bb\u6389\u63a7\u5236\u5668\u540d\u79f0 ",(0,l.kt)("inlineCode",{parentName:"li"},"Controller")," \u540e\u7f00\uff0c\u540c\u65f6\u4e5f\u4f1a\u53bb\u6389\u52a8\u4f5c\u65b9\u6cd5\u5339\u914d\u7684 ",(0,l.kt)("inlineCode",{parentName:"li"},"HttpVerb")," \u8c13\u8bcd\uff0c\u5982 ",(0,l.kt)("inlineCode",{parentName:"li"},"GET\uff0cPOST\uff0cDELETE\uff0cPUT")," \u7b49"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u4e0d\u652f\u6301\u8fd4\u56de\u975e ",(0,l.kt)("inlineCode",{parentName:"strong"},"IEnumerable")," \u6cdb\u578b\u5bf9\u8c61")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u4e0d\u652f\u6301\u7c7b\u7c7b\u578b\u53c2\u6570\u5728 ",(0,l.kt)("inlineCode",{parentName:"strong"},"GET\uff0cHEAD")," \u8bf7\u6c42\u4e0b\u751f\u6210 ",(0,l.kt)("inlineCode",{parentName:"strong"},"Query")," \u53c2\u6570"))),(0,l.kt)("p",null,"\u9664\u4e86\u4e0a\u8ff0\u7ea6\u5b9a\u5916\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u8def\u7531\u5730\u5740",(0,l.kt)("strong",{parentName:"p"},"\u57fa\u672c\u9760\u624b\u5de5\u5b8c\u6210"),"\uff0c\u4e0d\u5229\u4e8e\u4e66\u5199\uff0c\u4e0d\u5229\u4e8e\u7ef4\u62a4\uff0c\u518d\u8005\uff0c\u5728\u79fb\u52a8\u5e94\u7528\u5bf9\u63a5\u4e2d\u96be\u4ee5\u8fdb\u884c\u591a\u7248\u672c\u63a7\u5236\u3002"),(0,l.kt)("h3",{id:"5122-net-core-webapi-\u7f3a\u70b9"},"5.1.2.2 ",(0,l.kt)("inlineCode",{parentName:"h3"},".NET Core WebAPI")," \u7f3a\u70b9"),(0,l.kt)("p",null,"\u901a\u8fc7\u4e0a\u4e00\u7ae0\u8282\u53ef\u4ee5\u770b\u51fa\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u5b9e\u73b0 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u9700\u8981\u9075\u5faa\u79cd\u79cd\u7ea6\u5b9a\uff0c\u800c\u4e14\u5bb9\u6613\u51fa\u9519\u3002"),(0,l.kt)("p",null,"\u9664\u4e86\u8fd9\u4e9b\u7ea6\u5b9a\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},".NET Core WebAPI")," \u6709\u4ee5\u4e0b\u7f3a\u70b9\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u8def\u7531\u5730\u5740\u57fa\u672c\u9760\u624b\u5de5\u5b8c\u6210"),(0,l.kt)("li",{parentName:"ul"},"\u5728\u73b0\u5728\u79fb\u52a8\u4e3a\u738b\u7684\u65f6\u4ee3\uff0c\u4e0d\u5229\u4e8e\u8fdb\u884c\u591a\u7248\u672c\u63a7\u5236"),(0,l.kt)("li",{parentName:"ul"},"\u5bf9\u63a5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Swagger")," \u6587\u6863\u5206\u7ec4\u6bd4\u8f83\u590d\u6742"),(0,l.kt)("li",{parentName:"ul"},"\u5b9e\u73b0 ",(0,l.kt)("inlineCode",{parentName:"li"},"Policy")," \u7b56\u7565\u6388\u6743\u4e5f\u6bd4\u8f83\u590d\u6742"),(0,l.kt)("li",{parentName:"ul"},"\u4e0d\u652f\u6301\u63a7\u5236\u5668\u70ed\u63d2\u62d4\u63d2\u4ef6\u5316"),(0,l.kt)("li",{parentName:"ul"},"\u96be\u4ee5\u5b9e\u73b0\u590d\u6742\u81ea\u5b9a\u4e49\u7684 ",(0,l.kt)("inlineCode",{parentName:"li"},"RESTful API")," \u98ce\u683c")),(0,l.kt)("h2",{id:"513-\u52a8\u6001-webapi-\u63a7\u5236\u5668"},"5.1.3 \u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"h2"},"WebAPI")," \u63a7\u5236\u5668"),(0,l.kt)("p",null,"\u9488\u5bf9\u4ee5\u4e0a ",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u63d0\u4f9b\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u5fc5\u987b\u9075\u5faa\u7684\u7ea6\u5b9a\u548c\u4e0d\u53ef\u907f\u514d\u7684\u7f3a\u70b9\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u521b\u9020\u51fa\u4e00\u79cd\u66f4\u52a0\u7075\u6d3b\u521b\u5efa ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a7\u5236\u5668\u7684\u65b9\u5f0f\u3002"),(0,l.kt)("p",null,"\u8fd9\u4e2a\u65b9\u5f0f\u5728\u7ee7\u627f\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core WebAPI")," \u6240\u6709\u4f18\u70b9\uff0c\u540c\u65f6\u8fdb\u884c\u4e86\u5927\u91cf\u62d3\u5c55\u548c\u4f18\u5316\u3002\u4f18\u5316\u540e\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u5177\u6709\u4ee5\u4e0b\u4f18\u70b9\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u5177\u5907\u539f\u6709\u7684 ",(0,l.kt)("inlineCode",{parentName:"li"},"ControllerBase")," \u6240\u6709\u529f\u80fd"),(0,l.kt)("li",{parentName:"ul"},"\u652f\u6301",(0,l.kt)("strong",{parentName:"li"},"\u4efb\u610f\u516c\u5f00 \u975e\u9759\u6001 \u975e\u62bd\u8c61 \u975e\u6cdb\u578b\u7c7b"),"\u8f6c\u63a7\u5236\u5668"),(0,l.kt)("li",{parentName:"ul"},"\u63d0\u4f9b\u66f4\u52a0\u7075\u6d3b\u65b9\u4fbf\u7684 ",(0,l.kt)("inlineCode",{parentName:"li"},"IDynamicApiController")," \u7a7a\u63a5\u53e3\u6216 ",(0,l.kt)("inlineCode",{parentName:"li"},"[DynamicApiController]")," \u7279\u6027\u66ff\u4ee3 ",(0,l.kt)("inlineCode",{parentName:"li"},"ControllerBase")," \u62bd\u8c61\u7c7b"),(0,l.kt)("li",{parentName:"ul"},"\u65e0\u9700\u624b\u52a8\u914d\u7f6e ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpMethod]")," \u7279\u6027\uff0c\u540c\u65f6\u652f\u6301\u4e00\u4e2a\u52a8\u4f5c\u65b9\u6cd5\u591a\u4e2a ",(0,l.kt)("inlineCode",{parentName:"li"},"HttpVerb")),(0,l.kt)("li",{parentName:"ul"},"\u65e0\u9700\u624b\u52a8\u914d\u7f6e ",(0,l.kt)("inlineCode",{parentName:"li"},"[Route]")," \u7279\u6027\uff0c\u652f\u6301\u66f4\u52a0\u7075\u6d3b\u7684\u914d\u7f6e\u53ca\u81ea\u52a8\u8def\u7531\u751f\u6210"),(0,l.kt)("li",{parentName:"ul"},"\u652f\u6301\u8fd4\u56de\u6cdb\u578b\u63a5\u53e3\uff0c\u6cdb\u578b\u7c7b"),(0,l.kt)("li",{parentName:"ul"},"\u548c ",(0,l.kt)("inlineCode",{parentName:"li"},"Swagger")," \u6df1\u5ea6\u7ed3\u5408\uff0c\u63d0\u4f9b\u6781\u5176\u65b9\u4fbf\u7684\u521b\u5efa ",(0,l.kt)("inlineCode",{parentName:"li"},"Swagger")," \u5206\u7ec4\u914d\u7f6e"),(0,l.kt)("li",{parentName:"ul"},"\u652f\u6301 ",(0,l.kt)("inlineCode",{parentName:"li"},"Basic Auth\uff0cJwt\uff0cApiKey")," \u7b49\u591a\u79cd\u6743\u9650\u7075\u6d3b\u914d\u7f6e"),(0,l.kt)("li",{parentName:"ul"},"\u652f\u6301\u63a7\u5236\u5668\u3001\u52a8\u4f5c\u65b9\u6cd5",(0,l.kt)("strong",{parentName:"li"},"\u7248\u672c\u63a7\u5236"),"\u529f\u80fd"),(0,l.kt)("li",{parentName:"ul"},"\u652f\u6301 ",(0,l.kt)("inlineCode",{parentName:"li"},"GET\u3001HEAD")," \u8bf7\u6c42\u81ea\u52a8\u8f6c\u6362 ",(0,l.kt)("inlineCode",{parentName:"li"},"\u7c7b\u7c7b\u578b\u53c2\u6570")),(0,l.kt)("li",{parentName:"ul"},"\u652f\u6301\u751f\u6210 ",(0,l.kt)("inlineCode",{parentName:"li"},"OAS3")," \u63a5\u53e3\u89c4\u8303")),(0,l.kt)("h2",{id:"514-\u6ce8\u518c\u52a8\u6001-webapi-\u670d\u52a1"},"5.1.4 \u6ce8\u518c\u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"h2"},"WebAPI")," \u670d\u52a1"),(0,l.kt)("admonition",{title:"\u5907\u6ce8",type:"important"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"p"},".AddDynamicApiControllers()")," \u9ed8\u8ba4\u5df2\u7ecf\u96c6\u6210\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"AddInject()")," \u4e2d\u4e86\uff0c\u65e0\u9700\u518d\u6b21\u6ce8\u518c\u3002\u4e5f\u5c31\u662f\u4e0b\u5217\u4ee3\u7801\u53ef\u4e0d\u914d\u7f6e\u3002")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {11} title="Furion.Web.Core\\FurWebCoreStartup.cs"',showLineNumbers:!0,"":!0,"{11}":!0,title:'"Furion.Web.Core\\FurWebCoreStartup.cs"'},"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.Web.Core\n{\n [AppStartup(800)]\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddControllers()\n .AddDynamicApiControllers();\n }\n }\n}\n")),(0,l.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"p"},".AddDynamicApiControllers()")," \u5fc5\u987b\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"services.AddControllers()")," \u4e4b\u540e\u6ce8\u518c\u3002")),(0,l.kt)("h2",{id:"515-\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"5.1.5 \u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,l.kt)("p",null,"\u521b\u5efa\u4e00\u4e2a ",(0,l.kt)("inlineCode",{parentName:"p"},"FurionAppService")," \u7c7b\u7ee7\u627f ",(0,l.kt)("inlineCode",{parentName:"p"},"IDynamicApiController")," \u63a5\u53e3 \u6216 \u8d34 ",(0,l.kt)("inlineCode",{parentName:"p"},"[DynamicApiController]")," \u7279\u6027\uff0c\u5e76\u5728\u8fd9\u4e2a\u7c7b\u4e2d\u7f16\u5199\u4e00\u4e2a ",(0,l.kt)("inlineCode",{parentName:"p"},"Get")," \u65b9\u6cd5\u3002"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},(0,l.kt)("inlineCode",{parentName:"strong"},"IDynamicApiController")," \u65b9\u5f0f"))),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,7}",showLineNumbers:!0,"":!0,"{1,5,7}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return $"Hello {nameof(Furion)}";\n }\n }\n}\n')),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},(0,l.kt)("inlineCode",{parentName:"strong"},"[DynamicApiController]")," \u65b9\u5f0f"))),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,8}",showLineNumbers:!0,"":!0,"{1,5,8}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [DynamicApiController]\n public class FurionAppService\n {\n public string Get()\n {\n return $"Hello {nameof(Furion)}";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff0c\u4e00\u4e2a ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a5\u53e3\u5c31\u8fd9\u4e48\u751f\u6210\u4e86\u3002"),(0,l.kt)("img",{src:(0,r.Z)("img/dyglz.gif")}),(0,l.kt)("h2",{id:"516-\u52a8\u6001-webapi-\u539f\u7406\u89e3\u6790"},"5.1.6 \u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"h2"},"WebAPI")," \u539f\u7406\u89e3\u6790"),(0,l.kt)("h3",{id:"5161-\u63a7\u5236\u5668\u7279\u6027\u63d0\u4f9b\u5668"},"5.1.6.1 \u63a7\u5236\u5668\u7279\u6027\u63d0\u4f9b\u5668"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4f1a\u5728\u5e94\u7528\u542f\u52a8\u65f6\u6ce8\u518c ",(0,l.kt)("inlineCode",{parentName:"p"},"DynamicApiControllerFeatureProvider")," \u63a7\u5236\u5668\u7279\u6027\u63d0\u4f9b\u5668\uff0c\u8be5\u63d0\u4f9b\u5668\u7ee7\u627f\u81ea ",(0,l.kt)("inlineCode",{parentName:"p"},"ControllerFeatureProvider")," \u7c7b\u3002"),(0,l.kt)("p",null,"\u63a5\u7740\u91cd\u5199 ",(0,l.kt)("inlineCode",{parentName:"p"},"bool IsController(TypeInfo typeInfo)")," \u65b9\u6cd5\uff0c\u7528\u6765\u6807\u8bc6\u63a7\u5236\u5668\u7c7b\u578b\u3002\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c",(0,l.kt)("strong",{parentName:"p"},"\u7ee7\u627f\u81ea ",(0,l.kt)("inlineCode",{parentName:"strong"},"ControllerBase")," \u7c7b\u6216 ",(0,l.kt)("inlineCode",{parentName:"strong"},"IDynamicApiController")," \u63a5\u53e3\u6216 ",(0,l.kt)("inlineCode",{parentName:"strong"},"[DynamicApiController]")," \u7279\u6027\u90fd\u4f1a\u88ab\u6807\u8bb0\u4e3a\u63a7\u5236\u5668\u7c7b\u578b\u3002")),(0,l.kt)("h3",{id:"5162-\u5e94\u7528\u6a21\u578b\u8f6c\u6362\u5668"},"5.1.6.2 \u5e94\u7528\u6a21\u578b\u8f6c\u6362\u5668"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u540c\u65f6\u5728\u5e94\u7528\u542f\u52a8\u65f6\u6ce8\u518c ",(0,l.kt)("inlineCode",{parentName:"p"},"DynamicApiControllerApplicationModelConvention")," \u5e94\u7528\u6a21\u578b\u8f6c\u6362\u5668\uff0c\u8be5\u8f6c\u6362\u5668\u7ee7\u627f\u81ea ",(0,l.kt)("inlineCode",{parentName:"p"},"IApplicationModelConvention")," \u63a5\u53e3\u3002"),(0,l.kt)("p",null,"\u63a5\u7740\u5b9e\u73b0 ",(0,l.kt)("inlineCode",{parentName:"p"},"void Apply(ApplicationModel application)")," \u63a5\u53e3\u65b9\u6cd5\u3002\u5728\u8be5\u65b9\u6cd5\u4e2d\u914d\u7f6e\u63a7\u5236\u5668\u540d\u79f0\u3001\u8def\u7531\u3001\u5bfc\u51fa\u53ef\u89c1\u6027\u53ca\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u3001\u8def\u7531\u3001\u5bfc\u51fa\u53ef\u89c1\u6027\u7b49\u3002"),(0,l.kt)("p",null,"\u5b9e\u9645\u4e0a\u8be5\u65b9\u6cd5\u505a\u7684\u5c31\u662f\u6309\u7167 ",(0,l.kt)("strong",{parentName:"p"},(0,l.kt)("a",{parentName:"strong",href:"#521-webapi-%E7%BA%A6%E5%AE%9A"},"WebAPI \u7ea6\u5b9a"))," \u63d0\u524d\u5e2e\u6211\u4eec\u914d\u7f6e\u597d\u8def\u7531\u3001\u8bf7\u6c42\u8c13\u8bcd\u7b49\u4fe1\u606f\u3002\u907f\u514d\u4e86\u624b\u52a8\u914d\u7f6e\u7684\u540c\u65f6\u8fd8\u589e\u52a0\u4e86\u8bb8\u591a\u65b0\u7279\u6027\uff0c\u5982",(0,l.kt)("strong",{parentName:"p"},"\u7248\u672c\u63a7\u5236\u3002")),(0,l.kt)("h2",{id:"517-\u52a8\u6001-webapi-\u914d\u7f6e\u7ea6\u5b9a"},"5.1.7 \u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"h2"},"WebAPI")," \u914d\u7f6e\u7ea6\u5b9a"),(0,l.kt)("h3",{id:"5171-\u63a7\u5236\u5668\u9ed8\u8ba4\u7ea6\u5b9a"},"5.1.7.1 \u63a7\u5236\u5668\u9ed8\u8ba4\u7ea6\u5b9a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u751f\u6210\u63a7\u5236\u5668\u540d\u79f0\u9ed8\u8ba4\u53bb\u9664\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"AppServices\uff0cAppService\uff0cApiController\uff0cController\uff0cServices\uff0cService")," \u4f5c\u4e3a\u524d\u540e\u7f00\u7684\u5b57\u7b26\u4e32\u3002\u89c1\u7b2c\u4e00\u4e2a\u4f8b\u5b50\u4e2d\u7684 ",(0,l.kt)("inlineCode",{parentName:"li"},"FurionAppService -> Furion")," ",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u63a7\u5236\u5668\u540d\u79f0\u5e26 ",(0,l.kt)("inlineCode",{parentName:"li"},"V[0-9_]")," \u7ed3\u5c3e\u7684\uff0c\u4f1a\u81ea\u52a8\u751f\u6210\u63a7\u5236\u5668\u7248\u672c\u53f7\uff0c\u5982 ",(0,l.kt)("inlineCode",{parentName:"li"},"FurionAppServiceV2 -> Furion@2"),"\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"FurionAppServiceV1_1_0 -> Furion@1.1.0"),"\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u7248\u672c\u5206\u9694\u7b26\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u63a7\u5236\u540d\u79f0\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"\u9a86\u9a7c\u547d\u540d\uff08CamelCase\uff09")," \u4f1a\u81ea\u52a8\u5207\u5272\u6210\u591a\u4e2a\u5355\u8bcd ",(0,l.kt)("inlineCode",{parentName:"li"},"-")," \u8fde\u63a5\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"))),(0,l.kt)("h3",{id:"5172-\u52a8\u4f5c\u65b9\u6cd5\u9ed8\u8ba4\u7ea6\u5b9a"},"5.1.7.2 \u52a8\u4f5c\u65b9\u6cd5\u9ed8\u8ba4\u7ea6\u5b9a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u751f\u6210\u7684\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u9ed8\u8ba4\u53bb\u9664\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Post/Add/Create/Insert/Submit\uff0cGetAll/GetList/Get/Find/Fetch/Query/Search\uff0cPut/Update\uff0cDelete/Remove/Clear\uff0cPatch")," \u5f00\u5934\u7684\u5b57\u7b26\u4e32\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u751f\u6210\u7684\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u9ed8\u8ba4\u53bb\u9664\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Async")," \u4f5c\u4e3a\u524d\u540e\u7f00\u7684\u5b57\u7b26\u4e32\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u5e26 ",(0,l.kt)("inlineCode",{parentName:"li"},"V[0-9_]")," \u7ed3\u5c3e\u7684\uff0c\u4f1a\u81ea\u52a8\u751f\u6210\u52a8\u4f5c\u65b9\u6cd5\u7248\u672c\u53f7\uff0c\u5982 ",(0,l.kt)("inlineCode",{parentName:"li"},"ChangePasswordV2 -> ChangePassword@2"),"\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"ChangePasswordV1_1_0 -> ChangePassword@1.1.0"),"\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u7248\u672c\u5206\u9694\u7b26\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"\u9a86\u9a7c(\u9a7c\u5cf0)/\u5e15\u65af\u5361\u547d\u540d\uff08CamelCase/Pascal\uff09")," \u4f1a\u81ea\u52a8\u5207\u5272\u6210\u591a\u4e2a\u5355\u8bcd ",(0,l.kt)("inlineCode",{parentName:"li"},"-")," \u8fde\u63a5\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u52a8\u4f5c\u65b9\u6cd5\u53c2\u6570\u5c06\u81ea\u52a8\u8f6c\u4e3a\u5c0f\u5199\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"))),(0,l.kt)("h3",{id:"5173-\u8bf7\u6c42\u8c13\u8bcd\u9ed8\u8ba4\u7ea6\u5b9a"},"5.1.7.3 \u8bf7\u6c42\u8c13\u8bcd\u9ed8\u8ba4\u7ea6\u5b9a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u52a8\u4f5c\u65b9\u6cd5\u540d",(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Post/Add/Create/Insert/Submit/Change")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPost]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"GetAll/GetList/Get/Find/Fetch/Query")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpGet]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Put/Update")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPut]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Delete/Remove/Clear")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpDelete]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Patch")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPatch]")," \u7279\u6027"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")))),(0,l.kt)("li",{parentName:"ul"},"\u5982\u679c\u4e0d\u5728\u4e0a\u9762\u7ea6\u5b9a\u4e2d\uff0c\u5219\u9ed8\u8ba4\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPost]")," \u7279\u6027\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"))),(0,l.kt)("h3",{id:"5174-\u8def\u7531\u5730\u5740\u9ed8\u8ba4\u7ea6\u5b9a"},"5.1.7.4 \u8def\u7531\u5730\u5740\u9ed8\u8ba4\u7ea6\u5b9a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u9ed8\u8ba4\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"api")," \u5f00\u5934\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u9ed8\u8ba4\u8f6c\u6362\u4e3a\u5c0f\u5199\u8def\u7531\u5730\u5740\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u751f\u6210\u63a7\u5236\u5668\u8def\u7531\u6a21\u677f\u683c\u5f0f\u4e3a\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"api/\u524d\u7f6e\u53c2\u6570\u5217\u8868/\u6a21\u5757\u540d\u6216\u9ed8\u8ba4\u533a\u57df\u540d/[controller@\u7248\u672c\u53f7]/\u540e\u7f6e\u53c2\u6570\u5217\u8868")),(0,l.kt)("li",{parentName:"ul"},"\u751f\u6210\u52a8\u4f5c\u65b9\u6cd5\u8def\u7531\u6a21\u677f\u683c\u5f0f\u4e3a\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"\u524d\u7f6e\u53c2\u6570\u5217\u8868/\u6a21\u5757\u540d/[action@\u7248\u672c\u53f7]/\u540e\u7f6e\u53c2\u6570\u5217\u8868"))),(0,l.kt)("h3",{id:"5175-\u5176\u4ed6\u7ea6\u5b9a"},"5.1.7.5 \u5176\u4ed6\u7ea6\u5b9a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u9ed8\u8ba4\u4e0d\u5904\u7406 ",(0,l.kt)("inlineCode",{parentName:"li"},"ControllerBase")," \u63a7\u5236\u5668\u7c7b\u578b\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")),(0,l.kt)("li",{parentName:"ul"},"\u9ed8\u8ba4\u4e0d\u5904\u7406 ",(0,l.kt)("inlineCode",{parentName:"li"},"GET\uff0cHEAD")," \u8bf7\u6c42\u7684\u5f15\u7528\u7c7b\u578b\u53c2\u6570\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"))),(0,l.kt)("h2",{id:"518-\u66f4\u591a\u4f8b\u5b50"},"5.1.8 \u66f4\u591a\u4f8b\u5b50"),(0,l.kt)("h3",{id:"5181-\u591a\u79cd\u8bf7\u6c42\u8c13\u8bcd\u65b9\u6cd5"},"5.1.8.1 \u591a\u79cd\u8bf7\u6c42\u8c13\u8bcd\u65b9\u6cd5"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,12,17,22,27}",showLineNumbers:!0,"":!0,"{7,12,17,22,27}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return $"GET \u8bf7\u6c42";\n }\n\n public string Post()\n {\n return $"POST \u8bf7\u6c42";\n }\n\n public string Delete()\n {\n return $"DELETE \u8bf7\u6c42";\n }\n\n public string Put()\n {\n return $"PUT \u8bf7\u6c42";\n }\n\n public string Patch()\n {\n return $"PATCH \u8bf7\u6c42";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dgqqwc.png")}),(0,l.kt)("h3",{id:"5182-\u591a\u4e2a\u81ea\u5b9a\u4e49\u52a8\u4f5c\u65b9\u6cd5"},"5.1.8.2 \u591a\u4e2a\u81ea\u5b9a\u4e49\u52a8\u4f5c\u65b9\u6cd5"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,12,17}",showLineNumbers:!0,"":!0,"{7,12,17}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string GetVersion()\n {\n return $"v1.0.0";\n }\n\n public string ChangeProfile()\n {\n return "\u4fee\u6539\u6210\u529f";\n }\n\n public string DeleteUser()\n {\n return "\u5220\u9664\u6210\u529f";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dzmc.png")}),(0,l.kt)("h3",{id:"5183-\u5e26\u53c2\u6570\u52a8\u4f5c\u65b9\u6cd5"},"5.1.8.3 \u5e26\u53c2\u6570\u52a8\u4f5c\u65b9\u6cd5"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,12,17}",showLineNumbers:!0,"":!0,"{7,12,17}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string GetUser(int id)\n {\n return $"{id}";\n }\n\n public string GetUser(int id, string name)\n {\n return $"{id} {name}";\n }\n\n public TestDto Add(TestDto testDto)\n {\n return testDto;\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dcsff.gif")}),(0,l.kt)("h3",{id:"5184-gethead-\u7c7b\u7c7b\u578b\u53c2\u6570"},"5.1.8.4 ",(0,l.kt)("inlineCode",{parentName:"h3"},"GET/HEAD")," \u7c7b\u7c7b\u578b\u53c2\u6570"),(0,l.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u4f1a\u5c06 ",(0,l.kt)("inlineCode",{parentName:"p"},"GET/HEAD")," \u8bf7\u6c42\u4e2d\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"\u7c7b\u7c7b\u578b\u53c2\u6570")," \u8bbe\u7f6e\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"[FromBody]")," \u7ed1\u5b9a\uff0c\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7}",showLineNumbers:!0,"":!0,"{7}":!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public TestDto GetTest(TestDto testDto)\n {\n return testDto;\n }\n }\n}\n")),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/getyycs.png")}),(0,l.kt)("p",null,"\u4f46\u662f\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"GET\u3001HEAD")," \u8bf7\u6c42\u4e0d\u652f\u6301 ",(0,l.kt)("inlineCode",{parentName:"p"},"From Body")," \u7ed1\u5b9a\u3002\u6240\u4ee5\u6211\u4eec\u9700\u8981\u8f6c\u6362\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"Query")," \u67e5\u8be2\u53c2\u6570\u3002"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u652f\u6301\u4ee5\u4e0b\u4e24\u79cd\u65b9\u5f0f\u914d\u7f6e\uff1a"),(0,l.kt)(o.Z,{defaultValue:"fromquery",values:[{label:"[FromQuery] \u7279\u6027",value:"fromquery"},{label:"\u914d\u7f6e DynamicApiControllerSettings",value:"DynamicApiControllerSettings"}],mdxType:"Tabs"},(0,l.kt)(p.Z,{value:"fromquery",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,8}",showLineNumbers:!0,"":!0,"{2,8}":!0},"using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public TestDto GetTest([FromQuery] TestDto testDto)\n {\n return testDto;\n }\n }\n}\n"))),(0,l.kt)(p.Z,{value:"DynamicApiControllerSettings",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers {2-4} title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,"{2-4}":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "DynamicApiControllerSettings": {\n "ModelToQuery": true\n }\n}\n')))),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/modeltoquery.png")}),(0,l.kt)("h3",{id:"5185-\u81ea\u5b9a\u4e49\u53c2\u6570\u4f4d\u7f6e"},"5.1.8.5 \u81ea\u5b9a\u4e49\u53c2\u6570\u4f4d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u975e\u5e38\u65b9\u4fbf\u7684\u81ea\u5b9a\u4e49\u53c2\u6570\u4f4d\u7f6e\u7684\u7279\u6027 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiSeat]"),"\uff0c\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiSeat]")," \u53ef\u914d\u7f6e\u53c2\u6570\u4f4d\u7f6e\uff0c\u652f\u6301\u4ee5\u4e0b\u56db\u79cd\u4f4d\u7f6e\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ApiSeats.ControllerStart"),"\uff1a\u63a7\u5236\u5668\u4e4b\u524d"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ApiSeats.ControllerEnd"),"\uff1a\u63a7\u5236\u5668\u4e4b\u540e"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ApiSeats.ActionStart"),"\uff1a\u52a8\u4f5c\u65b9\u6cd5\u4e4b\u524d"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ApiSeats.ActionEnd"),"\uff1a\u52a8\u4f5c\u65b9\u6cd5\u4e4b\u540e\u3002",(0,l.kt)("strong",{parentName:"li"},"\u9ed8\u8ba4\u503c"))),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8-9,15-20}",showLineNumbers:!0,"":!0,"{8-9,15-20}":!0},'using Furion.DynamicApiController;\nusing System;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n // \u53c2\u6570\u9ed8\u8ba4\u4e3a ApiSeats.ActionEnd\n public string RouteSeat(int id, string name)\n {\n return "\u914d\u7f6e\u8def\u7531\u53c2\u6570\u4f4d\u7f6e";\n }\n\n public string RouteSeat(\n [ApiSeat(ApiSeats.ControllerStart)] int id, // \u63a7\u5236\u5668\u540d\u79f0\u4e4b\u524d\n [ApiSeat(ApiSeats.ControllerEnd)] string name, // \u63a7\u5236\u5668\u540d\u79f0\u4e4b\u540e\n [ApiSeat(ApiSeats.ControllerEnd)] int age, // \u63a7\u5236\u5668\u540d\u79f0\u4e4b\u540e\n [ApiSeat(ApiSeats.ActionStart)] decimal weight, // \u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u4e4b\u524d\n [ApiSeat(ApiSeats.ActionStart)] float height, // \u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u4e4b\u524d\n [ApiSeat(ApiSeats.ActionEnd)] DateTime birthday) // \u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u4e4b\u540e\uff08\u9ed8\u8ba4\u503c\uff09\n {\n return "\u914d\u7f6e\u8def\u7531\u53c2\u6570\u4f4d\u7f6e";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/cswz.png")}),(0,l.kt)("admonition",{title:"\u6e29\u99a8\u63d0\u793a",type:"note"},(0,l.kt)("p",{parentName:"admonition"},"\u591a\u4e2a ",(0,l.kt)("strong",{parentName:"p"},(0,l.kt)("inlineCode",{parentName:"strong"},"\u540c\u4f4d\u7f6e"))," \u914d\u7f6e\u7684\u53c2\u6570\u5c06\u6309\u7167 ",(0,l.kt)("strong",{parentName:"p"},(0,l.kt)("inlineCode",{parentName:"strong"},"\u5b9a\u4e49\u53c2\u6570\u987a\u5e8f"))," \u8fdb\u884c\u6392\u5e8f\u3002")),(0,l.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"p"},"[ApiSeat]")," \u53ea\u80fd\u5e94\u7528\u4e8e\u8d34\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},"[FromRoute]")," \u7279\u6027\u7684\u53c2\u6570\u6216 ",(0,l.kt)("inlineCode",{parentName:"p"},"\u57fa\u5143\u7c7b\u578b\u3001\u503c\u7c7b\u578b\u3001\u53ef\u7a7a\u57fa\u5143\u7c7b\u578b\u548c\u53ef\u7a7a\u503c\u7c7b\u578b"),"\u3002")),(0,l.kt)("h3",{id:"5186-\u81ea\u5b9a\u4e49\u8bf7\u6c42\u8c13\u8bcd"},"5.1.8.6 \u81ea\u5b9a\u4e49\u8bf7\u6c42\u8c13\u8bcd"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,8}",showLineNumbers:!0,"":!0,"{2,8}":!0},'using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n [HttpPost]\n public string GetVersion()\n {\n return "1.0.0";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/zdywc.png")}),(0,l.kt)("h3",{id:"5187-\u652f\u6301\u591a\u4e2a\u8c13\u8bcd"},"5.1.8.7 \u652f\u6301\u591a\u4e2a\u8c13\u8bcd"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,8}",showLineNumbers:!0,"":!0,"{2,8}":!0},'using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n [HttpPost, HttpGet, AcceptVerbs("PUT", "DELETE")]\n public string GetVersion()\n {\n return "1.0.0";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dgwc.png")}),(0,l.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,l.kt)("p",{parentName:"admonition"},"\u5982\u679c\u52a8\u4f5c\u65b9\u6cd5\u4e2d\u542b\u6709 ",(0,l.kt)("inlineCode",{parentName:"p"},"\u7c7b\u7c7b\u578b\u53c2\u6570"),"\uff0c\u4e14\u542b\u6709 ",(0,l.kt)("inlineCode",{parentName:"p"},"POST/PUT/DELETE")," \u4efb\u610f\u8bf7\u6c42\u8c13\u8bcd\uff0c\u90a3\u4e48\u8be5\u53c2\u6570\u4f1a\u81ea\u52a8\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"p"},"[FromBody]")," \u53c2\u6570\uff0c\u5373\u4f7f\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"GET/HEAD")," \u8bf7\u6c42\u4e2d\u4e0d\u652f\u6301\u3002")),(0,l.kt)("h3",{id:"5188-\u652f\u6301\u81ea\u5b9a\u4e49\u8def\u7531"},"5.1.8.8 \u652f\u6301\u81ea\u5b9a\u4e49\u8def\u7531"),(0,l.kt)("p",null,"\u652f\u6301\u63a7\u5236\u5668\u548c\u52a8\u4f5c\u65b9\u6cd5\u81ea\u5b9a\u4e49\u8def\u7531\uff1a"),(0,l.kt)(o.Z,{defaultValue:"kzqrl",values:[{label:"\u81ea\u5b9a\u4e49\u63a7\u5236\u5668\u8def\u7531",value:"kzqrl"},{label:"\u81ea\u5b9a\u4e49\u52a8\u4f5c\u65b9\u6cd5\u8def\u7531",value:"dzffrl"},{label:"\u540c\u65f6\u81ea\u5b9a\u4e49\u8def\u7531",value:"allrl"},{label:"\u8c13\u8bcd\u81ea\u5b9a\u4e49\u8def\u7531",value:"vcrl"}],mdxType:"Tabs"},(0,l.kt)(p.Z,{value:"kzqrl",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6}",showLineNumbers:!0,"":!0,"{2,6}":!0},'using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n [Route("customapi/mobile/[controller]")]\n public class FurionAppService : IDynamicApiController\n {\n public string GetVersion()\n {\n return "1.0.0";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/kzqrl.png")})),(0,l.kt)(p.Z,{value:"dzffrl",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,8}",showLineNumbers:!0,"":!0,"{2,8}":!0},'using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n [Route("customapi/[action]")]\n public string GetVersion()\n {\n return "1.0.0";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dzffrl.png")})),(0,l.kt)(p.Z,{value:"allrl",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6,9}",showLineNumbers:!0,"":!0,"{2,6,9}":!0},'using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n [Route("customapi/mobile/[controller]")]\n public class FurionAppService : IDynamicApiController\n {\n [Route("get/[action]")]\n public string GetVersion()\n {\n return "1.0.0";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/allrl.png")})),(0,l.kt)(p.Z,{value:"vcrl",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9}",showLineNumbers:!0,"":!0,"{9}":!0},'using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n [Route("api/[controller]")]\n public class FurionAppService : IDynamicApiController\n {\n [HttpGet("get/[action]")]\n public string GetVersion()\n {\n return "1.0.0";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/wcrl.png")}))),(0,l.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"important"},(0,l.kt)("p",{parentName:"admonition"},"\u52a8\u4f5c\u65b9\u6cd5\u81ea\u5b9a\u4e49\u8def\u7531\u5982\u679c\u4ee5 ",(0,l.kt)("strong",{parentName:"p"},(0,l.kt)("inlineCode",{parentName:"strong"},"/"))," \u5f00\u5934\uff0c\u5219\u4e0d\u4f1a\u5408\u5e76\u63a7\u5236\u5668\u8def\u7531\u3002")),(0,l.kt)("admonition",{title:"\u63a8\u8350\u914d\u7f6e",type:"tip"},(0,l.kt)("p",{parentName:"admonition"},"\u81ea\u5b9a\u4e49\u8def\u7531\u5982\u679c\u9700\u8981\u7528\u5230 ",(0,l.kt)("strong",{parentName:"p"},"\u63a7\u5236\u5668/\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0"),"\uff0c\u63a8\u8350\u4f7f\u7528 ",(0,l.kt)("inlineCode",{parentName:"p"},"[controller]")," \u6216 ",(0,l.kt)("inlineCode",{parentName:"p"},"[action]")," \u5360\u4f4d\u7b26\uff0c\u56e0\u4e3a\u8be5\u5360\u4f4d\u7b26\u5df2\u7ecf\u81ea\u52a8\u5904\u7406\u4e86 ",(0,l.kt)("strong",{parentName:"p"},"\u524d\u540e\u7f00\u3001\u7248\u672c\u53f7\u3001\u6a21\u5757\u540d\u79f0"),"\u7b49\u3002")),(0,l.kt)("h3",{id:"5189-\u591a\u8def\u7531\u968f\u610f\u7ec4\u5408"},"5.1.8.9 \u591a\u8def\u7531\u968f\u610f\u7ec4\u5408"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u7684\u5404\u79cd\u8def\u7531\u7ec4\u5408\u65b9\u5f0f\uff0c\u652f\u6301\u4e00\u5bf9\u591a\uff0c\u591a\u5bf9\u591a\u8def\u7531\u7ec4\u5408\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6-8,11-14}",showLineNumbers:!0,"":!0,"{6-8,11-14}":!0},'using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n [Route("api/[controller]")]\n [Route("api/[controller]/second")]\n [Route("api/[controller]/three")]\n public class FurionAppService : IDynamicApiController\n {\n [HttpGet]\n [HttpGet("get/[action]")]\n [HttpPost]\n [HttpPost("post/cus-version")]\n public string GetVersion()\n {\n return "1.0.0";\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dlrzh.gif")}),(0,l.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,l.kt)("p",{parentName:"admonition"},"\u52a8\u4f5c\u65b9\u6cd5\u4e0d\u80fd\u540c\u65f6\u8d34 ",(0,l.kt)("inlineCode",{parentName:"p"},"[Route]")," \u548c ",(0,l.kt)("inlineCode",{parentName:"p"},"[HttpMethod]")," \u7279\u6027\uff0c\u53ea\u80fd\u4e8c\u53d6\u4e00\u3002")),(0,l.kt)("h3",{id:"51810-\u652f\u6301\u7248\u672c\u63a7\u5236"},"5.1.8.10 \u652f\u6301\u7248\u672c\u63a7\u5236"),(0,l.kt)(o.Z,{defaultValue:"kzqbb",values:[{label:"\u63a7\u5236\u5668\u7248\u672c",value:"kzqbb"},{label:"\u52a8\u4f5c\u65b9\u6cd5\u7248\u672c",value:"dzffbb"}],mdxType:"Tabs"},(0,l.kt)(p.Z,{value:"kzqbb",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,13,21}",showLineNumbers:!0,"":!0,"{5,13,21}":!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppServiceV1 : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n }\n\n public class FurionAppServiceV1_2 : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n }\n\n public class FurionAppServiceV1_2_1 : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n }\n}\n")),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/kzqbb.png")})),(0,l.kt)(p.Z,{value:"dzffbb",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,12,16}",showLineNumbers:!0,"":!0,"{7,12,16}":!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public string GetV1()\n {\n return nameof(Furion);\n }\n public string GetV2_1()\n {\n return nameof(Furion);\n }\n }\n}\n")),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dzffbb.png")}))),(0,l.kt)("admonition",{title:"\u7248\u672c\u751f\u6210\u539f\u7406",type:"note"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("strong",{parentName:"p"},(0,l.kt)("inlineCode",{parentName:"strong"},"V[0-9_]"))," \u7ed3\u5c3e\u7684\u547d\u540d\u81ea\u52a8\u89e3\u6790\u6210\u7248\u672c\u53f7\uff0c\u5982 ",(0,l.kt)("strong",{parentName:"p"},(0,l.kt)("inlineCode",{parentName:"strong"},"FurionAppServiceV2 -> Furion@2")),"\u3002")),(0,l.kt)("admonition",{title:"\u7248\u672c\u590d\u5199",type:"tip"},(0,l.kt)("p",{parentName:"admonition"},"\u9664\u4e86\u901a\u8fc7\u7279\u5b9a\u540e\u7f00\u65b9\u5f0f\u4ee5\u5916\uff0c\u7248\u672c\u8fd8\u76f4\u63a5\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiDescriptionSettings]")," \u8fdb\u884c\u590d\u5199\u3002\u5982\uff1a"),(0,l.kt)("pre",{parentName:"admonition"},(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,2}",showLineNumbers:!0,"":!0,"{1,2}":!0},'[ApiDescriptionSettings(Version = "4.0")]\npublic string GetV1()\n{\n return nameof(Furion);\n}\n')),(0,l.kt)("p",{parentName:"admonition"},"\u8fd9\u65f6\uff0c\u751f\u6210\u7248\u672c\u5c06\u91c7\u7528 ",(0,l.kt)("inlineCode",{parentName:"p"},"4.0")," \u66ff\u4ee3 ",(0,l.kt)("inlineCode",{parentName:"p"},"1"))),(0,l.kt)("h3",{id:"51811-\u4e0d\u516c\u5f00\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5"},"5.1.8.11 \u4e0d\u516c\u5f00\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5"),(0,l.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u65e0\u9700\u5bfc\u51fa\u67d0\u4e2a\u52a8\u4f5c\u65b9\u6cd5\u6216\u63a7\u5236\u5668\uff08",(0,l.kt)("strong",{parentName:"p"},"\u4e0d\u663e\u793a\u5230 Swagger"),"\uff09\uff0c\u53ea\u9700\u8981\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiDescriptionSettings(false)]")," \u6216 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiExplorerSettings(IgnoreApi = true)]"),"\u5373\u53ef\u3002"),(0,l.kt)("p",null,"\u53e6\u5916\u52a8\u4f5c\u65b9\u6cd5\u8fd8\u652f\u6301 ",(0,l.kt)("inlineCode",{parentName:"p"},"[NonAction]")," \u6807\u8bb0\u4e0d\u662f\u4e00\u4e2a\u6709\u6548\u7684\u63a7\u5236\u5668\u6216 Action\u3002"),(0,l.kt)("admonition",{title:"\u63a8\u8350\u4f7f\u7528",type:"tip"},(0,l.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5\u8bbe\u7f6e\u4e0d\u5bfc\u51fa\u4f7f\u7528 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiDescriptionSettings(false)]")," \u7279\u6027\u3002\u8be5\u7279\u6027\u9ed8\u8ba4\u7ee7\u627f\u81ea ",(0,l.kt)("inlineCode",{parentName:"p"},"ApiExplorerSettingsAttribute")," \u7c7b\u3002")),(0,l.kt)("h3",{id:"51812-\u4fdd\u6301\u63a7\u5236\u5668\u548c\u65b9\u6cd5\u547d\u540d"},"5.1.8.12 \u4fdd\u6301\u63a7\u5236\u5668\u548c\u65b9\u6cd5\u547d\u540d"),(0,l.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u52a8\u6001 API \u4f1a\u5c06\u63a7\u5236\u5668\u548c\u65b9\u6cd5\u540d\u8f93\u51fa\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"RESTFul")," \u98ce\u683c\u7684\u8def\u7531\uff0c\u5982\u9700\u4fdd\u7559\u539f\u6709\u8bbe\u8ba1\uff0c\u53ea\u9700\u914d\u7f6e\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "DynamicApiControllerSettings": {\n "KeepName": true,\n "KeepVerb": true,\n "LowercaseRoute": false\n }\n}\n')),(0,l.kt)("h3",{id:"51813-\u65b9\u6cd5\u53c2\u6570-fromquery-\u5316\u53c2\u6570\u975e\u5fc5\u586b\u53c2\u6570\u53ef\u9009"},"5.1.8.13 \u65b9\u6cd5\u53c2\u6570 ",(0,l.kt)("inlineCode",{parentName:"h3"},"[FromQuery]")," \u5316/\u53c2\u6570\u975e\u5fc5\u586b/\u53c2\u6570\u53ef\u9009"),(0,l.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u6240\u6709\u7684\u57fa\u5143\u7c7b\u578b\u53c2\u6570\u90fd\u4f1a\u8d34\u4e0a ",(0,l.kt)("inlineCode",{parentName:"p"},"[FromRoute]")," \u7279\u6027\uff0c\u5982\u679c\u9700\u8981\u5c06\u53c2\u6570\u8c03\u6574\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"[FromQuery]")," \u4fee\u9970\uff0c\u53ea\u9700\u8981\u5728\u65b9\u6cd5\u4e0a\u9762\u8d34 ",(0,l.kt)("inlineCode",{parentName:"p"},"[QueryParameters]")," \u7279\u6027\u5373\u53ef\uff0c\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[QueryParameters]\npublic string Get(int id, string name)\n{\n return nameof($"{id} {name}");\n}\n')),(0,l.kt)("p",null,"\u751f\u6210\u7684\u8def\u7531\u4e3a\uff1a",(0,l.kt)("inlineCode",{parentName:"p"},"https://xxx.com?id=1&name=Furion")),(0,l.kt)("p",null,"\u5982\u679c\u4e0d\u559c\u6b22\u6bcf\u4e2a\u90fd\u914d\u7f6e\uff0c\u4e5f\u53ef\u4ee5\u5168\u5c40\u914d\u7f6e\uff08",(0,l.kt)("strong",{parentName:"p"},"\u53ea\u4f1a\u5f71\u54cd\u57fa\u5143\u7c7b\u578b\u7684\u53c2\u6570"),"\uff09\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "DynamicApiControllerSettings": {\n "UrlParameterization": true\n }\n}\n')),(0,l.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,l.kt)("p",{parentName:"admonition"},"\u8d34\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},"[QueryParameters]")," \u4e4b\u540e\uff0c\u4f1a\u5bf9\u6240\u6709\u53c2\u6570\u5f71\u54cd\uff0c\u5305\u62ec\u7c7b\u7c7b\u578b\u53c2\u6570\uff0c\u5982\u679c\u4e0d\u9700\u8981\u5904\u7406\u67d0\u4e2a\u53c2\u6570\uff0c\u53ea\u9700\u8981\u8d34 ",(0,l.kt)("inlineCode",{parentName:"p"},"[FromXXX]")," \u7279\u6027\u5373\u53ef\u3002")),(0,l.kt)("h3",{id:"51814-\u53c2\u6570\u7ed1\u5b9a\u914d\u7f6e"},"5.1.8.14 \u53c2\u6570\u7ed1\u5b9a\u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u591a\u79cd\u53c2\u6570\u7279\u6027\u914d\u7f6e\u53c2\u6570\u7ed1\u5b9a\u89c4\u5219\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[FromRoute]"),"\uff1a\u901a\u8fc7\u8def\u7531\u53c2\u6570\u7ed1\u5b9a\u503c"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[FromQuery]"),"\uff1a\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"li"},"Url")," \u5730\u5740\u53c2\u6570\u7ed1\u5b9a\u503c"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[FromBody]"),"\uff1a\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"li"},"Request Body")," \u53c2\u6570\u7ed1\u5b9a\u503c"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[FromForm]"),"\uff1a\u901a\u8fc7\u8868\u5355\u63d0\u4ea4\u7ed1\u5b9a\u503c"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"[FromHeader]"),"\uff1a\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"li"},"Request Header")," \u53c2\u6570\u7ed1\u5b9a\u503c")),(0,l.kt)("h3",{id:"51815-\u81ea\u5b9a\u4e49\u6839\u636e\u65b9\u6cd5\u540d\u751f\u6210-httpmethod-\u89c4\u5219"},"5.1.8.15 \u81ea\u5b9a\u4e49\u6839\u636e\u65b9\u6cd5\u540d\u751f\u6210 ",(0,l.kt)("inlineCode",{parentName:"h3"},"[HttpMethod]")," \u89c4\u5219"),(0,l.kt)("p",null,"\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5728\u6ca1\u6709\u914d\u7f6e ",(0,l.kt)("inlineCode",{parentName:"p"},"[HttpMethod]")," \u7279\u6027\u7684\u60c5\u51b5\u4e0b\uff0c\u4f1a\u81ea\u52a8\u6839\u636e\u65b9\u6cd5\u540d\u7b2c\u4e00\u4e2a\u53c2\u6570\u8fdb\u884c\u5206\u6790\uff0c\u5e76\u751f\u6210\u5bf9\u5e94\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"[HttpMethod]")," \u7279\u6027\uff0c\u89c4\u5219\u5982\u4e0b\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"\u52a8\u4f5c\u65b9\u6cd5\u540d",(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Post/Add/Create/Insert/Submit")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPost]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"GetAll/GetList/Get/Find/Fetch/Query")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpGet]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Put/Update")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPut]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Delete/Remove/Clear")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpDelete]")," \u7279\u6027\u3002"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Patch")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPatch]")," \u7279\u6027"),(0,l.kt)("li",{parentName:"ul"},"\u4ee5 ",(0,l.kt)("inlineCode",{parentName:"li"},"Head")," \u5f00\u5934\uff0c\u5219\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpHead]")," \u7279\u6027"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e")))),(0,l.kt)("li",{parentName:"ul"},"\u5982\u679c\u4e0d\u5728\u4e0a\u9762\u7ea6\u5b9a\u4e2d\uff0c\u5219\u9ed8\u8ba4\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpPost]")," \u7279\u6027\u3002",(0,l.kt)("strong",{parentName:"li"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"))),(0,l.kt)("p",null,(0,l.kt)("strong",{parentName:"p"},"\u4f46\u662f\uff0c\u6709\u4e9b\u65f6\u5019\u8fd9\u4e0d\u662f\u6211\u4eec\u60f3\u8981\u7684\u89c4\u5219"),"\uff0c\u8fd9\u65f6\u6211\u4eec\u53ea\u9700\u8981\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u4e2d\u914d\u7f6e\u5373\u53ef\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2,3}",showLineNumbers:!0,"":!0,"{2,3}":!0},'{\n "DynamicApiControllerSettings": {\n "VerbToHttpMethods": [\n ["getall", "HEAD"], // => getall \u4f1a\u88ab\u590d\u5199\u4e3a `[HttpHead]`\n ["other", "PUT"] // => \u65b0\u589e\u4e00\u6761\u65b0\u89c4\u5219\uff0c\u6bd4\u5982\uff0c\u4e00 `[other]` \u5f00\u5934\u4f1a\u8f6c\u6362\u4e3a `[HttpPut]` \u8bf7\u6c42\n ]\n }\n}\n')),(0,l.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,l.kt)("p",{parentName:"admonition"},"\u4e8c\u7ef4\u6570\u7ec4\u4e2d\u7684\u6bcf\u4e00\u4e2a\u5143\u7d20\u7684\u7b2c\u4e00\u4e2a\u5143\u7d20",(0,l.kt)("strong",{parentName:"p"},"\u5fc5\u987b\u662f\u5168\u5c0f\u5199"),"\uff0c\u7b2c\u4e8c\u4e2a\u5143\u7d20",(0,l.kt)("strong",{parentName:"p"},"\u5fc5\u987b\u662f\u5168\u5927\u5199\u5927\u5199"),"\uff0c\u7b2c\u4e8c\u4e2a\u5143\u7d20\u53d6\u503c\u6709\uff1a",(0,l.kt)("inlineCode",{parentName:"p"},"HEAD, GET, PUT, POST, PATCH, DELETE"))),(0,l.kt)("h3",{id:"51816-\u8def\u7531\u53c2\u6570\u975e\u5fc5\u586b\u9009\u586b"},"5.1.8.16 \u8def\u7531\u53c2\u6570\u975e\u5fc5\u586b/\u9009\u586b"),(0,l.kt)("p",null,"\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"Furion v2.8.6")," \u7248\u672c\u4e2d\u5b9e\u73b0\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},"[FromRoute]")," \u53c2\u6570\u975e\u5fc5\u586b\u529f\u80fd\uff0c\u652f\u6301\u4ee5\u4e0b\u51e0\u79cd\u65b9\u5f0f\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6,11,16}",showLineNumbers:!0,"":!0,"{2,6,11,16}":!0},"// \u65b9\u5f0f\u4e00\uff0c\u901a\u8fc7\u53ef\u7a7a ?\npublic object Method1(int id, Datetime? dateTime)\n{\n}\n\n// \u65b9\u5f0f\u4e8c\uff0c\u901a\u8fc7\u9ed8\u8ba4\u503c\npublic object Method1(int id, int age = 10)\n{\n}\n\n// \u65b9\u5f0f\u4e09\uff0c\u9ed8\u8ba4\u503c + \u53ef\u7a7a ?\npublic object Method1(int id, int? age = 10)\n{\n}\n\n// \u65b9\u5f0f\u56db\uff0c[FromQuery] \u4fee\u9970\npublic object Method1(int id, [FromQuery]string keyword)\n{\n}\n")),(0,l.kt)("h3",{id:"51817-formroute-\u8def\u7531\u7ea6\u675f"},"5.1.8.17 ",(0,l.kt)("inlineCode",{parentName:"h3"},"[FormRoute]")," \u8def\u7531\u7ea6\u675f"),(0,l.kt)("p",null,"\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"Furion v2.8.6")," \u7248\u672c\u4e2d\uff0c\u6dfb\u52a0\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},"[RouteConstraint]")," \u7279\u6027\uff0c\u53ef\u914d\u7f6e\u8def\u7531\u7ea6\u675f\uff0c\u5982\uff1a",(0,l.kt)("inlineCode",{parentName:"p"},'[RouteConstraint(":min(10)")]')),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},'// \u6700\u5c0f\u503c 10\npublic object Method1([RouteConstraint(":min(10)")] int id)\n{\n}\n')),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"[RouteConstraint]")," \u652f\u6301\u8def\u7531\u7ea6\u675f\u7b26\u53f7\u5982\u4e0b\uff1a"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"\u7b26\u53f7"),(0,l.kt)("th",{parentName:"tr",align:null},"\u63cf\u8ff0"),(0,l.kt)("th",{parentName:"tr",align:null},"\u4f8b\u5b50"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"alpha")),(0,l.kt)("td",{parentName:"tr",align:null},"\u5339\u914d\u5927\u5199\u6216\u5c0f\u5199\u62c9\u4e01\u5b57\u6bcd\u5b57\u7b26\uff08a-z\u3001A-Z\uff09"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":alpha"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"bool")),(0,l.kt)("td",{parentName:"tr",align:null},"bool \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":bool"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"datetime")),(0,l.kt)("td",{parentName:"tr",align:null},"DateTime \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":datetime"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"decimal")),(0,l.kt)("td",{parentName:"tr",align:null},"decimal \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":decimal"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"double")),(0,l.kt)("td",{parentName:"tr",align:null},"double \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":double"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"float")),(0,l.kt)("td",{parentName:"tr",align:null},"float \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":float"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"guid")),(0,l.kt)("td",{parentName:"tr",align:null},"guid \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":guid"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"int")),(0,l.kt)("td",{parentName:"tr",align:null},"int \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":int"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"long")),(0,l.kt)("td",{parentName:"tr",align:null},"long \u7c7b\u578b"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":long"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"length")),(0,l.kt)("td",{parentName:"tr",align:null},"\u5339\u914d\u957f\u5ea6\uff08\u5b57\u7b26\u4e32\uff09"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":length(6)")," \u6216 ",(0,l.kt)("inlineCode",{parentName:"td"},":length(1,20)"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"max")),(0,l.kt)("td",{parentName:"tr",align:null},"\u6700\u5927\u503c"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":max(10)"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"maxlength")),(0,l.kt)("td",{parentName:"tr",align:null},"\u6700\u5927\u957f\u5ea6\uff08\u5b57\u7b26\u4e32\uff09"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":maxlength(10)"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"min")),(0,l.kt)("td",{parentName:"tr",align:null},"\u6700\u5c0f\u503c"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":min(10)"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"minlength")),(0,l.kt)("td",{parentName:"tr",align:null},"\u6700\u5c0f\u957f\u5ea6\uff08\u5b57\u7b26\u4e32\uff09"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":minlength(10)"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"range")),(0,l.kt)("td",{parentName:"tr",align:null},"\u53d6\u503c\u8303\u56f4"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":range(10,50)"))),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},"regex")),(0,l.kt)("td",{parentName:"tr",align:null},"\u6b63\u5219\u8868\u8fbe\u5f0f"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("inlineCode",{parentName:"td"},":regex(^\\d{3}-\\d{3}-\\d{4}$)"))))),(0,l.kt)("h3",{id:"51818-\u5c0f\u9a7c\u5cf0-\u8def\u7531\u8def\u5f84"},"5.1.8.18 ",(0,l.kt)("inlineCode",{parentName:"h3"},"\u5c0f\u9a7c\u5cf0")," \u8def\u7531\u8def\u5f84"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "DynamicApiControllerSettings": {\n "LowercaseRoute": false,\n "KeepName": true,\n "AsLowerCamelCase": true\n }\n}\n')),(0,l.kt)("h2",{id:"519-apidescriptionsettings"},"5.1.9 ",(0,l.kt)("inlineCode",{parentName:"h2"},"[ApiDescriptionSettings]")),(0,l.kt)("p",null,"\u9664\u4e86\u4e0a\u8ff0 ",(0,l.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u63d0\u4f9b\u7684\u914d\u7f6e\u5916\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u8fd8\u63d0\u4f9b\u4e86\u975e\u5e38\u5f3a\u5927\u4e14\u7075\u6d3b\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiDescriptionSettings]")," \u7279\u6027\u3002"),(0,l.kt)("h3",{id:"5191-\u5185\u7f6e\u914d\u7f6e"},"5.1.9.1 \u5185\u7f6e\u914d\u7f6e"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Name"),"\uff1a\u81ea\u5b9a\u4e49\u63a7\u5236\u5668/\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"null")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"KeepName"),"\uff1a\u662f\u5426\u4fdd\u6301\u539f\u6709\u540d\u79f0\u4e0d\u5904\u7406\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"false")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"SplitCamelCase"),"\uff1a\u5207\u5272\u9a86\u9a7c(\u9a7c\u5cf0)/\u5e15\u65af\u5361\u547d\u540d\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"true")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"KeepVerb"),"\uff1a\u662f\u5426\u4fdd\u7559\u52a8\u4f5c\u65b9\u6cd5\u8bf7\u6c42\u8c13\u8bcd\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"false")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Enabled"),"\uff1a\u662f\u5426\u5bfc\u51fa\u63a5\u53e3\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"true")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Module"),"\uff1a\u6a21\u5757\u540d\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"null")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Version"),"\uff1a\u7248\u672c\u53f7\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"null")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Groups"),"\uff1a\u63a5\u53e3\u5206\u7ec4\uff0c\u53ef\u7ed3\u5408 ",(0,l.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e00\u8d77\u4f7f\u7528\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string[]"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"null")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Tags"),"\uff1a\u63a5\u53e3\u6807\u7b7e\uff0c\u53ef\u7ed3\u5408 ",(0,l.kt)("inlineCode",{parentName:"li"},"Swagger")," \u4e00\u8d77\u4f7f\u7528\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string[]"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"null")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Order"),"\uff1a\u914d\u7f6e\u63a7\u5236\u5668/\u52a8\u4f5c\u65b9\u6cd5\u6392\u5e8f"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"LowercaseRoute"),"\uff1a\u662f\u5426\u91c7\u7528\u5c0f\u5199\u8def\u7531\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"true")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"AsLowerCamelCase"),"\uff1a\u542f\u7528\u5c0f\u9a7c\u5cf0\u547d\u540d\uff08\u9996\u5b57\u6bcd\u5c0f\u5199\uff09\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"false")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Area"),"\uff1a\u914d\u7f6e\u533a\u57df\u540d\u79f0\uff0c\u9ed8\u8ba4\u7a7a\uff0c",(0,l.kt)("strong",{parentName:"li"},"\u53ea\u4f5c\u7528\u4e8e\u7c7b\u4e2d\u8d34")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Description"),"\uff1a\u914d\u7f6e\u5355\u4e00\u63a5\u53e3\u66f4\u591a\u63cf\u8ff0\u529f\u80fd\uff0c\u53ea\u5728 ",(0,l.kt)("inlineCode",{parentName:"li"},"\u65b9\u6cd5")," \u4e2d\u6709\u6548\uff0c",(0,l.kt)("strong",{parentName:"li"},"\u4ec5\u9650 v3.3.5+\u7248\u672c\u6709\u6548")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ForceWithRoutePrefix"),"\uff1a\u914d\u7f6e\u662f\u5426\u5f3a\u5236\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"DefaultRoutePrefix"),"\uff0c\u5f53\u63a7\u5236\u5668\u81ea\u5b9a\u4e49\u4e86 ",(0,l.kt)("inlineCode",{parentName:"li"},"[Route]")," \u6709\u6548\uff0c",(0,l.kt)("strong",{parentName:"li"},"\u4ec5\u9650 v3.4.1+\u7248\u672c\u6709\u6548"))),(0,l.kt)("h3",{id:"5192-name-\u914d\u7f6e"},"5.1.9.2 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Name")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Name")," \u53c2\u6570\u53ef\u4ee5\u8986\u76d6\u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u81ea\u52a8\u751f\u6210\u7684\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u3002\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8}",showLineNumbers:!0,"":!0,"{5,8}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(Name = "MyFur")]\n public class FurionAppService : IDynamicApiController\n {\n [ApiDescriptionSettings(Name = "MyGet")]\n public string Get()\n {\n return nameof(Furion);\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/namepz.png")}),(0,l.kt)("h3",{id:"5193-keepname-\u914d\u7f6e"},"5.1.9.3 ",(0,l.kt)("inlineCode",{parentName:"h3"},"KeepName")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"KeepName")," \u53c2\u6570\u53ef\u4ee5\u4fdd\u7559\u539f\u6709\u7684\u63a7\u5236\u5668\u6216\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u3002\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8}",showLineNumbers:!0,"":!0,"{5,8}":!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(KeepName = true)]\n public class FurionAppService : IDynamicApiController\n {\n [ApiDescriptionSettings(KeepName = true)]\n public string Get()\n {\n return nameof(Furion);\n }\n }\n}\n")),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/keepnamepz.png")}),(0,l.kt)("h3",{id:"5194-splitcamelcase-\u914d\u7f6e"},"5.1.9.4 ",(0,l.kt)("inlineCode",{parentName:"h3"},"SplitCamelCase")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"SplitCamelCase")," \u53c2\u6570\u9ed8\u8ba4\u5c06\u9a86\u9a7c(\u9a7c\u5cf0)\u547d\u540d\u5207\u5272\u6210\u591a\u4e2a\u5355\u8bcd\u5e76\u901a\u8fc7\u6307\u5b9a ",(0,l.kt)("inlineCode",{parentName:"p"},"\u5360\u4f4d\u7b26")," \u8fde\u63a5\u8d77\u6765\u3002\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"p"},"\u5360\u4f4d\u7b26")," \u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"-"),"\u3002\u9ed8\u8ba4\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"true"),"\u3002\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8}",showLineNumbers:!0,"":!0,"{5,8}":!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(SplitCamelCase = false)]\n public class MyFurionAppService : IDynamicApiController\n {\n [ApiDescriptionSettings(SplitCamelCase = true)]\n public string ChangeUserName()\n {\n return nameof(Furion);\n }\n }\n}\n")),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/splitnamepz.png")}),(0,l.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"p"},"KeepName")," \u4f18\u5148\u7ea7\u9ad8\u4e8e ",(0,l.kt)("inlineCode",{parentName:"p"},"SplitCamelCase"),"\uff0c\u4e5f\u5c31\u662f ",(0,l.kt)("inlineCode",{parentName:"p"},"KeepName")," \u8bbe\u7f6e\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"true"),"\uff0c\u5219\u4e0d\u4f1a\u5904\u7406 ",(0,l.kt)("inlineCode",{parentName:"p"},"SplitCamelCase")," \u53c2\u6570\u3002")),(0,l.kt)("h3",{id:"5195-keepverb-\u914d\u7f6e"},"5.1.9.5 ",(0,l.kt)("inlineCode",{parentName:"h3"},"KeepVerb")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"KeepVerb")," \u53c2\u6570\u4f5c\u7528\u4e8e\u52a8\u4f5c\u65b9\u6cd5\uff0c\u6807\u8bc6\u662f\u5426\u4fdd\u7559\u52a8\u4f5c\u8c13\u8bcd\u3002\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7}",showLineNumbers:!0,"":!0,"{7}":!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n [ApiDescriptionSettings(KeepVerb = true)]\n public string GetVersion()\n {\n return nameof(Furion);\n }\n }\n}\n")),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/keepverbpz.png")}),(0,l.kt)("h3",{id:"5196-enabled-\u914d\u7f6e"},"5.1.9.6 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Enabled")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Enabled")," \u53c2\u6570\u914d\u7f6e\u63a5\u53e3\u662f\u5426\u5bfc\u51fa\u3002\u901a\u5e38\u7528\u4e8e\u52a8\u4f5c\u65b9\u6cd5\uff0c\u5982\u679c\u7528\u4e8e\u63a7\u5236\u5668\u5b9e\u9645\u4f5c\u7528\u4e0d\u5927\u3002"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {12}",showLineNumbers:!0,"":!0,"{12}":!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string GetVersion()\n {\n return nameof(Furion);\n }\n\n [ApiDescriptionSettings(false)]\n public string NoExport()\n {\n return nameof(Furion);\n }\n }\n}\n")),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/enablepz.png")}),(0,l.kt)("h3",{id:"5197-module-\u914d\u7f6e"},"5.1.9.7 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Module")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Module")," \u53c2\u6570\u53ef\u4ee5\u914d\u7f6e\u8def\u7531\u5206\u79bb\uff0c\u7c7b\u4f3c\u4e8e ",(0,l.kt)("inlineCode",{parentName:"p"},"Mvc \u533a\u57df")," \u7684\u4f5c\u7528\u3002"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8}",showLineNumbers:!0,"":!0,"{5,8}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(Module = "mobile")]\n public class FurionAppService : IDynamicApiController\n {\n [ApiDescriptionSettings(Module = "user")]\n public string GetVersion()\n {\n return nameof(Furion);\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/modulepz.png")}),(0,l.kt)("h3",{id:"5198-version-\u914d\u7f6e"},"5.1.9.8 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Version")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Version")," \u53c2\u6570\u53ef\u4ee5\u914d\u7f6e\u63a5\u53e3\u7248\u672c\uff0c\u540c\u65f6\u53c8\u53ef\u4ee5\u590d\u5199\u7279\u6b8a\u7248\u672c\u547d\u540d\u914d\u7f6e\u3002\u9ed8\u8ba4\u7248\u672c\u5206\u9694\u7b26\u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"@"),"\u3002\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,9-10}",showLineNumbers:!0,"":!0,"{5,9-10}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(Version = "1.0")]\n public class FurionAppService : IDynamicApiController\n {\n // V2.0.0 \u88ab\u590d\u5199\u6210 V2.1.1\n [ApiDescriptionSettings(Version = "2.1.1")]\n public string GetVersionV2_0_0()\n {\n return nameof(Furion);\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/versionpz.png")}),(0,l.kt)("h3",{id:"5199-groups-\u914d\u7f6e"},"5.1.9.9 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Groups")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Groups")," \u914d\u7f6e\u4e3b\u8981\u7528\u4e8e\u914d\u7f6e ",(0,l.kt)("inlineCode",{parentName:"p"},"Swagger")," \u5206\u7ec4\u4fe1\u606f\u3002"),(0,l.kt)("p",null,"\u901a\u8fc7\u914d\u7f6e ",(0,l.kt)("inlineCode",{parentName:"p"},"Groups")," \u53c2\u6570\u53ef\u4ee5\u5c06",(0,l.kt)("inlineCode",{parentName:"p"},"\u63a7\u5236\u5668\u548c\u52a8\u4f5c\u65b9\u6cd5")," \u8fdb\u884c\u5f52\u7c7b\u548c\u591a\u4e2a\u5206\u7ec4\u76f4\u63a5\u5171\u4eab\u3002\u53ef\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiDescriptionSettings(params Groups)]")," \u6784\u9020\u51fd\u6570\u4f20\u5165\u6216\u6307\u5b9a ",(0,l.kt)("inlineCode",{parentName:"p"},"Groups")," \u53c2\u6570\u914d\u7f6e\u63a5\u53e3\u662f\u5426\u5bfc\u51fa\u3002\u901a\u5e38\u7528\u4e8e\u52a8\u4f5c\u65b9\u6cd5\uff0c\u5982\u679c\u7528\u4e8e\u63a7\u5236\u5668\u5b9e\u9645\u4f5c\u7528\u4e0d\u5927\u3002"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,13}",showLineNumbers:!0,"":!0,"{5,13}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings("Default", "Common")]\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n [ApiDescriptionSettings("Custom")]\n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/dfz.gif")}),(0,l.kt)("h3",{id:"51910-tag-\u914d\u7f6e"},"5.1.9.10 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Tag")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Tag")," \u914d\u7f6e\u4e3b\u8981\u7528\u4e8e\u914d\u7f6e ",(0,l.kt)("inlineCode",{parentName:"p"},"Swagger")," \u6807\u7b7e\u5206\u7ec4\u4fe1\u606f\u53ca\u5408\u5e76\u6807\u7b7e\u3002\u4e5f\u5c31\u662f ",(0,l.kt)("inlineCode",{parentName:"p"},"\u7ec4\u4e2d\u7ec4"),":"),(0,l.kt)(o.Z,{defaultValue:"tag1",values:[{label:"\u6807\u7b7e\u547d\u540d",value:"tag1"},{label:"\u5408\u5e76\u6807\u7b7e",value:"tag2"}],mdxType:"Tabs"},(0,l.kt)(p.Z,{value:"tag1",mdxType:"TabItem"},(0,l.kt)("h4",{id:"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d"},"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n\n public class TestAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n}\n")),(0,l.kt)("h4",{id:"\u8d34\u6807\u7b7e\u4e4b\u540e"},"\u8d34\u6807\u7b7e\u4e4b\u540e"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,19}",showLineNumbers:!0,"":!0,"{5,19}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(Tag = "\u5206\u7ec4\u4e00")]\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n\n [ApiDescriptionSettings(Tag = "\u5206\u7ec4\u4e8c")]\n public class TestAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/tag1.png")})),(0,l.kt)(p.Z,{value:"tag2",mdxType:"TabItem"},(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,19}",showLineNumbers:!0,"":!0,"{5,19}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(Tag = "\u5408\u5e76\u6240\u6709\u6807\u7b7e")]\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n\n [ApiDescriptionSettings(Tag = "\u5408\u5e76\u6240\u6709\u6807\u7b7e")]\n public class TestAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,l.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,l.kt)("img",{src:(0,r.Z)("img/tag2.png")}))),(0,l.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,l.kt)("p",{parentName:"admonition"},"\u5982\u679c ",(0,l.kt)("inlineCode",{parentName:"p"},"Tag")," \u540d\u5b57\u4e00\u6837\uff0c\u5219\u4f1a\u81ea\u52a8\u5408\u5e76\uff0c\u5426\u5219\u53ea\u662f\u547d\u540d\u3002")),(0,l.kt)("h2",{id:"5110-dynamicapicontrollersettings-\u914d\u7f6e"},"5.1.10 ",(0,l.kt)("inlineCode",{parentName:"h2"},"DynamicApiControllerSettings")," \u914d\u7f6e"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fd8\u63d0\u4f9b\u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a5\u53e3\u4e00\u4e9b\u5168\u5c40\u914d\u7f6e\u9009\u9879\uff0c\u5982\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"DefaultRoutePrefix"),"\uff1a\u9ed8\u8ba4\u8def\u7531\u524d\u7f00\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"api")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"DefaultHttpMethod"),"\uff1a\u9ed8\u8ba4\u8bf7\u6c42\u8c13\u8bcd\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"POST")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"DefaultModule"),"\uff1a\u9ed8\u8ba4\u6a21\u5757\u540d\u79f0\uff08\u533a\u57df\uff09\uff0c\u53ef\u7528\u4f5c\u63a5\u53e3\u7248\u672c\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"v1")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"LowercaseRoute"),"\uff1a\u5c0f\u5199\u8def\u7531\u683c\u5f0f\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"true")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"AsLowerCamelCase"),"\uff1a\u542f\u7528\u5c0f\u9a7c\u5cf0\u547d\u540d\uff08\u9996\u5b57\u6bcd\u5c0f\u5199\uff09\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"false")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"KeepVerb"),"\uff1a\u662f\u5426\u4fdd\u7559\u52a8\u4f5c\u8c13\u8bcd\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"false")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"KeepName"),"\uff1a\u662f\u5426\u4fdd\u7559\u9ed8\u8ba4\u540d\u79f0\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"fasle")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"CamelCaseSeparator"),"\uff1a\u9a86\u9a7c(\u9a7c\u5cf0)/\u5e15\u65af\u5361\u547d\u540d\u5206\u9694\u7b26\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"-")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"VersionSeparator"),"\uff1a\u7248\u672c\u5206\u9694\u7b26\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"@")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ModelToQuery"),"\uff1a",(0,l.kt)("inlineCode",{parentName:"li"},"GET/HEAD")," \u8bf7\u6c42\u5c06 ",(0,l.kt)("inlineCode",{parentName:"li"},"\u7c7b\u7c7b\u578b\u53c2\u6570\u8f6c\u67e5\u8be2\u53c2\u6570"),"\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"false")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"SupportedMvcController"),"\uff1a\u662f\u5426\u652f\u6301 ",(0,l.kt)("inlineCode",{parentName:"li"},"Mvc Controller")," \u52a8\u6001\u914d\u7f6e\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"false")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"UrlParameterization"),"\uff1a\u8def\u7531\u53c2\u6570\u91c7\u7528 ",(0,l.kt)("inlineCode",{parentName:"li"},"[FromQuery]")," \u5316\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"false"),"\uff08",(0,l.kt)("inlineCode",{parentName:"li"},"[FromRoute]")," \u65b9\u5f0f\uff09"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"DefaultArea"),"\uff1a\u914d\u7f6e\u9ed8\u8ba4\u533a\u57df\uff0c\u9ed8\u8ba4 ",(0,l.kt)("inlineCode",{parentName:"li"},"null")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ForceWithRoutePrefix"),"\uff1a\u914d\u7f6e\u662f\u5426\u5f3a\u5236\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"DefaultRoutePrefix"),"\uff0c\u5f53\u63a7\u5236\u5668\u81ea\u5b9a\u4e49\u4e86 ",(0,l.kt)("inlineCode",{parentName:"li"},"[Route]")," \u6709\u6548\uff0c",(0,l.kt)("strong",{parentName:"li"},"\u4ec5\u9650 v3.4.1+\u7248\u672c\u6709\u6548")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"AbandonControllerAffixes"),"\uff1a\u9ed8\u8ba4\u53bb\u9664\u63a7\u5236\u5668\u540d\u79f0\u524d\u540e\u7f00\u5217\u8868\u540d\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string[]"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"AppServices")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"AppService")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"ApiController")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Controller")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Services")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Service")))),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"AbandonActionAffixes"),"\uff1a\u9ed8\u8ba4\u53bb\u9664\u52a8\u4f5c\u65b9\u6cd5\u540d\u79f0\u524d\u540e\u7f00\u5217\u8868\u540d\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string[]"),"\uff0c\u9ed8\u8ba4\uff1a",(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Async")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"VerbToHttpMethods"),"\uff1a\u590d\u5199\u9ed8\u8ba4\u65b9\u6cd5\u540d\u8f6c ",(0,l.kt)("inlineCode",{parentName:"li"},"[HttpMethod]")," \u89c4\u5219\uff0c",(0,l.kt)("inlineCode",{parentName:"li"},"string[][]")," \u4e8c\u7ef4\u6570\u7ec4\u7c7b\u578b\uff0c\u5185\u7f6e\u5339\u914d\u89c4\u5219\u4e3a\uff1a",(0,l.kt)("pre",{parentName:"li"},(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'["post"] = "POST",\n["add"] = "POST",\n["create"] = "POST",\n["insert"] = "POST",\n["submit"] = "POST",\n["get"] = "GET",\n["find"] = "GET",\n["fetch"] = "GET",\n["query"] = "GET",\n["getlist"] = "GET",\n["getall"] = "GET",\n["put"] = "PUT",\n["update"] = "PUT",\n["delete"] = "DELETE",\n["remove"] = "DELETE",\n["clear"] = "DELETE",\n["patch"] = "PATCH"\n')),(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},"\u590d\u5199\u793a\u4f8b")),(0,l.kt)("pre",{parentName:"li"},(0,l.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'"DynamicApiControllerSettings": {\n "VerbToHttpMethods": [\n [ "getall", "HEAD" ], // => getall \u4f1a\u88ab\u590d\u5199\u4e3a `[HttpHead]`\n [ "other", "PUT" ] // => \u65b0\u589e\u4e00\u6761\u65b0\u89c4\u5219\uff0c\u6bd4\u5982\uff0c\u4e00 `[other]` \u5f00\u5934\u4f1a\u8f6c\u6362\u4e3a `[HttpPut]` \u8bf7\u6c42\n ]\n }\n')))))),(0,l.kt)("h3",{id:"51101-\u652f\u6301-mvc-\u63a7\u5236\u5668-\u52a8\u6001\u914d\u7f6e"},"5.1.10.1 \u652f\u6301 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Mvc \u63a7\u5236\u5668")," \u52a8\u6001\u914d\u7f6e"),(0,l.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u63a5\u53e3\u4e0d\u5bf9 ",(0,l.kt)("inlineCode",{parentName:"p"},"ControllerBase")," \u7c7b\u578b\u8fdb\u884c\u4efb\u4f55\u5904\u7406\u3002\u5f53\u7136\uff0c\u6211\u4eec\u4e5f\u53ef\u4ee5\u624b\u52a8\u542f\u7528 ",(0,l.kt)("inlineCode",{parentName:"p"},"ControllerBase")," \u652f\u6301\u3002"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers {2-4} title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,"{2-4}":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "DynamicApiControllerSettings": {\n "SupportedMvcController": true\n }\n}\n')),(0,l.kt)("p",null,"\u8bbe\u7f6e ",(0,l.kt)("inlineCode",{parentName:"p"},"SupportedMvcController: true")," \u540e\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"Mvc ControllerBase")," \u7c7b\u578b\u4e5f\u80fd\u548c\u52a8\u6001 ",(0,l.kt)("inlineCode",{parentName:"p"},"WebAPI")," \u4e00\u6837\u7684\u7075\u6d3b\u4e86\u3002\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},"using Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n public class MvcController : ControllerBase\n {\n public string Get()\n {\n return nameof(Furion);\n }\n }\n}\n\n")),(0,l.kt)("admonition",{title:"\u6ce8\u610f\u4e8b\u9879",type:"warning"},(0,l.kt)("p",{parentName:"admonition"},"\u542f\u7528\u8be5\u914d\u7f6e\u540e\uff0c\u5982\u679c ",(0,l.kt)("inlineCode",{parentName:"p"},"Mvc \u63a7\u5236\u5668")," \u6ca1\u6709\u4efb\u4f55 ",(0,l.kt)("inlineCode",{parentName:"p"},"[Route]")," \u7279\u6027\uff0c\u4f46\u662f\u8d34\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiController]")," \u7279\u6027\u5c06\u4f1a\u62a5\u9519\u3002\u539f\u56e0\u662f ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiController]")," \u7279\u6027\u5185\u90e8\u505a\u4e86\u8def\u7531\u7279\u6027\u68c0\u6d4b\u3002\u6240\u4ee5\u5efa\u8bae\u4f7f\u7528 ",(0,l.kt)("inlineCode",{parentName:"p"},"[ApiDataValidation]")," \u4ee3\u66ff\u3002"),(0,l.kt)("p",{parentName:"admonition"},"\u67e5\u770b ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/dotnet/aspnetcore/blob/c565386a3ed135560bc2e9017aa54a950b4e35dd/src/Mvc/Mvc.Core/src/ApplicationModels/ApiBehaviorApplicationModelProvider.cs#L90"},"ASP.NET Core - ApiBehaviorApplicationModelProvider \u6e90\u7801"))),(0,l.kt)("h2",{id:"5111-\u5173\u4e8e-aop-\u62e6\u622a"},"5.1.11 \u5173\u4e8e AOP \u62e6\u622a"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"\u52a8\u6001WebAPI")," \u652f\u6301 ",(0,l.kt)("inlineCode",{parentName:"p"},"Controller")," \u7684\u6240\u6709\u8fc7\u6ee4\u5668/\u7b5b\u9009\u5668\u62e6\u622a\uff0c\u4e5f\u5c31\u662f\u53ef\u4ee5\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"ActionFilter"),"\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"ResultFilter")," \u8fdb\u884c\u62e6\u622a\u64cd\u4f5c\u3002\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3}",showLineNumbers:!0,"":!0,"{1,3}":!0},"public class SampleAsyncActionFilter : IAsyncActionFilter\n{\n public async Task OnActionExecutionAsync(ActionExecutingContext context,ActionExecutionDelegate next)\n {\n // \u62e6\u622a\u4e4b\u524d\n\n var resultContext = await next();\n\n // \u62e6\u622a\u4e4b\u540e\n\n // \u5f02\u5e38\u62e6\u622a\n if(resultContext.Exception != null)\n {\n\n }\n }\n}\n")),(0,l.kt)("p",null,"\u8be6\u7ec6\u7528\u6cd5\u53ef\u53c2\u89c1 ",(0,l.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/mvc/controllers/filters?view=aspnetcore-5.0"},"ASP.NET Core 5.0 - \u7b5b\u9009\u5668")),(0,l.kt)("h2",{id:"5112-\u8bbe\u7f6e-api-\u8d85\u65f6\u8bf7\u6c42\u65f6\u95f4"},"5.1.12 \u8bbe\u7f6e ",(0,l.kt)("inlineCode",{parentName:"h2"},"api")," \u8d85\u65f6\u8bf7\u6c42\u65f6\u95f4"),(0,l.kt)("p",null,"\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"p"},".UseKestrel")," \u914d\u7f6e\u5373\u53ef\uff0c\u5982\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},".NET5 \u7248\u672c"))),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8-12}",showLineNumbers:!0,"":!0,"{8-12}":!0},"public static IHostBuilder CreateHostBuilder(string[] args)\n{\n return Host.CreateDefaultBuilder(args)\n .ConfigureWebHostDefaults(webBuilder =>\n {\n webBuilder.Inject()\n .UseStartup()\n .UseKestrel(option =>\n {\n option.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(20);\n option.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(20);\n });\n });\n}\n")),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},".NET6 \u7248\u672c"))),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-7}",showLineNumbers:!0,"":!0,"{3-7}":!0},"var app = builder.Build();\n\napp.Configuration.Get().ConfigureKestrel(x =>\n{\n x.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(20);\n x.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(20);\n});\n")),(0,l.kt)("h2",{id:"5113-\u53cd\u9988\u4e0e\u5efa\u8bae"},"5.1.13 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,l.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,l.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,l.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}C.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return u},kt:function(){return k}});var i=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function l(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function r(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var p=i.createContext({}),m=function(e){var n=i.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):r(r({},n),e)),t},u=function(e){var n=m(e.components);return i.createElement(p.Provider,{value:n},e.children)},s={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},d=i.forwardRef((function(e,n){var t=e.components,a=e.mdxType,l=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),d=m(t),k=a,c=d["".concat(p,".").concat(k)]||d[k]||s[k]||l;return t?i.createElement(c,r(r({ref:n},u),{},{components:t})):i.createElement(c,r({ref:n},u))}));function k(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var l=t.length,r=new Array(l);r[0]=d;var o={};for(var p in n)hasOwnProperty.call(n,p)&&(o[p]=n[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,r[1]=o;for(var m=2;m { user, user2 });\n\n// \u793a\u4f8b\u4e09\nrepository.Insert(new[] {user, user2 });\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.InsertAsync(user, user2);\n\n// \u793a\u4f8b\u4e8c\nawait repository.InsertAsync(new List { user, user2 });\n\n// \u793a\u4f8b\u4e09\nawait repository.InsertAsync(new[] {user, user2 });\n")),(0,s.kt)("h2",{id:"954-\u65b0\u589e\u591a\u6761\u7acb\u5373\u63d0\u4ea4"},"9.5.4 \u65b0\u589e\u591a\u6761\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.InsertNow(user, user2);\n\n// \u793a\u4f8b\u4e8c\nrepository.InsertNow(new List { user, user2 });\n\n// \u793a\u4f8b\u4e09\nrepository.InsertNow(new[] {user, user2 });\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.InsertNowAsync(user, user2);\n\n// \u793a\u4f8b\u4e8c\nawait repository.InsertNowAsync(new List { user, user2 });\n\n// \u793a\u4f8b\u4e09\nawait repository.InsertNowAsync(new[] {user, user2 });\n")),(0,s.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,s.kt)("p",{parentName:"admonition"},"\u6240\u6709\u5e26 ",(0,s.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u8868\u793a\u7acb\u5373\u63d0\u4ea4\u5230\u6570\u636e\u5e93\uff0c\u4e5f\u5c31\u662f\u7acb\u5373\u8c03\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216 ",(0,s.kt)("inlineCode",{parentName:"p"},"SaveChangesAsync"),"\u3002")),(0,s.kt)("h2",{id:"955-\u5ffd\u7565\u7a7a\u503c\u65b0\u589e"},"9.5.5 \u5ffd\u7565\u7a7a\u503c\u65b0\u589e"),(0,s.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,s.kt)("inlineCode",{parentName:"p"},"EFCore")," \u65b0\u589e\u4f1a\u63d2\u5165\u5168\u90e8\u5217\uff08\u9664\u5b9e\u4f53\u8ddf\u8e2a\u65b9\u5f0f\u4ee5\u5916\uff09\uff0c\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u5e0c\u671b ",(0,s.kt)("inlineCode",{parentName:"p"},"Null")," \u503c\u65e0\u9700\u63d2\u5165\uff0c\u8fd9\u662f\u6211\u4eec\u53ea\u9700\u8981\u5728\u66f4\u65b0\u65f6\u5019\u914d\u7f6e ",(0,s.kt)("inlineCode",{parentName:"p"},"ignoreNullValues")," \u53c2\u6570\u5373\u53ef\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"repository.Insert(entity, ignoreNullValues: true);\n")),(0,s.kt)("p",null,"\u4e5f\u53ef\u4ee5\u5168\u5c40\u914d\u7f6e\uff0c\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u7684\u6d3e\u751f\u7c7b\u7684\u6784\u9020\u51fd\u6570\u4e2d\u542f\u7528\u5373\u53ef\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11}",showLineNumbers:!0,"":!0,"{11}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]\n public class DefaultDbContext : AppDbContext\n {\n public DefaultDbContext(DbContextOptions options) : base(options)\n {\n InsertOrUpdateIgnoreNullValues = true;\n }\n }\n}\n')),(0,s.kt)("h2",{id:"956-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.5.6 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,s.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,s.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,s.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return l},kt:function(){return m}});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function s(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function a(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var u=r.createContext({}),p=function(e){var n=r.useContext(u),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},l=function(e){var n=p(e.components);return r.createElement(u.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,s=e.originalType,u=e.parentName,l=i(e,["components","mdxType","originalType","parentName"]),d=p(t),m=o,y=d["".concat(u,".").concat(m)]||d[m]||c[m]||s;return t?r.createElement(y,a(a({ref:n},l),{},{components:t})):r.createElement(y,a({ref:n},l))}));function m(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var s=t.length,a=new Array(s);a[0]=d;var i={};for(var u in n)hasOwnProperty.call(n,u)&&(i[u]=n[u]);i.originalType=e,i.mdxType="string"==typeof e?e:o,a[1]=i;for(var p=2;p=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var u=r.createContext({}),p=function(e){var n=r.useContext(u),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},l=function(e){var n=p(e.components);return r.createElement(u.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,s=e.originalType,u=e.parentName,l=i(e,["components","mdxType","originalType","parentName"]),d=p(t),m=o,y=d["".concat(u,".").concat(m)]||d[m]||c[m]||s;return t?r.createElement(y,a(a({ref:n},l),{},{components:t})):r.createElement(y,a({ref:n},l))}));function m(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var s=t.length,a=new Array(s);a[0]=d;var i={};for(var u in n)hasOwnProperty.call(n,u)&&(i[u]=n[u]);i.originalType=e,i.mdxType="string"==typeof e?e:o,a[1]=i;for(var p=2;p { user, user2 });\n\n// \u793a\u4f8b\u4e09\nrepository.Insert(new[] {user, user2 });\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.InsertAsync(user, user2);\n\n// \u793a\u4f8b\u4e8c\nawait repository.InsertAsync(new List { user, user2 });\n\n// \u793a\u4f8b\u4e09\nawait repository.InsertAsync(new[] {user, user2 });\n")),(0,s.kt)("h2",{id:"954-\u65b0\u589e\u591a\u6761\u7acb\u5373\u63d0\u4ea4"},"9.5.4 \u65b0\u589e\u591a\u6761\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.InsertNow(user, user2);\n\n// \u793a\u4f8b\u4e8c\nrepository.InsertNow(new List { user, user2 });\n\n// \u793a\u4f8b\u4e09\nrepository.InsertNow(new[] {user, user2 });\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.InsertNowAsync(user, user2);\n\n// \u793a\u4f8b\u4e8c\nawait repository.InsertNowAsync(new List { user, user2 });\n\n// \u793a\u4f8b\u4e09\nawait repository.InsertNowAsync(new[] {user, user2 });\n")),(0,s.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,s.kt)("p",{parentName:"admonition"},"\u6240\u6709\u5e26 ",(0,s.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u8868\u793a\u7acb\u5373\u63d0\u4ea4\u5230\u6570\u636e\u5e93\uff0c\u4e5f\u5c31\u662f\u7acb\u5373\u8c03\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216 ",(0,s.kt)("inlineCode",{parentName:"p"},"SaveChangesAsync"),"\u3002")),(0,s.kt)("h2",{id:"955-\u5ffd\u7565\u7a7a\u503c\u65b0\u589e"},"9.5.5 \u5ffd\u7565\u7a7a\u503c\u65b0\u589e"),(0,s.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,s.kt)("inlineCode",{parentName:"p"},"EFCore")," \u65b0\u589e\u4f1a\u63d2\u5165\u5168\u90e8\u5217\uff08\u9664\u5b9e\u4f53\u8ddf\u8e2a\u65b9\u5f0f\u4ee5\u5916\uff09\uff0c\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u5e0c\u671b ",(0,s.kt)("inlineCode",{parentName:"p"},"Null")," \u503c\u65e0\u9700\u63d2\u5165\uff0c\u8fd9\u662f\u6211\u4eec\u53ea\u9700\u8981\u5728\u66f4\u65b0\u65f6\u5019\u914d\u7f6e ",(0,s.kt)("inlineCode",{parentName:"p"},"ignoreNullValues")," \u53c2\u6570\u5373\u53ef\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"repository.Insert(entity, ignoreNullValues: true);\n")),(0,s.kt)("p",null,"\u4e5f\u53ef\u4ee5\u5168\u5c40\u914d\u7f6e\uff0c\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u7684\u6d3e\u751f\u7c7b\u7684\u6784\u9020\u51fd\u6570\u4e2d\u542f\u7528\u5373\u53ef\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11}",showLineNumbers:!0,"":!0,"{11}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]\n public class DefaultDbContext : AppDbContext\n {\n public DefaultDbContext(DbContextOptions options) : base(options)\n {\n InsertOrUpdateIgnoreNullValues = true;\n }\n }\n}\n')),(0,s.kt)("h2",{id:"956-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.5.6 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,s.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,s.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,s.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/6875c492.9175ef0f.js b/handbook/build/assets/js/6875c492.9175ef0f.js new file mode 100644 index 0000000000..4e3102a4f0 --- /dev/null +++ b/handbook/build/assets/js/6875c492.9175ef0f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[8610],{9703:function(e,t,a){a.d(t,{Z:function(){return i}});var n=a(7294),r=a(5999),l=a(2244);function i(e){var t=e.metadata,a=t.previousPage,i=t.nextPage;return n.createElement("nav",{className:"pagination-nav","aria-label":(0,r.I)({id:"theme.blog.paginator.navAriaLabel",message:"Blog list page navigation",description:"The ARIA label for the blog pagination"})},a&&n.createElement(l.Z,{permalink:a,title:n.createElement(r.Z,{id:"theme.blog.paginator.newerEntries",description:"The label used to navigate to the newer blog posts page (previous page)"},"Newer Entries")}),i&&n.createElement(l.Z,{permalink:i,title:n.createElement(r.Z,{id:"theme.blog.paginator.olderEntries",description:"The label used to navigate to the older blog posts page (next page)"},"Older Entries"),isNext:!0}))}},9985:function(e,t,a){a.d(t,{Z:function(){return i}});var n=a(7294),r=a(9460),l=a(390);function i(e){var t=e.items,a=e.component,i=void 0===a?l.Z:a;return n.createElement(n.Fragment,null,t.map((function(e){var t=e.content;return n.createElement(r.n,{key:t.metadata.permalink,content:t},n.createElement(i,null,n.createElement(t,null)))})))}},1714:function(e,t,a){a.r(t),a.d(t,{default:function(){return f}});var n=a(7294),r=a(4334),l=a(5999),i=a(8824),o=a(833),s=a(5281),g=a(9960),c=a(9058),u=a(9703),m=a(197),p=a(9985);function d(e){var t,a=(t=(0,i.c)().selectMessage,function(e){return t(e,(0,l.I)({id:"theme.blog.post.plurals",description:'Pluralized label for "{count} posts". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',message:"One post|{count} posts"},{count:e}))});return(0,l.I)({id:"theme.blog.tagTitle",description:"The title of the page for a blog tag",message:'{nPosts} tagged with "{tagName}"'},{nPosts:a(e.count),tagName:e.label})}function h(e){var t=d(e.tag);return n.createElement(n.Fragment,null,n.createElement(o.d,{title:t}),n.createElement(m.Z,{tag:"blog_tags_posts"}))}function b(e){var t=e.tag,a=e.items,r=e.sidebar,i=e.listMetadata,o=d(t);return n.createElement(c.Z,{sidebar:r},n.createElement("header",{className:"margin-bottom--xl"},n.createElement("h1",null,o),n.createElement(g.Z,{href:t.allTagsPath},n.createElement(l.Z,{id:"theme.tags.tagsPageLink",description:"The label of the link targeting the tag list page"},"View All Tags"))),n.createElement(p.Z,{items:a}),n.createElement(u.Z,{metadata:i}))}function f(e){return n.createElement(o.FG,{className:(0,r.Z)(s.k.wrapper.blogPages,s.k.page.blogTagPostListPage)},n.createElement(h,e),n.createElement(b,e))}}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/6875c492.d10d6e87.js b/handbook/build/assets/js/6875c492.d10d6e87.js deleted file mode 100644 index 6e55da149e..0000000000 --- a/handbook/build/assets/js/6875c492.d10d6e87.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[8610],{1052:function(e,t,a){a.d(t,{Z:function(){return i}});var n=a(7294),r=a(1614),l=a(3500);function i(e){var t=e.metadata,a=t.previousPage,i=t.nextPage;return n.createElement("nav",{className:"pagination-nav","aria-label":(0,r.I)({id:"theme.blog.paginator.navAriaLabel",message:"Blog list page navigation",description:"The ARIA label for the blog pagination"})},a&&n.createElement(l.Z,{permalink:a,title:n.createElement(r.Z,{id:"theme.blog.paginator.newerEntries",description:"The label used to navigate to the newer blog posts page (previous page)"},"Newer Entries")}),i&&n.createElement(l.Z,{permalink:i,title:n.createElement(r.Z,{id:"theme.blog.paginator.olderEntries",description:"The label used to navigate to the older blog posts page (next page)"},"Older Entries"),isNext:!0}))}},6903:function(e,t,a){a.d(t,{Z:function(){return i}});var n=a(7294),r=a(7762),l=a(1827);function i(e){var t=e.items,a=e.component,i=void 0===a?l.Z:a;return n.createElement(n.Fragment,null,t.map((function(e){var t=e.content;return n.createElement(r.n,{key:t.metadata.permalink,content:t},n.createElement(i,null,n.createElement(t,null)))})))}},5462:function(e,t,a){a.r(t),a.d(t,{default:function(){return f}});var n=a(7294),r=a(4334),l=a(1614),i=a(7880),o=a(4873),s=a(8015),g=a(8746),c=a(1485),u=a(1052),m=a(6145),p=a(6903);function d(e){var t,a=(t=(0,i.c)().selectMessage,function(e){return t(e,(0,l.I)({id:"theme.blog.post.plurals",description:'Pluralized label for "{count} posts". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',message:"One post|{count} posts"},{count:e}))});return(0,l.I)({id:"theme.blog.tagTitle",description:"The title of the page for a blog tag",message:'{nPosts} tagged with "{tagName}"'},{nPosts:a(e.count),tagName:e.label})}function h(e){var t=d(e.tag);return n.createElement(n.Fragment,null,n.createElement(o.d,{title:t}),n.createElement(m.Z,{tag:"blog_tags_posts"}))}function b(e){var t=e.tag,a=e.items,r=e.sidebar,i=e.listMetadata,o=d(t);return n.createElement(c.Z,{sidebar:r},n.createElement("header",{className:"margin-bottom--xl"},n.createElement("h1",null,o),n.createElement(g.Z,{href:t.allTagsPath},n.createElement(l.Z,{id:"theme.tags.tagsPageLink",description:"The label of the link targeting the tag list page"},"View All Tags"))),n.createElement(p.Z,{items:a}),n.createElement(u.Z,{metadata:i}))}function f(e){return n.createElement(o.FG,{className:(0,r.Z)(s.k.wrapper.blogPages,s.k.page.blogTagPostListPage)},n.createElement(h,e),n.createElement(b,e))}}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/68ec177d.96ded009.js b/handbook/build/assets/js/68ec177d.96ded009.js deleted file mode 100644 index cbba668b46..0000000000 --- a/handbook/build/assets/js/68ec177d.96ded009.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[223],{5593:function(e,r,n){n.r(r),n.d(r,{assets:function(){return u},contentTitle:function(){return s},default:function(){return d},frontMatter:function(){return l},metadata:function(){return c},toc:function(){return p}});var t=n(3117),a=n(102),o=(n(7294),n(3905)),i=["components"],l={id:"sparetime",title:"12. SpareTime \u9759\u6001\u7c7b",sidebar_label:"12. SpareTime \u9759\u6001\u7c7b"},s=void 0,c={unversionedId:"global/sparetime",id:"global/sparetime",title:"12. SpareTime \u9759\u6001\u7c7b",description:"SpareTime \u9759\u6001\u7c7b\u63d0\u4f9b\u4e86\u4e00\u4e9b\u65b9\u6cd5\u65b9\u4fbf\u521d\u59cb\u5316\u548c\u7ba1\u7406\u4efb\u52a1",source:"@site/docs/global/sparetime.mdx",sourceDirName:"global",slug:"/global/sparetime",permalink:"/furion/docs/global/sparetime",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/global/sparetime.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"sparetime",title:"12. SpareTime \u9759\u6001\u7c7b",sidebar_label:"12. SpareTime \u9759\u6001\u7c7b"},sidebar:"global",previous:{title:"11. Scoped \u9759\u6001\u7c7b",permalink:"/furion/docs/global/scoped"},next:{title:"13. FS \u9759\u6001\u7c7b",permalink:"/furion/docs/global/fs"}},u={},p=[{value:"12.1 \u521d\u59cb\u5316\u4efb\u52a1",id:"121-\u521d\u59cb\u5316\u4efb\u52a1",level:2},{value:"12.2 \u5b9e\u73b0\u540e\u53f0\u6267\u884c",id:"122-\u5b9e\u73b0\u540e\u53f0\u6267\u884c",level:2},{value:"12.3 \u5f00\u59cb\u4e00\u4e2a\u4efb\u52a1",id:"123-\u5f00\u59cb\u4e00\u4e2a\u4efb\u52a1",level:2},{value:"12.4 \u6682\u505c\u4e00\u4e2a\u4efb\u52a1",id:"124-\u6682\u505c\u4e00\u4e2a\u4efb\u52a1",level:2},{value:"12.5 \u53d6\u6d88\u4e00\u4e2a\u4efb\u52a1",id:"125-\u53d6\u6d88\u4e00\u4e2a\u4efb\u52a1",level:2},{value:"12.6 \u9500\u6bc1\u6240\u6709\u4efb\u52a1",id:"126-\u9500\u6bc1\u6240\u6709\u4efb\u52a1",level:2},{value:"12.7 \u83b7\u53d6\u6240\u6709\u4efb\u52a1",id:"127-\u83b7\u53d6\u6240\u6709\u4efb\u52a1",level:2},{value:"12.8 \u83b7\u53d6\u5355\u4e2a\u4efb\u52a1",id:"128-\u83b7\u53d6\u5355\u4e2a\u4efb\u52a1",level:2},{value:"12.9 \u89e3\u6790 Cron \u8868\u8fbe\u5f0f",id:"129-\u89e3\u6790-cron-\u8868\u8fbe\u5f0f",level:2},{value:"12.10 BackgroundService \u95f4\u9694\u5b9a\u65f6\u4efb\u52a1",id:"1210-backgroundservice-\u95f4\u9694\u5b9a\u65f6\u4efb\u52a1",level:2},{value:"12.11 BackgroundService Cron \u5b9a\u65f6\u4efb\u52a1",id:"1211-backgroundservice-cron-\u5b9a\u65f6\u4efb\u52a1",level:2}],m={toc:p};function d(e){var r=e.components,n=(0,a.Z)(e,i);return(0,o.kt)("wrapper",(0,t.Z)({},m,n,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"SpareTime")," \u9759\u6001\u7c7b\u63d0\u4f9b\u4e86\u4e00\u4e9b\u65b9\u6cd5\u65b9\u4fbf\u521d\u59cb\u5316\u548c\u7ba1\u7406\u4efb\u52a1"),(0,o.kt)("h2",{id:"121-\u521d\u59cb\u5316\u4efb\u52a1"},"12.1 \u521d\u59cb\u5316\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u5f00\u542f\u95f4\u9694\u4efb\u52a1\nSpareTime.Do(interval, [options]);\n\n// \u5f00\u542f Cron \u8868\u8fbe\u5f0f\u4efb\u52a1\nSpareTime.Do(expression, [options]);\n\n// \u53ea\u6267\u884c\u4e00\u6b21\u4efb\u52a1\nSpareTime.DoOnce(interval, [options]);\n\n// \u5b9e\u73b0\u81ea\u5b9a\u4e49\u4efb\u52a1\nSpareTime.Do(()=>{\n return DateTime.Now.AddMinutes(10);\n},[options]);\n")),(0,o.kt)("h2",{id:"122-\u5b9e\u73b0\u540e\u53f0\u6267\u884c"},"12.2 \u5b9e\u73b0\u540e\u53f0\u6267\u884c"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u5b9e\u73b0\u540e\u53f0\u6267\u884c\nSpareTime.DoIt(()=>{});\n")),(0,o.kt)("h2",{id:"123-\u5f00\u59cb\u4e00\u4e2a\u4efb\u52a1"},"12.3 \u5f00\u59cb\u4e00\u4e2a\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SpareTime.Start("\u4efb\u52a1\u6807\u8bc6");\n')),(0,o.kt)("h2",{id:"124-\u6682\u505c\u4e00\u4e2a\u4efb\u52a1"},"12.4 \u6682\u505c\u4e00\u4e2a\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SpareTime.Stop("\u4efb\u52a1\u6807\u8bc6");\n// \u8fd8\u53ef\u4ee5\u6807\u8bb0\u4e00\u4e2a\u4efb\u52a1\u6267\u884c\u5931\u8d25\nSpareTime.Stop("\u4efb\u52a1\u6807\u8bc6", true);\n')),(0,o.kt)("h2",{id:"125-\u53d6\u6d88\u4e00\u4e2a\u4efb\u52a1"},"12.5 \u53d6\u6d88\u4e00\u4e2a\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SpareTime.Cancel("\u4efb\u52a1\u540d\u79f0");\n')),(0,o.kt)("h2",{id:"126-\u9500\u6bc1\u6240\u6709\u4efb\u52a1"},"12.6 \u9500\u6bc1\u6240\u6709\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"SpareTime.Dispose();\n")),(0,o.kt)("h2",{id:"127-\u83b7\u53d6\u6240\u6709\u4efb\u52a1"},"12.7 \u83b7\u53d6\u6240\u6709\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var workers = SpareTime.GetWorkers();\n")),(0,o.kt)("h2",{id:"128-\u83b7\u53d6\u5355\u4e2a\u4efb\u52a1"},"12.8 \u83b7\u53d6\u5355\u4e2a\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var worker = SpareTime.GetWorker("workerName");\n')),(0,o.kt)("h2",{id:"129-\u89e3\u6790-cron-\u8868\u8fbe\u5f0f"},"12.9 \u89e3\u6790 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Cron")," \u8868\u8fbe\u5f0f"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var nextTime = SpareTime.GetCronNextOccurrence("* * * * *");\n')),(0,o.kt)("h2",{id:"1210-backgroundservice-\u95f4\u9694\u5b9a\u65f6\u4efb\u52a1"},"12.10 ",(0,o.kt)("inlineCode",{parentName:"h2"},"BackgroundService")," \u95f4\u9694\u5b9a\u65f6\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u95f4\u9694\u6267\u884c\u4efb\u52a1\nawait SpareTime.DoAsync(1000, () =>\n{\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n}, stoppingToken);\n')),(0,o.kt)("h2",{id:"1211-backgroundservice-cron-\u5b9a\u65f6\u4efb\u52a1"},"12.11 ",(0,o.kt)("inlineCode",{parentName:"h2"},"BackgroundService")," ",(0,o.kt)("inlineCode",{parentName:"h2"},"Cron")," \u5b9a\u65f6\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},' // \u6267\u884c Cron \u8868\u8fbe\u5f0f\u4efb\u52a1\nawait SpareTime.DoAsync("*/5 * * * * *", () =>\n{\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n}, stoppingToken, CronFormat.IncludeSeconds);\n')))}d.isMDXComponent=!0},3905:function(e,r,n){n.d(r,{Zo:function(){return u},kt:function(){return d}});var t=n(7294);function a(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function o(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function i(e){for(var r=1;r=0||(a[n]=e[n]);return a}(e,r);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=t.createContext({}),c=function(e){var r=t.useContext(s),n=r;return e&&(n="function"==typeof e?e(r):i(i({},r),e)),n},u=function(e){var r=c(e.components);return t.createElement(s.Provider,{value:r},e.children)},p={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},m=t.forwardRef((function(e,r){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=c(n),d=a,g=m["".concat(s,".").concat(d)]||m[d]||p[d]||o;return n?t.createElement(g,i(i({ref:r},u),{},{components:n})):t.createElement(g,i({ref:r},u))}));function d(e,r){var n=arguments,a=r&&r.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=m;var l={};for(var s in r)hasOwnProperty.call(r,s)&&(l[s]=r[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;c=0||(a[n]=e[n]);return a}(e,r);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=t.createContext({}),c=function(e){var r=t.useContext(s),n=r;return e&&(n="function"==typeof e?e(r):i(i({},r),e)),n},u=function(e){var r=c(e.components);return t.createElement(s.Provider,{value:r},e.children)},p={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},m=t.forwardRef((function(e,r){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=c(n),d=a,g=m["".concat(s,".").concat(d)]||m[d]||p[d]||o;return n?t.createElement(g,i(i({ref:r},u),{},{components:n})):t.createElement(g,i({ref:r},u))}));function d(e,r){var n=arguments,a=r&&r.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=m;var l={};for(var s in r)hasOwnProperty.call(r,s)&&(l[s]=r[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;cCron \u8868\u8fbe\u5f0f",id:"129-\u89e3\u6790-cron-\u8868\u8fbe\u5f0f",level:2},{value:"12.10 BackgroundService \u95f4\u9694\u5b9a\u65f6\u4efb\u52a1",id:"1210-backgroundservice-\u95f4\u9694\u5b9a\u65f6\u4efb\u52a1",level:2},{value:"12.11 BackgroundService Cron \u5b9a\u65f6\u4efb\u52a1",id:"1211-backgroundservice-cron-\u5b9a\u65f6\u4efb\u52a1",level:2}],m={toc:p};function d(e){var r=e.components,n=(0,a.Z)(e,i);return(0,o.kt)("wrapper",(0,t.Z)({},m,n,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"SpareTime")," \u9759\u6001\u7c7b\u63d0\u4f9b\u4e86\u4e00\u4e9b\u65b9\u6cd5\u65b9\u4fbf\u521d\u59cb\u5316\u548c\u7ba1\u7406\u4efb\u52a1"),(0,o.kt)("h2",{id:"121-\u521d\u59cb\u5316\u4efb\u52a1"},"12.1 \u521d\u59cb\u5316\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u5f00\u542f\u95f4\u9694\u4efb\u52a1\nSpareTime.Do(interval, [options]);\n\n// \u5f00\u542f Cron \u8868\u8fbe\u5f0f\u4efb\u52a1\nSpareTime.Do(expression, [options]);\n\n// \u53ea\u6267\u884c\u4e00\u6b21\u4efb\u52a1\nSpareTime.DoOnce(interval, [options]);\n\n// \u5b9e\u73b0\u81ea\u5b9a\u4e49\u4efb\u52a1\nSpareTime.Do(()=>{\n return DateTime.Now.AddMinutes(10);\n},[options]);\n")),(0,o.kt)("h2",{id:"122-\u5b9e\u73b0\u540e\u53f0\u6267\u884c"},"12.2 \u5b9e\u73b0\u540e\u53f0\u6267\u884c"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u5b9e\u73b0\u540e\u53f0\u6267\u884c\nSpareTime.DoIt(()=>{});\n")),(0,o.kt)("h2",{id:"123-\u5f00\u59cb\u4e00\u4e2a\u4efb\u52a1"},"12.3 \u5f00\u59cb\u4e00\u4e2a\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SpareTime.Start("\u4efb\u52a1\u6807\u8bc6");\n')),(0,o.kt)("h2",{id:"124-\u6682\u505c\u4e00\u4e2a\u4efb\u52a1"},"12.4 \u6682\u505c\u4e00\u4e2a\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SpareTime.Stop("\u4efb\u52a1\u6807\u8bc6");\n// \u8fd8\u53ef\u4ee5\u6807\u8bb0\u4e00\u4e2a\u4efb\u52a1\u6267\u884c\u5931\u8d25\nSpareTime.Stop("\u4efb\u52a1\u6807\u8bc6", true);\n')),(0,o.kt)("h2",{id:"125-\u53d6\u6d88\u4e00\u4e2a\u4efb\u52a1"},"12.5 \u53d6\u6d88\u4e00\u4e2a\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SpareTime.Cancel("\u4efb\u52a1\u540d\u79f0");\n')),(0,o.kt)("h2",{id:"126-\u9500\u6bc1\u6240\u6709\u4efb\u52a1"},"12.6 \u9500\u6bc1\u6240\u6709\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"SpareTime.Dispose();\n")),(0,o.kt)("h2",{id:"127-\u83b7\u53d6\u6240\u6709\u4efb\u52a1"},"12.7 \u83b7\u53d6\u6240\u6709\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var workers = SpareTime.GetWorkers();\n")),(0,o.kt)("h2",{id:"128-\u83b7\u53d6\u5355\u4e2a\u4efb\u52a1"},"12.8 \u83b7\u53d6\u5355\u4e2a\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var worker = SpareTime.GetWorker("workerName");\n')),(0,o.kt)("h2",{id:"129-\u89e3\u6790-cron-\u8868\u8fbe\u5f0f"},"12.9 \u89e3\u6790 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Cron")," \u8868\u8fbe\u5f0f"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var nextTime = SpareTime.GetCronNextOccurrence("* * * * *");\n')),(0,o.kt)("h2",{id:"1210-backgroundservice-\u95f4\u9694\u5b9a\u65f6\u4efb\u52a1"},"12.10 ",(0,o.kt)("inlineCode",{parentName:"h2"},"BackgroundService")," \u95f4\u9694\u5b9a\u65f6\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u95f4\u9694\u6267\u884c\u4efb\u52a1\nawait SpareTime.DoAsync(1000, () =>\n{\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n}, stoppingToken);\n')),(0,o.kt)("h2",{id:"1211-backgroundservice-cron-\u5b9a\u65f6\u4efb\u52a1"},"12.11 ",(0,o.kt)("inlineCode",{parentName:"h2"},"BackgroundService")," ",(0,o.kt)("inlineCode",{parentName:"h2"},"Cron")," \u5b9a\u65f6\u4efb\u52a1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},' // \u6267\u884c Cron \u8868\u8fbe\u5f0f\u4efb\u52a1\nawait SpareTime.DoAsync("*/5 * * * * *", () =>\n{\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n}, stoppingToken, CronFormat.IncludeSeconds);\n')))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/698c3fb7.49c7b7fe.js b/handbook/build/assets/js/698c3fb7.49c7b7fe.js deleted file mode 100644 index 8b3cee3dc3..0000000000 --- a/handbook/build/assets/js/698c3fb7.49c7b7fe.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4249],{3634:function(e,t,a){a.r(t),a.d(t,{assets:function(){return u},contentTitle:function(){return m},default:function(){return c},frontMatter:function(){return o},metadata:function(){return s},toc:function(){return g}});var n=a(3117),r=a(102),l=(a(7294),a(3905)),i=a(1402),p=["components"],o={id:"template",title:"2.2 \u5b98\u65b9\u811a\u624b\u67b6",sidebar_label:"2.2 \u5b98\u65b9\u811a\u624b\u67b6"},m=void 0,s={unversionedId:"template",id:"template",title:"2.2 \u5b98\u65b9\u811a\u624b\u67b6",description:"",source:"@site/docs/template.mdx",sourceDirName:".",slug:"/template",permalink:"/furion/docs/template",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/template.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1662091827,formattedLastUpdatedAt:"Sep 2, 2022",frontMatter:{id:"template",title:"2.2 \u5b98\u65b9\u811a\u624b\u67b6",sidebar_label:"2.2 \u5b98\u65b9\u811a\u624b\u67b6"},sidebar:"docs",previous:{title:"2.1 ASP.NET 6 \u96c6\u6210",permalink:"/furion/docs/get-start-net6"},next:{title:"2.3 \u624b\u52a8\u642d\u5efa\u5206\u5c42",permalink:"/furion/docs/reference"}},u={},g=[{value:"2.2.1 \u811a\u624b\u67b6",id:"221-\u811a\u624b\u67b6",level:2},{value:"2.2.1.1 Furion + EFCore",id:"2211-furion--efcore",level:3},{value:"2.2.1.2 Furion + SqlSugar",id:"2212-furion--sqlsugar",level:3},{value:"2.2.2 \u5b89\u88c5\u811a\u624b\u67b6",id:"222-\u5b89\u88c5\u811a\u624b\u67b6",level:2},{value:"2.2.3 \u4f7f\u7528\u811a\u624b\u67b6",id:"223-\u4f7f\u7528\u811a\u624b\u67b6",level:2},{value:"2.2.4 \u811a\u624b\u67b6\u66f4\u65b0",id:"224-\u811a\u624b\u67b6\u66f4\u65b0",level:2},{value:"2.2.5 Visual Studio \u96c6\u6210",id:"225-visual-studio-\u96c6\u6210",level:2},{value:"2.2.6 \u5173\u4e8e MVC \u6dfb\u52a0\u533a\u57df\u51fa\u9519\u95ee\u9898",id:"226-\u5173\u4e8e-mvc-\u6dfb\u52a0\u533a\u57df\u51fa\u9519\u95ee\u9898",level:2},{value:"2.2.7 \u4f7f\u7528 .NET5 \u811a\u624b\u67b6",id:"227-\u4f7f\u7528-net5-\u811a\u624b\u67b6",level:2},{value:"2.2.8 \u642d\u5efa\u811a\u624b\u67b6",id:"228-\u642d\u5efa\u811a\u624b\u67b6",level:2},{value:"2.2.9 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"229-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:g};function c(e){var t=e.components,a=(0,r.Z)(e,p);return(0,l.kt)("wrapper",(0,n.Z)({},d,a,{components:t,mdxType:"MDXLayout"}),(0,l.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("strong",{parentName:"p"},"\u811a\u624b\u67b6\u4e0d\u662f\u5b89\u88c5\u5728\u9879\u76ee\u4e2d\u7684\uff01")," \u800c\u662f\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"CMD")," \u6216 ",(0,l.kt)("inlineCode",{parentName:"p"},"PowerShell")," \u5b89\u88c5\u5230\u64cd\u4f5c\u7cfb\u7edf\u4e2d\u7684\u3002")),(0,l.kt)("h2",{id:"221-\u811a\u624b\u67b6"},"2.2.1 \u811a\u624b\u67b6"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u5b98\u65b9\u63d0\u4f9b\u4e86\u591a\u79cd ",(0,l.kt)("inlineCode",{parentName:"p"},"Web")," \u5e94\u7528\u7c7b\u578b\u7684\u811a\u624b\u67b6\uff0c\u65b9\u4fbf\u5927\u5bb6\u5feb\u901f\u521b\u5efa\u591a\u5c42\u67b6\u6784\u9879\u76ee\u3002\u76ee\u524d\u652f\u6301\u4ee5\u4e0b\u5e94\u7528\u811a\u624b\u67b6\uff1a"),(0,l.kt)("h3",{id:"2211-furion--efcore"},"2.2.1.1 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Furion + EFCore")),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:"center"},"\u6a21\u677f\u7c7b\u578b"),(0,l.kt)("th",{parentName:"tr",align:null},"\u540d\u79f0"),(0,l.kt)("th",{parentName:"tr",align:null},"\u7248\u672c"),(0,l.kt)("th",{parentName:"tr",align:null},"\u5173\u952e\u8bcd"),(0,l.kt)("th",{parentName:"tr",align:null},"\u63cf\u8ff0"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Mvc/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.Template.Mvc"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Mvc/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Mvc.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"furionmvc")),(0,l.kt)("td",{parentName:"tr",align:null},"Mvc \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Api/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.Template.Api"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Api/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Api.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"furionapi")),(0,l.kt)("td",{parentName:"tr",align:null},"WebApi \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.App/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.Template.App"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.App/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.App.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"furionapp")),(0,l.kt)("td",{parentName:"tr",align:null},"Mvc/WebApi \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Razor/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.Template.Razor"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Razor/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Razor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"furionrazor")),(0,l.kt)("td",{parentName:"tr",align:null},"RazorPages \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.RazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.Template.RazorWithWebApi"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.RazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.RazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"furionrazorapi")),(0,l.kt)("td",{parentName:"tr",align:null},"RazorPages/WebApi \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Blazor/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.Template.Blazor"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Blazor/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Blazor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"furionblazor")),(0,l.kt)("td",{parentName:"tr",align:null},"Blazor \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.BlazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.Template.BlazorWithWebApi"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.BlazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.BlazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"furionblazorapi")),(0,l.kt)("td",{parentName:"tr",align:null},"Blazor/WebApi \u6a21\u677f")))),(0,l.kt)("h3",{id:"2212-furion--sqlsugar"},"2.2.1.2 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Furion + SqlSugar")),(0,l.kt)("admonition",{type:"tip"},(0,l.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"SqlSugar")," \u4f18\u70b9"),(0,l.kt)("p",{parentName:"admonition"},"\u5f25\u8865 ",(0,l.kt)("inlineCode",{parentName:"p"},"EF Core")," \u4e0a\u624b\u96be\u5ea6\uff1a\u652f\u6301\u7ebf\u7a0b\u5b89\u5168\u3001\u652f\u6301\u591a\u5e93\u4e8b\u52a1\u3001\u591a\u5e93\u517c\u5bb9\u3001\u591a\u5e93\u67e5\u8be2\u548c\u591a\u5e93\u5207\u6362\u3002")),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:"center"},"\u6a21\u677f\u7c7b\u578b"),(0,l.kt)("th",{parentName:"tr",align:null},"\u540d\u79f0"),(0,l.kt)("th",{parentName:"tr",align:null},"\u7248\u672c"),(0,l.kt)("th",{parentName:"tr",align:null},"\u5173\u952e\u8bcd"),(0,l.kt)("th",{parentName:"tr",align:null},"\u63cf\u8ff0"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Mvc/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Mvc"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Mvc/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Mvc.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"fsmvc")),(0,l.kt)("td",{parentName:"tr",align:null},"Mvc \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Api/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Api"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Api/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Api.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"fsapi")),(0,l.kt)("td",{parentName:"tr",align:null},"WebApi \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.App/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.App"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.App/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.App.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"fsapp")),(0,l.kt)("td",{parentName:"tr",align:null},"Mvc/WebApi \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Razor/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Razor"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Razor/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Razor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"fsrazor")),(0,l.kt)("td",{parentName:"tr",align:null},"RazorPages \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.RazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.RazorWithWebApi"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.RazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.RazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"fsrazorapi")),(0,l.kt)("td",{parentName:"tr",align:null},"RazorPages/WebApi \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Blazor/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Blazor"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Blazor/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Blazor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"fsblazor")),(0,l.kt)("td",{parentName:"tr",align:null},"Blazor \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.BlazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.BlazorWithWebApi"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.BlazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.BlazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"fsblazorapi")),(0,l.kt)("td",{parentName:"tr",align:null},"Blazor/WebApi \u6a21\u677f")))),(0,l.kt)("h2",{id:"222-\u5b89\u88c5\u811a\u624b\u67b6"},"2.2.2 \u5b89\u88c5\u811a\u624b\u67b6"),(0,l.kt)("p",null,"\u6253\u5f00 ",(0,l.kt)("inlineCode",{parentName:"p"},"CMD")," \u6216 ",(0,l.kt)("inlineCode",{parentName:"p"},"Powershell")," \u6267\u884c\u6a21\u677f\u5b89\u88c5\u547d\u4ee4\uff08\u65b0\u7248\u672c ",(0,l.kt)("inlineCode",{parentName:"p"},"--install")," \u53ef\u6362\u6210 ",(0,l.kt)("inlineCode",{parentName:"p"},"install"),"\uff09\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"// EFCore\ndotnet new --install Furion.Template.Mvc::4.3.9\n// SqlSugar\ndotnet new --install Furion.SqlSugar.Template.Mvc::4.3.9\n")),(0,l.kt)("admonition",{type:"tip"},(0,l.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"SqlSugar")," \u811a\u624b\u67b6\u57fa\u672c\u4f7f\u7528"),(0,l.kt)("p",{parentName:"admonition"},"\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"SqlSugar")," \u811a\u624b\u67b6\u4e2d\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"Core")," \u5c42\u5305\u542b\u4e86\u4e00\u4e2a ",(0,l.kt)("inlineCode",{parentName:"p"},"DbContext.cs")," \u7c7b\uff0c\u53ef\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"DbContext.Instance")," \u5c31\u53ef\u4ee5\u83b7\u53d6\u5230 ",(0,l.kt)("inlineCode",{parentName:"p"},"SqlSugarScope")," \u5bf9\u8c61\u3002"),(0,l.kt)("p",{parentName:"admonition"},"\u6570\u636e\u5e93\u94fe\u63a5\u5b57\u7b26\u4e32\u5728\u542f\u52a8\u5c42 ",(0,l.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u6587\u4ef6\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"ConnectionConfigs")," \u8282\u70b9\u4e2d\u914d\u7f6e\uff0c\u5bf9\u5e94\u7684\u662f ",(0,l.kt)("inlineCode",{parentName:"p"},"SqlSugar")," \u4e2d\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"ConnectionConfig[]")," \u5bf9\u8c61\u3002")),(0,l.kt)("h2",{id:"223-\u4f7f\u7528\u811a\u624b\u67b6"},"2.2.3 \u4f7f\u7528\u811a\u624b\u67b6"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new furionmvc -n \u9879\u76ee\u540d\u79f0\n")),(0,l.kt)("p",null,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u751f\u6210\u9879\u76ee\u4ee3\u7801\u4e86\uff0c",(0,l.kt)("strong",{parentName:"p"},"\u751f\u6210\u4e4b\u540e\u63a8\u8350\u5c06\u6240\u6709\u7684 ",(0,l.kt)("inlineCode",{parentName:"strong"},"nuget")," \u5305\u66f4\u65b0\u5230\u6700\u65b0\u7248\u672c\u3002")),(0,l.kt)("admonition",{title:"\u5173\u4e8e\u9879\u76ee\u540d\u79f0",type:"tip"},(0,l.kt)("p",{parentName:"admonition"},"\u901a\u8fc7\u811a\u624b\u67b6\u751f\u6210\u7684\u9879\u76ee\u540d\u79f0\u4e0d\u80fd\u5305\u542b ",(0,l.kt)("inlineCode",{parentName:"p"},"\u77ed\u6a2a\u7ebf")," \u7b49\u7279\u6b8a\u5b57\u7b26\uff0c\u5982\u6709\u8be5\u9700\u6c42\uff0c\u53ef\u5728\u751f\u6210\u4e4b\u540e\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u8fdb\u884c\u624b\u52a8\u4fee\u6539\u3002")),(0,l.kt)("admonition",{title:"\u7279\u522b\u63d0\u9192",type:"important"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"p"},"furionmvc")," \u5bf9\u5e94\u7684\u662f\u4e0a\u9762\u5217\u8868\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"\u5173\u952e\u5b57"),"\uff0c\u6211\u4eec\u4e5f\u53ef\u4ee5\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"dotnet new --list")," \u67e5\u770b\u3002"),(0,l.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a\u53ef\u4ee5\u4f7f\u7528 ",(0,l.kt)("inlineCode",{parentName:"p"},"dotnet new \u5173\u952e\u5b57 --help")," \u67e5\u770b\u66f4\u591a\u53c2\u6570\u3002")),(0,l.kt)("h2",{id:"224-\u811a\u624b\u67b6\u66f4\u65b0"},"2.2.4 \u811a\u624b\u67b6\u66f4\u65b0"),(0,l.kt)("p",null,"\u53ea\u9700\u8981\u91cd\u65b0\u5b89\u88c5\u6700\u65b0\u7248\u66ff\u6362\u5373\u53ef\uff0c\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new --install Furion.Template.Mvc::2.x.x\n")),(0,l.kt)("p",null,"\u4e0d\u5e26\u7248\u672c\u53f7\u603b\u662f\u5b89\u88c5\u6700\u65b0\u7684\u7248\u672c\u3002"),(0,l.kt)("h2",{id:"225-visual-studio-\u96c6\u6210"},"2.2.5 ",(0,l.kt)("inlineCode",{parentName:"h2"},"Visual Studio")," \u96c6\u6210"),(0,l.kt)("p",null,"\u901a\u8fc7\u547d\u4ee4\u5b89\u88c5\u811a\u624b\u67b6\u540e\uff0c\u5347\u7ea7 ",(0,l.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u5230\u6700\u65b0\u7248\u53ef\u4f7f\u7528\u53ef\u89c6\u5316\u65b9\u5f0f\u521b\u5efa\u54e6\u3002"),(0,l.kt)("img",{src:(0,i.Z)("img/ksh.png")}),(0,l.kt)("h2",{id:"226-\u5173\u4e8e-mvc-\u6dfb\u52a0\u533a\u57df\u51fa\u9519\u95ee\u9898"},"2.2.6 ",(0,l.kt)("inlineCode",{parentName:"h2"},"\u5173\u4e8e MVC \u6dfb\u52a0\u533a\u57df\u51fa\u9519\u95ee\u9898")),(0,l.kt)("p",null,"\u7531\u4e8e ",(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u5e95\u5c42\u4f9d\u8d56\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},"Microsoft.CodeAnalysis.CSharp")," \u5305\uff0c\u6240\u4ee5\u53ef\u80fd\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"Viusal Studio")," \u7684\u754c\u9762\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"p"},"Area \u533a\u57df")," \u65f6\u4f1a\u51fa\u9519\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"Web.Entry")," \u5c42\u5b89\u88c5\u4e0b\u9762\u51e0\u4e2a\u5305\u5373\u53ef\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Microsoft.CodeAnalysis.CSharp.Features")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Microsoft.CodeAnalysis.CSharp.Scripting")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Microsoft.CodeAnalysis.VisualBasic.Features")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Microsoft.CodeAnalysis.Workspaces.MSBuild")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Microsoft.VisualStudio.Web.CodeGeneration.Design"))),(0,l.kt)("h2",{id:"227-\u4f7f\u7528-net5-\u811a\u624b\u67b6"},"2.2.7 \u4f7f\u7528 ",(0,l.kt)("inlineCode",{parentName:"h2"},".NET5")," \u811a\u624b\u67b6"),(0,l.kt)("p",null,"\u76ee\u524d ",(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u53ea\u63d0\u4f9b\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},".NET6+")," \u7248\u672c\u811a\u624b\u67b6\uff0c\u5982\u9700\u4f7f\u7528 ",(0,l.kt)("inlineCode",{parentName:"p"},".NET")," \u7248\u672c\uff0c\u53ef\u521b\u5efa\u4e4b\u540e\u6267\u884c\u4e0b\u9762\u6b65\u9aa4\uff1a"),(0,l.kt)("ol",null,(0,l.kt)("li",{parentName:"ol"},(0,l.kt)("p",{parentName:"li"},"\u66ff\u6362 ",(0,l.kt)("inlineCode",{parentName:"p"},"net6.0")," \u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"net5.0"))),(0,l.kt)("li",{parentName:"ol"},(0,l.kt)("p",{parentName:"li"},"\u7f16\u8f91\u6240\u6709\u5c42 ",(0,l.kt)("inlineCode",{parentName:"p"},".csproj")," \u6587\u4ef6\u5e76\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"p"},"10.0"),"\uff0c\u5982\uff1a"))),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-xml",metastring:"showLineNumbers {3}",showLineNumbers:!0,"{3}":!0},"\n net5.0\n 10.0\n \x3c!-- \u5176\u4ed6\u914d\u7f6e --\x3e\n\n")),(0,l.kt)("ol",{start:3},(0,l.kt)("li",{parentName:"ol"},"\u5982\u679c\u4f7f\u7528\u7684\u662f ",(0,l.kt)("inlineCode",{parentName:"li"},"EFCore")," \u7248\u672c\u5219\u9700\u8981\u5c06\u542f\u52a8\u5c42\u7684 ",(0,l.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.Tools")," \u7248\u672c\u6539\u4e3a ",(0,l.kt)("inlineCode",{parentName:"li"},"5.0.17")," \u7248\u672c\uff0c\u5982\u7f16\u8f91\u542f\u52a8\u5c42\u7684 ",(0,l.kt)("inlineCode",{parentName:"li"},"Web.Entry.csproj"),"\uff1a")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-xml",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},'\n all\n runtime; build; native; contentfiles; analyzers; buildtransitive\n\n')),(0,l.kt)("p",null,"\u6539\u4e3a\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-xml",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},'\n all\n runtime; build; native; contentfiles; analyzers; buildtransitive\n\n')),(0,l.kt)("ol",{start:4},(0,l.kt)("li",{parentName:"ol"},"\u5728\u542f\u52a8\u5c42\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u6587\u4ef6")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"namespace YourProject.Web.Entry; // \u4f60\u7684\u9879\u76ee\u547d\u540d\u7a7a\u95f4\n\npublic class Startup\n{\n public Startup(IConfiguration configuration)\n {\n Configuration = configuration;\n }\n\n public IConfiguration Configuration { get; }\n\n public void ConfigureServices(IServiceCollection services)\n {\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n }\n}\n")),(0,l.kt)("ol",{start:5},(0,l.kt)("li",{parentName:"ol"},"\u4fee\u6539 ",(0,l.kt)("inlineCode",{parentName:"li"},"Program.cs")," \u4e3a\uff1a")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"{3}":!0},"using YourProject.Web.Entry;\n\nServe.Run(RunOptions.Default);\n")),(0,l.kt)("h2",{id:"228-\u642d\u5efa\u811a\u624b\u67b6"},"2.2.8 \u642d\u5efa\u811a\u624b\u67b6"),(0,l.kt)("p",null,"\u811a\u624b\u67b6\u53ef\u4ee5\u6781\u5927\u7684\u63d0\u9ad8\u6211\u4eec\u642d\u5efa\u65b0\u9879\u76ee\u7684\u901f\u5ea6\uff0c\u63a8\u8350\u4e24\u7bc7\u6587\u7ae0\u7ed9\u5927\u5bb6\u5b66\u4e60\uff1a"),(0,l.kt)("p",null,(0,l.kt)("a",{parentName:"p",href:"https://www.cnblogs.com/laozhang-is-phi/p/10205495.html"},"https://www.cnblogs.com/laozhang-is-phi/p/10205495.html")),(0,l.kt)("p",null,(0,l.kt)("a",{parentName:"p",href:"https://www.cnblogs.com/catcher1994/p/10061470.html"},"https://www.cnblogs.com/catcher1994/p/10061470.html")),(0,l.kt)("p",null,(0,l.kt)("strong",{parentName:"p"},"\u63a8\u8350\u76f4\u63a5\u62f7\u8d1d ",(0,l.kt)("inlineCode",{parentName:"strong"},"Furion")," \u811a\u624b\u67b6\u6587\u4ef6\u5939\u8fdb\u884c\u4fee\u6539\uff0c\u53ef\u907f\u514d\u5f88\u591a\u95ee\u9898\u3002")),(0,l.kt)("p",null,(0,l.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/tree/net6/templates"},"Furion \u811a\u624b\u67b6\u6e90\u7801")),(0,l.kt)("h2",{id:"229-\u53cd\u9988\u4e0e\u5efa\u8bae"},"2.2.9 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,l.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,l.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,l.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,l.kt)("hr",null),(0,l.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,l.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,l.kt)("inlineCode",{parentName:"p"},"\u6a21\u677f\u77e5\u8bc6")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,l.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/dotnet/core/tools/dotnet-new"},"dotnet-new \u6a21\u677f")," \u7ae0\u8282\u3002")))}c.isMDXComponent=!0},3905:function(e,t,a){a.d(t,{Zo:function(){return s},kt:function(){return d}});var n=a(7294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function l(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function i(e){for(var t=1;t=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var o=n.createContext({}),m=function(e){var t=n.useContext(o),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},s=function(e){var t=m(e.components);return n.createElement(o.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},g=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,l=e.originalType,o=e.parentName,s=p(e,["components","mdxType","originalType","parentName"]),g=m(a),d=r,c=g["".concat(o,".").concat(d)]||g[d]||u[d]||l;return a?n.createElement(c,i(i({ref:t},s),{},{components:a})):n.createElement(c,i({ref:t},s))}));function d(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=a.length,i=new Array(l);i[0]=g;var p={};for(var o in t)hasOwnProperty.call(t,o)&&(p[o]=t[o]);p.originalType=e,p.mdxType="string"==typeof e?e:r,i[1]=p;for(var m=2;m=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var o=n.createContext({}),m=function(e){var t=n.useContext(o),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},s=function(e){var t=m(e.components);return n.createElement(o.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},g=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,l=e.originalType,o=e.parentName,s=p(e,["components","mdxType","originalType","parentName"]),g=m(a),d=r,c=g["".concat(o,".").concat(d)]||g[d]||u[d]||l;return a?n.createElement(c,i(i({ref:t},s),{},{components:a})):n.createElement(c,i({ref:t},s))}));function d(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=a.length,i=new Array(l);i[0]=g;var p={};for(var o in t)hasOwnProperty.call(t,o)&&(p[o]=t[o]);p.originalType=e,p.mdxType="string"==typeof e?e:r,i[1]=p;for(var m=2;mFurion + EFCore",id:"2211-furion--efcore",level:3},{value:"2.2.1.2 Furion + SqlSugar",id:"2212-furion--sqlsugar",level:3},{value:"2.2.2 \u5b89\u88c5\u811a\u624b\u67b6",id:"222-\u5b89\u88c5\u811a\u624b\u67b6",level:2},{value:"2.2.3 \u4f7f\u7528\u811a\u624b\u67b6",id:"223-\u4f7f\u7528\u811a\u624b\u67b6",level:2},{value:"2.2.4 \u811a\u624b\u67b6\u66f4\u65b0",id:"224-\u811a\u624b\u67b6\u66f4\u65b0",level:2},{value:"2.2.5 Visual Studio \u96c6\u6210",id:"225-visual-studio-\u96c6\u6210",level:2},{value:"2.2.6 \u5173\u4e8e MVC \u6dfb\u52a0\u533a\u57df\u51fa\u9519\u95ee\u9898",id:"226-\u5173\u4e8e-mvc-\u6dfb\u52a0\u533a\u57df\u51fa\u9519\u95ee\u9898",level:2},{value:"2.2.7 \u4f7f\u7528 .NET5 \u811a\u624b\u67b6",id:"227-\u4f7f\u7528-net5-\u811a\u624b\u67b6",level:2},{value:"2.2.8 \u642d\u5efa\u811a\u624b\u67b6",id:"228-\u642d\u5efa\u811a\u624b\u67b6",level:2},{value:"2.2.9 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"229-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:g};function c(e){var t=e.components,a=(0,r.Z)(e,p);return(0,l.kt)("wrapper",(0,n.Z)({},d,a,{components:t,mdxType:"MDXLayout"}),(0,l.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("strong",{parentName:"p"},"\u811a\u624b\u67b6\u4e0d\u662f\u5b89\u88c5\u5728\u9879\u76ee\u4e2d\u7684\uff01")," \u800c\u662f\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"CMD")," \u6216 ",(0,l.kt)("inlineCode",{parentName:"p"},"PowerShell")," \u5b89\u88c5\u5230\u64cd\u4f5c\u7cfb\u7edf\u4e2d\u7684\u3002")),(0,l.kt)("h2",{id:"221-\u811a\u624b\u67b6"},"2.2.1 \u811a\u624b\u67b6"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u5b98\u65b9\u63d0\u4f9b\u4e86\u591a\u79cd ",(0,l.kt)("inlineCode",{parentName:"p"},"Web")," \u5e94\u7528\u7c7b\u578b\u7684\u811a\u624b\u67b6\uff0c\u65b9\u4fbf\u5927\u5bb6\u5feb\u901f\u521b\u5efa\u591a\u5c42\u67b6\u6784\u9879\u76ee\u3002\u76ee\u524d\u652f\u6301\u4ee5\u4e0b\u5e94\u7528\u811a\u624b\u67b6\uff1a"),(0,l.kt)("h3",{id:"2211-furion--efcore"},"2.2.1.1 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Furion + EFCore")),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:"center"},"\u6a21\u677f\u7c7b\u578b"),(0,l.kt)("th",{parentName:"tr",align:null},"\u540d\u79f0"),(0,l.kt)("th",{parentName:"tr",align:null},"\u7248\u672c"),(0,l.kt)("th",{parentName:"tr",align:null},"\u5173\u952e\u8bcd"),(0,l.kt)("th",{parentName:"tr",align:null},"\u63cf\u8ff0"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Mvc/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.Template.Mvc"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Mvc/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Mvc.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"furionmvc")),(0,l.kt)("td",{parentName:"tr",align:null},"Mvc \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Api/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.Template.Api"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Api/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Api.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"furionapi")),(0,l.kt)("td",{parentName:"tr",align:null},"WebApi \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.App/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.Template.App"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.App/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.App.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"furionapp")),(0,l.kt)("td",{parentName:"tr",align:null},"Mvc/WebApi \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Razor/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.Template.Razor"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Razor/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Razor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"furionrazor")),(0,l.kt)("td",{parentName:"tr",align:null},"RazorPages \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.RazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.Template.RazorWithWebApi"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.RazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.RazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"furionrazorapi")),(0,l.kt)("td",{parentName:"tr",align:null},"RazorPages/WebApi \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Blazor/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.Template.Blazor"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Blazor/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Blazor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"furionblazor")),(0,l.kt)("td",{parentName:"tr",align:null},"Blazor \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.BlazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.Template.BlazorWithWebApi"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.BlazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.BlazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"furionblazorapi")),(0,l.kt)("td",{parentName:"tr",align:null},"Blazor/WebApi \u6a21\u677f")))),(0,l.kt)("h3",{id:"2212-furion--sqlsugar"},"2.2.1.2 ",(0,l.kt)("inlineCode",{parentName:"h3"},"Furion + SqlSugar")),(0,l.kt)("admonition",{type:"tip"},(0,l.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"SqlSugar")," \u4f18\u70b9"),(0,l.kt)("p",{parentName:"admonition"},"\u5f25\u8865 ",(0,l.kt)("inlineCode",{parentName:"p"},"EF Core")," \u4e0a\u624b\u96be\u5ea6\uff1a\u652f\u6301\u7ebf\u7a0b\u5b89\u5168\u3001\u652f\u6301\u591a\u5e93\u4e8b\u52a1\u3001\u591a\u5e93\u517c\u5bb9\u3001\u591a\u5e93\u67e5\u8be2\u548c\u591a\u5e93\u5207\u6362\u3002")),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:"center"},"\u6a21\u677f\u7c7b\u578b"),(0,l.kt)("th",{parentName:"tr",align:null},"\u540d\u79f0"),(0,l.kt)("th",{parentName:"tr",align:null},"\u7248\u672c"),(0,l.kt)("th",{parentName:"tr",align:null},"\u5173\u952e\u8bcd"),(0,l.kt)("th",{parentName:"tr",align:null},"\u63cf\u8ff0"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Mvc/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Mvc"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Mvc/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Mvc.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"fsmvc")),(0,l.kt)("td",{parentName:"tr",align:null},"Mvc \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Api/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Api"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Api/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Api.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"fsapi")),(0,l.kt)("td",{parentName:"tr",align:null},"WebApi \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.App/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.App"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.App/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.App.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"fsapp")),(0,l.kt)("td",{parentName:"tr",align:null},"Mvc/WebApi \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Razor/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Razor"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Razor/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Razor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"fsrazor")),(0,l.kt)("td",{parentName:"tr",align:null},"RazorPages \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.RazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.RazorWithWebApi"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.RazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.RazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"fsrazorapi")),(0,l.kt)("td",{parentName:"tr",align:null},"RazorPages/WebApi \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Blazor/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Blazor"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Blazor/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Blazor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"fsblazor")),(0,l.kt)("td",{parentName:"tr",align:null},"Blazor \u6a21\u677f")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:"center"},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.BlazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.BlazorWithWebApi"),(0,l.kt)("td",{parentName:"tr",align:null},(0,l.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.BlazorWithWebApi/"},(0,l.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.BlazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,l.kt)("td",{parentName:"tr",align:null},"\ud83d\udc49 ",(0,l.kt)("strong",{parentName:"td"},"fsblazorapi")),(0,l.kt)("td",{parentName:"tr",align:null},"Blazor/WebApi \u6a21\u677f")))),(0,l.kt)("h2",{id:"222-\u5b89\u88c5\u811a\u624b\u67b6"},"2.2.2 \u5b89\u88c5\u811a\u624b\u67b6"),(0,l.kt)("p",null,"\u6253\u5f00 ",(0,l.kt)("inlineCode",{parentName:"p"},"CMD")," \u6216 ",(0,l.kt)("inlineCode",{parentName:"p"},"Powershell")," \u6267\u884c\u6a21\u677f\u5b89\u88c5\u547d\u4ee4\uff08\u65b0\u7248\u672c ",(0,l.kt)("inlineCode",{parentName:"p"},"--install")," \u53ef\u6362\u6210 ",(0,l.kt)("inlineCode",{parentName:"p"},"install"),"\uff09\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"// EFCore\ndotnet new --install Furion.Template.Mvc::4.4.0\n// SqlSugar\ndotnet new --install Furion.SqlSugar.Template.Mvc::4.4.0\n")),(0,l.kt)("admonition",{type:"tip"},(0,l.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"SqlSugar")," \u811a\u624b\u67b6\u57fa\u672c\u4f7f\u7528"),(0,l.kt)("p",{parentName:"admonition"},"\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"SqlSugar")," \u811a\u624b\u67b6\u4e2d\uff0c",(0,l.kt)("inlineCode",{parentName:"p"},"Core")," \u5c42\u5305\u542b\u4e86\u4e00\u4e2a ",(0,l.kt)("inlineCode",{parentName:"p"},"DbContext.cs")," \u7c7b\uff0c\u53ef\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"DbContext.Instance")," \u5c31\u53ef\u4ee5\u83b7\u53d6\u5230 ",(0,l.kt)("inlineCode",{parentName:"p"},"SqlSugarScope")," \u5bf9\u8c61\u3002"),(0,l.kt)("p",{parentName:"admonition"},"\u6570\u636e\u5e93\u94fe\u63a5\u5b57\u7b26\u4e32\u5728\u542f\u52a8\u5c42 ",(0,l.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u6587\u4ef6\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"ConnectionConfigs")," \u8282\u70b9\u4e2d\u914d\u7f6e\uff0c\u5bf9\u5e94\u7684\u662f ",(0,l.kt)("inlineCode",{parentName:"p"},"SqlSugar")," \u4e2d\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"ConnectionConfig[]")," \u5bf9\u8c61\u3002")),(0,l.kt)("h2",{id:"223-\u4f7f\u7528\u811a\u624b\u67b6"},"2.2.3 \u4f7f\u7528\u811a\u624b\u67b6"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new furionmvc -n \u9879\u76ee\u540d\u79f0\n")),(0,l.kt)("p",null,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u751f\u6210\u9879\u76ee\u4ee3\u7801\u4e86\uff0c",(0,l.kt)("strong",{parentName:"p"},"\u751f\u6210\u4e4b\u540e\u63a8\u8350\u5c06\u6240\u6709\u7684 ",(0,l.kt)("inlineCode",{parentName:"strong"},"nuget")," \u5305\u66f4\u65b0\u5230\u6700\u65b0\u7248\u672c\u3002")),(0,l.kt)("admonition",{title:"\u5173\u4e8e\u9879\u76ee\u540d\u79f0",type:"tip"},(0,l.kt)("p",{parentName:"admonition"},"\u901a\u8fc7\u811a\u624b\u67b6\u751f\u6210\u7684\u9879\u76ee\u540d\u79f0\u4e0d\u80fd\u5305\u542b ",(0,l.kt)("inlineCode",{parentName:"p"},"\u77ed\u6a2a\u7ebf")," \u7b49\u7279\u6b8a\u5b57\u7b26\uff0c\u5982\u6709\u8be5\u9700\u6c42\uff0c\u53ef\u5728\u751f\u6210\u4e4b\u540e\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u8fdb\u884c\u624b\u52a8\u4fee\u6539\u3002")),(0,l.kt)("admonition",{title:"\u7279\u522b\u63d0\u9192",type:"important"},(0,l.kt)("p",{parentName:"admonition"},(0,l.kt)("inlineCode",{parentName:"p"},"furionmvc")," \u5bf9\u5e94\u7684\u662f\u4e0a\u9762\u5217\u8868\u7684 ",(0,l.kt)("inlineCode",{parentName:"p"},"\u5173\u952e\u5b57"),"\uff0c\u6211\u4eec\u4e5f\u53ef\u4ee5\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"dotnet new --list")," \u67e5\u770b\u3002"),(0,l.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a\u53ef\u4ee5\u4f7f\u7528 ",(0,l.kt)("inlineCode",{parentName:"p"},"dotnet new \u5173\u952e\u5b57 --help")," \u67e5\u770b\u66f4\u591a\u53c2\u6570\u3002")),(0,l.kt)("h2",{id:"224-\u811a\u624b\u67b6\u66f4\u65b0"},"2.2.4 \u811a\u624b\u67b6\u66f4\u65b0"),(0,l.kt)("p",null,"\u53ea\u9700\u8981\u91cd\u65b0\u5b89\u88c5\u6700\u65b0\u7248\u66ff\u6362\u5373\u53ef\uff0c\u5982\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new --install Furion.Template.Mvc::2.x.x\n")),(0,l.kt)("p",null,"\u4e0d\u5e26\u7248\u672c\u53f7\u603b\u662f\u5b89\u88c5\u6700\u65b0\u7684\u7248\u672c\u3002"),(0,l.kt)("h2",{id:"225-visual-studio-\u96c6\u6210"},"2.2.5 ",(0,l.kt)("inlineCode",{parentName:"h2"},"Visual Studio")," \u96c6\u6210"),(0,l.kt)("p",null,"\u901a\u8fc7\u547d\u4ee4\u5b89\u88c5\u811a\u624b\u67b6\u540e\uff0c\u5347\u7ea7 ",(0,l.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u5230\u6700\u65b0\u7248\u53ef\u4f7f\u7528\u53ef\u89c6\u5316\u65b9\u5f0f\u521b\u5efa\u54e6\u3002"),(0,l.kt)("img",{src:(0,i.Z)("img/ksh.png")}),(0,l.kt)("h2",{id:"226-\u5173\u4e8e-mvc-\u6dfb\u52a0\u533a\u57df\u51fa\u9519\u95ee\u9898"},"2.2.6 ",(0,l.kt)("inlineCode",{parentName:"h2"},"\u5173\u4e8e MVC \u6dfb\u52a0\u533a\u57df\u51fa\u9519\u95ee\u9898")),(0,l.kt)("p",null,"\u7531\u4e8e ",(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u5e95\u5c42\u4f9d\u8d56\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},"Microsoft.CodeAnalysis.CSharp")," \u5305\uff0c\u6240\u4ee5\u53ef\u80fd\u901a\u8fc7 ",(0,l.kt)("inlineCode",{parentName:"p"},"Viusal Studio")," \u7684\u754c\u9762\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"p"},"Area \u533a\u57df")," \u65f6\u4f1a\u51fa\u9519\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u5728 ",(0,l.kt)("inlineCode",{parentName:"p"},"Web.Entry")," \u5c42\u5b89\u88c5\u4e0b\u9762\u51e0\u4e2a\u5305\u5373\u53ef\uff1a"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Microsoft.CodeAnalysis.CSharp.Features")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Microsoft.CodeAnalysis.CSharp.Scripting")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Microsoft.CodeAnalysis.VisualBasic.Features")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Microsoft.CodeAnalysis.Workspaces.MSBuild")),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"Microsoft.VisualStudio.Web.CodeGeneration.Design"))),(0,l.kt)("h2",{id:"227-\u4f7f\u7528-net5-\u811a\u624b\u67b6"},"2.2.7 \u4f7f\u7528 ",(0,l.kt)("inlineCode",{parentName:"h2"},".NET5")," \u811a\u624b\u67b6"),(0,l.kt)("p",null,"\u76ee\u524d ",(0,l.kt)("inlineCode",{parentName:"p"},"Furion")," \u53ea\u63d0\u4f9b\u4e86 ",(0,l.kt)("inlineCode",{parentName:"p"},".NET6+")," \u7248\u672c\u811a\u624b\u67b6\uff0c\u5982\u9700\u4f7f\u7528 ",(0,l.kt)("inlineCode",{parentName:"p"},".NET")," \u7248\u672c\uff0c\u53ef\u521b\u5efa\u4e4b\u540e\u6267\u884c\u4e0b\u9762\u6b65\u9aa4\uff1a"),(0,l.kt)("ol",null,(0,l.kt)("li",{parentName:"ol"},(0,l.kt)("p",{parentName:"li"},"\u66ff\u6362 ",(0,l.kt)("inlineCode",{parentName:"p"},"net6.0")," \u4e3a ",(0,l.kt)("inlineCode",{parentName:"p"},"net5.0"))),(0,l.kt)("li",{parentName:"ol"},(0,l.kt)("p",{parentName:"li"},"\u7f16\u8f91\u6240\u6709\u5c42 ",(0,l.kt)("inlineCode",{parentName:"p"},".csproj")," \u6587\u4ef6\u5e76\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"p"},"10.0"),"\uff0c\u5982\uff1a"))),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-xml",metastring:"showLineNumbers {3}",showLineNumbers:!0,"{3}":!0},"\n net5.0\n 10.0\n \x3c!-- \u5176\u4ed6\u914d\u7f6e --\x3e\n\n")),(0,l.kt)("ol",{start:3},(0,l.kt)("li",{parentName:"ol"},"\u5982\u679c\u4f7f\u7528\u7684\u662f ",(0,l.kt)("inlineCode",{parentName:"li"},"EFCore")," \u7248\u672c\u5219\u9700\u8981\u5c06\u542f\u52a8\u5c42\u7684 ",(0,l.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.Tools")," \u7248\u672c\u6539\u4e3a ",(0,l.kt)("inlineCode",{parentName:"li"},"5.0.17")," \u7248\u672c\uff0c\u5982\u7f16\u8f91\u542f\u52a8\u5c42\u7684 ",(0,l.kt)("inlineCode",{parentName:"li"},"Web.Entry.csproj"),"\uff1a")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-xml",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},'\n all\n runtime; build; native; contentfiles; analyzers; buildtransitive\n\n')),(0,l.kt)("p",null,"\u6539\u4e3a\uff1a"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-xml",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},'\n all\n runtime; build; native; contentfiles; analyzers; buildtransitive\n\n')),(0,l.kt)("ol",{start:4},(0,l.kt)("li",{parentName:"ol"},"\u5728\u542f\u52a8\u5c42\u6dfb\u52a0 ",(0,l.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u6587\u4ef6")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"namespace YourProject.Web.Entry; // \u4f60\u7684\u9879\u76ee\u547d\u540d\u7a7a\u95f4\n\npublic class Startup\n{\n public Startup(IConfiguration configuration)\n {\n Configuration = configuration;\n }\n\n public IConfiguration Configuration { get; }\n\n public void ConfigureServices(IServiceCollection services)\n {\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n }\n}\n")),(0,l.kt)("ol",{start:5},(0,l.kt)("li",{parentName:"ol"},"\u4fee\u6539 ",(0,l.kt)("inlineCode",{parentName:"li"},"Program.cs")," \u4e3a\uff1a")),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"{3}":!0},"using YourProject.Web.Entry;\n\nServe.Run(RunOptions.Default);\n")),(0,l.kt)("h2",{id:"228-\u642d\u5efa\u811a\u624b\u67b6"},"2.2.8 \u642d\u5efa\u811a\u624b\u67b6"),(0,l.kt)("p",null,"\u811a\u624b\u67b6\u53ef\u4ee5\u6781\u5927\u7684\u63d0\u9ad8\u6211\u4eec\u642d\u5efa\u65b0\u9879\u76ee\u7684\u901f\u5ea6\uff0c\u63a8\u8350\u4e24\u7bc7\u6587\u7ae0\u7ed9\u5927\u5bb6\u5b66\u4e60\uff1a"),(0,l.kt)("p",null,(0,l.kt)("a",{parentName:"p",href:"https://www.cnblogs.com/laozhang-is-phi/p/10205495.html"},"https://www.cnblogs.com/laozhang-is-phi/p/10205495.html")),(0,l.kt)("p",null,(0,l.kt)("a",{parentName:"p",href:"https://www.cnblogs.com/catcher1994/p/10061470.html"},"https://www.cnblogs.com/catcher1994/p/10061470.html")),(0,l.kt)("p",null,(0,l.kt)("strong",{parentName:"p"},"\u63a8\u8350\u76f4\u63a5\u62f7\u8d1d ",(0,l.kt)("inlineCode",{parentName:"strong"},"Furion")," \u811a\u624b\u67b6\u6587\u4ef6\u5939\u8fdb\u884c\u4fee\u6539\uff0c\u53ef\u907f\u514d\u5f88\u591a\u95ee\u9898\u3002")),(0,l.kt)("p",null,(0,l.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/tree/net6/templates"},"Furion \u811a\u624b\u67b6\u6e90\u7801")),(0,l.kt)("h2",{id:"229-\u53cd\u9988\u4e0e\u5efa\u8bae"},"2.2.9 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,l.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,l.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,l.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,l.kt)("hr",null),(0,l.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,l.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,l.kt)("inlineCode",{parentName:"p"},"\u6a21\u677f\u77e5\u8bc6")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,l.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/dotnet/core/tools/dotnet-new"},"dotnet-new \u6a21\u677f")," \u7ae0\u8282\u3002")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/69b28fcd.6676266a.js b/handbook/build/assets/js/69b28fcd.6676266a.js deleted file mode 100644 index b3cdf8543f..0000000000 --- a/handbook/build/assets/js/69b28fcd.6676266a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[1186],{7557:function(e,n,t){t.r(n),t.d(n,{assets:function(){return u},contentTitle:function(){return p},default:function(){return v},frontMatter:function(){return l},metadata:function(){return c},toc:function(){return d}});var r=t(3117),a=t(102),i=(t(7294),t(3905)),o=t(1402),s=["components"],l={id:"event-bus-old",title:"22. \u4e8b\u4ef6\u603b\u7ebf",sidebar_label:"22. \u4e8b\u4ef6\u603b\u7ebf"},p=void 0,c={unversionedId:"event-bus-old",id:"event-bus-old",title:"22. \u4e8b\u4ef6\u603b\u7ebf",description:"",source:"@site/docs/event-bus-old.mdx",sourceDirName:".",slug:"/event-bus-old",permalink:"/furion/docs/event-bus-old",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/event-bus-old.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"event-bus-old",title:"22. \u4e8b\u4ef6\u603b\u7ebf",sidebar_label:"22. \u4e8b\u4ef6\u603b\u7ebf"}},u={},d=[{value:"22.1 \u4ec0\u4e48\u662f\u4e8b\u4ef6\u603b\u7ebf",id:"221-\u4ec0\u4e48\u662f\u4e8b\u4ef6\u603b\u7ebf",level:2},{value:"22.2 MessageCenter \u6d88\u606f\u4e2d\u5fc3",id:"222-messagecenter-\u6d88\u606f\u4e2d\u5fc3",level:2},{value:"22.2.1 \u6ce8\u518c \u8f7b\u91cf\u7ea7\u4e8b\u4ef6\u603b\u7ebf\u670d\u52a1",id:"2221-\u6ce8\u518c-\u8f7b\u91cf\u7ea7\u4e8b\u4ef6\u603b\u7ebf\u670d\u52a1",level:3},{value:"22.2.2 \u5b9a\u4e49\u8ba2\u9605\u5904\u7406\u7a0b\u5e8f",id:"2222-\u5b9a\u4e49\u8ba2\u9605\u5904\u7406\u7a0b\u5e8f",level:3},{value:"22.2.3 \u53d1\u5e03\u6d88\u606f",id:"2223-\u53d1\u5e03\u6d88\u606f",level:3},{value:"22.2.4 \u76f4\u63a5\u8ba2\u9605\u6d88\u606f",id:"2224-\u76f4\u63a5\u8ba2\u9605\u6d88\u606f",level:3},{value:"22.3 \u540c\u6b65\u65b9\u5f0f\u6267\u884c",id:"223-\u540c\u6b65\u65b9\u5f0f\u6267\u884c",level:2},{value:"22.4 \u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165",id:"224-\u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165",level:2},{value:"22.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"225-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:d};function v(e){var n=e.components,t=(0,a.Z)(e,s);return(0,i.kt)("wrapper",(0,r.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{title:"v2.20+ \u7248\u672c\u8bf4\u660e",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("strong",{parentName:"p"},"\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v2.20+")," \u7248\u672c\u540e\u91c7\u7528 ",(0,i.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Jaina"},"Jaina")," \u4e8b\u4ef6\u603b\u7ebf\u66ff\u6362\u539f\u6709\u7684 ",(0,i.kt)("inlineCode",{parentName:"strong"},"EventBus")),"\uff0c",(0,i.kt)("strong",{parentName:"p"},"\ud83d\ude36",(0,i.kt)("a",{parentName:"strong",href:"./event-bus"},"\u67e5\u770b\u65b0\u6587\u6863")))),(0,i.kt)("h2",{id:"221-\u4ec0\u4e48\u662f\u4e8b\u4ef6\u603b\u7ebf"},"22.1 \u4ec0\u4e48\u662f\u4e8b\u4ef6\u603b\u7ebf"),(0,i.kt)("p",null,"\u4e8b\u4ef6\u603b\u7ebf\u662f\u5bf9\u53d1\u5e03-\u8ba2\u9605\u6a21\u5f0f\u7684\u4e00\u79cd\u5b9e\u73b0\u3002\u5b83\u662f\u4e00\u79cd\u96c6\u4e2d\u5f0f\u4e8b\u4ef6\u5904\u7406\u673a\u5236\uff0c\u5141\u8bb8\u4e0d\u540c\u7684\u7ec4\u4ef6\u4e4b\u95f4\u8fdb\u884c\u5f7c\u6b64\u901a\u4fe1\u800c\u53c8\u4e0d\u9700\u8981\u76f8\u4e92\u4f9d\u8d56\uff0c\u8fbe\u5230\u4e00\u79cd\u89e3\u8026\u7684\u76ee\u7684\u3002"),(0,i.kt)("p",null,"\u6211\u4eec\u6765\u770b\u770b\u4e8b\u4ef6\u603b\u7ebf\u7684\u5904\u7406\u6d41\u7a0b\uff1a"),(0,i.kt)("img",{src:(0,o.Z)("img/event1.png")}),(0,i.kt)("h2",{id:"222-messagecenter-\u6d88\u606f\u4e2d\u5fc3"},"22.2 ",(0,i.kt)("inlineCode",{parentName:"h2"},"MessageCenter")," \u6d88\u606f\u4e2d\u5fc3"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5b9e\u73b0\u4e86\u4e00\u79cd\u8f7b\u91cf\u7ea7\u7684\u4e8b\u4ef6\u603b\u7ebf\u5b9e\u73b0\u673a\u5236\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"MessageCenter"),"\uff08\u6d88\u606f\u4e2d\u5fc3\uff09\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"MessageCenter")," \u91c7\u7528\u5b57\u7b26\u4e32\u6d88\u606f\u673a\u5236\u8fdb\u884c\u5e7f\u64ad\uff0c \u53ef\u4ee5\u5728\u7edd\u5927\u591a\u6570\u4e2d\u5c0f\u578b\u9879\u76ee\u4e2d\u53d1\u6325\u4f5c\u7528\uff0c\u7f3a\u70b9\u662f\u6d88\u606f\u5904\u7406\u662f\u5728\u4e3b\u7ebf\u7a0b\u4e2d\u5b8c\u6210\u5e76\u4e14\u6d88\u606f\u4e0d\u652f\u6301\u5206\u5e03\u5f0f\u5b58\u50a8\u3002"),(0,i.kt)("p",null,"\u53e6\u5916\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"MessageCenter")," \u652f\u6301\u5355\u64ad\u3001\u591a\u64ad\u53d1\u5e03\u53ca\u591a\u8ba2\u9605\u3002\u5982\u56fe\u6240\u793a\uff1a"),(0,i.kt)("img",{src:(0,o.Z)("img/event2.png")}),(0,i.kt)("h3",{id:"2221-\u6ce8\u518c-\u8f7b\u91cf\u7ea7\u4e8b\u4ef6\u603b\u7ebf\u670d\u52a1"},"22.2.1 \u6ce8\u518c ",(0,i.kt)("inlineCode",{parentName:"h3"},"\u8f7b\u91cf\u7ea7\u4e8b\u4ef6\u603b\u7ebf\u670d\u52a1")),(0,i.kt)("p",null,"\u5982\u679c\u60f3\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"MessageCenter")," \u8f7b\u91cf\u7ea7\u4e8b\u4ef6\u603b\u7ebf\uff0c\u53ea\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c\u670d\u52a1\u5373\u53ef\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public void ConfigureServices(IServiceCollection services)\n{\n services.AddSimpleEventBus();\n}\n")),(0,i.kt)("h3",{id:"2222-\u5b9a\u4e49\u8ba2\u9605\u5904\u7406\u7a0b\u5e8f"},"22.2.2 \u5b9a\u4e49\u8ba2\u9605\u5904\u7406\u7a0b\u5e8f"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"MessageCenter")," \u662f\u6839\u636e ",(0,i.kt)("inlineCode",{parentName:"p"},"MesseageId")," \u6d88\u606f Id \u6765\u89e6\u53d1\u5bf9\u5e94\u7684\u5904\u7406\u7a0b\u5e8f\u7684\uff0c\u6240\u4ee5\u6211\u4eec\u9700\u8981\u5b9a\u4e49 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u8ba2\u9605\u5904\u7406\u7a0b\u5e8f\u7c7b"),"\uff0c\u8be5\u7c7b\u9700\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"p"},"ISubscribeHandler")," \u63a5\u53e3\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4-5,11-13}",showLineNumbers:!0,"":!0,"{1,4-5,11-13}":!0},'public class UserChangeSubscribeHandler : ISubscribeHandler\n{\n // \u5b9a\u4e49\u4e00\u6761\u6d88\u606f\n [SubscribeMessage("create:user")]\n public void CreateUser(string eventId, object payload)\n {\n Console.WriteLine("\u6211\u662f"+eventId);\n }\n\n // \u591a\u6761\u6d88\u606f\u5171\u7528\u540c\u4e00\u4e2a\u5904\u7406\u7a0b\u5e8f\n [SubscribeMessage("delete:user")]\n [SubscribeMessage("remove:user")]\n public void RemoveUser(string eventId, object payload)\n {\n Console.WriteLine("\u6211\u662f"+eventId);\n }\n\n // \u652f\u6301\u5f02\u6b65\n [SubscribeMessage("delete:user")]\n public async Task SupportAsync(string eventId, object payload)\n {\n await MethodAsync();\n }\n}\n')),(0,i.kt)("h3",{id:"2223-\u53d1\u5e03\u6d88\u606f"},"22.2.3 \u53d1\u5e03\u6d88\u606f"),(0,i.kt)("p",null,"\u5b9a\u4e49\u597d\u8ba2\u9605\u5904\u7406\u7a0b\u5e8f\u540e\uff0c\u6211\u4eec\u5c31\u53ef\u4ee5\u5728\u7a0b\u5e8f\u4efb\u4f55\u5730\u65b9\u8fdb\u884c\u5e7f\u64ad\u6d88\u606f\uff0c\u4e8b\u4ef6\u603b\u7ebf\u4f1a\u81ea\u52a8\u6839\u636e ",(0,i.kt)("inlineCode",{parentName:"p"},"\u6d88\u606f Id")," \u89e6\u53d1\u5bf9\u5e94\u7684\u5904\u7406\u7a0b\u5e8f\u65b9\u6cd5\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'MessageCenter.Send("create:user", new User {}); // => \u6253\u5370\uff1a\u6211\u662fcreate:user\n\nMessageCenter.Send("delete:user", new User {}); // => \u6253\u5370\uff1a\u6211\u662fdelete:user\nMessageCenter.Send("remove:user", new User {}); // => \u6253\u5370\uff1a\u6211\u662fremove:user\n')),(0,i.kt)("h3",{id:"2224-\u76f4\u63a5\u8ba2\u9605\u6d88\u606f"},"22.2.4 \u76f4\u63a5\u8ba2\u9605\u6d88\u606f"),(0,i.kt)("p",null,"\u5728\u4e0a\u9762\u7684\u4f8b\u5b50\u4e2d\uff0c\u6211\u4eec\u9700\u8981\u521b\u5efa ",(0,i.kt)("inlineCode",{parentName:"p"},"ISubscribeHandler")," \u7684\u6d3e\u751f\u7c7b\u8fdb\u884c\u76f8\u5173\u914d\u7f6e\u624d\u80fd\u5b9e\u73b0\u8ba2\u9605\u5904\u7406\u3002"),(0,i.kt)("p",null,"\u5728\u67d0\u4e9b\u7279\u6b8a\u60c5\u51b5\u4e0b\uff0c\u53ef\u80fd\u53ea\u9700\u8981\u8ba2\u9605\u4e00\u6b21\u5373\u53ef\u3002\u6240\u4ee5\uff0c\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u4e3a\u4e86\u66f4\u7b80\u4fbf\u7684\u8ba2\u9605\u6d88\u606f\uff0c\u4e5f\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"MessageCenter.Subscribe")," \u9759\u6001\u65b9\u6cd5\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'MessageCenter.Subscribe("create:user", (i,p) => {\n // do something\u3002\u3002\u3002\n});\n')),(0,i.kt)("h2",{id:"223-\u540c\u6b65\u65b9\u5f0f\u6267\u884c"},"22.3 \u540c\u6b65\u65b9\u5f0f\u6267\u884c"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u4e8b\u4ef6\u603b\u7ebf\u603b\u662f\u91c7\u7528\u65b0\u7ebf\u7a0b\u65b9\u5f0f\u6267\u884c\uff0c\u4f46\u662f\u6211\u4eec\u53ef\u4ee5\u914d\u7f6e\u4e3a\u540c\u6b65\u65b9\u5f0f\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'MessageCenter.Send("create:user", isSync: true);\n')),(0,i.kt)("h2",{id:"224-\u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165"},"22.4 \u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u4e8b\u4ef6\u603b\u7ebf\u662f\u4e0d\u652f\u6301\u6784\u9020\u51fd\u6570\u6ce8\u5165\u7684\uff0c\u800c\u4e14\u6784\u9020\u51fd\u6570\u4e5f\u53ea\u4f1a\u6267\u884c\u4e00\u6b21\u3002\u6240\u4ee5\u9700\u8981\u7528\u5230\u670d\u52a1\uff0c\u5e94\u8be5\u901a\u8fc7\u9759\u6001\u7c7b\u89e3\u6790\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"App.GetService()")," \u6216 ",(0,i.kt)("inlineCode",{parentName:"p"},"Db.GetRepository()"),"\u3002"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,12-20}",showLineNumbers:!0,"":!0,"{5,12-20}":!0},'public class UserChangeSubscribeHandler : ISubscribeHandler\n{\n public UserChangeSubscribeHandler()\n {\n // \u4e0d\u652f\u6301\u8fd9\u91cc\u89e3\u6790\u670d\u52a1\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\n }\n\n // \u5b9a\u4e49\u4e00\u6761\u6d88\u606f\n [SubscribeMessage("create:user")]\n public void CreateUser(string eventId, object payload)\n {\n // \u521b\u5efa\u4e00\u4e2a\u4f5c\u7528\u57df\uff0c\u5bf9\u8c61\u4f7f\u7528\u5b8c\u6210\u81ea\u52a8\u91ca\u653e\n Scoped.Create((_, scope) =>\n {\n var services = scope.ServiceProvider;\n\n var repository = Db.GetRepository(services); // services \u4f20\u9012\u8fdb\u53bb\n var someService = App.GetService(services); // services \u4f20\u9012\u8fdb\u53bb\n var otherService = services.GetService(); // \u76f4\u63a5\u7528 services \u89e3\u6790\n });\n }\n}\n')),(0,i.kt)("admonition",{type:"note"},(0,i.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u5173\u4e8e ",(0,i.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"App.GetService()")," \u89e3\u6790\u670d\u52a1"),(0,i.kt)("p",{parentName:"admonition"},"\u5728\u9ad8\u9891\u5b9a\u65f6\u4efb\u52a1\u4e2d\u8c03\u7528",(0,i.kt)("inlineCode",{parentName:"p"},"App.GetService(TService)"),"\uff0c\u53ef\u80fd\u4f1a\u51fa\u73b0\u5185\u5b58\u65e0\u6cd5\u56de\u6536\u7684\u60c5\u51b5\uff0c\u5efa\u8bae\u59cb\u7ec8\u4f7f\u7528",(0,i.kt)("inlineCode",{parentName:"p"},"scope.ServiceProvider.GetService(TService)"),"\u6765\u83b7\u53d6",(0,i.kt)("inlineCode",{parentName:"p"},"TService"))),(0,i.kt)("admonition",{title:"\u6570\u636e\u5e93\u64cd\u4f5c\u6ce8\u610f",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f5c\u7528\u57df\u4e2d\u5bf9",(0,i.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u6709\u4efb\u4f55\u53d8\u66f4\u64cd\u4f5c"),"\uff0c\u9700\u624b\u52a8\u8c03\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216\u5e26 ",(0,i.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u65b9\u6cd5\u3002\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Scoped.CreateUow(handler)")," \u4ee3\u66ff\u3002")),(0,i.kt)("admonition",{title:"\u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"ISubscribeHandler")," \u63a5\u53e3\u4e3b\u8981\u662f\u7528\u6765\u67e5\u627e\u5b9a\u4e49\u4e8b\u4ef6\u5bf9\u8c61\u7684\uff0c\u4e5f\u5c31\u662f\u5b83\u7684\u5b9e\u73b0\u7c7b\u5e76\u672a\u63d0\u4f9b\u4f9d\u8d56\u6ce8\u5165\u529f\u80fd\uff0c\u6240\u4ee5\u5728\u5b9e\u73b0\u7c7b\u5e76\u4e0d\u652f\u6301\u6784\u9020\u51fd\u6570\u6ce8\u5165\u4f9d\u8d56\u9879\u3002")),(0,i.kt)("h2",{id:"225-\u53cd\u9988\u4e0e\u5efa\u8bae"},"22.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}v.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return c},kt:function(){return m}});var r=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function o(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=r.createContext({}),p=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},c=function(e){var n=p(e.components);return r.createElement(l.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),d=p(t),m=a,v=d["".concat(l,".").concat(m)]||d[m]||u[m]||i;return t?r.createElement(v,o(o({ref:n},c),{},{components:t})):r.createElement(v,o({ref:n},c))}));function m(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,o=new Array(i);o[0]=d;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var p=2;p=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=r.createContext({}),p=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},c=function(e){var n=p(e.components);return r.createElement(l.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),d=p(t),m=a,v=d["".concat(l,".").concat(m)]||d[m]||u[m]||i;return t?r.createElement(v,o(o({ref:n},c),{},{components:t})):r.createElement(v,o({ref:n},c))}));function m(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,o=new Array(i);o[0]=d;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var p=2;pMessageCenter \u6d88\u606f\u4e2d\u5fc3",id:"222-messagecenter-\u6d88\u606f\u4e2d\u5fc3",level:2},{value:"22.2.1 \u6ce8\u518c \u8f7b\u91cf\u7ea7\u4e8b\u4ef6\u603b\u7ebf\u670d\u52a1",id:"2221-\u6ce8\u518c-\u8f7b\u91cf\u7ea7\u4e8b\u4ef6\u603b\u7ebf\u670d\u52a1",level:3},{value:"22.2.2 \u5b9a\u4e49\u8ba2\u9605\u5904\u7406\u7a0b\u5e8f",id:"2222-\u5b9a\u4e49\u8ba2\u9605\u5904\u7406\u7a0b\u5e8f",level:3},{value:"22.2.3 \u53d1\u5e03\u6d88\u606f",id:"2223-\u53d1\u5e03\u6d88\u606f",level:3},{value:"22.2.4 \u76f4\u63a5\u8ba2\u9605\u6d88\u606f",id:"2224-\u76f4\u63a5\u8ba2\u9605\u6d88\u606f",level:3},{value:"22.3 \u540c\u6b65\u65b9\u5f0f\u6267\u884c",id:"223-\u540c\u6b65\u65b9\u5f0f\u6267\u884c",level:2},{value:"22.4 \u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165",id:"224-\u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165",level:2},{value:"22.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"225-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:d};function v(e){var n=e.components,t=(0,a.Z)(e,s);return(0,i.kt)("wrapper",(0,r.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{title:"v2.20+ \u7248\u672c\u8bf4\u660e",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("strong",{parentName:"p"},"\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v2.20+")," \u7248\u672c\u540e\u91c7\u7528 ",(0,i.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Jaina"},"Jaina")," \u4e8b\u4ef6\u603b\u7ebf\u66ff\u6362\u539f\u6709\u7684 ",(0,i.kt)("inlineCode",{parentName:"strong"},"EventBus")),"\uff0c",(0,i.kt)("strong",{parentName:"p"},"\ud83d\ude36",(0,i.kt)("a",{parentName:"strong",href:"./event-bus"},"\u67e5\u770b\u65b0\u6587\u6863")))),(0,i.kt)("h2",{id:"221-\u4ec0\u4e48\u662f\u4e8b\u4ef6\u603b\u7ebf"},"22.1 \u4ec0\u4e48\u662f\u4e8b\u4ef6\u603b\u7ebf"),(0,i.kt)("p",null,"\u4e8b\u4ef6\u603b\u7ebf\u662f\u5bf9\u53d1\u5e03-\u8ba2\u9605\u6a21\u5f0f\u7684\u4e00\u79cd\u5b9e\u73b0\u3002\u5b83\u662f\u4e00\u79cd\u96c6\u4e2d\u5f0f\u4e8b\u4ef6\u5904\u7406\u673a\u5236\uff0c\u5141\u8bb8\u4e0d\u540c\u7684\u7ec4\u4ef6\u4e4b\u95f4\u8fdb\u884c\u5f7c\u6b64\u901a\u4fe1\u800c\u53c8\u4e0d\u9700\u8981\u76f8\u4e92\u4f9d\u8d56\uff0c\u8fbe\u5230\u4e00\u79cd\u89e3\u8026\u7684\u76ee\u7684\u3002"),(0,i.kt)("p",null,"\u6211\u4eec\u6765\u770b\u770b\u4e8b\u4ef6\u603b\u7ebf\u7684\u5904\u7406\u6d41\u7a0b\uff1a"),(0,i.kt)("img",{src:(0,o.Z)("img/event1.png")}),(0,i.kt)("h2",{id:"222-messagecenter-\u6d88\u606f\u4e2d\u5fc3"},"22.2 ",(0,i.kt)("inlineCode",{parentName:"h2"},"MessageCenter")," \u6d88\u606f\u4e2d\u5fc3"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5b9e\u73b0\u4e86\u4e00\u79cd\u8f7b\u91cf\u7ea7\u7684\u4e8b\u4ef6\u603b\u7ebf\u5b9e\u73b0\u673a\u5236\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"MessageCenter"),"\uff08\u6d88\u606f\u4e2d\u5fc3\uff09\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"MessageCenter")," \u91c7\u7528\u5b57\u7b26\u4e32\u6d88\u606f\u673a\u5236\u8fdb\u884c\u5e7f\u64ad\uff0c \u53ef\u4ee5\u5728\u7edd\u5927\u591a\u6570\u4e2d\u5c0f\u578b\u9879\u76ee\u4e2d\u53d1\u6325\u4f5c\u7528\uff0c\u7f3a\u70b9\u662f\u6d88\u606f\u5904\u7406\u662f\u5728\u4e3b\u7ebf\u7a0b\u4e2d\u5b8c\u6210\u5e76\u4e14\u6d88\u606f\u4e0d\u652f\u6301\u5206\u5e03\u5f0f\u5b58\u50a8\u3002"),(0,i.kt)("p",null,"\u53e6\u5916\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"MessageCenter")," \u652f\u6301\u5355\u64ad\u3001\u591a\u64ad\u53d1\u5e03\u53ca\u591a\u8ba2\u9605\u3002\u5982\u56fe\u6240\u793a\uff1a"),(0,i.kt)("img",{src:(0,o.Z)("img/event2.png")}),(0,i.kt)("h3",{id:"2221-\u6ce8\u518c-\u8f7b\u91cf\u7ea7\u4e8b\u4ef6\u603b\u7ebf\u670d\u52a1"},"22.2.1 \u6ce8\u518c ",(0,i.kt)("inlineCode",{parentName:"h3"},"\u8f7b\u91cf\u7ea7\u4e8b\u4ef6\u603b\u7ebf\u670d\u52a1")),(0,i.kt)("p",null,"\u5982\u679c\u60f3\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"MessageCenter")," \u8f7b\u91cf\u7ea7\u4e8b\u4ef6\u603b\u7ebf\uff0c\u53ea\u9700\u8981\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c\u670d\u52a1\u5373\u53ef\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public void ConfigureServices(IServiceCollection services)\n{\n services.AddSimpleEventBus();\n}\n")),(0,i.kt)("h3",{id:"2222-\u5b9a\u4e49\u8ba2\u9605\u5904\u7406\u7a0b\u5e8f"},"22.2.2 \u5b9a\u4e49\u8ba2\u9605\u5904\u7406\u7a0b\u5e8f"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"MessageCenter")," \u662f\u6839\u636e ",(0,i.kt)("inlineCode",{parentName:"p"},"MesseageId")," \u6d88\u606f Id \u6765\u89e6\u53d1\u5bf9\u5e94\u7684\u5904\u7406\u7a0b\u5e8f\u7684\uff0c\u6240\u4ee5\u6211\u4eec\u9700\u8981\u5b9a\u4e49 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u8ba2\u9605\u5904\u7406\u7a0b\u5e8f\u7c7b"),"\uff0c\u8be5\u7c7b\u9700\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"p"},"ISubscribeHandler")," \u63a5\u53e3\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4-5,11-13}",showLineNumbers:!0,"":!0,"{1,4-5,11-13}":!0},'public class UserChangeSubscribeHandler : ISubscribeHandler\n{\n // \u5b9a\u4e49\u4e00\u6761\u6d88\u606f\n [SubscribeMessage("create:user")]\n public void CreateUser(string eventId, object payload)\n {\n Console.WriteLine("\u6211\u662f"+eventId);\n }\n\n // \u591a\u6761\u6d88\u606f\u5171\u7528\u540c\u4e00\u4e2a\u5904\u7406\u7a0b\u5e8f\n [SubscribeMessage("delete:user")]\n [SubscribeMessage("remove:user")]\n public void RemoveUser(string eventId, object payload)\n {\n Console.WriteLine("\u6211\u662f"+eventId);\n }\n\n // \u652f\u6301\u5f02\u6b65\n [SubscribeMessage("delete:user")]\n public async Task SupportAsync(string eventId, object payload)\n {\n await MethodAsync();\n }\n}\n')),(0,i.kt)("h3",{id:"2223-\u53d1\u5e03\u6d88\u606f"},"22.2.3 \u53d1\u5e03\u6d88\u606f"),(0,i.kt)("p",null,"\u5b9a\u4e49\u597d\u8ba2\u9605\u5904\u7406\u7a0b\u5e8f\u540e\uff0c\u6211\u4eec\u5c31\u53ef\u4ee5\u5728\u7a0b\u5e8f\u4efb\u4f55\u5730\u65b9\u8fdb\u884c\u5e7f\u64ad\u6d88\u606f\uff0c\u4e8b\u4ef6\u603b\u7ebf\u4f1a\u81ea\u52a8\u6839\u636e ",(0,i.kt)("inlineCode",{parentName:"p"},"\u6d88\u606f Id")," \u89e6\u53d1\u5bf9\u5e94\u7684\u5904\u7406\u7a0b\u5e8f\u65b9\u6cd5\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'MessageCenter.Send("create:user", new User {}); // => \u6253\u5370\uff1a\u6211\u662fcreate:user\n\nMessageCenter.Send("delete:user", new User {}); // => \u6253\u5370\uff1a\u6211\u662fdelete:user\nMessageCenter.Send("remove:user", new User {}); // => \u6253\u5370\uff1a\u6211\u662fremove:user\n')),(0,i.kt)("h3",{id:"2224-\u76f4\u63a5\u8ba2\u9605\u6d88\u606f"},"22.2.4 \u76f4\u63a5\u8ba2\u9605\u6d88\u606f"),(0,i.kt)("p",null,"\u5728\u4e0a\u9762\u7684\u4f8b\u5b50\u4e2d\uff0c\u6211\u4eec\u9700\u8981\u521b\u5efa ",(0,i.kt)("inlineCode",{parentName:"p"},"ISubscribeHandler")," \u7684\u6d3e\u751f\u7c7b\u8fdb\u884c\u76f8\u5173\u914d\u7f6e\u624d\u80fd\u5b9e\u73b0\u8ba2\u9605\u5904\u7406\u3002"),(0,i.kt)("p",null,"\u5728\u67d0\u4e9b\u7279\u6b8a\u60c5\u51b5\u4e0b\uff0c\u53ef\u80fd\u53ea\u9700\u8981\u8ba2\u9605\u4e00\u6b21\u5373\u53ef\u3002\u6240\u4ee5\uff0c\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u4e3a\u4e86\u66f4\u7b80\u4fbf\u7684\u8ba2\u9605\u6d88\u606f\uff0c\u4e5f\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"MessageCenter.Subscribe")," \u9759\u6001\u65b9\u6cd5\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'MessageCenter.Subscribe("create:user", (i,p) => {\n // do something\u3002\u3002\u3002\n});\n')),(0,i.kt)("h2",{id:"223-\u540c\u6b65\u65b9\u5f0f\u6267\u884c"},"22.3 \u540c\u6b65\u65b9\u5f0f\u6267\u884c"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u4e8b\u4ef6\u603b\u7ebf\u603b\u662f\u91c7\u7528\u65b0\u7ebf\u7a0b\u65b9\u5f0f\u6267\u884c\uff0c\u4f46\u662f\u6211\u4eec\u53ef\u4ee5\u914d\u7f6e\u4e3a\u540c\u6b65\u65b9\u5f0f\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'MessageCenter.Send("create:user", isSync: true);\n')),(0,i.kt)("h2",{id:"224-\u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165"},"22.4 \u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u4e8b\u4ef6\u603b\u7ebf\u662f\u4e0d\u652f\u6301\u6784\u9020\u51fd\u6570\u6ce8\u5165\u7684\uff0c\u800c\u4e14\u6784\u9020\u51fd\u6570\u4e5f\u53ea\u4f1a\u6267\u884c\u4e00\u6b21\u3002\u6240\u4ee5\u9700\u8981\u7528\u5230\u670d\u52a1\uff0c\u5e94\u8be5\u901a\u8fc7\u9759\u6001\u7c7b\u89e3\u6790\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"App.GetService()")," \u6216 ",(0,i.kt)("inlineCode",{parentName:"p"},"Db.GetRepository()"),"\u3002"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,12-20}",showLineNumbers:!0,"":!0,"{5,12-20}":!0},'public class UserChangeSubscribeHandler : ISubscribeHandler\n{\n public UserChangeSubscribeHandler()\n {\n // \u4e0d\u652f\u6301\u8fd9\u91cc\u89e3\u6790\u670d\u52a1\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\n }\n\n // \u5b9a\u4e49\u4e00\u6761\u6d88\u606f\n [SubscribeMessage("create:user")]\n public void CreateUser(string eventId, object payload)\n {\n // \u521b\u5efa\u4e00\u4e2a\u4f5c\u7528\u57df\uff0c\u5bf9\u8c61\u4f7f\u7528\u5b8c\u6210\u81ea\u52a8\u91ca\u653e\n Scoped.Create((_, scope) =>\n {\n var services = scope.ServiceProvider;\n\n var repository = Db.GetRepository(services); // services \u4f20\u9012\u8fdb\u53bb\n var someService = App.GetService(services); // services \u4f20\u9012\u8fdb\u53bb\n var otherService = services.GetService(); // \u76f4\u63a5\u7528 services \u89e3\u6790\n });\n }\n}\n')),(0,i.kt)("admonition",{type:"note"},(0,i.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u5173\u4e8e ",(0,i.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"App.GetService()")," \u89e3\u6790\u670d\u52a1"),(0,i.kt)("p",{parentName:"admonition"},"\u5728\u9ad8\u9891\u5b9a\u65f6\u4efb\u52a1\u4e2d\u8c03\u7528",(0,i.kt)("inlineCode",{parentName:"p"},"App.GetService(TService)"),"\uff0c\u53ef\u80fd\u4f1a\u51fa\u73b0\u5185\u5b58\u65e0\u6cd5\u56de\u6536\u7684\u60c5\u51b5\uff0c\u5efa\u8bae\u59cb\u7ec8\u4f7f\u7528",(0,i.kt)("inlineCode",{parentName:"p"},"scope.ServiceProvider.GetService(TService)"),"\u6765\u83b7\u53d6",(0,i.kt)("inlineCode",{parentName:"p"},"TService"))),(0,i.kt)("admonition",{title:"\u6570\u636e\u5e93\u64cd\u4f5c\u6ce8\u610f",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f5c\u7528\u57df\u4e2d\u5bf9",(0,i.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u6709\u4efb\u4f55\u53d8\u66f4\u64cd\u4f5c"),"\uff0c\u9700\u624b\u52a8\u8c03\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216\u5e26 ",(0,i.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u65b9\u6cd5\u3002\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Scoped.CreateUow(handler)")," \u4ee3\u66ff\u3002")),(0,i.kt)("admonition",{title:"\u5173\u4e8e\u4f9d\u8d56\u6ce8\u5165",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"ISubscribeHandler")," \u63a5\u53e3\u4e3b\u8981\u662f\u7528\u6765\u67e5\u627e\u5b9a\u4e49\u4e8b\u4ef6\u5bf9\u8c61\u7684\uff0c\u4e5f\u5c31\u662f\u5b83\u7684\u5b9e\u73b0\u7c7b\u5e76\u672a\u63d0\u4f9b\u4f9d\u8d56\u6ce8\u5165\u529f\u80fd\uff0c\u6240\u4ee5\u5728\u5b9e\u73b0\u7c7b\u5e76\u4e0d\u652f\u6301\u6784\u9020\u51fd\u6570\u6ce8\u5165\u4f9d\u8d56\u9879\u3002")),(0,i.kt)("h2",{id:"225-\u53cd\u9988\u4e0e\u5efa\u8bae"},"22.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}v.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/6b7b862c.ac22c3a5.js b/handbook/build/assets/js/6b7b862c.ac22c3a5.js deleted file mode 100644 index 6e572c8cd8..0000000000 --- a/handbook/build/assets/js/6b7b862c.ac22c3a5.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[6366],{2925:function(e,n,t){t.r(n),t.d(n,{assets:function(){return d},contentTitle:function(){return i},default:function(){return c},frontMatter:function(){return u},metadata:function(){return p},toc:function(){return m}});var r=t(3117),a=t(102),s=(t(7294),t(3905)),o=["components"],u={id:"dbcontext-update",title:"9.6 \u66f4\u65b0\u64cd\u4f5c",sidebar_label:"9.6 \u66f4\u65b0\u64cd\u4f5c"},i=void 0,p={unversionedId:"dbcontext-update",id:"dbcontext-update",title:"9.6 \u66f4\u65b0\u64cd\u4f5c",description:"\u4ee5\u4e0b\u5185\u5bb9\u5305\u542b Exists \u5355\u8bcd\u7684\u5728 Furion 2.6.0 + \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002",source:"@site/docs/dbcontext-update.mdx",sourceDirName:".",slug:"/dbcontext-update",permalink:"/furion/docs/dbcontext-update",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-update.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"dbcontext-update",title:"9.6 \u66f4\u65b0\u64cd\u4f5c",sidebar_label:"9.6 \u66f4\u65b0\u64cd\u4f5c"},sidebar:"docs",previous:{title:"9.5 \u65b0\u589e\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-add"},next:{title:"9.7 \u65b0\u589e\u6216\u66f4\u65b0\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-add-or-update"}},d={},m=[{value:"9.6.1 \u66f4\u65b0\u5168\u90e8\u5217\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09",id:"961-\u66f4\u65b0\u5168\u90e8\u5217\u4e0d\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.6.2 \u66f4\u65b0\u5168\u90e8\u5217\uff08\u7acb\u5373\u63d0\u4ea4\uff09",id:"962-\u66f4\u65b0\u5168\u90e8\u5217\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.6.3 \u66f4\u65b0\u90e8\u5206\u5217\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09",id:"963-\u66f4\u65b0\u90e8\u5206\u5217\u4e0d\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.6.4 \u66f4\u65b0\u90e8\u5206\u5217\uff08\u7acb\u5373\u63d0\u4ea4\uff09",id:"964-\u66f4\u65b0\u90e8\u5206\u5217\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.6.5 \u6392\u9664\u7279\u5b9a\u5217\u66f4\u65b0\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09",id:"965-\u6392\u9664\u7279\u5b9a\u5217\u66f4\u65b0\u4e0d\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.6.6 \u6392\u9664\u7279\u5b9a\u5217\u66f4\u65b0\uff08\u7acb\u5373\u63d0\u4ea4\uff09",id:"966-\u6392\u9664\u7279\u5b9a\u5217\u66f4\u65b0\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.6.7 \u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u6240\u6709\u5217\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09",id:"967-\u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u6240\u6709\u5217\u4e0d\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.6.8 \u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u6240\u6709\u5217\uff08\u7acb\u5373\u63d0\u4ea4\uff09",id:"968-\u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u6240\u6709\u5217\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.6.9 \u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u90e8\u5206\u5217\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09",id:"969-\u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u90e8\u5206\u5217\u4e0d\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.6.10 \u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u90e8\u5206\u5217\uff08\u7acb\u5373\u63d0\u4ea4\uff09",id:"9610-\u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u90e8\u5206\u5217\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.6.11 \u6570\u636e\u5b58\u5728\u624d\u6392\u9664\u7279\u5b9a\u90e8\u5206\u5217\u66f4\u65b0\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09",id:"9611-\u6570\u636e\u5b58\u5728\u624d\u6392\u9664\u7279\u5b9a\u90e8\u5206\u5217\u66f4\u65b0\u4e0d\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.6.12 \u6570\u636e\u5b58\u5728\u624d\u6392\u9664\u7279\u5b9a\u90e8\u5206\u5217\u66f4\u65b0\uff08\u7acb\u5373\u63d0\u4ea4\uff09",id:"9612-\u6570\u636e\u5b58\u5728\u624d\u6392\u9664\u7279\u5b9a\u90e8\u5206\u5217\u66f4\u65b0\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.6.13 \u66f4\u65b0\u591a\u6761\u8bb0\u5f55\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09",id:"9613-\u66f4\u65b0\u591a\u6761\u8bb0\u5f55\u4e0d\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.6.14 \u66f4\u65b0\u591a\u6761\u8bb0\u5f55\uff08\u7acb\u5373\u63d0\u4ea4\uff09",id:"9614-\u66f4\u65b0\u591a\u6761\u8bb0\u5f55\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.6.15 \u5ffd\u7565\u7a7a\u503c\u66f4\u65b0",id:"9615-\u5ffd\u7565\u7a7a\u503c\u66f4\u65b0",level:2},{value:"9.6.16 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9616-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],l={toc:m};function c(e){var n=e.components,t=(0,a.Z)(e,o);return(0,s.kt)("wrapper",(0,r.Z)({},l,t,{components:n,mdxType:"MDXLayout"}),(0,s.kt)("admonition",{title:"\u529f\u80fd\u79fb\u9664\u58f0\u660e",type:"warning"},(0,s.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u5305\u542b ",(0,s.kt)("inlineCode",{parentName:"p"},"Exists")," \u5355\u8bcd\u7684\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion 2.6.0 +")," \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002")),(0,s.kt)("h2",{id:"961-\u66f4\u65b0\u5168\u90e8\u5217\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.6.1 \u66f4\u65b0\u5168\u90e8\u5217\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.Update(user);\n\n// \u793a\u4f8b\u4e8c\nuser.Update();\n\n// \u793a\u4f8b\u4e09\nrepository.ChangeEntityState(user, EntityState.Modified);\n\n// \u793a\u4f8b\u56db\nrepository.Entities.Update(user);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateAsync(user);\n\n// \u793a\u4f8b\u4e8c\nawait user.UpdateAsync();\n")),(0,s.kt)("h2",{id:"962-\u66f4\u65b0\u5168\u90e8\u5217\u7acb\u5373\u63d0\u4ea4"},"9.6.2 \u66f4\u65b0\u5168\u90e8\u5217\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.UpdateNow(user);\n\n// \u793a\u4f8b\u4e8c\nuser.UpdateNow();\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateNowAsync(user);\n\n// \u793a\u4f8b\u4e8c\nawait user.UpdateNowAsync();\n")),(0,s.kt)("h2",{id:"963-\u66f4\u65b0\u90e8\u5206\u5217\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.6.3 \u66f4\u65b0\u90e8\u5206\u5217\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.UpdateInclude(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nrepository.UpdateInclude(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nrepository.UpdateInclude(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n// \u793a\u4f8b\u56db\nuser.UpdateInclude(new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nuser.UpdateInclude(new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u516d\nuser.UpdateInclude(new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateIncludeAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nawait repository.UpdateIncludeAsync(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nawait repository.UpdateIncludeAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n// \u793a\u4f8b\u56db\nawait user.UpdateIncludeAsync(new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nawait user.UpdateIncludeAsync(new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u516d\nawait user.UpdateIncludeAsync(new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n')),(0,s.kt)("h2",{id:"964-\u66f4\u65b0\u90e8\u5206\u5217\u7acb\u5373\u63d0\u4ea4"},"9.6.4 \u66f4\u65b0\u90e8\u5206\u5217\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.UpdateIncludeNow(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nrepository.UpdateIncludeNow(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nrepository.UpdateIncludeNow(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n// \u793a\u4f8b\u56db\nuser.UpdateIncludeNow(new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nuser.UpdateIncludeNow(new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u516d\nuser.UpdateInclude(new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateIncludeNowAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nawait repository.UpdateIncludeNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nawait repository.UpdateIncludeNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n// \u793a\u4f8b\u56db\nawait user.UpdateIncludeNowAsync(new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nawait user.UpdateIncludeNowAsync(new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u516d\nawait user.UpdateIncludeNowAsync(new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n')),(0,s.kt)("h2",{id:"965-\u6392\u9664\u7279\u5b9a\u5217\u66f4\u65b0\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.6.5 \u6392\u9664\u7279\u5b9a\u5217\u66f4\u65b0\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.UpdateExclude(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nrepository.UpdateExclude(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nrepository.UpdateExclude(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n// \u793a\u4f8b\u56db\nuser.UpdateExclude(new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nuser.UpdateExclude(new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u516d\nuser.UpdateExclude(new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateExcludeAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nawait repository.UpdateExcludeAsync(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nawait repository.UpdateExcludeAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n// \u793a\u4f8b\u56db\nawait user.UpdateExcludeAsync(new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nawait user.UpdateExcludeAsync(new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u516d\nawait user.UpdateExcludeAsync(new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n')),(0,s.kt)("h2",{id:"966-\u6392\u9664\u7279\u5b9a\u5217\u66f4\u65b0\u7acb\u5373\u63d0\u4ea4"},"9.6.6 \u6392\u9664\u7279\u5b9a\u5217\u66f4\u65b0\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.UpdateExcludeNow(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nrepository.UpdateExcludeNow(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nrepository.UpdateExcludeNow(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n// \u793a\u4f8b\u56db\nuser.UpdateExcludeNow(new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nuser.UpdateExcludeNow(new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u516d\nuser.UpdateExcludeNow(new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateExcludeNowAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nawait repository.UpdateExcludeNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nawait repository.UpdateExcludeNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n// \u793a\u4f8b\u56db\nawait user.UpdateExcludeNowAsync(new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e94\nawait user.UpdateExcludeNowAsync(new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u516d\nawait user.UpdateExcludeNowAsync(new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n')),(0,s.kt)("h2",{id:"967-\u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u6240\u6709\u5217\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.6.7 \u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u6240\u6709\u5217\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.UpdateExists(user);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateExistsAsync(user);\n")),(0,s.kt)("h2",{id:"968-\u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u6240\u6709\u5217\u7acb\u5373\u63d0\u4ea4"},"9.6.8 \u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u6240\u6709\u5217\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.UpdateExistsNow(user);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateExistsNowAsync(user);\n")),(0,s.kt)("h2",{id:"969-\u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u90e8\u5206\u5217\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.6.9 \u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u90e8\u5206\u5217\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.UpdateIncludeExists(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nrepository.UpdateIncludeExists(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nrepository.UpdateIncludeExists(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateIncludeExistsAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nawait repository.UpdateIncludeExistsAsync(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nawait repository.UpdateIncludeExistsAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n')),(0,s.kt)("h2",{id:"9610-\u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u90e8\u5206\u5217\u7acb\u5373\u63d0\u4ea4"},"9.6.10 \u6570\u636e\u5b58\u5728\u624d\u66f4\u65b0\u90e8\u5206\u5217\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.UpdateIncludeExistsNow(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nrepository.UpdateIncludeExistsNow(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nrepository.UpdateIncludeExistsNow(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateIncludeExistsNowAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nawait repository.UpdateIncludeExistsNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nawait repository.UpdateIncludeExistsNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n')),(0,s.kt)("h2",{id:"9611-\u6570\u636e\u5b58\u5728\u624d\u6392\u9664\u7279\u5b9a\u90e8\u5206\u5217\u66f4\u65b0\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.6.11 \u6570\u636e\u5b58\u5728\u624d\u6392\u9664\u7279\u5b9a\u90e8\u5206\u5217\u66f4\u65b0\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.UpdateExcludeExists(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nrepository.UpdateExcludeExists(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nrepository.UpdateExcludeExists(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateExcludeExistsAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nawait repository.UpdateExcludeExistsAsync(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nawait repository.UpdateExcludeExistsAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n')),(0,s.kt)("h2",{id:"9612-\u6570\u636e\u5b58\u5728\u624d\u6392\u9664\u7279\u5b9a\u90e8\u5206\u5217\u66f4\u65b0\u7acb\u5373\u63d0\u4ea4"},"9.6.12 \u6570\u636e\u5b58\u5728\u624d\u6392\u9664\u7279\u5b9a\u90e8\u5206\u5217\u66f4\u65b0\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.UpdateExcludeExistsNow(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nrepository.UpdateExcludeExistsNow(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nrepository.UpdateExcludeExistsNow(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateExcludeExistsNowAsync(user, new[] {"Age", "Name"});\n\n// \u793a\u4f8b\u4e8c\nawait repository.UpdateExcludeExistsNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)});\n\n// \u793a\u4f8b\u4e09\nawait repository.UpdateExcludeExistsNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true); // \u5ffd\u7565\u7a7a\u503c\n')),(0,s.kt)("h2",{id:"9613-\u66f4\u65b0\u591a\u6761\u8bb0\u5f55\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.6.13 \u66f4\u65b0\u591a\u6761\u8bb0\u5f55\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.Update(user, user2);\n\n// \u793a\u4f8b\u4e8c\nrepository.Update(new List { user, user2 });\n\n// \u793a\u4f8b\u4e09\nrepository.Update(new[] {user, user2 });\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateAsync(user, user2);\n\n// \u793a\u4f8b\u4e8c\nawait repository.UpdateAsync(new List { user, user2 });\n\n// \u793a\u4f8b\u4e09\nawait repository.UpdateAsync(new[] {user, user2 });\n")),(0,s.kt)("h2",{id:"9614-\u66f4\u65b0\u591a\u6761\u8bb0\u5f55\u7acb\u5373\u63d0\u4ea4"},"9.6.14 \u66f4\u65b0\u591a\u6761\u8bb0\u5f55\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.UpdateNow(user, user2);\n\n// \u793a\u4f8b\u4e8c\nrepository.UpdateNow(new List { user, user2 });\n\n// \u793a\u4f8b\u4e09\nrepository.UpdateNow(new[] {user, user2 });\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateNowAsync(user, user2);\n\n// \u793a\u4f8b\u4e8c\nawait repository.UpdateNowAsync(new List { user, user2 });\n\n// \u793a\u4f8b\u4e09\nawait repository.UpdateNowAsync(new[] {user, user2 });\n")),(0,s.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,s.kt)("p",{parentName:"admonition"},"\u6240\u6709\u5e26 ",(0,s.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u8868\u793a\u7acb\u5373\u63d0\u4ea4\u5230\u6570\u636e\u5e93\uff0c\u4e5f\u5c31\u662f\u7acb\u5373\u8c03\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216 ",(0,s.kt)("inlineCode",{parentName:"p"},"SaveChangesAsync"),"\u3002")),(0,s.kt)("h2",{id:"9615-\u5ffd\u7565\u7a7a\u503c\u66f4\u65b0"},"9.6.15 \u5ffd\u7565\u7a7a\u503c\u66f4\u65b0"),(0,s.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,s.kt)("inlineCode",{parentName:"p"},"EFCore")," \u66f4\u65b0\u4f1a\u66f4\u65b0\u5168\u90e8\u5217\uff08\u9664\u5b9e\u4f53\u8ddf\u8e2a\u65b9\u5f0f\u4ee5\u5916\uff09\uff0c\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u5e0c\u671b ",(0,s.kt)("inlineCode",{parentName:"p"},"Null")," \u503c\u65e0\u9700\u66f4\u65b0\uff0c\u8fd9\u662f\u6211\u4eec\u53ea\u9700\u8981\u5728\u66f4\u65b0\u65f6\u5019\u914d\u7f6e ",(0,s.kt)("inlineCode",{parentName:"p"},"ignoreNullValues")," \u53c2\u6570\u5373\u53ef\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"repository.Update(entity, ignoreNullValues: true);\n")),(0,s.kt)("p",null,"\u4e5f\u53ef\u4ee5\u5168\u5c40\u914d\u7f6e\uff0c\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u7684\u6d3e\u751f\u7c7b\u7684\u6784\u9020\u51fd\u6570\u4e2d\u542f\u7528\u5373\u53ef\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11}",showLineNumbers:!0,"":!0,"{11}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]\n public class DefaultDbContext : AppDbContext\n {\n public DefaultDbContext(DbContextOptions options) : base(options)\n {\n InsertOrUpdateIgnoreNullValues = true;\n }\n }\n}\n')),(0,s.kt)("h2",{id:"9616-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.6.16 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,s.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,s.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,s.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return d},kt:function(){return c}});var r=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function s(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function o(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var i=r.createContext({}),p=function(e){var n=r.useContext(i),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},d=function(e){var n=p(e.components);return r.createElement(i.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},l=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,s=e.originalType,i=e.parentName,d=u(e,["components","mdxType","originalType","parentName"]),l=p(t),c=a,w=l["".concat(i,".").concat(c)]||l[c]||m[c]||s;return t?r.createElement(w,o(o({ref:n},d),{},{components:t})):r.createElement(w,o({ref:n},d))}));function c(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var s=t.length,o=new Array(s);o[0]=l;var u={};for(var i in n)hasOwnProperty.call(n,i)&&(u[i]=n[i]);u.originalType=e,u.mdxType="string"==typeof e?e:a,o[1]=u;for(var p=2;p=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var i=r.createContext({}),p=function(e){var n=r.useContext(i),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},d=function(e){var n=p(e.components);return r.createElement(i.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},l=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,s=e.originalType,i=e.parentName,d=u(e,["components","mdxType","originalType","parentName"]),l=p(t),c=a,w=l["".concat(i,".").concat(c)]||l[c]||m[c]||s;return t?r.createElement(w,o(o({ref:n},d),{},{components:t})):r.createElement(w,o({ref:n},d))}));function c(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var s=t.length,o=new Array(s);o[0]=l;var u={};for(var i in n)hasOwnProperty.call(n,i)&&(u[i]=n[i]);u.originalType=e,u.mdxType="string"==typeof e?e:a,o[1]=u;for(var p=2;p { user, user2 });\n\n// \u793a\u4f8b\u4e09\nrepository.Update(new[] {user, user2 });\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateAsync(user, user2);\n\n// \u793a\u4f8b\u4e8c\nawait repository.UpdateAsync(new List { user, user2 });\n\n// \u793a\u4f8b\u4e09\nawait repository.UpdateAsync(new[] {user, user2 });\n")),(0,s.kt)("h2",{id:"9614-\u66f4\u65b0\u591a\u6761\u8bb0\u5f55\u7acb\u5373\u63d0\u4ea4"},"9.6.14 \u66f4\u65b0\u591a\u6761\u8bb0\u5f55\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.UpdateNow(user, user2);\n\n// \u793a\u4f8b\u4e8c\nrepository.UpdateNow(new List { user, user2 });\n\n// \u793a\u4f8b\u4e09\nrepository.UpdateNow(new[] {user, user2 });\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.UpdateNowAsync(user, user2);\n\n// \u793a\u4f8b\u4e8c\nawait repository.UpdateNowAsync(new List { user, user2 });\n\n// \u793a\u4f8b\u4e09\nawait repository.UpdateNowAsync(new[] {user, user2 });\n")),(0,s.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,s.kt)("p",{parentName:"admonition"},"\u6240\u6709\u5e26 ",(0,s.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u8868\u793a\u7acb\u5373\u63d0\u4ea4\u5230\u6570\u636e\u5e93\uff0c\u4e5f\u5c31\u662f\u7acb\u5373\u8c03\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216 ",(0,s.kt)("inlineCode",{parentName:"p"},"SaveChangesAsync"),"\u3002")),(0,s.kt)("h2",{id:"9615-\u5ffd\u7565\u7a7a\u503c\u66f4\u65b0"},"9.6.15 \u5ffd\u7565\u7a7a\u503c\u66f4\u65b0"),(0,s.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,s.kt)("inlineCode",{parentName:"p"},"EFCore")," \u66f4\u65b0\u4f1a\u66f4\u65b0\u5168\u90e8\u5217\uff08\u9664\u5b9e\u4f53\u8ddf\u8e2a\u65b9\u5f0f\u4ee5\u5916\uff09\uff0c\u6709\u4e9b\u65f6\u5019\u6211\u4eec\u5e0c\u671b ",(0,s.kt)("inlineCode",{parentName:"p"},"Null")," \u503c\u65e0\u9700\u66f4\u65b0\uff0c\u8fd9\u662f\u6211\u4eec\u53ea\u9700\u8981\u5728\u66f4\u65b0\u65f6\u5019\u914d\u7f6e ",(0,s.kt)("inlineCode",{parentName:"p"},"ignoreNullValues")," \u53c2\u6570\u5373\u53ef\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"repository.Update(entity, ignoreNullValues: true);\n")),(0,s.kt)("p",null,"\u4e5f\u53ef\u4ee5\u5168\u5c40\u914d\u7f6e\uff0c\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u7684\u6d3e\u751f\u7c7b\u7684\u6784\u9020\u51fd\u6570\u4e2d\u542f\u7528\u5373\u53ef\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11}",showLineNumbers:!0,"":!0,"{11}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]\n public class DefaultDbContext : AppDbContext\n {\n public DefaultDbContext(DbContextOptions options) : base(options)\n {\n InsertOrUpdateIgnoreNullValues = true;\n }\n }\n}\n')),(0,s.kt)("h2",{id:"9616-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.6.16 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,s.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,s.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,s.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/6eaa010c.a430e57a.js b/handbook/build/assets/js/6eaa010c.a430e57a.js new file mode 100644 index 0000000000..90e36bfc61 --- /dev/null +++ b/handbook/build/assets/js/6eaa010c.a430e57a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[9742],{3905:function(e,n,t){t.d(n,{Zo:function(){return u},kt:function(){return k}});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function i(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var l=r.createContext({}),s=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u=function(e){var n=s(e.components);return r.createElement(l.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),d=s(t),k=o,m=d["".concat(l,".").concat(k)]||d[k]||p[k]||a;return t?r.createElement(m,i(i({ref:n},u),{},{components:t})):r.createElement(m,i({ref:n},u))}));function k(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var a=t.length,i=new Array(a);i[0]=d;var c={};for(var l in n)hasOwnProperty.call(n,l)&&(c[l]=n[l]);c.originalType=e,c.mdxType="string"==typeof e?e:o,i[1]=c;for(var s=2;sToken",id:"141-\u751f\u6210-token",level:2},{value:"14.2 \u751f\u6210\u5237\u65b0 Token",id:"142-\u751f\u6210\u5237\u65b0-token",level:2},{value:"14.3 \u6839\u636e\u8fc7\u671f Token \u4ea4\u6362\u65b0 Token",id:"143-\u6839\u636e\u8fc7\u671f-token-\u4ea4\u6362\u65b0-token",level:2},{value:"14.4 \u6388\u6743\u5904\u7406\u7a0b\u5e8f\u81ea\u52a8\u5237\u65b0 Token",id:"144-\u6388\u6743\u5904\u7406\u7a0b\u5e8f\u81ea\u52a8\u5237\u65b0-token",level:2},{value:"14.5 \u9a8c\u8bc1 Token \u6709\u6548\u6027",id:"145-\u9a8c\u8bc1-token-\u6709\u6548\u6027",level:2},{value:"14.6 \u9a8c\u8bc1\u8bf7\u6c42\u4e2d Token \u6709\u6548\u6027",id:"146-\u9a8c\u8bc1\u8bf7\u6c42\u4e2d-token-\u6709\u6548\u6027",level:2},{value:"14.7 \u8bfb\u53d6 Token \u4fe1\u606f\uff08\u4e0d\u542b\u9a8c\u8bc1\uff09",id:"147-\u8bfb\u53d6-token-\u4fe1\u606f\u4e0d\u542b\u9a8c\u8bc1",level:2}],d={toc:p};function k(e){var n=e.components,t=(0,o.Z)(e,i);return(0,a.kt)("wrapper",(0,r.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"141-\u751f\u6210-token"},"14.1 \u751f\u6210 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u8bfb\u53d6\u914d\u7f6e\u4fe1\u606f\u751f\u6210 Token\nvar token = JWTEncryption.Encrypt(new Dictionary { { "UserId", 1 } });\n\n// \u914d\u7f6e Token \u8fc7\u671f\u65f6\u95f4\nvar token = JWTEncryption.Encrypt(new Dictionary { { "UserId", 1 } }, 20);\n\n// \u914d\u7f6e Token \u5bc6\u94a5\nvar token = JWTEncryption.Encrypt("monksoul@outlook.com", new Dictionary { { "UserId", 1 } });\n\n// \u914d\u7f6e\u7b97\u6cd5\nvar token = JWTEncryption.Encrypt("monksoul@outlook.com", new Dictionary { { "UserId", 1 } }, SecurityAlgorithms.HmacSha256);\n')),(0,a.kt)("h2",{id:"142-\u751f\u6210\u5237\u65b0-token"},"14.2 \u751f\u6210\u5237\u65b0 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var refreshToken = JWTEncryption.GenerateRefreshToken("token", 43200);\n')),(0,a.kt)("h2",{id:"143-\u6839\u636e\u8fc7\u671f-token-\u4ea4\u6362\u65b0-token"},"14.3 \u6839\u636e\u8fc7\u671f ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")," \u4ea4\u6362\u65b0 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var newToken = JWTEncryption.Exchange("\u8fc7\u671f token", "\u4e0e\u4e4b\u5339\u914d\u7684\u5237\u65b0 token", [\u65b0\u7684token\u8fc7\u671f\u65f6\u95f4], [\u5bb9\u9519\u503c]);\n')),(0,a.kt)("h2",{id:"144-\u6388\u6743\u5904\u7406\u7a0b\u5e8f\u81ea\u52a8\u5237\u65b0-token"},"14.4 \u6388\u6743\u5904\u7406\u7a0b\u5e8f\u81ea\u52a8\u5237\u65b0 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"JWTEncryption.AutoRefreshToken(context, httpContext);\n")),(0,a.kt)("h2",{id:"145-\u9a8c\u8bc1-token-\u6709\u6548\u6027"},"14.5 \u9a8c\u8bc1 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")," \u6709\u6548\u6027"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var (isVaild, tokenInfo) = JWTEncryption.Validate("token");\n')),(0,a.kt)("h2",{id:"146-\u9a8c\u8bc1\u8bf7\u6c42\u4e2d-token-\u6709\u6548\u6027"},"14.6 \u9a8c\u8bc1\u8bf7\u6c42\u4e2d ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")," \u6709\u6548\u6027"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var isValid = JWTEncryption.ValidateJwtBearerToken(httpContext, out tokenInfo);\n")),(0,a.kt)("h2",{id:"147-\u8bfb\u53d6-token-\u4fe1\u606f\u4e0d\u542b\u9a8c\u8bc1"},"14.7 \u8bfb\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")," \u4fe1\u606f\uff08\u4e0d\u542b\u9a8c\u8bc1\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var tokenInfo = JWTEncryption.ReadJwtToken("token");\n\n// 3.8.2+ \u4e4b\u540e\u652f\u6301\u66f4\u5f3a\u5927\u7684\u8bfb\u53d6\nvar securityToken = JWTEncryption.SecurityReadJwtToken("token");\n')))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/6eaa010c.e6f407eb.js b/handbook/build/assets/js/6eaa010c.e6f407eb.js deleted file mode 100644 index 064820ff92..0000000000 --- a/handbook/build/assets/js/6eaa010c.e6f407eb.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[9742],{3392:function(e,n,t){t.r(n),t.d(n,{assets:function(){return u},contentTitle:function(){return l},default:function(){return k},frontMatter:function(){return c},metadata:function(){return s},toc:function(){return p}});var r=t(3117),o=t(102),a=(t(7294),t(3905)),i=["components"],c={id:"jwt",title:"14. JWTEncryption \u9759\u6001\u7c7b",sidebar_label:"14. JWTEncryption \u9759\u6001\u7c7b"},l=void 0,s={unversionedId:"global/jwt",id:"global/jwt",title:"14. JWTEncryption \u9759\u6001\u7c7b",description:"14.1 \u751f\u6210 Token",source:"@site/docs/global/jwt.mdx",sourceDirName:"global",slug:"/global/jwt",permalink:"/furion/docs/global/jwt",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/global/jwt.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1657776203,formattedLastUpdatedAt:"Jul 14, 2022",frontMatter:{id:"jwt",title:"14. JWTEncryption \u9759\u6001\u7c7b",sidebar_label:"14. JWTEncryption \u9759\u6001\u7c7b"},sidebar:"global",previous:{title:"13. FS \u9759\u6001\u7c7b",permalink:"/furion/docs/global/fs"},next:{title:"15. TP \u9759\u6001\u7c7b",permalink:"/furion/docs/global/tp"}},u={},p=[{value:"14.1 \u751f\u6210 Token",id:"141-\u751f\u6210-token",level:2},{value:"14.2 \u751f\u6210\u5237\u65b0 Token",id:"142-\u751f\u6210\u5237\u65b0-token",level:2},{value:"14.3 \u6839\u636e\u8fc7\u671f Token \u4ea4\u6362\u65b0 Token",id:"143-\u6839\u636e\u8fc7\u671f-token-\u4ea4\u6362\u65b0-token",level:2},{value:"14.4 \u6388\u6743\u5904\u7406\u7a0b\u5e8f\u81ea\u52a8\u5237\u65b0 Token",id:"144-\u6388\u6743\u5904\u7406\u7a0b\u5e8f\u81ea\u52a8\u5237\u65b0-token",level:2},{value:"14.5 \u9a8c\u8bc1 Token \u6709\u6548\u6027",id:"145-\u9a8c\u8bc1-token-\u6709\u6548\u6027",level:2},{value:"14.6 \u9a8c\u8bc1\u8bf7\u6c42\u4e2d Token \u6709\u6548\u6027",id:"146-\u9a8c\u8bc1\u8bf7\u6c42\u4e2d-token-\u6709\u6548\u6027",level:2},{value:"14.7 \u8bfb\u53d6 Token \u4fe1\u606f\uff08\u4e0d\u542b\u9a8c\u8bc1\uff09",id:"147-\u8bfb\u53d6-token-\u4fe1\u606f\u4e0d\u542b\u9a8c\u8bc1",level:2}],d={toc:p};function k(e){var n=e.components,t=(0,o.Z)(e,i);return(0,a.kt)("wrapper",(0,r.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"141-\u751f\u6210-token"},"14.1 \u751f\u6210 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u8bfb\u53d6\u914d\u7f6e\u4fe1\u606f\u751f\u6210 Token\nvar token = JWTEncryption.Encrypt(new Dictionary { { "UserId", 1 } });\n\n// \u914d\u7f6e Token \u8fc7\u671f\u65f6\u95f4\nvar token = JWTEncryption.Encrypt(new Dictionary { { "UserId", 1 } }, 20);\n\n// \u914d\u7f6e Token \u5bc6\u94a5\nvar token = JWTEncryption.Encrypt("monksoul@outlook.com", new Dictionary { { "UserId", 1 } });\n\n// \u914d\u7f6e\u7b97\u6cd5\nvar token = JWTEncryption.Encrypt("monksoul@outlook.com", new Dictionary { { "UserId", 1 } }, SecurityAlgorithms.HmacSha256);\n')),(0,a.kt)("h2",{id:"142-\u751f\u6210\u5237\u65b0-token"},"14.2 \u751f\u6210\u5237\u65b0 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var refreshToken = JWTEncryption.GenerateRefreshToken("token", 43200);\n')),(0,a.kt)("h2",{id:"143-\u6839\u636e\u8fc7\u671f-token-\u4ea4\u6362\u65b0-token"},"14.3 \u6839\u636e\u8fc7\u671f ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")," \u4ea4\u6362\u65b0 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var newToken = JWTEncryption.Exchange("\u8fc7\u671f token", "\u4e0e\u4e4b\u5339\u914d\u7684\u5237\u65b0 token", [\u65b0\u7684token\u8fc7\u671f\u65f6\u95f4], [\u5bb9\u9519\u503c]);\n')),(0,a.kt)("h2",{id:"144-\u6388\u6743\u5904\u7406\u7a0b\u5e8f\u81ea\u52a8\u5237\u65b0-token"},"14.4 \u6388\u6743\u5904\u7406\u7a0b\u5e8f\u81ea\u52a8\u5237\u65b0 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"JWTEncryption.AutoRefreshToken(context, httpContext);\n")),(0,a.kt)("h2",{id:"145-\u9a8c\u8bc1-token-\u6709\u6548\u6027"},"14.5 \u9a8c\u8bc1 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")," \u6709\u6548\u6027"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var (isVaild, tokenInfo) = JWTEncryption.Validate("token");\n')),(0,a.kt)("h2",{id:"146-\u9a8c\u8bc1\u8bf7\u6c42\u4e2d-token-\u6709\u6548\u6027"},"14.6 \u9a8c\u8bc1\u8bf7\u6c42\u4e2d ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")," \u6709\u6548\u6027"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var isValid = JWTEncryption.ValidateJwtBearerToken(httpContext, out tokenInfo);\n")),(0,a.kt)("h2",{id:"147-\u8bfb\u53d6-token-\u4fe1\u606f\u4e0d\u542b\u9a8c\u8bc1"},"14.7 \u8bfb\u53d6 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Token")," \u4fe1\u606f\uff08\u4e0d\u542b\u9a8c\u8bc1\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var tokenInfo = JWTEncryption.ReadJwtToken("token");\n\n// 3.8.2+ \u4e4b\u540e\u652f\u6301\u66f4\u5f3a\u5927\u7684\u8bfb\u53d6\nvar securityToken = JWTEncryption.SecurityReadJwtToken("token");\n')))}k.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return u},kt:function(){return k}});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function i(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var l=r.createContext({}),s=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u=function(e){var n=s(e.components);return r.createElement(l.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),d=s(t),k=o,m=d["".concat(l,".").concat(k)]||d[k]||p[k]||a;return t?r.createElement(m,i(i({ref:n},u),{},{components:t})):r.createElement(m,i({ref:n},u))}));function k(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var a=t.length,i=new Array(a);i[0]=d;var c={};for(var l in n)hasOwnProperty.call(n,l)&&(c[l]=n[l]);c.originalType=e,c.mdxType="string"==typeof e?e:o,i[1]=c;for(var s=2;s=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=i.createContext({}),u=function(e){var t=i.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},s=function(e){var t=u(e.components);return i.createElement(p.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},d=i.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,p=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=u(n),c=r,k=d["".concat(p,".").concat(c)]||d[c]||m[c]||a;return n?i.createElement(k,l(l({ref:t},s),{},{components:n})):i.createElement(k,l({ref:t},s))}));function c(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,l=new Array(a);l[0]=d;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,l[1]=o;for(var u=2;u=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=i.createContext({}),u=function(e){var t=i.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},s=function(e){var t=u(e.components);return i.createElement(p.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},d=i.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,p=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=u(n),c=r,k=d["".concat(p,".").concat(c)]||d[c]||m[c]||a;return n?i.createElement(k,l(l({ref:t},s),{},{components:n})):i.createElement(k,l({ref:t},s))}));function c(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,l=new Array(a);l[0]=d;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,l[1]=o;for(var u=2;uDapper \u670d\u52a1",id:"10221-\u6ce8\u518c-dapper-\u670d\u52a1",level:3},{value:"10.2.2.2 \u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93\u63d0\u4f9b\u5668",id:"10222-\u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93\u63d0\u4f9b\u5668",level:3},{value:"10.2.3 \u57fa\u672c\u4f7f\u7528",id:"1023-\u57fa\u672c\u4f7f\u7528",level:2},{value:"10.2.3.1 sql \u64cd\u4f5c",id:"10231-sql-\u64cd\u4f5c",level:3},{value:"10.2.3.2 <TEntity> \u64cd\u4f5c",id:"10232-tentity-\u64cd\u4f5c",level:3},{value:"10.2.4 \u9ad8\u7ea7\u4f7f\u7528",id:"1024-\u9ad8\u7ea7\u4f7f\u7528",level:2},{value:"10.2.4.1 \u67e5\u8be2\u4e00\u5bf9\u4e00",id:"10241-\u67e5\u8be2\u4e00\u5bf9\u4e00",level:3},{value:"10.2.4.2 \u67e5\u8be2\u591a\u4e2a\u7ed3\u679c",id:"10242-\u67e5\u8be2\u591a\u4e2a\u7ed3\u679c",level:3},{value:"10.2.4.3 \u66f4\u591a\u64cd\u4f5c",id:"10243-\u66f4\u591a\u64cd\u4f5c",level:3},{value:"10.2.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"1025-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:u};function m(e){var r=e.components,n=(0,a.Z)(e,o);return(0,p.kt)("wrapper",(0,t.Z)({},c,n,{components:r,mdxType:"MDXLayout"}),(0,p.kt)("admonition",{title:"\u6e29\u99a8\u63d0\u9192",type:"warning"},(0,p.kt)("p",{parentName:"admonition"},"\u5728 ",(0,p.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\u4e2d\u9ed8\u8ba4\u96c6\u6210\u4e86 ",(0,p.kt)("inlineCode",{parentName:"p"},"EFCore"),"\uff0c",(0,p.kt)("strong",{parentName:"p"},"\u5982\u679c\u4e0d\u4f7f\u7528 ",(0,p.kt)("inlineCode",{parentName:"strong"},"EFCore"),"\uff0c\u53ef\u5b89\u88c5\u7eaf\u51c0\u7248 ",(0,p.kt)("inlineCode",{parentName:"strong"},"Furion.Pure")," \u4ee3\u66ff ",(0,p.kt)("inlineCode",{parentName:"strong"},"Furion")),"\u3002")),(0,p.kt)("h2",{id:"1021-\u5173\u4e8e-dapper"},"10.2.1 \u5173\u4e8e Dapper"),(0,p.kt)("p",null,(0,p.kt)("inlineCode",{parentName:"p"},"Dapper")," \u662f .NET/C# \u5e73\u53f0\u975e\u5e38\u4f18\u79c0\u7684 ",(0,p.kt)("inlineCode",{parentName:"p"},"\u5fae\u578b ORM")," \u6846\u67b6\uff0c\u4e3b\u8981\u662f\u4e3a ",(0,p.kt)("inlineCode",{parentName:"p"},"ADO.NET")," \u64cd\u4f5c\u5bf9\u8c61\u63d0\u4f9b\u62d3\u5c55\u80fd\u529b\uff0c\u63a8\u5d07\u539f\u751f ",(0,p.kt)("inlineCode",{parentName:"p"},"sql")," \u64cd\u4f5c\u6cd5\u3002"),(0,p.kt)("p",null,(0,p.kt)("inlineCode",{parentName:"p"},"Dapper")," \u5b98\u65b9\u4ed3\u5e93\u5730\u5740\uff1a",(0,p.kt)("a",{parentName:"p",href:"https://github.com/StackExchange/Dapper"},"https://github.com/StackExchange/Dapper")),(0,p.kt)("h2",{id:"1022-\u5982\u4f55\u96c6\u6210"},"10.2.2 \u5982\u4f55\u96c6\u6210"),(0,p.kt)("p",null,"\u5728 ",(0,p.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5df2\u7ecf\u63a8\u51fa ",(0,p.kt)("inlineCode",{parentName:"p"},"Dapper")," \u62d3\u5c55\u5305 ",(0,p.kt)("a",{parentName:"p",href:"https://www.nuget.org/packages/Furion.Extras.DatabaseAccessor.Dapper"},"Furion.Extras.DatabaseAccessor.Dapper"),"\u3002"),(0,p.kt)("h3",{id:"10221-\u6ce8\u518c-dapper-\u670d\u52a1"},"10.2.2.1 \u6ce8\u518c ",(0,p.kt)("inlineCode",{parentName:"h3"},"Dapper")," \u670d\u52a1"),(0,p.kt)("p",null,"\u4f7f\u7528\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700\u8981\u5728 ",(0,p.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6dfb\u52a0 ",(0,p.kt)("inlineCode",{parentName:"p"},"services.AddDapper(connStr, SqlProvider)")," \u5373\u53ef\u3002\u5982\uff1a"),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'services.AddDapper("Data Source=./Furion.db", SqlProvider.Sqlite);\n\n// \u66f4\u591a\u914d\u7f6e\uff0c\u4ec5 v3.4.3+ \u7248\u672c\u6709\u6548\nservers.AddDapper("Data Source=./Furion.db", SqlProvider.Sqlite, () => {\n DefaultTypeMap.MatchNamesWithUnderscores = true;\n})\n')),(0,p.kt)("h3",{id:"10222-\u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93\u63d0\u4f9b\u5668"},"10.2.2.2 \u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93\u63d0\u4f9b\u5668"),(0,p.kt)("ul",null,(0,p.kt)("li",{parentName:"ul"},(0,p.kt)("inlineCode",{parentName:"li"},"SqlServer"),"\uff1a",(0,p.kt)("inlineCode",{parentName:"li"},"Microsoft.Data.SqlClient")),(0,p.kt)("li",{parentName:"ul"},(0,p.kt)("inlineCode",{parentName:"li"},"Sqlite"),"\uff1a",(0,p.kt)("inlineCode",{parentName:"li"},"Microsoft.Data.Sqlite")),(0,p.kt)("li",{parentName:"ul"},(0,p.kt)("inlineCode",{parentName:"li"},"MySql"),"\uff1a",(0,p.kt)("inlineCode",{parentName:"li"},"MySql.Data")),(0,p.kt)("li",{parentName:"ul"},(0,p.kt)("inlineCode",{parentName:"li"},"Npgsql"),"\uff1a",(0,p.kt)("inlineCode",{parentName:"li"},"Npgsql")),(0,p.kt)("li",{parentName:"ul"},(0,p.kt)("inlineCode",{parentName:"li"},"Oracle"),"\uff1a",(0,p.kt)("inlineCode",{parentName:"li"},"Oracle.ManagedDataAccess.Core")),(0,p.kt)("li",{parentName:"ul"},(0,p.kt)("inlineCode",{parentName:"li"},"Firebird"),"\uff1a",(0,p.kt)("inlineCode",{parentName:"li"},"FirebirdSql.Data.FirebirdClient"))),(0,p.kt)("admonition",{title:"\u5b89\u88c5\u62d3\u5c55\u5305\u4f4d\u7f6e",type:"important"},(0,p.kt)("p",{parentName:"admonition"},"\u5728 ",(0,p.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u63a8\u8350\u5c06\u62d3\u5c55\u5305 ",(0,p.kt)("inlineCode",{parentName:"p"},"Furion.Extras.DatabaseAccessor.Dapper")," \u5b89\u88c5\u5230 ",(0,p.kt)("inlineCode",{parentName:"p"},"Furion.Core")," \u5c42\u4e2d\u3002")),(0,p.kt)("h2",{id:"1023-\u57fa\u672c\u4f7f\u7528"},"10.2.3 \u57fa\u672c\u4f7f\u7528"),(0,p.kt)("p",null,"\u5728\u4f7f\u7528\u4e4b\u524d\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u6784\u9020\u51fd\u6570\u6ce8\u5165 ",(0,p.kt)("inlineCode",{parentName:"p"},"IDapperRepository")," \u6216 ",(0,p.kt)("inlineCode",{parentName:"p"},"IDapperRepository")," \u63a5\u53e3\uff0c\u5982\uff1a"),(0,p.kt)("ul",null,(0,p.kt)("li",{parentName:"ul"},"\u975e\u6cdb\u578b\u7248\u672c")),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"private readonly IDapperRepository _dapperRepository;\npublic PersonService(IDapperRepository dapperRepository)\n{\n _dapperRepository = dapperRepository;\n}\n")),(0,p.kt)("ul",null,(0,p.kt)("li",{parentName:"ul"},"\u6cdb\u578b\u7248\u672c")),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"private readonly IDapperRepository _personRepository;\npublic PersonService(IDapperRepository personRepository)\n{\n _personRepository = personRepository;\n}\n")),(0,p.kt)("h3",{id:"10231-sql-\u64cd\u4f5c"},"10.2.3.1 ",(0,p.kt)("inlineCode",{parentName:"h3"},"sql")," \u64cd\u4f5c"),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var data = _dapperRepository.Query("select * from person");\nvar data = await _dapperRepository.QueryAsync("select * from person");\n\nvar data = _dapperRepository.Query("select * from person");\n\nvar guid = Guid.NewGuid();\nvar dog = _dapperRepository.Query("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });\n')),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var count = _dapperRepository.Execute(@"insert MyTable(colA, colB) values (@a, @b)",\n new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }\n );\n\nvar user = _dapperRepository.Query("spGetUser", new {Id = 1},\n commandType: CommandType.StoredProcedure).SingleOrDefault();\n')),(0,p.kt)("p",null,"\u7528\u6cd5\u548c\u5b98\u65b9\u4e00\u81f4\uff0c\u6b64\u5904\u4e0d\u518d\u4e3e\u66f4\u591a\u4f8b\u5b50\u3002"),(0,p.kt)("h3",{id:"10232-tentity-\u64cd\u4f5c"},"10.2.3.2 ",(0,p.kt)("inlineCode",{parentName:"h3"},"")," \u64cd\u4f5c"),(0,p.kt)("p",null,(0,p.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,p.kt)("inlineCode",{parentName:"p"},"IDapperRepository")," \u548c ",(0,p.kt)("inlineCode",{parentName:"p"},"IDapperRepository")," \u4e24\u4e2a\u64cd\u4f5c\u4ed3\u50a8\uff0c\u540e\u8005\u7ee7\u627f\u524d\u8005\u3002\u4f7f\u7528\u5982\u4e0b\uff1a"),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var person = personRepository.Get(1);\nvar persons = personRepository.GetAll();\n\nvar effects = personRepository.Insert(person);\nvar effects = personRepository.Update(person);\nvar effects = personRepository.Delete(person);\n\nvar effects = personRepository.Insert(persons); // \u63d2\u5165\u591a\u4e2a\nvar effects = personRepository.Update(persons); // \u66f4\u65b0\u591a\u4e2a\nvar effects = personRepository.Delete(persons); // \u5220\u9664\u591a\u4e2a\n\nvar effects = await personRepository.InsertAsync(person);\n")),(0,p.kt)("h2",{id:"1024-\u9ad8\u7ea7\u4f7f\u7528"},"10.2.4 \u9ad8\u7ea7\u4f7f\u7528"),(0,p.kt)("p",null,(0,p.kt)("inlineCode",{parentName:"p"},"IDapperRepository")," \u548c ",(0,p.kt)("inlineCode",{parentName:"p"},"IDapperRepository")," \u4ed3\u50a8\u63d0\u4f9b\u4e86 ",(0,p.kt)("inlineCode",{parentName:"p"},"Context")," \u548c ",(0,p.kt)("inlineCode",{parentName:"p"},"DynamicContext")," \u5c5e\u6027\uff0c\u8be5\u5c5e\u6027\u8fd4\u56de ",(0,p.kt)("inlineCode",{parentName:"p"},"IDbConnection")," \u5bf9\u8c61\u3002"),(0,p.kt)("p",null,"\u62ff\u5230\u8be5\u5bf9\u8c61\u540e\uff0c\u6211\u4eec\u5c31\u53ef\u4ee5\u64cd\u4f5c ",(0,p.kt)("inlineCode",{parentName:"p"},"Dapper")," \u63d0\u4f9b\u7684\u6240\u6709\u64cd\u4f5c\u4e86\uff0c\u5982\uff1a"),(0,p.kt)("h3",{id:"10241-\u67e5\u8be2\u4e00\u5bf9\u4e00"},"10.2.4.1 \u67e5\u8be2\u4e00\u5bf9\u4e00"),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var sql =\n@"select * from #Posts p\nleft join #Users u on u.Id = p.OwnerId\nOrder by p.Id";\n\nvar data = dapperRepository.Context.Query(sql, (post, user) => { post.Owner = user; return post;});\nvar post = data.First();\n')),(0,p.kt)("h3",{id:"10242-\u67e5\u8be2\u591a\u4e2a\u7ed3\u679c"},"10.2.4.2 \u67e5\u8be2\u591a\u4e2a\u7ed3\u679c"),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var sql =\n@"\nselect * from Customers where CustomerId = @id\nselect * from Orders where CustomerId = @id\nselect * from Returns where CustomerId = @id";\n\nusing (var multi = dapperRepository.Context.QueryMultiple(sql, new {id=selectedId}))\n{\n var customer = multi.Read().Single();\n var orders = multi.Read().ToList();\n var returns = multi.Read().ToList();\n // ...\n}\n')),(0,p.kt)("h3",{id:"10243-\u66f4\u591a\u64cd\u4f5c"},"10.2.4.3 \u66f4\u591a\u64cd\u4f5c"),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var shapes = new List();\nusing (var reader = dapperRepository.Context.ExecuteReader("select * from Shapes"))\n{\n var circleParser = reader.GetRowParser(typeof(Circle));\n var squareParser = reader.GetRowParser(typeof(Square));\n var triangleParser = reader.GetRowParser(typeof(Triangle));\n\n var typeColumnIndex = reader.GetOrdinal("Type");\n\n while (reader.Read())\n {\n IShape shape;\n var type = (ShapeType)reader.GetInt32(typeColumnIndex);\n switch (type)\n {\n case ShapeType.Circle:\n shape = circleParser(reader);\n break;\n case ShapeType.Square:\n shape = squareParser(reader);\n break;\n case ShapeType.Triangle:\n shape = triangleParser(reader);\n break;\n default:\n throw new NotImplementedException();\n }\n\n shapes.Add(shape);\n }\n}\n')),(0,p.kt)("h2",{id:"1025-\u53cd\u9988\u4e0e\u5efa\u8bae"},"10.2.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,p.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,p.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,p.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,p.kt)("hr",null),(0,p.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,p.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,p.kt)("inlineCode",{parentName:"p"},"Dapper")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,p.kt)("a",{parentName:"p",href:"https://github.com/StackExchange/Dapper"},"Dapper \u5b98\u7f51"),"\u3002")))}m.isMDXComponent=!0},3905:function(e,r,n){n.d(r,{Zo:function(){return d},kt:function(){return m}});var t=n(7294);function a(e,r,n){return r in e?Object.defineProperty(e,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[r]=n,e}function p(e,r){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);r&&(t=t.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),n.push.apply(n,t)}return n}function o(e){for(var r=1;r=0||(a[n]=e[n]);return a}(e,r);if(Object.getOwnPropertySymbols){var p=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=t.createContext({}),l=function(e){var r=t.useContext(s),n=r;return e&&(n="function"==typeof e?e(r):o(o({},r),e)),n},d=function(e){var r=l(e.components);return t.createElement(s.Provider,{value:r},e.children)},u={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},c=t.forwardRef((function(e,r){var n=e.components,a=e.mdxType,p=e.originalType,s=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),c=l(n),m=a,k=c["".concat(s,".").concat(m)]||c[m]||u[m]||p;return n?t.createElement(k,o(o({ref:r},d),{},{components:n})):t.createElement(k,o({ref:r},d))}));function m(e,r){var n=arguments,a=r&&r.mdxType;if("string"==typeof e||a){var p=n.length,o=new Array(p);o[0]=c;var i={};for(var s in r)hasOwnProperty.call(r,s)&&(i[s]=r[s]);i.originalType=e,i.mdxType="string"==typeof e?e:a,o[1]=i;for(var l=2;l=0||(a[n]=e[n]);return a}(e,r);if(Object.getOwnPropertySymbols){var p=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=t.createContext({}),l=function(e){var r=t.useContext(s),n=r;return e&&(n="function"==typeof e?e(r):o(o({},r),e)),n},d=function(e){var r=l(e.components);return t.createElement(s.Provider,{value:r},e.children)},u={inlineCode:"code",wrapper:function(e){var r=e.children;return t.createElement(t.Fragment,{},r)}},c=t.forwardRef((function(e,r){var n=e.components,a=e.mdxType,p=e.originalType,s=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),c=l(n),m=a,k=c["".concat(s,".").concat(m)]||c[m]||u[m]||p;return n?t.createElement(k,o(o({ref:r},d),{},{components:n})):t.createElement(k,o({ref:r},d))}));function m(e,r){var n=arguments,a=r&&r.mdxType;if("string"==typeof e||a){var p=n.length,o=new Array(p);o[0]=c;var i={};for(var s in r)hasOwnProperty.call(r,s)&&(i[s]=r[s]);i.originalType=e,i.mdxType="string"==typeof e?e:a,o[1]=i;for(var l=2;lDapper \u670d\u52a1",id:"10221-\u6ce8\u518c-dapper-\u670d\u52a1",level:3},{value:"10.2.2.2 \u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93\u63d0\u4f9b\u5668",id:"10222-\u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93\u63d0\u4f9b\u5668",level:3},{value:"10.2.3 \u57fa\u672c\u4f7f\u7528",id:"1023-\u57fa\u672c\u4f7f\u7528",level:2},{value:"10.2.3.1 sql \u64cd\u4f5c",id:"10231-sql-\u64cd\u4f5c",level:3},{value:"10.2.3.2 <TEntity> \u64cd\u4f5c",id:"10232-tentity-\u64cd\u4f5c",level:3},{value:"10.2.4 \u9ad8\u7ea7\u4f7f\u7528",id:"1024-\u9ad8\u7ea7\u4f7f\u7528",level:2},{value:"10.2.4.1 \u67e5\u8be2\u4e00\u5bf9\u4e00",id:"10241-\u67e5\u8be2\u4e00\u5bf9\u4e00",level:3},{value:"10.2.4.2 \u67e5\u8be2\u591a\u4e2a\u7ed3\u679c",id:"10242-\u67e5\u8be2\u591a\u4e2a\u7ed3\u679c",level:3},{value:"10.2.4.3 \u66f4\u591a\u64cd\u4f5c",id:"10243-\u66f4\u591a\u64cd\u4f5c",level:3},{value:"10.2.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"1025-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:u};function m(e){var r=e.components,n=(0,a.Z)(e,o);return(0,p.kt)("wrapper",(0,t.Z)({},c,n,{components:r,mdxType:"MDXLayout"}),(0,p.kt)("admonition",{title:"\u6e29\u99a8\u63d0\u9192",type:"warning"},(0,p.kt)("p",{parentName:"admonition"},"\u5728 ",(0,p.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\u4e2d\u9ed8\u8ba4\u96c6\u6210\u4e86 ",(0,p.kt)("inlineCode",{parentName:"p"},"EFCore"),"\uff0c",(0,p.kt)("strong",{parentName:"p"},"\u5982\u679c\u4e0d\u4f7f\u7528 ",(0,p.kt)("inlineCode",{parentName:"strong"},"EFCore"),"\uff0c\u53ef\u5b89\u88c5\u7eaf\u51c0\u7248 ",(0,p.kt)("inlineCode",{parentName:"strong"},"Furion.Pure")," \u4ee3\u66ff ",(0,p.kt)("inlineCode",{parentName:"strong"},"Furion")),"\u3002")),(0,p.kt)("h2",{id:"1021-\u5173\u4e8e-dapper"},"10.2.1 \u5173\u4e8e Dapper"),(0,p.kt)("p",null,(0,p.kt)("inlineCode",{parentName:"p"},"Dapper")," \u662f .NET/C# \u5e73\u53f0\u975e\u5e38\u4f18\u79c0\u7684 ",(0,p.kt)("inlineCode",{parentName:"p"},"\u5fae\u578b ORM")," \u6846\u67b6\uff0c\u4e3b\u8981\u662f\u4e3a ",(0,p.kt)("inlineCode",{parentName:"p"},"ADO.NET")," \u64cd\u4f5c\u5bf9\u8c61\u63d0\u4f9b\u62d3\u5c55\u80fd\u529b\uff0c\u63a8\u5d07\u539f\u751f ",(0,p.kt)("inlineCode",{parentName:"p"},"sql")," \u64cd\u4f5c\u6cd5\u3002"),(0,p.kt)("p",null,(0,p.kt)("inlineCode",{parentName:"p"},"Dapper")," \u5b98\u65b9\u4ed3\u5e93\u5730\u5740\uff1a",(0,p.kt)("a",{parentName:"p",href:"https://github.com/StackExchange/Dapper"},"https://github.com/StackExchange/Dapper")),(0,p.kt)("h2",{id:"1022-\u5982\u4f55\u96c6\u6210"},"10.2.2 \u5982\u4f55\u96c6\u6210"),(0,p.kt)("p",null,"\u5728 ",(0,p.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5df2\u7ecf\u63a8\u51fa ",(0,p.kt)("inlineCode",{parentName:"p"},"Dapper")," \u62d3\u5c55\u5305 ",(0,p.kt)("a",{parentName:"p",href:"https://www.nuget.org/packages/Furion.Extras.DatabaseAccessor.Dapper"},"Furion.Extras.DatabaseAccessor.Dapper"),"\u3002"),(0,p.kt)("h3",{id:"10221-\u6ce8\u518c-dapper-\u670d\u52a1"},"10.2.2.1 \u6ce8\u518c ",(0,p.kt)("inlineCode",{parentName:"h3"},"Dapper")," \u670d\u52a1"),(0,p.kt)("p",null,"\u4f7f\u7528\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700\u8981\u5728 ",(0,p.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6dfb\u52a0 ",(0,p.kt)("inlineCode",{parentName:"p"},"services.AddDapper(connStr, SqlProvider)")," \u5373\u53ef\u3002\u5982\uff1a"),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'services.AddDapper("Data Source=./Furion.db", SqlProvider.Sqlite);\n\n// \u66f4\u591a\u914d\u7f6e\uff0c\u4ec5 v3.4.3+ \u7248\u672c\u6709\u6548\nservers.AddDapper("Data Source=./Furion.db", SqlProvider.Sqlite, () => {\n DefaultTypeMap.MatchNamesWithUnderscores = true;\n})\n')),(0,p.kt)("h3",{id:"10222-\u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93\u63d0\u4f9b\u5668"},"10.2.2.2 \u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93\u63d0\u4f9b\u5668"),(0,p.kt)("ul",null,(0,p.kt)("li",{parentName:"ul"},(0,p.kt)("inlineCode",{parentName:"li"},"SqlServer"),"\uff1a",(0,p.kt)("inlineCode",{parentName:"li"},"Microsoft.Data.SqlClient")),(0,p.kt)("li",{parentName:"ul"},(0,p.kt)("inlineCode",{parentName:"li"},"Sqlite"),"\uff1a",(0,p.kt)("inlineCode",{parentName:"li"},"Microsoft.Data.Sqlite")),(0,p.kt)("li",{parentName:"ul"},(0,p.kt)("inlineCode",{parentName:"li"},"MySql"),"\uff1a",(0,p.kt)("inlineCode",{parentName:"li"},"MySql.Data")),(0,p.kt)("li",{parentName:"ul"},(0,p.kt)("inlineCode",{parentName:"li"},"Npgsql"),"\uff1a",(0,p.kt)("inlineCode",{parentName:"li"},"Npgsql")),(0,p.kt)("li",{parentName:"ul"},(0,p.kt)("inlineCode",{parentName:"li"},"Oracle"),"\uff1a",(0,p.kt)("inlineCode",{parentName:"li"},"Oracle.ManagedDataAccess.Core")),(0,p.kt)("li",{parentName:"ul"},(0,p.kt)("inlineCode",{parentName:"li"},"Firebird"),"\uff1a",(0,p.kt)("inlineCode",{parentName:"li"},"FirebirdSql.Data.FirebirdClient"))),(0,p.kt)("admonition",{title:"\u5b89\u88c5\u62d3\u5c55\u5305\u4f4d\u7f6e",type:"important"},(0,p.kt)("p",{parentName:"admonition"},"\u5728 ",(0,p.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u63a8\u8350\u5c06\u62d3\u5c55\u5305 ",(0,p.kt)("inlineCode",{parentName:"p"},"Furion.Extras.DatabaseAccessor.Dapper")," \u5b89\u88c5\u5230 ",(0,p.kt)("inlineCode",{parentName:"p"},"Furion.Core")," \u5c42\u4e2d\u3002")),(0,p.kt)("h2",{id:"1023-\u57fa\u672c\u4f7f\u7528"},"10.2.3 \u57fa\u672c\u4f7f\u7528"),(0,p.kt)("p",null,"\u5728\u4f7f\u7528\u4e4b\u524d\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u6784\u9020\u51fd\u6570\u6ce8\u5165 ",(0,p.kt)("inlineCode",{parentName:"p"},"IDapperRepository")," \u6216 ",(0,p.kt)("inlineCode",{parentName:"p"},"IDapperRepository")," \u63a5\u53e3\uff0c\u5982\uff1a"),(0,p.kt)("ul",null,(0,p.kt)("li",{parentName:"ul"},"\u975e\u6cdb\u578b\u7248\u672c")),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"private readonly IDapperRepository _dapperRepository;\npublic PersonService(IDapperRepository dapperRepository)\n{\n _dapperRepository = dapperRepository;\n}\n")),(0,p.kt)("ul",null,(0,p.kt)("li",{parentName:"ul"},"\u6cdb\u578b\u7248\u672c")),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"private readonly IDapperRepository _personRepository;\npublic PersonService(IDapperRepository personRepository)\n{\n _personRepository = personRepository;\n}\n")),(0,p.kt)("h3",{id:"10231-sql-\u64cd\u4f5c"},"10.2.3.1 ",(0,p.kt)("inlineCode",{parentName:"h3"},"sql")," \u64cd\u4f5c"),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var data = _dapperRepository.Query("select * from person");\nvar data = await _dapperRepository.QueryAsync("select * from person");\n\nvar data = _dapperRepository.Query("select * from person");\n\nvar guid = Guid.NewGuid();\nvar dog = _dapperRepository.Query("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });\n')),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var count = _dapperRepository.Execute(@"insert MyTable(colA, colB) values (@a, @b)",\n new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }\n );\n\nvar user = _dapperRepository.Query("spGetUser", new {Id = 1},\n commandType: CommandType.StoredProcedure).SingleOrDefault();\n')),(0,p.kt)("p",null,"\u7528\u6cd5\u548c\u5b98\u65b9\u4e00\u81f4\uff0c\u6b64\u5904\u4e0d\u518d\u4e3e\u66f4\u591a\u4f8b\u5b50\u3002"),(0,p.kt)("h3",{id:"10232-tentity-\u64cd\u4f5c"},"10.2.3.2 ",(0,p.kt)("inlineCode",{parentName:"h3"},"")," \u64cd\u4f5c"),(0,p.kt)("p",null,(0,p.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,p.kt)("inlineCode",{parentName:"p"},"IDapperRepository")," \u548c ",(0,p.kt)("inlineCode",{parentName:"p"},"IDapperRepository")," \u4e24\u4e2a\u64cd\u4f5c\u4ed3\u50a8\uff0c\u540e\u8005\u7ee7\u627f\u524d\u8005\u3002\u4f7f\u7528\u5982\u4e0b\uff1a"),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var person = personRepository.Get(1);\nvar persons = personRepository.GetAll();\n\nvar effects = personRepository.Insert(person);\nvar effects = personRepository.Update(person);\nvar effects = personRepository.Delete(person);\n\nvar effects = personRepository.Insert(persons); // \u63d2\u5165\u591a\u4e2a\nvar effects = personRepository.Update(persons); // \u66f4\u65b0\u591a\u4e2a\nvar effects = personRepository.Delete(persons); // \u5220\u9664\u591a\u4e2a\n\nvar effects = await personRepository.InsertAsync(person);\n")),(0,p.kt)("h2",{id:"1024-\u9ad8\u7ea7\u4f7f\u7528"},"10.2.4 \u9ad8\u7ea7\u4f7f\u7528"),(0,p.kt)("p",null,(0,p.kt)("inlineCode",{parentName:"p"},"IDapperRepository")," \u548c ",(0,p.kt)("inlineCode",{parentName:"p"},"IDapperRepository")," \u4ed3\u50a8\u63d0\u4f9b\u4e86 ",(0,p.kt)("inlineCode",{parentName:"p"},"Context")," \u548c ",(0,p.kt)("inlineCode",{parentName:"p"},"DynamicContext")," \u5c5e\u6027\uff0c\u8be5\u5c5e\u6027\u8fd4\u56de ",(0,p.kt)("inlineCode",{parentName:"p"},"IDbConnection")," \u5bf9\u8c61\u3002"),(0,p.kt)("p",null,"\u62ff\u5230\u8be5\u5bf9\u8c61\u540e\uff0c\u6211\u4eec\u5c31\u53ef\u4ee5\u64cd\u4f5c ",(0,p.kt)("inlineCode",{parentName:"p"},"Dapper")," \u63d0\u4f9b\u7684\u6240\u6709\u64cd\u4f5c\u4e86\uff0c\u5982\uff1a"),(0,p.kt)("h3",{id:"10241-\u67e5\u8be2\u4e00\u5bf9\u4e00"},"10.2.4.1 \u67e5\u8be2\u4e00\u5bf9\u4e00"),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var sql =\n@"select * from #Posts p\nleft join #Users u on u.Id = p.OwnerId\nOrder by p.Id";\n\nvar data = dapperRepository.Context.Query(sql, (post, user) => { post.Owner = user; return post;});\nvar post = data.First();\n')),(0,p.kt)("h3",{id:"10242-\u67e5\u8be2\u591a\u4e2a\u7ed3\u679c"},"10.2.4.2 \u67e5\u8be2\u591a\u4e2a\u7ed3\u679c"),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var sql =\n@"\nselect * from Customers where CustomerId = @id\nselect * from Orders where CustomerId = @id\nselect * from Returns where CustomerId = @id";\n\nusing (var multi = dapperRepository.Context.QueryMultiple(sql, new {id=selectedId}))\n{\n var customer = multi.Read().Single();\n var orders = multi.Read().ToList();\n var returns = multi.Read().ToList();\n // ...\n}\n')),(0,p.kt)("h3",{id:"10243-\u66f4\u591a\u64cd\u4f5c"},"10.2.4.3 \u66f4\u591a\u64cd\u4f5c"),(0,p.kt)("pre",null,(0,p.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var shapes = new List();\nusing (var reader = dapperRepository.Context.ExecuteReader("select * from Shapes"))\n{\n var circleParser = reader.GetRowParser(typeof(Circle));\n var squareParser = reader.GetRowParser(typeof(Square));\n var triangleParser = reader.GetRowParser(typeof(Triangle));\n\n var typeColumnIndex = reader.GetOrdinal("Type");\n\n while (reader.Read())\n {\n IShape shape;\n var type = (ShapeType)reader.GetInt32(typeColumnIndex);\n switch (type)\n {\n case ShapeType.Circle:\n shape = circleParser(reader);\n break;\n case ShapeType.Square:\n shape = squareParser(reader);\n break;\n case ShapeType.Triangle:\n shape = triangleParser(reader);\n break;\n default:\n throw new NotImplementedException();\n }\n\n shapes.Add(shape);\n }\n}\n')),(0,p.kt)("h2",{id:"1025-\u53cd\u9988\u4e0e\u5efa\u8bae"},"10.2.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,p.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,p.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,p.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,p.kt)("hr",null),(0,p.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,p.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,p.kt)("inlineCode",{parentName:"p"},"Dapper")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,p.kt)("a",{parentName:"p",href:"https://github.com/StackExchange/Dapper"},"Dapper \u5b98\u7f51"),"\u3002")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/713.e2d721b5.js b/handbook/build/assets/js/713.e2d721b5.js deleted file mode 100644 index 30c9d8219f..0000000000 --- a/handbook/build/assets/js/713.e2d721b5.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[713],{713:function(e,t,n){n.r(t),n.d(t,{default:function(){return i}});var a=n(7294),o=n(1614),l=n(4873),r=n(4832);function i(){return a.createElement(a.Fragment,null,a.createElement(l.d,{title:(0,o.I)({id:"theme.NotFound.title",message:"Page Not Found"})}),a.createElement(r.Z,null,a.createElement("main",{className:"container margin-vert--xl"},a.createElement("div",{className:"row"},a.createElement("div",{className:"col col--6 col--offset-3"},a.createElement("h1",{className:"hero__title"},a.createElement(o.Z,{id:"theme.NotFound.title",description:"The title of the 404 page"},"Page Not Found")),a.createElement("p",null,a.createElement(o.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page"},"We could not find what you were looking for.")),a.createElement("p",null,a.createElement(o.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page"},"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.")))))))}}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/713be7bb.0b389d71.js b/handbook/build/assets/js/713be7bb.0b389d71.js deleted file mode 100644 index c08a08f913..0000000000 --- a/handbook/build/assets/js/713be7bb.0b389d71.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[6696],{433:function(e,n,t){t.d(n,{Z:function(){return s}});var r=t(7294),a=t(4334),i="tabItem_Ymn6";function s(e){var n=e.children,t=e.hidden,s=e.className;return r.createElement("div",{role:"tabpanel",className:(0,a.Z)(i,s),hidden:t},n)}},5559:function(e,n,t){t.d(n,{Z:function(){return c}});var r=t(3117),a=t(7294),i=t(4334),s=t(5730),o=t(636),l=t(6602),u=t(3735),m="tabList__CuJ",p="tabItem_LNqP";function d(e){var n,t,s=e.lazy,d=e.block,c=e.defaultValue,y=e.values,b=e.groupId,g=e.className,N=a.Children.map(e.children,(function(e){if((0,a.isValidElement)(e)&&"value"in e.props)return e;throw new Error("Docusaurus error: Bad child <"+("string"==typeof e.type?e.type:e.type.name)+'>: all children of the component should be , and every should have a unique "value" prop.')})),h=null!=y?y:N.map((function(e){var n=e.props;return{value:n.value,label:n.label,attributes:n.attributes}})),k=(0,o.l)(h,(function(e,n){return e.value===n.value}));if(k.length>0)throw new Error('Docusaurus error: Duplicate values "'+k.map((function(e){return e.value})).join(", ")+'" found in . Every value needs to be unique.');var v=null===c?c:null!=(n=null!=c?c:null==(t=N.find((function(e){return e.props.default})))?void 0:t.props.value)?n:N[0].props.value;if(null!==v&&!h.some((function(e){return e.value===v})))throw new Error('Docusaurus error: The has a defaultValue "'+v+'" but none of its children has the corresponding value. Available values are: '+h.map((function(e){return e.value})).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");var C=(0,l.U)(),f=C.tabGroupChoices,w=C.setTabGroupChoices,I=(0,a.useState)(v),D=I[0],T=I[1],P=[],L=(0,u.o5)().blockElementScrollPositionUntilNextRender;if(null!=b){var x=f[b];null!=x&&x!==D&&h.some((function(e){return e.value===x}))&&T(x)}var A=function(e){var n=e.currentTarget,t=P.indexOf(n),r=h[t].value;r!==D&&(L(n),T(r),null!=b&&w(b,String(r)))},E=function(e){var n,t=null;switch(e.key){case"ArrowRight":var r,a=P.indexOf(e.currentTarget)+1;t=null!=(r=P[a])?r:P[0];break;case"ArrowLeft":var i,s=P.indexOf(e.currentTarget)-1;t=null!=(i=P[s])?i:P[P.length-1]}null==(n=t)||n.focus()};return a.createElement("div",{className:(0,i.Z)("tabs-container",m)},a.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,i.Z)("tabs",{"tabs--block":d},g)},h.map((function(e){var n=e.value,t=e.label,s=e.attributes;return a.createElement("li",(0,r.Z)({role:"tab",tabIndex:D===n?0:-1,"aria-selected":D===n,key:n,ref:function(e){return P.push(e)},onKeyDown:E,onFocus:A,onClick:A},s,{className:(0,i.Z)("tabs__item",p,null==s?void 0:s.className,{"tabs__item--active":D===n})}),null!=t?t:n)}))),s?(0,a.cloneElement)(N.filter((function(e){return e.props.value===D}))[0],{className:"margin-top--md"}):a.createElement("div",{className:"margin-top--md"},N.map((function(e,n){return(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==D})}))))}function c(e){var n=(0,s.Z)();return a.createElement(d,(0,r.Z)({key:String(n)},e))}},9354:function(e,n,t){t.r(n),t.d(n,{assets:function(){return d},contentTitle:function(){return m},default:function(){return b},frontMatter:function(){return u},metadata:function(){return p},toc:function(){return c}});var r=t(3117),a=t(102),i=(t(7294),t(3905)),s=(t(1402),t(5559)),o=t(433),l=["components"],u={id:"dbcontext-hight-query",title:"9.11 \u9ad8\u7ea7\u67e5\u8be2\u64cd\u4f5c",sidebar_label:"9.11 \u9ad8\u7ea7\u67e5\u8be2\u64cd\u4f5c"},m=void 0,p={unversionedId:"dbcontext-hight-query",id:"dbcontext-hight-query",title:"9.11 \u9ad8\u7ea7\u67e5\u8be2\u64cd\u4f5c",description:"",source:"@site/docs/dbcontext-high-query.mdx",sourceDirName:".",slug:"/dbcontext-hight-query",permalink:"/furion/docs/dbcontext-hight-query",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-high-query.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"dbcontext-hight-query",title:"9.11 \u9ad8\u7ea7\u67e5\u8be2\u64cd\u4f5c",sidebar_label:"9.11 \u9ad8\u7ea7\u67e5\u8be2\u64cd\u4f5c"},sidebar:"docs",previous:{title:"9.10 \u67e5\u8be2\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-query"},next:{title:"9.12 \u89c6\u56fe\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-view"}},d={},c=[{value:"9.11.1 \u5173\u8054\u6570\u636e\u6a21\u578b",id:"9111-\u5173\u8054\u6570\u636e\u6a21\u578b",level:2},{value:"9.11.2 \u4e00\u5bf9\u4e00\u67e5\u8be2",id:"9112-\u4e00\u5bf9\u4e00\u67e5\u8be2",level:2},{value:"9.11.3 \u4e00\u5bf9\u591a\u67e5\u8be2",id:"9113-\u4e00\u5bf9\u591a\u67e5\u8be2",level:2},{value:"9.11.4 \u591a\u5bf9\u591a\u67e5\u8be2",id:"9114-\u591a\u5bf9\u591a\u67e5\u8be2",level:2},{value:"9.11.5 \u8054\u8868\u67e5\u8be2",id:"9115-\u8054\u8868\u67e5\u8be2",level:2},{value:"9.11.5.1 \u5185\u8fde\u63a5 Inner Join",id:"91151-\u5185\u8fde\u63a5-inner-join",level:3},{value:"9.11.5.2 \u5de6\u8fde\u63a5 Left Join",id:"91152-\u5de6\u8fde\u63a5-left-join",level:3},{value:"9.11.5.3 \u53f3\u8fde\u63a5 Right Join",id:"91153-\u53f3\u8fde\u63a5-right-join",level:3},{value:"9.11.6 \u5206\u7ec4\u67e5\u8be2",id:"9116-\u5206\u7ec4\u67e5\u8be2",level:2},{value:"9.11.7 \u5408\u5e76\u7ed3\u679c\u96c6",id:"9117-\u5408\u5e76\u7ed3\u679c\u96c6",level:2},{value:"9.11.8 \u67e5\u8be2\u6392\u5e8f",id:"9118-\u67e5\u8be2\u6392\u5e8f",level:2},{value:"9.11.8.1 \u6b63\u5e8f",id:"91181-\u6b63\u5e8f",level:3},{value:"9.11.8.2 \u5012\u5e8f",id:"91182-\u5012\u5e8f",level:3},{value:"9.11.8.3 \u6df7\u5408\u5012\u5e8f",id:"91183-\u6df7\u5408\u5012\u5e8f",level:3},{value:"9.11.9 \u9012\u5f52\u67e5\u8be2",id:"9119-\u9012\u5f52\u67e5\u8be2",level:2},{value:"9.11.10 \u52a8\u6001 Sql \u67e5\u8be2",id:"91110-\u52a8\u6001-sql-\u67e5\u8be2",level:2},{value:"9.11.10.1 \u52a8\u6001 Sql",id:"911101-\u52a8\u6001-sql",level:3},{value:"9.11.10.2 \u52a8\u6001 Lambda",id:"911102-\u52a8\u6001-lambda",level:3},{value:"9.11.11 \u65f6\u6001\u67e5\u8be2",id:"91111-\u65f6\u6001\u67e5\u8be2",level:2},{value:"9.11.12 \u6027\u80fd\u4f18\u5316",id:"91112-\u6027\u80fd\u4f18\u5316",level:2},{value:"9.11.13 \u5206\u8868\u67e5\u8be2\u5c0f\u4f8b\u5b50",id:"91113-\u5206\u8868\u67e5\u8be2\u5c0f\u4f8b\u5b50",level:2},{value:"9.11.14 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"91114-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],y={toc:c};function b(e){var n=e.components,t=(0,a.Z)(e,l);return(0,i.kt)("wrapper",(0,r.Z)({},y,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"9111-\u5173\u8054\u6570\u636e\u6a21\u578b"},"9.11.1 \u5173\u8054\u6570\u636e\u6a21\u578b"),(0,i.kt)(s.Z,{defaultValue:"person",values:[{label:"Person",value:"person"},{label:"PersonDetail",value:"person-detail"},{label:"Children",value:"children"},{label:"Post",value:"post"}],mdxType:"Tabs"},(0,i.kt)(o.Z,{value:"person",mdxType:"TabItem"},(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {38,43,48}",showLineNumbers:!0,"":!0,"{38,43,48}":!0},"using Furion.DatabaseAccessor;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Furion.Core\n{\n public class Person : Entity\n {\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n public Person()\n {\n CreatedTime = DateTime.Now;\n }\n\n /// \n /// \u59d3\u540d\n /// \n [MaxLength(32)]\n public string Name { get; set; }\n\n /// \n /// \u5e74\u9f84\n /// \n public int Age { get; set; }\n\n /// \n /// \u4f4f\u5740\n /// \n public string Address { get; set; }\n\n /// \n /// \u4ece\u8868\n /// \n public PersonDetail PersonDetail { get; set; }\n\n /// \n /// \u4e00\u5bf9\u591a\n /// \n public ICollection Childrens { get; set; }\n\n /// \n /// \u591a\u5bf9\u591a\n /// \n public ICollection Posts { get; set; }\n }\n}\n"))),(0,i.kt)(o.Z,{value:"person-detail",mdxType:"TabItem"},(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {25}",showLineNumbers:!0,"":!0,"{25}":!0},"using Furion.DatabaseAccessor;\n\nnamespace Furion.Core\n{\n public class PersonDetail : EntityBase\n {\n /// \n /// \u7535\u8bdd\u53f7\u7801\n /// \n public string PhoneNumber { get; set; }\n\n /// \n /// QQ \u53f7\u7801\n /// \n public string QQ { get; set; }\n\n /// \n /// \u5916\u952e\n /// \n public int PersonId { get; set; }\n\n /// \n /// \u4e3b\u8868\n /// \n public Person Person { get; set; }\n }\n}\n"))),(0,i.kt)(o.Z,{value:"children",mdxType:"TabItem"},(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {35}",showLineNumbers:!0,"":!0,"{35}":!0},"using Furion.DatabaseAccessor;\nusing System;\n\nnamespace Furion.Core\n{\n public class Children : Entity\n {\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n public Children()\n {\n CreatedTime = DateTime.Now;\n \n }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n\n /// \n /// \u6027\u522b\n /// \n public Gender Gender { get; set; }\n\n /// \n /// \u5916\u952e\n /// \n public int PersonId { get; set; }\n\n /// \n /// \u4e3b\u8868\n /// \n public Person Person { get; set; }\n }\n}\n"))),(0,i.kt)(o.Z,{value:"post",mdxType:"TabItem"},(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {26}",showLineNumbers:!0,"":!0,"{26}":!0},"using Furion.DatabaseAccessor;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Furion.Core\n{\n public class Post : Entity\n {\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n public Post()\n {\n CreatedTime = DateTime.Now;\n \n }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n\n /// \n /// Person \u96c6\u5408\n /// \n public ICollection Persons { get; set; }\n }\n}\n")))),(0,i.kt)("h2",{id:"9112-\u4e00\u5bf9\u4e00\u67e5\u8be2"},"9.11.2 \u4e00\u5bf9\u4e00\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u793a\u4f8b\u4e00\nvar person = repository.Include(u => u.Detail);\n\n// \u793a\u4f8b\u4e8c\nvar person = repository.Include(u => u.Detail)\n .Include(u => u.Post);\n\n// \u793a\u4f8b\u4e09\nvar person = repository.Include(u => u.Detail)\n .ThenInclude(d => d.Review)\n .Include(u => u.Post);\n\n// \u793a\u4f8b\u56db\nvar person = repository.Include(u => u.Detail.Where(d => d.Id > 10).OrderBy(d => d.Name))\n .ThenInclude(d => d.Review)\n .Include(u => u.Post);\n\n// \u793a\u4f8b\u4e94\nvar person = repository.Include(!string.IsNullOrEmpty(keyword), u => u.Detail);\n\n// \u793a\u4f8b\u516d\nvar person = repository.Include(!string.IsNullOrEmpty(keyword), u => u.Detail)\n .Include(age > 18, u => u.Detail.Where(d => d.Id > 10).OrderBy(d => d.Name))\n .ThenInclude(d => d.Review)\n .Include(u => u.Post);\n")),(0,i.kt)("h2",{id:"9113-\u4e00\u5bf9\u591a\u67e5\u8be2"},"9.11.3 \u4e00\u5bf9\u591a\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u793a\u4f8b\u4e00\nvar person = repository.Include(u => u.Childrens);\n\n// \u53c2\u8003 \u4e00\u5bf9\u4e00 \u4f8b\u5b50\n")),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"\u4e00\u5bf9\u4e00")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"\u4e00\u5bf9\u591a")," \u67e5\u8be2\u65b9\u6cd5\u4e00\u6837\uff0c\u552f\u4e00\u7684\u533a\u522b\u662f\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"\u4e00\u5bf9\u591a")," \u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"ICollection")," \u5b9a\u4e49\u5c5e\u6027\u3002")),(0,i.kt)("h2",{id:"9114-\u591a\u5bf9\u591a\u67e5\u8be2"},"9.11.4 \u591a\u5bf9\u591a\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u793a\u4f8b\u4e00\nvar person = repository.Include(u => u.Posts);\n\n// \u53c2\u8003 \u4e00\u5bf9\u4e00 \u4f8b\u5b50\n")),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"\u4e00\u5bf9\u4e00")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"\u591a\u5bf9\u591a")," \u67e5\u8be2\u65b9\u6cd5\u4e00\u6837\uff0c\u552f\u4e00\u7684\u533a\u522b\u662f\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"\u591a\u5bf9\u591a")," \u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"ICollection")," \u5b9a\u4e49\u5c5e\u6027\u3002")),(0,i.kt)("h2",{id:"9115-\u8054\u8868\u67e5\u8be2"},"9.11.5 \u8054\u8868\u67e5\u8be2"),(0,i.kt)("h3",{id:"91151-\u5185\u8fde\u63a5-inner-join"},"9.11.5.1 \u5185\u8fde\u63a5 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Inner Join")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var query = from p in _personRepository.AsQueryable()\n join d in _personDetailRepository.AsQueryable() on p.Id equals d.PersonId\n select new PersonDto\n {\n PhoneNumber = p.PersonDetail.PhoneNumber,\n Address = p.Address,\n Age = p.Age,\n Name = p.Name,\n Id = p.Id,\n QQ = p.PersonDetail.QQ\n };\n")),(0,i.kt)("h3",{id:"91152-\u5de6\u8fde\u63a5-left-join"},"9.11.5.2 \u5de6\u8fde\u63a5 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Left Join")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,3}",showLineNumbers:!0,"":!0,"{2,3}":!0},"var query = from p in _personRepository.AsQueryable()\n join d in _personDetailRepository.AsQueryable() on p.Id equals d.PersonId into results\n from d in results.DefaultIfEmpty()\n select new PersonDto\n {\n PhoneNumber = p.PersonDetail.PhoneNumber,\n Address = p.Address,\n Age = p.Age,\n Name = p.Name,\n Id = p.Id,\n QQ = p.PersonDetail.QQ\n };\n")),(0,i.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"note"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"Left Join"))," \u548c ",(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"Inner Join"))," \u4e0d\u540c\u7684\u662f\uff0c",(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"Left Join"))," \u4f1a\u5148\u5c06\u7ed3\u679c ",(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"into"))," \u5230\u65b0\u7684\u7ed3\u679c\u96c6\u7136\u540e\u518d\u67e5\u8be2\uff0c\u5e76\u8c03\u7528 ",(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"DefaultIfEmpty()"))," \u65b9\u6cd5\u3002")),(0,i.kt)("h3",{id:"91153-\u53f3\u8fde\u63a5-right-join"},"9.11.5.3 \u53f3\u8fde\u63a5 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Right Join")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Right Join")," \u53ea\u9700\u8981\u5c06 ",(0,i.kt)("inlineCode",{parentName:"p"},"Left Join")," \u4e3b\u4ece\u8868\u4f4d\u7f6e\u66f4\u6362\u5373\u53ef\u3002"),(0,i.kt)("h2",{id:"9116-\u5206\u7ec4\u67e5\u8be2"},"9.11.6 \u5206\u7ec4\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u793a\u4f8b\u4e00\nvar query = repository.AsQueryable().GroupBy(x => new { x.Column1, x.Column2 });\n\n// \u793a\u4f8b\u4e8c\nvar query = from student in repository.AsQueryable()\n group student by repository2.AsQueryable() into dateGroup\n select new ResultData()\n {\n Key = dateGroup.Key,\n Value = dateGroup.Count()\n };\n\n// \u793a\u4f8b\u4e09\nvar query = from a in repository.AsQueryable()\n join b in repository2.AsQueryable() on a.Id equals b.Aid\n join c in repository3.AsQueryable() on c.id equals b.Bid\n group a by new { a.Age, b.Sex } into g\n select new {\n Peo = g.Key,\n Count = g.Count()\n };\n")),(0,i.kt)("h2",{id:"9117-\u5408\u5e76\u7ed3\u679c\u96c6"},"9.11.7 \u5408\u5e76\u7ed3\u679c\u96c6"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var query = repository.AsQueryable(u => u.Id > 10)\n .Union(\n repository2.AsQueryable(u => u.Id <= 10)\n );\n")),(0,i.kt)("h2",{id:"9118-\u67e5\u8be2\u6392\u5e8f"},"9.11.8 \u67e5\u8be2\u6392\u5e8f"),(0,i.kt)("h3",{id:"91181-\u6b63\u5e8f"},"9.11.8.1 \u6b63\u5e8f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u793a\u4f8b\u4e00\nvar query = repository.AsQueryable()\n .OrderBy(u => u.Id);\n\n// \u793a\u4f8b\u4e8c\nvar query =repository.AsQueryable()\n .OrderBy(u => u.Id)\n .ThenBy(u => u.Name);\n")),(0,i.kt)("h3",{id:"91182-\u5012\u5e8f"},"9.11.8.2 \u5012\u5e8f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u793a\u4f8b\u4e00\nvar query = repository.AsQueryable()\n .OrderByDescending(u => u.Id);\n\n// \u793a\u4f8b\u4e8c\nvar query =repository.AsQueryable()\n .OrderByDescending(u => u.Id)\n .ThenByDescending(u => u.Name);\n")),(0,i.kt)("h3",{id:"91183-\u6df7\u5408\u5012\u5e8f"},"9.11.8.3 \u6df7\u5408\u5012\u5e8f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u793a\u4f8b\u4e00\nvar query = repository.AsQueryable()\n .OrderBy(u => u.Id)\n .OrderByDescending(u => u.Name)\n .ThenBy(u => u.Age);\n")),(0,i.kt)("h2",{id:"9119-\u9012\u5f52\u67e5\u8be2"},"9.11.9 \u9012\u5f52\u67e5\u8be2"),(0,i.kt)(s.Z,{defaultValue:"city",values:[{label:"City",value:"city"},{label:"CityDto",value:"citydto"}],mdxType:"Tabs"},(0,i.kt)(o.Z,{value:"city",mdxType:"TabItem"},(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {12,36,41,49-55}",showLineNumbers:!0,"":!0,"{12,36,41,49-55}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Furion.Core\n{\n /// \n /// \u57ce\u5e02\n /// \n public class City : Entity, IEntityTypeBuilder, IEntitySeedData\n {\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n public City()\n {\n CreatedTime = DateTime.Now;\n \n }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n\n /// \n /// \u4e0a\u7ea7Id\n /// \n public int? ParentId { get; set; }\n\n /// \n /// \u4e0a\u7ea7\n /// \n public virtual City Parent { get; set; }\n\n /// \n /// \u5b50\u96c6\n /// \n public virtual ICollection Childrens { get; set; }\n\n /// \n /// \u914d\u7f6e\u5b9e\u4f53\u5173\u7cfb\n /// \n /// \n /// \n /// \n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder\n .HasMany(x => x.Childrens)\n .WithOne(x => x.Parent)\n .HasForeignKey(x => x.ParentId)\n .OnDelete(DeleteBehavior.ClientSetNull); // \u5fc5\u987b\u8bbe\u7f6e\u8fd9\u4e00\u884c\n }\n\n /// \n /// \u79cd\u5b50\u6570\u636e\n /// \n /// \n /// \n /// \n public IEnumerable HasData(DbContext dbContext, Type dbContextLocator)\n {\n return new List\n {\n new City { Id=1,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="\u4e2d\u56fd" },\n new City { Id=2,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="\u5e7f\u4e1c\u7701",ParentId=1 },\n new City { Id=3,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="\u4e2d\u5c71\u5e02",ParentId=2 },\n new City { Id=4,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="\u73e0\u6d77\u5e02",ParentId=2 },\n new City { Id=5,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="\u6d59\u6c5f\u7701",ParentId=1 },\n };\n }\n }\n}\n'))),(0,i.kt)(o.Z,{value:"citydto",mdxType:"TabItem"},(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"using System.Collections.Generic;\n\nnamespace Furion.Application.Persons\n{\n public class CityDto\n {\n /// \n /// \u4e3b\u952e\n /// \n public int Id { get; set; }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n\n /// \n /// \u5b50\u96c6\n /// \n public ICollection Childrens { get; set; }\n }\n}\n")))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var cities = await repository.AsQueryable()\n .Include(u => u.Childrens)\n .Where(u => u.Id == 1)\n .ToListAsync();\n\nvar dtos = cities.Adapt>();\n")),(0,i.kt)("h2",{id:"91110-\u52a8\u6001-sql-\u67e5\u8be2"},"9.11.10 \u52a8\u6001 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Sql")," \u67e5\u8be2"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u9ed8\u8ba4\u4e0d\u652f\u6301 \u52a8\u6001 ",(0,i.kt)("inlineCode",{parentName:"p"},"Sql")," \u67e5\u8be2\u529f\u80fd\uff0c\u4e0d\u8fc7\u53ef\u4ee5\u901a\u8fc7\u7b2c\u4e09\u65b9\u5b9e\u73b0\uff1a"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u9879\u76ee\u5c42\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},"System.Linq.Dynamic.Core")," \u5305 ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/zzzprojects/System.Linq.Dynamic.Core"},"https://github.com/zzzprojects/System.Linq.Dynamic.Core")),(0,i.kt)("h3",{id:"911101-\u52a8\u6001-sql"},"9.11.10.1 \u52a8\u6001 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Sql")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u793a\u4f8b\u4e00\nvar query = repository.AsQueryable()\n .Where("City == @0 and Orders.Count >= @1", "China", 10)\n .OrderBy("CompanyName")\n .Select("new(CompanyName as Name, Phone)");\n\n// \u793a\u4f8b\u4e8c\nvar list = repository.AsQueryable()\n .Where("Name.Contains(@0)","Furion")\n .ToList();\n\n// \u793a\u4f8b\u4e09\uff0c\u652f\u6301 ? \u8bed\u6cd5\nvar customers = repository.AsQueryable()\n .Include(c => c.Location)\n .Where(c => c.Location?.Name == "test") // \u6ce8\u610f Location?.Name\n .ToList();\n')),(0,i.kt)("h3",{id:"911102-\u52a8\u6001-lambda"},"9.11.10.2 \u52a8\u6001 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Lambda")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u793a\u4f8b\u4e00\nvar x = Expression.Parameter(typeof(int), "x");\nvar y = Expression.Parameter(typeof(int), "y");\nvar e = DynamicExpressionParser\n .ParseLambda(new ParameterExpression[] { x, y }, null, "(x + y) * 2");\n\n// \u793a\u4f8b\u4e8c\nvar e = DynamicExpressionParser.ParseLambda(\n typeof(Customer), typeof(bool),\n "City = @0 and Orders.Count >= @1",\n "London", 10);\n')),(0,i.kt)("h2",{id:"91111-\u65f6\u6001\u67e5\u8be2"},"9.11.11 \u65f6\u6001\u67e5\u8be2"),(0,i.kt)("admonition",{title:"\u529f\u80fd\u79fb\u9664\u58f0\u660e",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 2.13 +")," \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u8fd8\u63d0\u4f9b\u4e86\u65f6\u6001\u67e5\u8be2\u529f\u80fd\uff0c\u53ef\u4ee5\u67e5\u8be2\u7279\u5b9a\u65f6\u95f4\u7684\u6570\u636e\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = rep.Entities\n .AsTemporalOf(DateTime.UtcNow.AddDays(-1))\n .Include(i=> i.Company)\n .FirstOrDefault(i => i.Name == "Furion");\n')),(0,i.kt)("p",null,"\u53e6\u5916\u63d0\u4f9b\u4e86\u591a\u4e2a\u65f6\u6001\u67e5\u8be2\u65b9\u6cd5"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"AsTemporalAll()"),(0,i.kt)("li",{parentName:"ul"},"AsTemporalAsOf(date)"),(0,i.kt)("li",{parentName:"ul"},"AsTemporalFrom(startDate, endDate)"),(0,i.kt)("li",{parentName:"ul"},"AsTemporalBetween(startDate, endDate)"),(0,i.kt)("li",{parentName:"ul"},"AsTemporalContained(startDate, endDate)")),(0,i.kt)("h2",{id:"91112-\u6027\u80fd\u4f18\u5316"},"9.11.12 \u6027\u80fd\u4f18\u5316"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"EF Core")," \u4f1a\u8ddf\u8e2a\u6240\u6709\u5b9e\u4f53\uff0c\u4e5f\u5c31\u662f\u4efb\u4f55\u6570\u636e\u6539\u53d8\u90fd\u4f1a\u5f15\u8d77\u6570\u636e\u68c0\u67e5\uff0c\u6240\u4ee5\u5982\u679c\u53ea\u505a\u67e5\u8be2\u64cd\u4f5c\uff0c\u5efa\u8bae\u5173\u95ed\u5b9e\u4f53\u8ddf\u8e2a\u529f\u80fd\u3002"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u4ee5\u4e0b\u9ad8\u6027\u80fd\u5b9e\u4f53\u96c6\u5408\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"DetachedEntities"),"\uff1a\u8131\u8f68/\u4e0d\u8ffd\u8e2a\u5b9e\u4f53"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"AsQueryable(false)"),"\uff1a\u4e0d\u8ffd\u8e2a\u5b9e\u4f53"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Entities.AsNoTracking()"),"\uff1a\u624b\u52a8\u5173\u95ed\u5b9e\u4f53\u8ffd\u8e2a")),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"EF Core")," \u4e2d\uff0c\u590d\u6742\u67e5\u8be2\u603b\u662f\u4f1a\u751f\u6210\u4e00\u4e2a ",(0,i.kt)("inlineCode",{parentName:"p"},"sql"),"\uff0c\u4e5f\u5c31\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"AsSingleQuery()"),"\uff0c\u6211\u4eec\u4e5f\u53ef\u4ee5\u8bbe\u7f6e\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"AsSplitQuery()")," \u5207\u5272\u6210\u591a\u4e2a\u67e5\u8be2\u3002"),(0,i.kt)("h2",{id:"91113-\u5206\u8868\u67e5\u8be2\u5c0f\u4f8b\u5b50"},"9.11.13 \u5206\u8868\u67e5\u8be2\u5c0f\u4f8b\u5b50"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Furion.Core\n{\n public class Person : Entity, IEntityTypeBuilder\n {\n public string Name { get; set; }\n\n /// \n /// \u914d\u7f6e\u5b9e\u4f53\u5173\u7cfb\n /// \n /// \n /// \n /// \n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.ToSqlQuery(\n @"select * from dbo.person.2020-09-19\n union all\n select * from dbo.person.2020-09-20");\n }\n }\n}\n')),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var posts = repository.Where(u => u.Id > 10).ToList();\n")),(0,i.kt)("h2",{id:"91114-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.11.14 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}b.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return m},kt:function(){return c}});var r=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=r.createContext({}),u=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},m=function(e){var n=u(e.components);return r.createElement(l.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,l=e.parentName,m=o(e,["components","mdxType","originalType","parentName"]),d=u(t),c=a,y=d["".concat(l,".").concat(c)]||d[c]||p[c]||i;return t?r.createElement(y,s(s({ref:n},m),{},{components:t})):r.createElement(y,s({ref:n},m))}));function c(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,s=new Array(i);s[0]=d;var o={};for(var l in n)hasOwnProperty.call(n,l)&&(o[l]=n[l]);o.originalType=e,o.mdxType="string"==typeof e?e:a,s[1]=o;for(var u=2;u=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=r.createContext({}),u=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},m=function(e){var n=u(e.components);return r.createElement(l.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,l=e.parentName,m=o(e,["components","mdxType","originalType","parentName"]),d=u(t),c=a,y=d["".concat(l,".").concat(c)]||d[c]||p[c]||i;return t?r.createElement(y,s(s({ref:n},m),{},{components:t})):r.createElement(y,s({ref:n},m))}));function c(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,s=new Array(i);s[0]=d;var o={};for(var l in n)hasOwnProperty.call(n,l)&&(o[l]=n[l]);o.originalType=e,o.mdxType="string"==typeof e?e:a,s[1]=o;for(var u=2;u child <"+("string"==typeof e.type?e.type:e.type.name)+'>: all children of the component should be , and every should have a unique "value" prop.')})),h=null!=y?y:N.map((function(e){var n=e.props;return{value:n.value,label:n.label,attributes:n.attributes}})),k=(0,o.l)(h,(function(e,n){return e.value===n.value}));if(k.length>0)throw new Error('Docusaurus error: Duplicate values "'+k.map((function(e){return e.value})).join(", ")+'" found in . Every value needs to be unique.');var v=null===c?c:null!=(n=null!=c?c:null==(t=N.find((function(e){return e.props.default})))?void 0:t.props.value)?n:N[0].props.value;if(null!==v&&!h.some((function(e){return e.value===v})))throw new Error('Docusaurus error: The has a defaultValue "'+v+'" but none of its children has the corresponding value. Available values are: '+h.map((function(e){return e.value})).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");var C=(0,l.U)(),f=C.tabGroupChoices,w=C.setTabGroupChoices,I=(0,a.useState)(v),D=I[0],T=I[1],P=[],L=(0,u.o5)().blockElementScrollPositionUntilNextRender;if(null!=b){var x=f[b];null!=x&&x!==D&&h.some((function(e){return e.value===x}))&&T(x)}var A=function(e){var n=e.currentTarget,t=P.indexOf(n),r=h[t].value;r!==D&&(L(n),T(r),null!=b&&w(b,String(r)))},E=function(e){var n,t=null;switch(e.key){case"ArrowRight":var r,a=P.indexOf(e.currentTarget)+1;t=null!=(r=P[a])?r:P[0];break;case"ArrowLeft":var i,s=P.indexOf(e.currentTarget)-1;t=null!=(i=P[s])?i:P[P.length-1]}null==(n=t)||n.focus()};return a.createElement("div",{className:(0,i.Z)("tabs-container",m)},a.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,i.Z)("tabs",{"tabs--block":d},g)},h.map((function(e){var n=e.value,t=e.label,s=e.attributes;return a.createElement("li",(0,r.Z)({role:"tab",tabIndex:D===n?0:-1,"aria-selected":D===n,key:n,ref:function(e){return P.push(e)},onKeyDown:E,onFocus:A,onClick:A},s,{className:(0,i.Z)("tabs__item",p,null==s?void 0:s.className,{"tabs__item--active":D===n})}),null!=t?t:n)}))),s?(0,a.cloneElement)(N.filter((function(e){return e.props.value===D}))[0],{className:"margin-top--md"}):a.createElement("div",{className:"margin-top--md"},N.map((function(e,n){return(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==D})}))))}function c(e){var n=(0,s.Z)();return a.createElement(d,(0,r.Z)({key:String(n)},e))}},2126:function(e,n,t){t.r(n),t.d(n,{assets:function(){return d},contentTitle:function(){return m},default:function(){return b},frontMatter:function(){return u},metadata:function(){return p},toc:function(){return c}});var r=t(3117),a=t(102),i=(t(7294),t(3905)),s=(t(4996),t(5488)),o=t(5162),l=["components"],u={id:"dbcontext-hight-query",title:"9.11 \u9ad8\u7ea7\u67e5\u8be2\u64cd\u4f5c",sidebar_label:"9.11 \u9ad8\u7ea7\u67e5\u8be2\u64cd\u4f5c"},m=void 0,p={unversionedId:"dbcontext-hight-query",id:"dbcontext-hight-query",title:"9.11 \u9ad8\u7ea7\u67e5\u8be2\u64cd\u4f5c",description:"",source:"@site/docs/dbcontext-high-query.mdx",sourceDirName:".",slug:"/dbcontext-hight-query",permalink:"/furion/docs/dbcontext-hight-query",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-high-query.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"dbcontext-hight-query",title:"9.11 \u9ad8\u7ea7\u67e5\u8be2\u64cd\u4f5c",sidebar_label:"9.11 \u9ad8\u7ea7\u67e5\u8be2\u64cd\u4f5c"},sidebar:"docs",previous:{title:"9.10 \u67e5\u8be2\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-query"},next:{title:"9.12 \u89c6\u56fe\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-view"}},d={},c=[{value:"9.11.1 \u5173\u8054\u6570\u636e\u6a21\u578b",id:"9111-\u5173\u8054\u6570\u636e\u6a21\u578b",level:2},{value:"9.11.2 \u4e00\u5bf9\u4e00\u67e5\u8be2",id:"9112-\u4e00\u5bf9\u4e00\u67e5\u8be2",level:2},{value:"9.11.3 \u4e00\u5bf9\u591a\u67e5\u8be2",id:"9113-\u4e00\u5bf9\u591a\u67e5\u8be2",level:2},{value:"9.11.4 \u591a\u5bf9\u591a\u67e5\u8be2",id:"9114-\u591a\u5bf9\u591a\u67e5\u8be2",level:2},{value:"9.11.5 \u8054\u8868\u67e5\u8be2",id:"9115-\u8054\u8868\u67e5\u8be2",level:2},{value:"9.11.5.1 \u5185\u8fde\u63a5 Inner Join",id:"91151-\u5185\u8fde\u63a5-inner-join",level:3},{value:"9.11.5.2 \u5de6\u8fde\u63a5 Left Join",id:"91152-\u5de6\u8fde\u63a5-left-join",level:3},{value:"9.11.5.3 \u53f3\u8fde\u63a5 Right Join",id:"91153-\u53f3\u8fde\u63a5-right-join",level:3},{value:"9.11.6 \u5206\u7ec4\u67e5\u8be2",id:"9116-\u5206\u7ec4\u67e5\u8be2",level:2},{value:"9.11.7 \u5408\u5e76\u7ed3\u679c\u96c6",id:"9117-\u5408\u5e76\u7ed3\u679c\u96c6",level:2},{value:"9.11.8 \u67e5\u8be2\u6392\u5e8f",id:"9118-\u67e5\u8be2\u6392\u5e8f",level:2},{value:"9.11.8.1 \u6b63\u5e8f",id:"91181-\u6b63\u5e8f",level:3},{value:"9.11.8.2 \u5012\u5e8f",id:"91182-\u5012\u5e8f",level:3},{value:"9.11.8.3 \u6df7\u5408\u5012\u5e8f",id:"91183-\u6df7\u5408\u5012\u5e8f",level:3},{value:"9.11.9 \u9012\u5f52\u67e5\u8be2",id:"9119-\u9012\u5f52\u67e5\u8be2",level:2},{value:"9.11.10 \u52a8\u6001 Sql \u67e5\u8be2",id:"91110-\u52a8\u6001-sql-\u67e5\u8be2",level:2},{value:"9.11.10.1 \u52a8\u6001 Sql",id:"911101-\u52a8\u6001-sql",level:3},{value:"9.11.10.2 \u52a8\u6001 Lambda",id:"911102-\u52a8\u6001-lambda",level:3},{value:"9.11.11 \u65f6\u6001\u67e5\u8be2",id:"91111-\u65f6\u6001\u67e5\u8be2",level:2},{value:"9.11.12 \u6027\u80fd\u4f18\u5316",id:"91112-\u6027\u80fd\u4f18\u5316",level:2},{value:"9.11.13 \u5206\u8868\u67e5\u8be2\u5c0f\u4f8b\u5b50",id:"91113-\u5206\u8868\u67e5\u8be2\u5c0f\u4f8b\u5b50",level:2},{value:"9.11.14 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"91114-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],y={toc:c};function b(e){var n=e.components,t=(0,a.Z)(e,l);return(0,i.kt)("wrapper",(0,r.Z)({},y,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"9111-\u5173\u8054\u6570\u636e\u6a21\u578b"},"9.11.1 \u5173\u8054\u6570\u636e\u6a21\u578b"),(0,i.kt)(s.Z,{defaultValue:"person",values:[{label:"Person",value:"person"},{label:"PersonDetail",value:"person-detail"},{label:"Children",value:"children"},{label:"Post",value:"post"}],mdxType:"Tabs"},(0,i.kt)(o.Z,{value:"person",mdxType:"TabItem"},(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {38,43,48}",showLineNumbers:!0,"":!0,"{38,43,48}":!0},"using Furion.DatabaseAccessor;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Furion.Core\n{\n public class Person : Entity\n {\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n public Person()\n {\n CreatedTime = DateTime.Now;\n }\n\n /// \n /// \u59d3\u540d\n /// \n [MaxLength(32)]\n public string Name { get; set; }\n\n /// \n /// \u5e74\u9f84\n /// \n public int Age { get; set; }\n\n /// \n /// \u4f4f\u5740\n /// \n public string Address { get; set; }\n\n /// \n /// \u4ece\u8868\n /// \n public PersonDetail PersonDetail { get; set; }\n\n /// \n /// \u4e00\u5bf9\u591a\n /// \n public ICollection Childrens { get; set; }\n\n /// \n /// \u591a\u5bf9\u591a\n /// \n public ICollection Posts { get; set; }\n }\n}\n"))),(0,i.kt)(o.Z,{value:"person-detail",mdxType:"TabItem"},(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {25}",showLineNumbers:!0,"":!0,"{25}":!0},"using Furion.DatabaseAccessor;\n\nnamespace Furion.Core\n{\n public class PersonDetail : EntityBase\n {\n /// \n /// \u7535\u8bdd\u53f7\u7801\n /// \n public string PhoneNumber { get; set; }\n\n /// \n /// QQ \u53f7\u7801\n /// \n public string QQ { get; set; }\n\n /// \n /// \u5916\u952e\n /// \n public int PersonId { get; set; }\n\n /// \n /// \u4e3b\u8868\n /// \n public Person Person { get; set; }\n }\n}\n"))),(0,i.kt)(o.Z,{value:"children",mdxType:"TabItem"},(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {35}",showLineNumbers:!0,"":!0,"{35}":!0},"using Furion.DatabaseAccessor;\nusing System;\n\nnamespace Furion.Core\n{\n public class Children : Entity\n {\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n public Children()\n {\n CreatedTime = DateTime.Now;\n \n }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n\n /// \n /// \u6027\u522b\n /// \n public Gender Gender { get; set; }\n\n /// \n /// \u5916\u952e\n /// \n public int PersonId { get; set; }\n\n /// \n /// \u4e3b\u8868\n /// \n public Person Person { get; set; }\n }\n}\n"))),(0,i.kt)(o.Z,{value:"post",mdxType:"TabItem"},(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {26}",showLineNumbers:!0,"":!0,"{26}":!0},"using Furion.DatabaseAccessor;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Furion.Core\n{\n public class Post : Entity\n {\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n public Post()\n {\n CreatedTime = DateTime.Now;\n \n }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n\n /// \n /// Person \u96c6\u5408\n /// \n public ICollection Persons { get; set; }\n }\n}\n")))),(0,i.kt)("h2",{id:"9112-\u4e00\u5bf9\u4e00\u67e5\u8be2"},"9.11.2 \u4e00\u5bf9\u4e00\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u793a\u4f8b\u4e00\nvar person = repository.Include(u => u.Detail);\n\n// \u793a\u4f8b\u4e8c\nvar person = repository.Include(u => u.Detail)\n .Include(u => u.Post);\n\n// \u793a\u4f8b\u4e09\nvar person = repository.Include(u => u.Detail)\n .ThenInclude(d => d.Review)\n .Include(u => u.Post);\n\n// \u793a\u4f8b\u56db\nvar person = repository.Include(u => u.Detail.Where(d => d.Id > 10).OrderBy(d => d.Name))\n .ThenInclude(d => d.Review)\n .Include(u => u.Post);\n\n// \u793a\u4f8b\u4e94\nvar person = repository.Include(!string.IsNullOrEmpty(keyword), u => u.Detail);\n\n// \u793a\u4f8b\u516d\nvar person = repository.Include(!string.IsNullOrEmpty(keyword), u => u.Detail)\n .Include(age > 18, u => u.Detail.Where(d => d.Id > 10).OrderBy(d => d.Name))\n .ThenInclude(d => d.Review)\n .Include(u => u.Post);\n")),(0,i.kt)("h2",{id:"9113-\u4e00\u5bf9\u591a\u67e5\u8be2"},"9.11.3 \u4e00\u5bf9\u591a\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u793a\u4f8b\u4e00\nvar person = repository.Include(u => u.Childrens);\n\n// \u53c2\u8003 \u4e00\u5bf9\u4e00 \u4f8b\u5b50\n")),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"\u4e00\u5bf9\u4e00")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"\u4e00\u5bf9\u591a")," \u67e5\u8be2\u65b9\u6cd5\u4e00\u6837\uff0c\u552f\u4e00\u7684\u533a\u522b\u662f\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"\u4e00\u5bf9\u591a")," \u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"ICollection")," \u5b9a\u4e49\u5c5e\u6027\u3002")),(0,i.kt)("h2",{id:"9114-\u591a\u5bf9\u591a\u67e5\u8be2"},"9.11.4 \u591a\u5bf9\u591a\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u793a\u4f8b\u4e00\nvar person = repository.Include(u => u.Posts);\n\n// \u53c2\u8003 \u4e00\u5bf9\u4e00 \u4f8b\u5b50\n")),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"\u4e00\u5bf9\u4e00")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"\u591a\u5bf9\u591a")," \u67e5\u8be2\u65b9\u6cd5\u4e00\u6837\uff0c\u552f\u4e00\u7684\u533a\u522b\u662f\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"\u591a\u5bf9\u591a")," \u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"ICollection")," \u5b9a\u4e49\u5c5e\u6027\u3002")),(0,i.kt)("h2",{id:"9115-\u8054\u8868\u67e5\u8be2"},"9.11.5 \u8054\u8868\u67e5\u8be2"),(0,i.kt)("h3",{id:"91151-\u5185\u8fde\u63a5-inner-join"},"9.11.5.1 \u5185\u8fde\u63a5 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Inner Join")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var query = from p in _personRepository.AsQueryable()\n join d in _personDetailRepository.AsQueryable() on p.Id equals d.PersonId\n select new PersonDto\n {\n PhoneNumber = p.PersonDetail.PhoneNumber,\n Address = p.Address,\n Age = p.Age,\n Name = p.Name,\n Id = p.Id,\n QQ = p.PersonDetail.QQ\n };\n")),(0,i.kt)("h3",{id:"91152-\u5de6\u8fde\u63a5-left-join"},"9.11.5.2 \u5de6\u8fde\u63a5 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Left Join")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,3}",showLineNumbers:!0,"":!0,"{2,3}":!0},"var query = from p in _personRepository.AsQueryable()\n join d in _personDetailRepository.AsQueryable() on p.Id equals d.PersonId into results\n from d in results.DefaultIfEmpty()\n select new PersonDto\n {\n PhoneNumber = p.PersonDetail.PhoneNumber,\n Address = p.Address,\n Age = p.Age,\n Name = p.Name,\n Id = p.Id,\n QQ = p.PersonDetail.QQ\n };\n")),(0,i.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"note"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"Left Join"))," \u548c ",(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"Inner Join"))," \u4e0d\u540c\u7684\u662f\uff0c",(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"Left Join"))," \u4f1a\u5148\u5c06\u7ed3\u679c ",(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"into"))," \u5230\u65b0\u7684\u7ed3\u679c\u96c6\u7136\u540e\u518d\u67e5\u8be2\uff0c\u5e76\u8c03\u7528 ",(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"DefaultIfEmpty()"))," \u65b9\u6cd5\u3002")),(0,i.kt)("h3",{id:"91153-\u53f3\u8fde\u63a5-right-join"},"9.11.5.3 \u53f3\u8fde\u63a5 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Right Join")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Right Join")," \u53ea\u9700\u8981\u5c06 ",(0,i.kt)("inlineCode",{parentName:"p"},"Left Join")," \u4e3b\u4ece\u8868\u4f4d\u7f6e\u66f4\u6362\u5373\u53ef\u3002"),(0,i.kt)("h2",{id:"9116-\u5206\u7ec4\u67e5\u8be2"},"9.11.6 \u5206\u7ec4\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u793a\u4f8b\u4e00\nvar query = repository.AsQueryable().GroupBy(x => new { x.Column1, x.Column2 });\n\n// \u793a\u4f8b\u4e8c\nvar query = from student in repository.AsQueryable()\n group student by repository2.AsQueryable() into dateGroup\n select new ResultData()\n {\n Key = dateGroup.Key,\n Value = dateGroup.Count()\n };\n\n// \u793a\u4f8b\u4e09\nvar query = from a in repository.AsQueryable()\n join b in repository2.AsQueryable() on a.Id equals b.Aid\n join c in repository3.AsQueryable() on c.id equals b.Bid\n group a by new { a.Age, b.Sex } into g\n select new {\n Peo = g.Key,\n Count = g.Count()\n };\n")),(0,i.kt)("h2",{id:"9117-\u5408\u5e76\u7ed3\u679c\u96c6"},"9.11.7 \u5408\u5e76\u7ed3\u679c\u96c6"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var query = repository.AsQueryable(u => u.Id > 10)\n .Union(\n repository2.AsQueryable(u => u.Id <= 10)\n );\n")),(0,i.kt)("h2",{id:"9118-\u67e5\u8be2\u6392\u5e8f"},"9.11.8 \u67e5\u8be2\u6392\u5e8f"),(0,i.kt)("h3",{id:"91181-\u6b63\u5e8f"},"9.11.8.1 \u6b63\u5e8f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u793a\u4f8b\u4e00\nvar query = repository.AsQueryable()\n .OrderBy(u => u.Id);\n\n// \u793a\u4f8b\u4e8c\nvar query =repository.AsQueryable()\n .OrderBy(u => u.Id)\n .ThenBy(u => u.Name);\n")),(0,i.kt)("h3",{id:"91182-\u5012\u5e8f"},"9.11.8.2 \u5012\u5e8f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u793a\u4f8b\u4e00\nvar query = repository.AsQueryable()\n .OrderByDescending(u => u.Id);\n\n// \u793a\u4f8b\u4e8c\nvar query =repository.AsQueryable()\n .OrderByDescending(u => u.Id)\n .ThenByDescending(u => u.Name);\n")),(0,i.kt)("h3",{id:"91183-\u6df7\u5408\u5012\u5e8f"},"9.11.8.3 \u6df7\u5408\u5012\u5e8f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u793a\u4f8b\u4e00\nvar query = repository.AsQueryable()\n .OrderBy(u => u.Id)\n .OrderByDescending(u => u.Name)\n .ThenBy(u => u.Age);\n")),(0,i.kt)("h2",{id:"9119-\u9012\u5f52\u67e5\u8be2"},"9.11.9 \u9012\u5f52\u67e5\u8be2"),(0,i.kt)(s.Z,{defaultValue:"city",values:[{label:"City",value:"city"},{label:"CityDto",value:"citydto"}],mdxType:"Tabs"},(0,i.kt)(o.Z,{value:"city",mdxType:"TabItem"},(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {12,36,41,49-55}",showLineNumbers:!0,"":!0,"{12,36,41,49-55}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Furion.Core\n{\n /// \n /// \u57ce\u5e02\n /// \n public class City : Entity, IEntityTypeBuilder, IEntitySeedData\n {\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n public City()\n {\n CreatedTime = DateTime.Now;\n \n }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n\n /// \n /// \u4e0a\u7ea7Id\n /// \n public int? ParentId { get; set; }\n\n /// \n /// \u4e0a\u7ea7\n /// \n public virtual City Parent { get; set; }\n\n /// \n /// \u5b50\u96c6\n /// \n public virtual ICollection Childrens { get; set; }\n\n /// \n /// \u914d\u7f6e\u5b9e\u4f53\u5173\u7cfb\n /// \n /// \n /// \n /// \n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder\n .HasMany(x => x.Childrens)\n .WithOne(x => x.Parent)\n .HasForeignKey(x => x.ParentId)\n .OnDelete(DeleteBehavior.ClientSetNull); // \u5fc5\u987b\u8bbe\u7f6e\u8fd9\u4e00\u884c\n }\n\n /// \n /// \u79cd\u5b50\u6570\u636e\n /// \n /// \n /// \n /// \n public IEnumerable HasData(DbContext dbContext, Type dbContextLocator)\n {\n return new List\n {\n new City { Id=1,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="\u4e2d\u56fd" },\n new City { Id=2,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="\u5e7f\u4e1c\u7701",ParentId=1 },\n new City { Id=3,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="\u4e2d\u5c71\u5e02",ParentId=2 },\n new City { Id=4,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="\u73e0\u6d77\u5e02",ParentId=2 },\n new City { Id=5,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="\u6d59\u6c5f\u7701",ParentId=1 },\n };\n }\n }\n}\n'))),(0,i.kt)(o.Z,{value:"citydto",mdxType:"TabItem"},(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"using System.Collections.Generic;\n\nnamespace Furion.Application.Persons\n{\n public class CityDto\n {\n /// \n /// \u4e3b\u952e\n /// \n public int Id { get; set; }\n\n /// \n /// \u540d\u79f0\n /// \n public string Name { get; set; }\n\n /// \n /// \u5b50\u96c6\n /// \n public ICollection Childrens { get; set; }\n }\n}\n")))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var cities = await repository.AsQueryable()\n .Include(u => u.Childrens)\n .Where(u => u.Id == 1)\n .ToListAsync();\n\nvar dtos = cities.Adapt>();\n")),(0,i.kt)("h2",{id:"91110-\u52a8\u6001-sql-\u67e5\u8be2"},"9.11.10 \u52a8\u6001 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Sql")," \u67e5\u8be2"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u9ed8\u8ba4\u4e0d\u652f\u6301 \u52a8\u6001 ",(0,i.kt)("inlineCode",{parentName:"p"},"Sql")," \u67e5\u8be2\u529f\u80fd\uff0c\u4e0d\u8fc7\u53ef\u4ee5\u901a\u8fc7\u7b2c\u4e09\u65b9\u5b9e\u73b0\uff1a"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u9879\u76ee\u5c42\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},"System.Linq.Dynamic.Core")," \u5305 ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/zzzprojects/System.Linq.Dynamic.Core"},"https://github.com/zzzprojects/System.Linq.Dynamic.Core")),(0,i.kt)("h3",{id:"911101-\u52a8\u6001-sql"},"9.11.10.1 \u52a8\u6001 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Sql")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u793a\u4f8b\u4e00\nvar query = repository.AsQueryable()\n .Where("City == @0 and Orders.Count >= @1", "China", 10)\n .OrderBy("CompanyName")\n .Select("new(CompanyName as Name, Phone)");\n\n// \u793a\u4f8b\u4e8c\nvar list = repository.AsQueryable()\n .Where("Name.Contains(@0)","Furion")\n .ToList();\n\n// \u793a\u4f8b\u4e09\uff0c\u652f\u6301 ? \u8bed\u6cd5\nvar customers = repository.AsQueryable()\n .Include(c => c.Location)\n .Where(c => c.Location?.Name == "test") // \u6ce8\u610f Location?.Name\n .ToList();\n')),(0,i.kt)("h3",{id:"911102-\u52a8\u6001-lambda"},"9.11.10.2 \u52a8\u6001 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Lambda")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u793a\u4f8b\u4e00\nvar x = Expression.Parameter(typeof(int), "x");\nvar y = Expression.Parameter(typeof(int), "y");\nvar e = DynamicExpressionParser\n .ParseLambda(new ParameterExpression[] { x, y }, null, "(x + y) * 2");\n\n// \u793a\u4f8b\u4e8c\nvar e = DynamicExpressionParser.ParseLambda(\n typeof(Customer), typeof(bool),\n "City = @0 and Orders.Count >= @1",\n "London", 10);\n')),(0,i.kt)("h2",{id:"91111-\u65f6\u6001\u67e5\u8be2"},"9.11.11 \u65f6\u6001\u67e5\u8be2"),(0,i.kt)("admonition",{title:"\u529f\u80fd\u79fb\u9664\u58f0\u660e",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 2.13 +")," \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u8fd8\u63d0\u4f9b\u4e86\u65f6\u6001\u67e5\u8be2\u529f\u80fd\uff0c\u53ef\u4ee5\u67e5\u8be2\u7279\u5b9a\u65f6\u95f4\u7684\u6570\u636e\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = rep.Entities\n .AsTemporalOf(DateTime.UtcNow.AddDays(-1))\n .Include(i=> i.Company)\n .FirstOrDefault(i => i.Name == "Furion");\n')),(0,i.kt)("p",null,"\u53e6\u5916\u63d0\u4f9b\u4e86\u591a\u4e2a\u65f6\u6001\u67e5\u8be2\u65b9\u6cd5"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"AsTemporalAll()"),(0,i.kt)("li",{parentName:"ul"},"AsTemporalAsOf(date)"),(0,i.kt)("li",{parentName:"ul"},"AsTemporalFrom(startDate, endDate)"),(0,i.kt)("li",{parentName:"ul"},"AsTemporalBetween(startDate, endDate)"),(0,i.kt)("li",{parentName:"ul"},"AsTemporalContained(startDate, endDate)")),(0,i.kt)("h2",{id:"91112-\u6027\u80fd\u4f18\u5316"},"9.11.12 \u6027\u80fd\u4f18\u5316"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"EF Core")," \u4f1a\u8ddf\u8e2a\u6240\u6709\u5b9e\u4f53\uff0c\u4e5f\u5c31\u662f\u4efb\u4f55\u6570\u636e\u6539\u53d8\u90fd\u4f1a\u5f15\u8d77\u6570\u636e\u68c0\u67e5\uff0c\u6240\u4ee5\u5982\u679c\u53ea\u505a\u67e5\u8be2\u64cd\u4f5c\uff0c\u5efa\u8bae\u5173\u95ed\u5b9e\u4f53\u8ddf\u8e2a\u529f\u80fd\u3002"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u4ee5\u4e0b\u9ad8\u6027\u80fd\u5b9e\u4f53\u96c6\u5408\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"DetachedEntities"),"\uff1a\u8131\u8f68/\u4e0d\u8ffd\u8e2a\u5b9e\u4f53"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"AsQueryable(false)"),"\uff1a\u4e0d\u8ffd\u8e2a\u5b9e\u4f53"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Entities.AsNoTracking()"),"\uff1a\u624b\u52a8\u5173\u95ed\u5b9e\u4f53\u8ffd\u8e2a")),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"EF Core")," \u4e2d\uff0c\u590d\u6742\u67e5\u8be2\u603b\u662f\u4f1a\u751f\u6210\u4e00\u4e2a ",(0,i.kt)("inlineCode",{parentName:"p"},"sql"),"\uff0c\u4e5f\u5c31\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"AsSingleQuery()"),"\uff0c\u6211\u4eec\u4e5f\u53ef\u4ee5\u8bbe\u7f6e\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"AsSplitQuery()")," \u5207\u5272\u6210\u591a\u4e2a\u67e5\u8be2\u3002"),(0,i.kt)("h2",{id:"91113-\u5206\u8868\u67e5\u8be2\u5c0f\u4f8b\u5b50"},"9.11.13 \u5206\u8868\u67e5\u8be2\u5c0f\u4f8b\u5b50"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Furion.Core\n{\n public class Person : Entity, IEntityTypeBuilder\n {\n public string Name { get; set; }\n\n /// \n /// \u914d\u7f6e\u5b9e\u4f53\u5173\u7cfb\n /// \n /// \n /// \n /// \n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.ToSqlQuery(\n @"select * from dbo.person.2020-09-19\n union all\n select * from dbo.person.2020-09-20");\n }\n }\n}\n')),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var posts = repository.Where(u => u.Id > 10).ToList();\n")),(0,i.kt)("h2",{id:"91114-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.11.14 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}b.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/73d3b1ea.3825ed12.js b/handbook/build/assets/js/73d3b1ea.3825ed12.js new file mode 100644 index 0000000000..7cb9d191f1 --- /dev/null +++ b/handbook/build/assets/js/73d3b1ea.3825ed12.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[6709],{3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return m}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},s=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=o,f=d["".concat(u,".").concat(m)]||d[m]||c[m]||i;return n?r.createElement(f,a(a({ref:t},s),{},{components:n})):r.createElement(f,a({ref:t},s))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var p=2;p.NET 6 Preview 6 SDK",id:"\u5b89\u88c5-net-6-preview-6-sdk",level:2},{value:"\u65e7\u9879\u76ee\u5347\u7ea7",id:"\u65e7\u9879\u76ee\u5347\u7ea7",level:2},{value:"\u65b0\u9879\u76ee\u4f7f\u7528",id:"\u65b0\u9879\u76ee\u4f7f\u7528",level:2},{value:"\u5347\u7ea7 Visual Studio 2019",id:"\u5347\u7ea7-visual-studio-2019",level:3},{value:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:3},{value:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",level:3}],d={toc:c};function m(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"2021 \u5e74 08 \u6708 11 \u65e5\uff0c\u5fae\u8f6f\u53d1\u5e03\u4e86 ",(0,i.kt)("inlineCode",{parentName:"strong"},".NET 6 Preview 7")," \u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5728\u5f53\u5929\u7b2c\u4e00\u65f6\u95f4\u9002\u914d\u4e86\u8be5\u7248\u672c\uff0c\u5e76\u53d1\u5e03 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v3.0.0-rc.2")," \u7248\u672c\u3002")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/tree/3.0.0-rc.2/"},"Furion .NET 6 Preview 7 \u6e90\u7801\u5730\u5740")),(0,i.kt)("h2",{id:"\u5b89\u88c5-net-6-preview-6-sdk"},"\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h2"},".NET 6 Preview 6 SDK")),(0,i.kt)("p",null,"\u5c1d\u9c9c\u4e4b\u524d\uff0c\u9996\u5148\u5148\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 7 SDK"),"\uff0c\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/download/dotnet/6.0"},"https://dotnet.microsoft.com/download/dotnet/6.0")),(0,i.kt)("p",null,"\u4e0b\u8f7d\u5bf9\u5e94\u7cfb\u7edf\u548c\u5904\u7406\u5668\u7248\u672c\u5373\u53ef\u3002"),(0,i.kt)("h2",{id:"\u65e7\u9879\u76ee\u5347\u7ea7"},"\u65e7\u9879\u76ee\u5347\u7ea7"),(0,i.kt)("p",null,"\u7f16\u8f91\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},".csproj")," \u9879\u76ee\uff0c\u4fee\u6539 ",(0,i.kt)("inlineCode",{parentName:"p"},"net5.0")," \u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"net6.0"),"\u3002"),(0,i.kt)("p",null,"\u540c\u65f6\u5347\u7ea7\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"Microsoft")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\u4e3a\u6700\u65b0\u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6700\u65b0\u7248\u672c\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"v3.0.0-rc.1"),"\u3002"),(0,i.kt)("h2",{id:"\u65b0\u9879\u76ee\u4f7f\u7528"},"\u65b0\u9879\u76ee\u4f7f\u7528"),(0,i.kt)("h3",{id:"\u5347\u7ea7-visual-studio-2019"},"\u5347\u7ea7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Visual Studio 2019")),(0,i.kt)("p",null,"\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 7")," \u652f\u6301\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview 16.11.0 Preview 4.0")," \u7248\u672c\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u662f ",(0,i.kt)("inlineCode",{parentName:"strong"},"Preview")," \u6700\u65b0\u7248\u672c"),"\u3002\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16"},"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16")),(0,i.kt)("p",null,"\u5df2\u7ecf\u5b89\u88c5\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview")," \u7248\u672c\u7684\u670b\u53cb\u76f4\u63a5\u5347\u7ea7\u5230\u6700\u65b0\u7248\u5373\u53ef\u3002"),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio Code")," \u5f00\u53d1\uff0c\u53ef\u5ffd\u7565\u6b64\u9009\u9879\u3002")),(0,i.kt)("h3",{id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion v3.0.0-rc.2")," \u76ee\u524d\u63d0\u4f9b\u4e86\u6240\u6709\u7c7b\u578b\u7684\u811a\u624b\u67b6\uff0c\u7248\u672c\u53f7\u7edf\u4e00 ",(0,i.kt)("inlineCode",{parentName:"p"},"3.0.0-rc.2"),"\u3002"),(0,i.kt)("p",null,"\u5b89\u88c5\u811a\u624b\u67b6\uff0c\u6253\u5f00 ",(0,i.kt)("inlineCode",{parentName:"p"},"CMD/Powershell")," \u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new --install Furion.Template.Api::3.0.0-rc.2\n")),(0,i.kt)("p",null,"\u521b\u5efa\u9879\u76ee"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new furionapi -n FurionNET6\n")),(0,i.kt)("h3",{id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"},"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"),(0,i.kt)("p",null,"\u6253\u5f00\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u5373\u53ef\u3002"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/73d3b1ea.db30f856.js b/handbook/build/assets/js/73d3b1ea.db30f856.js deleted file mode 100644 index b372f553b0..0000000000 --- a/handbook/build/assets/js/73d3b1ea.db30f856.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[6709],{6680:function(e,t,n){n.r(t),n.d(t,{assets:function(){return s},contentTitle:function(){return u},default:function(){return m},frontMatter:function(){return l},metadata:function(){return p},toc:function(){return c}});var r=n(3117),o=n(102),i=(n(7294),n(3905)),a=(n(1402),["components"]),l={slug:"net6-preview7",title:"6. .NET 6 Preview 7 \u5c1d\u9c9c",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5",".net6"]},u=void 0,p={permalink:"/furion/blog/net6-preview7",editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/blog/2021-08-11-net6-preview7.mdx",source:"@site/blog/2021-08-11-net6-preview7.mdx",title:"6. .NET 6 Preview 7 \u5c1d\u9c9c",description:"",date:"2021-08-11T00:00:00.000Z",formattedDate:"August 11, 2021",tags:[{label:"furion",permalink:"/furion/blog/tags/furion"},{label:"furos",permalink:"/furion/blog/tags/furos"},{label:".net",permalink:"/furion/blog/tags/net"},{label:".netcore",permalink:"/furion/blog/tags/netcore"},{label:".net5",permalink:"/furion/blog/tags/net-5"},{label:".net6",permalink:"/furion/blog/tags/net-6"}],readingTime:1.485,hasTruncateMarker:!1,authors:[{name:"dotNET China",title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",url:"https://www.chinadot.net",imageURL:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png"}],frontMatter:{slug:"net6-preview7",title:"6. .NET 6 Preview 7 \u5c1d\u9c9c",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5",".net6"]},prevItem:{title:"7. GlobalUsings \u7684\u4f7f\u7528",permalink:"/furion/blog/global-usings"},nextItem:{title:"5. \u5728\u63a7\u5236\u53f0\u4e2d\u4f7f\u7528",permalink:"/furion/blog/console"}},s={authorsImageUrls:[void 0]},c=[{value:"\u5b89\u88c5 .NET 6 Preview 6 SDK",id:"\u5b89\u88c5-net-6-preview-6-sdk",level:2},{value:"\u65e7\u9879\u76ee\u5347\u7ea7",id:"\u65e7\u9879\u76ee\u5347\u7ea7",level:2},{value:"\u65b0\u9879\u76ee\u4f7f\u7528",id:"\u65b0\u9879\u76ee\u4f7f\u7528",level:2},{value:"\u5347\u7ea7 Visual Studio 2019",id:"\u5347\u7ea7-visual-studio-2019",level:3},{value:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:3},{value:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",level:3}],d={toc:c};function m(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"2021 \u5e74 08 \u6708 11 \u65e5\uff0c\u5fae\u8f6f\u53d1\u5e03\u4e86 ",(0,i.kt)("inlineCode",{parentName:"strong"},".NET 6 Preview 7")," \u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5728\u5f53\u5929\u7b2c\u4e00\u65f6\u95f4\u9002\u914d\u4e86\u8be5\u7248\u672c\uff0c\u5e76\u53d1\u5e03 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v3.0.0-rc.2")," \u7248\u672c\u3002")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/tree/3.0.0-rc.2/"},"Furion .NET 6 Preview 7 \u6e90\u7801\u5730\u5740")),(0,i.kt)("h2",{id:"\u5b89\u88c5-net-6-preview-6-sdk"},"\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h2"},".NET 6 Preview 6 SDK")),(0,i.kt)("p",null,"\u5c1d\u9c9c\u4e4b\u524d\uff0c\u9996\u5148\u5148\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 7 SDK"),"\uff0c\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/download/dotnet/6.0"},"https://dotnet.microsoft.com/download/dotnet/6.0")),(0,i.kt)("p",null,"\u4e0b\u8f7d\u5bf9\u5e94\u7cfb\u7edf\u548c\u5904\u7406\u5668\u7248\u672c\u5373\u53ef\u3002"),(0,i.kt)("h2",{id:"\u65e7\u9879\u76ee\u5347\u7ea7"},"\u65e7\u9879\u76ee\u5347\u7ea7"),(0,i.kt)("p",null,"\u7f16\u8f91\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},".csproj")," \u9879\u76ee\uff0c\u4fee\u6539 ",(0,i.kt)("inlineCode",{parentName:"p"},"net5.0")," \u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"net6.0"),"\u3002"),(0,i.kt)("p",null,"\u540c\u65f6\u5347\u7ea7\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"Microsoft")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\u4e3a\u6700\u65b0\u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6700\u65b0\u7248\u672c\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"v3.0.0-rc.1"),"\u3002"),(0,i.kt)("h2",{id:"\u65b0\u9879\u76ee\u4f7f\u7528"},"\u65b0\u9879\u76ee\u4f7f\u7528"),(0,i.kt)("h3",{id:"\u5347\u7ea7-visual-studio-2019"},"\u5347\u7ea7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Visual Studio 2019")),(0,i.kt)("p",null,"\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 7")," \u652f\u6301\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview 16.11.0 Preview 4.0")," \u7248\u672c\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u662f ",(0,i.kt)("inlineCode",{parentName:"strong"},"Preview")," \u6700\u65b0\u7248\u672c"),"\u3002\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16"},"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16")),(0,i.kt)("p",null,"\u5df2\u7ecf\u5b89\u88c5\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview")," \u7248\u672c\u7684\u670b\u53cb\u76f4\u63a5\u5347\u7ea7\u5230\u6700\u65b0\u7248\u5373\u53ef\u3002"),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio Code")," \u5f00\u53d1\uff0c\u53ef\u5ffd\u7565\u6b64\u9009\u9879\u3002")),(0,i.kt)("h3",{id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion v3.0.0-rc.2")," \u76ee\u524d\u63d0\u4f9b\u4e86\u6240\u6709\u7c7b\u578b\u7684\u811a\u624b\u67b6\uff0c\u7248\u672c\u53f7\u7edf\u4e00 ",(0,i.kt)("inlineCode",{parentName:"p"},"3.0.0-rc.2"),"\u3002"),(0,i.kt)("p",null,"\u5b89\u88c5\u811a\u624b\u67b6\uff0c\u6253\u5f00 ",(0,i.kt)("inlineCode",{parentName:"p"},"CMD/Powershell")," \u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new --install Furion.Template.Api::3.0.0-rc.2\n")),(0,i.kt)("p",null,"\u521b\u5efa\u9879\u76ee"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new furionapi -n FurionNET6\n")),(0,i.kt)("h3",{id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"},"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"),(0,i.kt)("p",null,"\u6253\u5f00\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u5373\u53ef\u3002"))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return m}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},s=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=o,f=d["".concat(u,".").concat(m)]||d[m]||c[m]||i;return n?r.createElement(f,a(a({ref:t},s),{},{components:n})):r.createElement(f,a({ref:t},s))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var p=2;p.NET 6 Preview 5 SDK",id:"\u5b89\u88c5-net-6-preview-5-sdk",level:3},{value:"\u5347\u7ea7 Visual Studio 2019",id:"\u5347\u7ea7-visual-studio-2019",level:3},{value:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:3},{value:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",level:3}],d={toc:c};function m(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"2021 \u5e74 06 \u6708 18 \u65e5\uff0c\u5fae\u8f6f\u53d1\u5e03\u4e86 ",(0,i.kt)("inlineCode",{parentName:"strong"},".NET 6 Preview 5")," \u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5728\u5f53\u5929\u7b2c\u4e00\u65f6\u95f4\u9002\u914d\u4e86\u8be5\u7248\u672c\uff0c\u5e76\u53d1\u5e03 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v3.0.0-preview.5.21301.9")," \u7248\u672c\u3002")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/tree/net6.0-preview5/"},"Furion .NET 6 Preview 5 \u6e90\u7801\u5730\u5740")),(0,i.kt)("h2",{id:"\u7b49\u4e0d\u53ca\u5c1d\u9c9c\u4e86"},"\u7b49\u4e0d\u53ca\u5c1d\u9c9c\u4e86"),(0,i.kt)("h3",{id:"\u5b89\u88c5-net-6-preview-5-sdk"},"\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h3"},".NET 6 Preview 5 SDK")),(0,i.kt)("p",null,"\u5c1d\u9c9c\u4e4b\u524d\uff0c\u9996\u5148\u5148\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 5 SDK"),"\uff0c\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/download/dotnet/6.0"},"https://dotnet.microsoft.com/download/dotnet/6.0")),(0,i.kt)("p",null,"\u4e0b\u8f7d\u5bf9\u5e94\u7cfb\u7edf\u548c\u5904\u7406\u5668\u7248\u672c\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"\u5347\u7ea7-visual-studio-2019"},"\u5347\u7ea7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Visual Studio 2019")),(0,i.kt)("p",null,"\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 5")," \u652f\u6301\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview 16.11.0 Preview 2.0")," \u7248\u672c\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u662f ",(0,i.kt)("inlineCode",{parentName:"strong"},"Preview")," \u6700\u65b0\u7248\u672c"),"\u3002\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16"},"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16")),(0,i.kt)("p",null,"\u5df2\u7ecf\u5b89\u88c5\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview")," \u7248\u672c\u7684\u670b\u53cb\u76f4\u63a5\u5347\u7ea7\u5230\u6700\u65b0\u7248\u5373\u53ef\u3002"),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio Code")," \u5f00\u53d1\uff0c\u53ef\u5ffd\u7565\u6b64\u9009\u9879\u3002")),(0,i.kt)("h3",{id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion v3.0.0-preview.5.21301.9")," \u76ee\u524d\u63d0\u4f9b\u4e86\u6240\u6709\u7c7b\u578b\u7684\u811a\u624b\u67b6\uff0c\u7248\u672c\u53f7\u7edf\u4e00 ",(0,i.kt)("inlineCode",{parentName:"p"},"3.0.0-preview.5.21301.9"),"\u3002"),(0,i.kt)("p",null,"\u5b89\u88c5\u811a\u624b\u67b6\uff0c\u6253\u5f00 ",(0,i.kt)("inlineCode",{parentName:"p"},"CMD/Powershell")," \u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9\n")),(0,i.kt)("p",null,"\u521b\u5efa\u9879\u76ee"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new furionapi -n FurionNET6\n")),(0,i.kt)("h3",{id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"},"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"),(0,i.kt)("p",null,"\u6253\u5f00\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u5373\u53ef\u3002"))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return m}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},s=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=o,f=d["".concat(u,".").concat(m)]||d[m]||c[m]||i;return n?r.createElement(f,a(a({ref:t},s),{},{components:n})):r.createElement(f,a({ref:t},s))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var p=2;p=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},s=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=o,f=d["".concat(u,".").concat(m)]||d[m]||c[m]||i;return n?r.createElement(f,a(a({ref:t},s),{},{components:n})):r.createElement(f,a({ref:t},s))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var p=2;p.NET 6 Preview 5 SDK",id:"\u5b89\u88c5-net-6-preview-5-sdk",level:3},{value:"\u5347\u7ea7 Visual Studio 2019",id:"\u5347\u7ea7-visual-studio-2019",level:3},{value:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:3},{value:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",level:3}],d={toc:c};function m(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"2021 \u5e74 06 \u6708 18 \u65e5\uff0c\u5fae\u8f6f\u53d1\u5e03\u4e86 ",(0,i.kt)("inlineCode",{parentName:"strong"},".NET 6 Preview 5")," \u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5728\u5f53\u5929\u7b2c\u4e00\u65f6\u95f4\u9002\u914d\u4e86\u8be5\u7248\u672c\uff0c\u5e76\u53d1\u5e03 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v3.0.0-preview.5.21301.9")," \u7248\u672c\u3002")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/tree/net6.0-preview5/"},"Furion .NET 6 Preview 5 \u6e90\u7801\u5730\u5740")),(0,i.kt)("h2",{id:"\u7b49\u4e0d\u53ca\u5c1d\u9c9c\u4e86"},"\u7b49\u4e0d\u53ca\u5c1d\u9c9c\u4e86"),(0,i.kt)("h3",{id:"\u5b89\u88c5-net-6-preview-5-sdk"},"\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h3"},".NET 6 Preview 5 SDK")),(0,i.kt)("p",null,"\u5c1d\u9c9c\u4e4b\u524d\uff0c\u9996\u5148\u5148\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 5 SDK"),"\uff0c\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/download/dotnet/6.0"},"https://dotnet.microsoft.com/download/dotnet/6.0")),(0,i.kt)("p",null,"\u4e0b\u8f7d\u5bf9\u5e94\u7cfb\u7edf\u548c\u5904\u7406\u5668\u7248\u672c\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"\u5347\u7ea7-visual-studio-2019"},"\u5347\u7ea7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Visual Studio 2019")),(0,i.kt)("p",null,"\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 5")," \u652f\u6301\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview 16.11.0 Preview 2.0")," \u7248\u672c\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u662f ",(0,i.kt)("inlineCode",{parentName:"strong"},"Preview")," \u6700\u65b0\u7248\u672c"),"\u3002\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16"},"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16")),(0,i.kt)("p",null,"\u5df2\u7ecf\u5b89\u88c5\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview")," \u7248\u672c\u7684\u670b\u53cb\u76f4\u63a5\u5347\u7ea7\u5230\u6700\u65b0\u7248\u5373\u53ef\u3002"),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio Code")," \u5f00\u53d1\uff0c\u53ef\u5ffd\u7565\u6b64\u9009\u9879\u3002")),(0,i.kt)("h3",{id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion v3.0.0-preview.5.21301.9")," \u76ee\u524d\u63d0\u4f9b\u4e86\u6240\u6709\u7c7b\u578b\u7684\u811a\u624b\u67b6\uff0c\u7248\u672c\u53f7\u7edf\u4e00 ",(0,i.kt)("inlineCode",{parentName:"p"},"3.0.0-preview.5.21301.9"),"\u3002"),(0,i.kt)("p",null,"\u5b89\u88c5\u811a\u624b\u67b6\uff0c\u6253\u5f00 ",(0,i.kt)("inlineCode",{parentName:"p"},"CMD/Powershell")," \u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9\n")),(0,i.kt)("p",null,"\u521b\u5efa\u9879\u76ee"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new furionapi -n FurionNET6\n")),(0,i.kt)("h3",{id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"},"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"),(0,i.kt)("p",null,"\u6253\u5f00\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u5373\u53ef\u3002"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/76437093.b81a4f82.js b/handbook/build/assets/js/76437093.b81a4f82.js new file mode 100644 index 0000000000..603a8f03a7 --- /dev/null +++ b/handbook/build/assets/js/76437093.b81a4f82.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4667],{3905:function(e,r,t){t.d(r,{Zo:function(){return c},kt:function(){return m}});var n=t(7294);function i(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function o(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function a(e){for(var r=1;r=0||(i[t]=e[t]);return i}(e,r);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var s=n.createContext({}),u=function(e){var r=n.useContext(s),t=r;return e&&(t="function"==typeof e?e(r):a(a({},r),e)),t},c=function(e){var r=u(e.components);return n.createElement(s.Provider,{value:r},e.children)},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},d=n.forwardRef((function(e,r){var t=e.components,i=e.mdxType,o=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),d=u(t),m=i,f=d["".concat(s,".").concat(m)]||d[m]||p[m]||o;return t?n.createElement(f,a(a({ref:r},c),{},{components:t})):n.createElement(f,a({ref:r},c))}));function m(e,r){var t=arguments,i=r&&r.mdxType;if("string"==typeof e||i){var o=t.length,a=new Array(o);a[0]=d;var l={};for(var s in r)hasOwnProperty.call(r,s)&&(l[s]=r[s]);l.originalType=e,l.mdxType="string"==typeof e?e:i,a[1]=l;for(var u=2;u(str, [options]);\n")),(0,o.kt)("h2",{id:"73-\u83b7\u53d6\u9ed8\u8ba4\u5e8f\u5217\u5316\u914d\u7f6e"},"7.3 \u83b7\u53d6\u9ed8\u8ba4\u5e8f\u5217\u5316\u914d\u7f6e"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var options = JsonSerializerUtility.GetDefaultJsonSerializerOptions();\n")),(0,o.kt)("h2",{id:"74-\u8bbe\u7f6e\u5e8f\u5217\u5316\u5c5e\u6027\u9996\u5b57\u6bcd\u5927\u5199"},"7.4 \u8bbe\u7f6e\u5e8f\u5217\u5316\u5c5e\u6027\u9996\u5b57\u6bcd\u5927\u5199"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},"services.AddControllersWithViews()\n .AddJsonSerializerPascalPropertyNaming();\n")),(0,o.kt)("h2",{id:"75-\u8bbe\u7f6e\u65f6\u95f4\u8f93\u51fa\u7edf\u4e00\u683c\u5f0f\u5316"},"7.5 \u8bbe\u7f6e\u65f6\u95f4\u8f93\u51fa\u7edf\u4e00\u683c\u5f0f\u5316"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},'services.AddControllersWithViews()\n .AddDateTimeJsonConverter("yyyy-MM-dd HH:mm:ss");\n')))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/76437093.ce2a8922.js b/handbook/build/assets/js/76437093.ce2a8922.js deleted file mode 100644 index 9b80a4c8b0..0000000000 --- a/handbook/build/assets/js/76437093.ce2a8922.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4667],{3550:function(e,r,t){t.r(r),t.d(r,{assets:function(){return c},contentTitle:function(){return s},default:function(){return m},frontMatter:function(){return l},metadata:function(){return u},toc:function(){return p}});var n=t(3117),i=t(102),o=(t(7294),t(3905)),a=["components"],l={id:"jsonserializer",title:"7. JsonSerializerUtility \u9759\u6001\u7c7b",sidebar_label:"7. JsonSerializerUtility \u9759\u6001\u7c7b"},s=void 0,u={unversionedId:"global/jsonserializer",id:"global/jsonserializer",title:"7. JsonSerializerUtility \u9759\u6001\u7c7b",description:"\u4ee5\u4e0b\u5185\u5bb9\u5728 Furion 1.16.0 + \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002\u8bf7\u4f7f\u7528 \u301023. JSON \u5e8f\u5217\u5316\u7ae0\u8282\u3011",source:"@site/docs/global/jsonserializer.mdx",sourceDirName:"global",slug:"/global/jsonserializer",permalink:"/furion/docs/global/jsonserializer",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/global/jsonserializer.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"jsonserializer",title:"7. JsonSerializerUtility \u9759\u6001\u7c7b",sidebar_label:"7. JsonSerializerUtility \u9759\u6001\u7c7b"},sidebar:"global",previous:{title:"6. Http \u9759\u6001\u7c7b",permalink:"/furion/docs/global/shttp"},next:{title:"8. L \u9759\u6001\u7c7b",permalink:"/furion/docs/global/l"}},c={},p=[{value:"7.1 \u5e8f\u5217\u5316",id:"71-\u5e8f\u5217\u5316",level:2},{value:"7.2 \u53cd\u5e8f\u5217\u5316",id:"72-\u53cd\u5e8f\u5217\u5316",level:2},{value:"7.3 \u83b7\u53d6\u9ed8\u8ba4\u5e8f\u5217\u5316\u914d\u7f6e",id:"73-\u83b7\u53d6\u9ed8\u8ba4\u5e8f\u5217\u5316\u914d\u7f6e",level:2},{value:"7.4 \u8bbe\u7f6e\u5e8f\u5217\u5316\u5c5e\u6027\u9996\u5b57\u6bcd\u5927\u5199",id:"74-\u8bbe\u7f6e\u5e8f\u5217\u5316\u5c5e\u6027\u9996\u5b57\u6bcd\u5927\u5199",level:2},{value:"7.5 \u8bbe\u7f6e\u65f6\u95f4\u8f93\u51fa\u7edf\u4e00\u683c\u5f0f\u5316",id:"75-\u8bbe\u7f6e\u65f6\u95f4\u8f93\u51fa\u7edf\u4e00\u683c\u5f0f\u5316",level:2}],d={toc:p};function m(e){var r=e.components,t=(0,i.Z)(e,a);return(0,o.kt)("wrapper",(0,n.Z)({},d,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{title:"\u91cd\u8981\u58f0\u660e",type:"warning"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 1.16.0 +")," \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002\u8bf7\u4f7f\u7528 ",(0,o.kt)("a",{parentName:"p",href:"/docs/json-serialization"},"\u301023. JSON \u5e8f\u5217\u5316\u7ae0\u8282\u3011"))),(0,o.kt)("h2",{id:"71-\u5e8f\u5217\u5316"},"7.1 \u5e8f\u5217\u5316"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var str = JsonSerializerUtility.Serialize(obj, [options]);\n")),(0,o.kt)("h2",{id:"72-\u53cd\u5e8f\u5217\u5316"},"7.2 \u53cd\u5e8f\u5217\u5316"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var obj = JsonSerializerUtility.Deserialize(str, [options]);\n")),(0,o.kt)("h2",{id:"73-\u83b7\u53d6\u9ed8\u8ba4\u5e8f\u5217\u5316\u914d\u7f6e"},"7.3 \u83b7\u53d6\u9ed8\u8ba4\u5e8f\u5217\u5316\u914d\u7f6e"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var options = JsonSerializerUtility.GetDefaultJsonSerializerOptions();\n")),(0,o.kt)("h2",{id:"74-\u8bbe\u7f6e\u5e8f\u5217\u5316\u5c5e\u6027\u9996\u5b57\u6bcd\u5927\u5199"},"7.4 \u8bbe\u7f6e\u5e8f\u5217\u5316\u5c5e\u6027\u9996\u5b57\u6bcd\u5927\u5199"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},"services.AddControllersWithViews()\n .AddJsonSerializerPascalPropertyNaming();\n")),(0,o.kt)("h2",{id:"75-\u8bbe\u7f6e\u65f6\u95f4\u8f93\u51fa\u7edf\u4e00\u683c\u5f0f\u5316"},"7.5 \u8bbe\u7f6e\u65f6\u95f4\u8f93\u51fa\u7edf\u4e00\u683c\u5f0f\u5316"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},'services.AddControllersWithViews()\n .AddDateTimeJsonConverter("yyyy-MM-dd HH:mm:ss");\n')))}m.isMDXComponent=!0},3905:function(e,r,t){t.d(r,{Zo:function(){return c},kt:function(){return m}});var n=t(7294);function i(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function o(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function a(e){for(var r=1;r=0||(i[t]=e[t]);return i}(e,r);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var s=n.createContext({}),u=function(e){var r=n.useContext(s),t=r;return e&&(t="function"==typeof e?e(r):a(a({},r),e)),t},c=function(e){var r=u(e.components);return n.createElement(s.Provider,{value:r},e.children)},p={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},d=n.forwardRef((function(e,r){var t=e.components,i=e.mdxType,o=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),d=u(t),m=i,f=d["".concat(s,".").concat(m)]||d[m]||p[m]||o;return t?n.createElement(f,a(a({ref:r},c),{},{components:t})):n.createElement(f,a({ref:r},c))}));function m(e,r){var t=arguments,i=r&&r.mdxType;if("string"==typeof e||i){var o=t.length,a=new Array(o);a[0]=d;var l={};for(var s in r)hasOwnProperty.call(r,s)&&(l[s]=r[s]);l.originalType=e,l.mdxType="string"==typeof e?e:i,a[1]=l;for(var u=2;uGlobalUsing",id:"261-\u5173\u4e8e-globalusing",level:2},{value:"2.6.2 \u5fc5\u8981\u914d\u7f6e",id:"262-\u5fc5\u8981\u914d\u7f6e",level:2},{value:"2.6.3 \u57fa\u672c\u4f7f\u7528",id:"263-\u57fa\u672c\u4f7f\u7528",level:2},{value:"2.6.3.1 \u9ed8\u8ba4\u5168\u5c40 using",id:"2631-\u9ed8\u8ba4\u5168\u5c40-using",level:3},{value:"2.6.4 .NET5 \u9879\u76ee\u5f00\u542f\u652f\u6301",id:"264-net5-\u9879\u76ee\u5f00\u542f\u652f\u6301",level:2},{value:"2.6.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"265-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:d};function c(e){var n=e.components,t=(0,i.Z)(e,l);return(0,a.kt)("wrapper",(0,o.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"261-\u5173\u4e8e-globalusing"},"2.6.1 \u5173\u4e8e ",(0,a.kt)("inlineCode",{parentName:"h2"},"GlobalUsing")),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET6/C#10")," \u4e4b\u540e\uff0c\u5fae\u8f6f\u65b0\u589e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings")," \u673a\u5236\uff0c\u53ef\u4ee5\u5728\u9879\u76ee\u7684\u6839\u76ee\u5f55\u4e0b\u521b\u5efa\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u6587\u4ef6\uff0c\u628a\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u653e\u7f6e\u5176\u4e2d\u3002"),(0,a.kt)("p",null,"\u8fd9\u6837 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u6240\u5728\u7684\u9879\u76ee ",(0,a.kt)("inlineCode",{parentName:"p"},".cs")," \u6587\u4ef6\u5c31\u65e0\u9700\u91cd\u590d ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u4e86\uff0c\u5927\u5927\u7684\u63d0\u9ad8\u5f00\u53d1\u6548\u7387\uff0c\u4e5f\u8ba9\u4ee3\u7801\u53d8\u7684\u66f4\u52a0\u7b80\u6d01\u3002"),(0,a.kt)("h2",{id:"262-\u5fc5\u8981\u914d\u7f6e"},"2.6.2 \u5fc5\u8981\u914d\u7f6e"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u542f\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"GlobalUsings")," \u673a\u5236\u9700\u8981\u4ee5\u4e0b\u4e24\u4e2a\u6b65\u9aa4\uff1a")),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"\u5728\u4f60\u9700\u8981\u5168\u5c40 ",(0,a.kt)("inlineCode",{parentName:"li"},"using")," \u7684\u9879\u76ee\u5c42\u6839\u76ee\u5f55\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"li"},"GlobalUsings.cs")," \u6587\u4ef6\uff0c\u5982\u679c\u591a\u4e2a\u9879\u76ee\u5c42\u9700\u8981\uff0c\u5219\u6bcf\u4e2a\u5c42\u90fd\u5e94\u8be5\u6709\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"li"},"GlobalUsings.cs")),(0,a.kt)("li",{parentName:"ol"},"\u7f16\u8f91\u9879\u76ee\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},".csproj")," \u6587\u4ef6\uff0c\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"li"},"enable"),"\uff0c\u6ce8\u610f\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"")," \u4e2d\u6dfb\u52a0\uff0c\u901a\u5e38\u548c ",(0,a.kt)("inlineCode",{parentName:"li"},"")," \u540c\u7236\u540c\u7ea7")),(0,a.kt)("h2",{id:"263-\u57fa\u672c\u4f7f\u7528"},"2.6.3 \u57fa\u672c\u4f7f\u7528"),(0,a.kt)("p",null,"\u914d\u7f6e\u4e4b\u540e\uff0c\u73b0\u5728\u5c31\u53ef\u4ee5\u628a\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u653e\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u4e2d\u4e86\uff0c\u5199\u6cd5\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="Furion \u63a8\u8350\u7684\u5168\u5c40\u547d\u540d\u7a7a\u95f4"',showLineNumbers:!0,title:'"Furion','\u63a8\u8350\u7684\u5168\u5c40\u547d\u540d\u7a7a\u95f4"':!0},"global using Furion;\nglobal using Furion.DatabaseAccessor;\nglobal using Furion.DataEncryption;\nglobal using Furion.DataValidation;\nglobal using Furion.DependencyInjection;\nglobal using Furion.DynamicApiController;\nglobal using Furion.Extensions;\nglobal using Furion.FriendlyException;\nglobal using Furion.Logging;\nglobal using Mapster;\nglobal using Microsoft.AspNetCore.Authorization;\nglobal using Microsoft.AspNetCore.Http;\nglobal using Microsoft.AspNetCore.Mvc;\nglobal using Microsoft.CodeAnalysis;\nglobal using Microsoft.EntityFrameworkCore;\nglobal using System.ComponentModel.DataAnnotations;\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u5fc5\u987b\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"strong"},"global")," \u5f00\u5934\uff01")),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u4e00\u822c\u63a8\u8350\u628a\u5b9e\u4f53\u7c7b\u7684\u547d\u540d\u7a7a\u95f4\u4e5f\u653e\u8fdb\u53bb\uff0c\u56e0\u4e3a\u4ed3\u50a8 ",(0,a.kt)("inlineCode",{parentName:"p"},"IRepository")," \u4f7f\u7528\u7684\u9891\u7387\u975e\u5e38\u9ad8\u3002"),(0,a.kt)("p",{parentName:"admonition"},"\u53e6\u5916\u63a8\u8350\u5927\u5bb6\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u4e2d\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"CodeMaid")," \u63d2\u4ef6\uff08\u6ce8\u610f ",(0,a.kt)("inlineCode",{parentName:"p"},"2019")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"2022")," \u7248\u672c\uff09\u54e6\uff0c\u81ea\u52a8\u6e05\u7406\u89e3\u51b3\u65b9\u6848\u6240\u6709\u65e0\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using"),"\uff0c\u7ed3\u5408 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u975e\u5e38\u68d2\uff01")),(0,a.kt)("admonition",{title:"\u4e2a\u522b\u60c5\u51b5",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u53ef\u80fd\u7531\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u7248\u672c\u7684\u95ee\u9898\uff0c\u5bfc\u81f4 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u5b9a\u4e49\u51fa\u9519\uff0c\u8fd9\u65f6\u5019\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u540e\u9762\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"global::"),"\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"global using global::Furion;\n"))),(0,a.kt)("p",null,"\u63a5\u4e0b\u6765\u5728\u4ee3\u7801\u4e2d\u4f7f\u7528\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},"// \u65e0\u9700 using Furion \u7684\u547d\u540d\u7a7a\u95f4\u4e86\u54e6\uff0c\u6e05\u723d\u4e86\u4e0d\u5c11\n\nnamespace Your.Application;\n\npublic class DefaultAppService : IDynamicApiController\n{\n private readonly IRepository _boardCardRepository;\n private readonly IRepository _boardGroupRepository;\n private readonly IRepository _boardCardAttachmentRepository;\n private readonly IRepository _boardCardUserRepository;\n}\n\n// ....\n")),(0,a.kt)("img",{src:(0,r.Z)("img/cd2223.png")}),(0,a.kt)("h3",{id:"2631-\u9ed8\u8ba4\u5168\u5c40-using"},"2.6.3.1 \u9ed8\u8ba4\u5168\u5c40 ",(0,a.kt)("inlineCode",{parentName:"h3"},"using")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u5b9e\u9645\u4e0a\u5fae\u8f6f\u5df2\u7ecf\u81ea\u52a8\u628a\u4e00\u4e9b\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"using")," \u5728\u7f16\u8bd1\u540e\u7684\u4ee3\u7801\u4e2d\u81ea\u52a8\u8865\u4e0a\u4e86"),"\uff0c\u8def\u5f84\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u9879\u76ee/obj/Debug/net6.0/\u9879\u76ee.GlobalUsings.cs")," \u6587\u4ef6\u4e2d\uff0c\u6587\u4ef6\u5185\u5bb9\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \nglobal using global::System;\nglobal using global::System.Collections.Generic;\nglobal using global::System.IO;\nglobal using global::System.Linq;\nglobal using global::System.Net.Http;\nglobal using global::System.Threading;\nglobal using global::System.Threading.Tasks;\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u4e5f\u5c31\u662f\u4ee5\u4e0a\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"using")," \u65e0\u9700\u5199\u5728\u4f60\u521b\u5efa\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"GlobalUsings.cs")," \u4e2d\u4e86\uff0c\u5fae\u8f6f\u4f1a\u5728\u7f16\u8bd1\u65f6\u81ea\u52a8\u5408\u5e76\u3002")),(0,a.kt)("h2",{id:"264-net5-\u9879\u76ee\u5f00\u542f\u652f\u6301"},"2.6.4 ",(0,a.kt)("inlineCode",{parentName:"h2"},".NET5")," \u9879\u76ee\u5f00\u542f\u652f\u6301"),(0,a.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},".NET5")," \u91c7\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"C# 9.0")," \u7f16\u8bd1\uff0c\u800c ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsing")," \u662f\u4ece ",(0,a.kt)("inlineCode",{parentName:"p"},"C# 10.0")," \u5f00\u59cb\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u7f16\u8f91\u9879\u76ee\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},".csproj")," \u5e76\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"10.0")," \u5373\u53ef\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-xml",metastring:"showLineNumbers {3}",showLineNumbers:!0,"{3}":!0},"\n net5.0\n 10.0\n \x3c!-- \u5176\u4ed6\u914d\u7f6e --\x3e\n\n")),(0,a.kt)("p",null,"\u5982\u9700\u4f7f\u7528\u6700\u65b0\u7248\u53ef\u914d\u7f6e\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"latest"),"\u3002"),(0,a.kt)("h2",{id:"265-\u53cd\u9988\u4e0e\u5efa\u8bae"},"2.6.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return u},kt:function(){return m}});var o=t(7294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function r(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var s=o.createContext({}),p=function(e){var n=o.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):r(r({},n),e)),t},u=function(e){var n=p(e.components);return o.createElement(s.Provider,{value:n},e.children)},g={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},d=o.forwardRef((function(e,n){var t=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=p(t),m=i,c=d["".concat(s,".").concat(m)]||d[m]||g[m]||a;return t?o.createElement(c,r(r({ref:n},u),{},{components:t})):o.createElement(c,r({ref:n},u))}));function m(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var a=t.length,r=new Array(a);r[0]=d;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:i,r[1]=l;for(var p=2;p=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var s=o.createContext({}),p=function(e){var n=o.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):r(r({},n),e)),t},u=function(e){var n=p(e.components);return o.createElement(s.Provider,{value:n},e.children)},g={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},d=o.forwardRef((function(e,n){var t=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=p(t),m=i,c=d["".concat(s,".").concat(m)]||d[m]||g[m]||a;return t?o.createElement(c,r(r({ref:n},u),{},{components:t})):o.createElement(c,r({ref:n},u))}));function m(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var a=t.length,r=new Array(a);r[0]=d;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:i,r[1]=l;for(var p=2;pGlobalUsing",id:"261-\u5173\u4e8e-globalusing",level:2},{value:"2.6.2 \u5fc5\u8981\u914d\u7f6e",id:"262-\u5fc5\u8981\u914d\u7f6e",level:2},{value:"2.6.3 \u57fa\u672c\u4f7f\u7528",id:"263-\u57fa\u672c\u4f7f\u7528",level:2},{value:"2.6.3.1 \u9ed8\u8ba4\u5168\u5c40 using",id:"2631-\u9ed8\u8ba4\u5168\u5c40-using",level:3},{value:"2.6.4 .NET5 \u9879\u76ee\u5f00\u542f\u652f\u6301",id:"264-net5-\u9879\u76ee\u5f00\u542f\u652f\u6301",level:2},{value:"2.6.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"265-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:d};function c(e){var n=e.components,t=(0,i.Z)(e,l);return(0,a.kt)("wrapper",(0,o.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"261-\u5173\u4e8e-globalusing"},"2.6.1 \u5173\u4e8e ",(0,a.kt)("inlineCode",{parentName:"h2"},"GlobalUsing")),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET6/C#10")," \u4e4b\u540e\uff0c\u5fae\u8f6f\u65b0\u589e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings")," \u673a\u5236\uff0c\u53ef\u4ee5\u5728\u9879\u76ee\u7684\u6839\u76ee\u5f55\u4e0b\u521b\u5efa\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u6587\u4ef6\uff0c\u628a\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u653e\u7f6e\u5176\u4e2d\u3002"),(0,a.kt)("p",null,"\u8fd9\u6837 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u6240\u5728\u7684\u9879\u76ee ",(0,a.kt)("inlineCode",{parentName:"p"},".cs")," \u6587\u4ef6\u5c31\u65e0\u9700\u91cd\u590d ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u4e86\uff0c\u5927\u5927\u7684\u63d0\u9ad8\u5f00\u53d1\u6548\u7387\uff0c\u4e5f\u8ba9\u4ee3\u7801\u53d8\u7684\u66f4\u52a0\u7b80\u6d01\u3002"),(0,a.kt)("h2",{id:"262-\u5fc5\u8981\u914d\u7f6e"},"2.6.2 \u5fc5\u8981\u914d\u7f6e"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u542f\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"GlobalUsings")," \u673a\u5236\u9700\u8981\u4ee5\u4e0b\u4e24\u4e2a\u6b65\u9aa4\uff1a")),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"\u5728\u4f60\u9700\u8981\u5168\u5c40 ",(0,a.kt)("inlineCode",{parentName:"li"},"using")," \u7684\u9879\u76ee\u5c42\u6839\u76ee\u5f55\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"li"},"GlobalUsings.cs")," \u6587\u4ef6\uff0c\u5982\u679c\u591a\u4e2a\u9879\u76ee\u5c42\u9700\u8981\uff0c\u5219\u6bcf\u4e2a\u5c42\u90fd\u5e94\u8be5\u6709\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"li"},"GlobalUsings.cs")),(0,a.kt)("li",{parentName:"ol"},"\u7f16\u8f91\u9879\u76ee\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},".csproj")," \u6587\u4ef6\uff0c\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"li"},"enable"),"\uff0c\u6ce8\u610f\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"")," \u4e2d\u6dfb\u52a0\uff0c\u901a\u5e38\u548c ",(0,a.kt)("inlineCode",{parentName:"li"},"")," \u540c\u7236\u540c\u7ea7")),(0,a.kt)("h2",{id:"263-\u57fa\u672c\u4f7f\u7528"},"2.6.3 \u57fa\u672c\u4f7f\u7528"),(0,a.kt)("p",null,"\u914d\u7f6e\u4e4b\u540e\uff0c\u73b0\u5728\u5c31\u53ef\u4ee5\u628a\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u653e\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u4e2d\u4e86\uff0c\u5199\u6cd5\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="Furion \u63a8\u8350\u7684\u5168\u5c40\u547d\u540d\u7a7a\u95f4"',showLineNumbers:!0,title:'"Furion','\u63a8\u8350\u7684\u5168\u5c40\u547d\u540d\u7a7a\u95f4"':!0},"global using Furion;\nglobal using Furion.DatabaseAccessor;\nglobal using Furion.DataEncryption;\nglobal using Furion.DataValidation;\nglobal using Furion.DependencyInjection;\nglobal using Furion.DynamicApiController;\nglobal using Furion.Extensions;\nglobal using Furion.FriendlyException;\nglobal using Furion.Logging;\nglobal using Mapster;\nglobal using Microsoft.AspNetCore.Authorization;\nglobal using Microsoft.AspNetCore.Http;\nglobal using Microsoft.AspNetCore.Mvc;\nglobal using Microsoft.CodeAnalysis;\nglobal using Microsoft.EntityFrameworkCore;\nglobal using System.ComponentModel.DataAnnotations;\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u5fc5\u987b\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"strong"},"global")," \u5f00\u5934\uff01")),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u4e00\u822c\u63a8\u8350\u628a\u5b9e\u4f53\u7c7b\u7684\u547d\u540d\u7a7a\u95f4\u4e5f\u653e\u8fdb\u53bb\uff0c\u56e0\u4e3a\u4ed3\u50a8 ",(0,a.kt)("inlineCode",{parentName:"p"},"IRepository")," \u4f7f\u7528\u7684\u9891\u7387\u975e\u5e38\u9ad8\u3002"),(0,a.kt)("p",{parentName:"admonition"},"\u53e6\u5916\u63a8\u8350\u5927\u5bb6\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u4e2d\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"CodeMaid")," \u63d2\u4ef6\uff08\u6ce8\u610f ",(0,a.kt)("inlineCode",{parentName:"p"},"2019")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"2022")," \u7248\u672c\uff09\u54e6\uff0c\u81ea\u52a8\u6e05\u7406\u89e3\u51b3\u65b9\u6848\u6240\u6709\u65e0\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using"),"\uff0c\u7ed3\u5408 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u975e\u5e38\u68d2\uff01")),(0,a.kt)("admonition",{title:"\u4e2a\u522b\u60c5\u51b5",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u53ef\u80fd\u7531\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u7248\u672c\u7684\u95ee\u9898\uff0c\u5bfc\u81f4 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u5b9a\u4e49\u51fa\u9519\uff0c\u8fd9\u65f6\u5019\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u540e\u9762\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"global::"),"\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"global using global::Furion;\n"))),(0,a.kt)("p",null,"\u63a5\u4e0b\u6765\u5728\u4ee3\u7801\u4e2d\u4f7f\u7528\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},"// \u65e0\u9700 using Furion \u7684\u547d\u540d\u7a7a\u95f4\u4e86\u54e6\uff0c\u6e05\u723d\u4e86\u4e0d\u5c11\n\nnamespace Your.Application;\n\npublic class DefaultAppService : IDynamicApiController\n{\n private readonly IRepository _boardCardRepository;\n private readonly IRepository _boardGroupRepository;\n private readonly IRepository _boardCardAttachmentRepository;\n private readonly IRepository _boardCardUserRepository;\n}\n\n// ....\n")),(0,a.kt)("img",{src:(0,r.Z)("img/cd2223.png")}),(0,a.kt)("h3",{id:"2631-\u9ed8\u8ba4\u5168\u5c40-using"},"2.6.3.1 \u9ed8\u8ba4\u5168\u5c40 ",(0,a.kt)("inlineCode",{parentName:"h3"},"using")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u5b9e\u9645\u4e0a\u5fae\u8f6f\u5df2\u7ecf\u81ea\u52a8\u628a\u4e00\u4e9b\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"using")," \u5728\u7f16\u8bd1\u540e\u7684\u4ee3\u7801\u4e2d\u81ea\u52a8\u8865\u4e0a\u4e86"),"\uff0c\u8def\u5f84\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u9879\u76ee/obj/Debug/net6.0/\u9879\u76ee.GlobalUsings.cs")," \u6587\u4ef6\u4e2d\uff0c\u6587\u4ef6\u5185\u5bb9\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \nglobal using global::System;\nglobal using global::System.Collections.Generic;\nglobal using global::System.IO;\nglobal using global::System.Linq;\nglobal using global::System.Net.Http;\nglobal using global::System.Threading;\nglobal using global::System.Threading.Tasks;\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u4e5f\u5c31\u662f\u4ee5\u4e0a\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"using")," \u65e0\u9700\u5199\u5728\u4f60\u521b\u5efa\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"GlobalUsings.cs")," \u4e2d\u4e86\uff0c\u5fae\u8f6f\u4f1a\u5728\u7f16\u8bd1\u65f6\u81ea\u52a8\u5408\u5e76\u3002")),(0,a.kt)("h2",{id:"264-net5-\u9879\u76ee\u5f00\u542f\u652f\u6301"},"2.6.4 ",(0,a.kt)("inlineCode",{parentName:"h2"},".NET5")," \u9879\u76ee\u5f00\u542f\u652f\u6301"),(0,a.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},".NET5")," \u91c7\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"C# 9.0")," \u7f16\u8bd1\uff0c\u800c ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsing")," \u662f\u4ece ",(0,a.kt)("inlineCode",{parentName:"p"},"C# 10.0")," \u5f00\u59cb\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u7f16\u8f91\u9879\u76ee\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},".csproj")," \u5e76\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"10.0")," \u5373\u53ef\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-xml",metastring:"showLineNumbers {3}",showLineNumbers:!0,"{3}":!0},"\n net5.0\n 10.0\n \x3c!-- \u5176\u4ed6\u914d\u7f6e --\x3e\n\n")),(0,a.kt)("p",null,"\u5982\u9700\u4f7f\u7528\u6700\u65b0\u7248\u53ef\u914d\u7f6e\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"latest"),"\u3002"),(0,a.kt)("h2",{id:"265-\u53cd\u9988\u4e0e\u5efa\u8bae"},"2.6.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/78e5e8dd.0f59ff26.js b/handbook/build/assets/js/78e5e8dd.0f59ff26.js deleted file mode 100644 index e3d7e35841..0000000000 --- a/handbook/build/assets/js/78e5e8dd.0f59ff26.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[5713],{5023:function(e,n,t){t.r(n),t.d(n,{assets:function(){return u},contentTitle:function(){return l},default:function(){return m},frontMatter:function(){return o},metadata:function(){return s},toc:function(){return c}});var i=t(3117),r=t(102),a=(t(7294),t(3905)),p=["components"],o={id:"appstartup",title:"3.1 AppStartup \u542f\u52a8",sidebar_label:"3.1 AppStartup \u542f\u52a8"},l=void 0,s={unversionedId:"appstartup",id:"appstartup",title:"3.1 AppStartup \u542f\u52a8",description:"3.1.1 Startup \u7c7b",source:"@site/docs/appstartup.mdx",sourceDirName:".",slug:"/appstartup",permalink:"/furion/docs/appstartup",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/appstartup.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1657072035,formattedLastUpdatedAt:"Jul 6, 2022",frontMatter:{id:"appstartup",title:"3.1 AppStartup \u542f\u52a8",sidebar_label:"3.1 AppStartup \u542f\u52a8"},sidebar:"docs",previous:{title:"2.9 Nuget \u672c\u5730\u8c03\u8bd5\u5305",permalink:"/furion/docs/nuget-local"},next:{title:"3.2 \u7ec4\u4ef6\u5316\u542f\u52a8 \u2728",permalink:"/furion/docs/component"}},u={},c=[{value:"3.1.1 Startup \u7c7b",id:"311-startup-\u7c7b",level:2},{value:"3.1.1.1 Startup \u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5",id:"3111-startup-\u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5",level:3},{value:"3.1.2 AppStartup",id:"312-appstartup",level:2},{value:"3.1.2.1 \u5982\u4f55\u914d\u7f6e AppStartup",id:"3121-\u5982\u4f55\u914d\u7f6e-appstartup",level:3},{value:"3.1.2.2 AppStartup \u7ea6\u5b9a",id:"3122-appstartup-\u7ea6\u5b9a",level:3},{value:"3.1.2.3 AppStartup \u914d\u7f6e\u987a\u5e8f",id:"3123-appstartup-\u914d\u7f6e\u987a\u5e8f",level:3},{value:"3.1.2.4 AppStartup \u65b9\u6cd5\u8c03\u7528\u987a\u5e8f",id:"3124-appstartup-\u65b9\u6cd5\u8c03\u7528\u987a\u5e8f",level:3},{value:"3.1.3 Startup \u914d\u7f6e\u6700\u4f73\u5b9e\u8df5",id:"313-startup-\u914d\u7f6e\u6700\u4f73\u5b9e\u8df5",level:2},{value:"3.1.4 \u6784\u9020\u51fd\u6570\u6ce8\u5165\u8bf4\u660e",id:"314-\u6784\u9020\u51fd\u6570\u6ce8\u5165\u8bf4\u660e",level:2},{value:"3.1.5 \u5173\u4e8e appsettings.json",id:"315-\u5173\u4e8e-appsettingsjson",level:2},{value:"3.1.6 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"316-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:c};function m(e){var n=e.components,t=(0,r.Z)(e,p);return(0,a.kt)("wrapper",(0,i.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"311-startup-\u7c7b"},"3.1.1 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Startup")," \u7c7b"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Startup")," \u7c7b\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u7a0b\u5e8f\u542f\u52a8\u9ed8\u8ba4\u8c03\u7528\u7684\u7c7b\uff0c\u8be5\u7c7b\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u914d\u7f6e\uff1a"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},".NET5")," \u65b9\u5f0f"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {18} title="Furion.Web.Entry\\Program.cs"',showLineNumbers:!0,"":!0,"{18}":!0,title:'"Furion.Web.Entry\\Program.cs"'},"using Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Furion.Web.Entry\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args)\n {\n return Host.CreateDefaultBuilder(args)\n .ConfigureWebHostDefaults(webBuilder =>\n {\n webBuilder.UseStartup();\n });\n }\n }\n}\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},".NET6 \u65b9\u5f0f")),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET6")," \u4e2d\u5fae\u8f6f\u5df2\u4e0d\u518d\u63a8\u8350 ",(0,a.kt)("inlineCode",{parentName:"p"},"UseStartup()")," \u65b9\u5f0f\u3002"),(0,a.kt)("h3",{id:"3111-startup-\u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5"},"3.1.1.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Startup")," \u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Startup")," \u9ed8\u8ba4\u6709\u4e24\u4e2a\u91cd\u8981\u7684\u65b9\u6cd5:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ConfigureServices"),"\uff1a\u914d\u7f6e\u5e94\u7528\u6240\u9700\u670d\u52a1\uff0c\u5728\u8be5\u65b9\u6cd5\u4e2d\u53ef\u4ee5\u6dfb\u52a0\u5e94\u7528\u6240\u9700\u8981\u7684\u529f\u80fd\u6216\u670d\u52a1"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Configure"),"\uff1a\u914d\u7f6e\u5e94\u7528\u8bf7\u6c42\u5904\u7406\u7ba1\u9053")),(0,a.kt)("p",null,"\u9ed8\u8ba4\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {9,13} title="Furion.Web.Entry\\Startup.cs"',showLineNumbers:!0,"":!0,"{9,13}":!0,title:'"Furion.Web.Entry\\Startup.cs"'},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.Web.Entry\n{\n public class Startup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n }\n }\n}\n")),(0,a.kt)("p",null,"\u5728\u8fd9\u91cc\uff0c\u4e0d\u6253\u7b97\u8be6\u7ec6\u8bb2 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup")," \u7c7b\u7684\u5177\u4f53\u529f\u80fd\u548c\u4f5c\u7528\u3002"),(0,a.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/startup?view=aspnetcore-3.1"},"ASP.NET Core - Startup \u7c7b")," \u7ae0\u8282\u3002")),(0,a.kt)("h2",{id:"312-appstartup"},"3.1.2 ",(0,a.kt)("inlineCode",{parentName:"h2"},"AppStartup")),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u63d0\u4f9b\u4e86\u66f4\u4e3a\u7075\u6d3b\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup")," \u7c7b\u914d\u7f6e\u65b9\u5f0f\uff0c",(0,a.kt)("strong",{parentName:"p"},"\u65e0\u9700\u5728 ",(0,a.kt)("inlineCode",{parentName:"strong"},"Web \u542f\u7528\u5c42")," \u4e2d\u914d\u7f6e\uff0c\u53ef\u5c06\u914d\u7f6e\u653e\u5230\u4efb\u4f55\u9879\u76ee\u5c42\u3002")),(0,a.kt)("p",null,"\u53ef\u80fd\u4f1a\u6709\u8bfb\u8005\u6709\u7591\u95ee\uff0c\u4e3a\u4ec0\u4e48\u8981\u591a\u6b64\u4e00\u4e3e\u5462\uff1f\u539f\u56e0\u6709\u51e0\u70b9\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Startup")," \u7c7b\u9ed8\u8ba4\u548c ",(0,a.kt)("inlineCode",{parentName:"li"},"Web \u5e94\u7528\u5c42")," \u7ed1\u5b9a\u5728\u4e00\u8d77\uff0c\u8fd9\u6837\u5c31\u4f1a\u5bfc\u81f4\u5982\u679c\u6211\u521b\u5efa\u4e86\u65b0\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"Web \u5e94\u7528\u5c42"),"\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"Startup")," \u53c8\u8981\u91cd\u65b0\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},"\u968f\u7740\u4e1a\u52a1\u7684\u589e\u957f\uff0c\u9700\u8981\u96c6\u6210\u8d8a\u6765\u8d8a\u591a\u7684\u7b2c\u4e09\u65b9\u670d\u52a1\uff0c\u8fd9\u65f6\u5019 ",(0,a.kt)("inlineCode",{parentName:"li"},"Startup")," \u7c7b\u5c31\u4f1a\u53d8\u5f97\u8d8a\u6765\u8d8a\u81c3\u80bf\uff0c\u96be\u4ee5\u7ef4\u62a4"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Startup")," \u7c7b\u65e0\u6cd5\u4e0e\u5176\u4ed6\u9879\u76ee\u7c7b\u578b\u8fdb\u884c\u5171\u7528")),(0,a.kt)("p",null,"\u6240\u4ee5\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u66f4\u52a0\u7075\u6d3b\u7684\u914d\u7f6e\u65b9\u5f0f\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup"),"\u3002"),(0,a.kt)("admonition",{title:"\u6ce8\u610f\u4e8b\u9879",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c ",(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u7684\u6d3e\u751f\u7c7b\u6240\u5728\u7684\u9879\u76ee\u5c42\u6ca1\u6709\u88ab\u542f\u52a8\u5c42\u76f4\u63a5\u6216\u95f4\u63a5\u6dfb\u52a0\u5f15\u7528\uff0c\u90a3\u4e48\u8fd9\u4e2a ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u5c31\u4f1a\u88ab\u5ffd\u7565\uff0c\u4e5f\u5c31\u662f\u4e0d\u4f1a\u81ea\u52a8\u8f7d\u5165\u6ce8\u518c\u3002")),(0,a.kt)("h3",{id:"3121-\u5982\u4f55\u914d\u7f6e-appstartup"},"3.1.2.1 \u5982\u4f55\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"h3"},"AppStartup")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u662f\u4e00\u4e2a\u62bd\u8c61\u7684\u7a7a\u7c7b\uff0c\u6ca1\u6709\u4efb\u4f55\u5b9a\u4e49\u6210\u5458\u3002\u6b63\u662f\u56e0\u4e3a\u8fd9\u6837\uff0c\u624d\u63d0\u4f9b\u66f4\u52a0\u7075\u6d3b\u7684\u914d\u7f6e\u65b9\u5f0f\u3002"),(0,a.kt)("h3",{id:"3122-appstartup-\u7ea6\u5b9a"},"3.1.2.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AppStartup")," \u7ea6\u5b9a"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u6d3e\u751f\u7c7b\u53ea\u6709\u4e24\u4e2a\u5c0f\u7ea6\u5b9a\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u4efb\u4f55\u516c\u5f00\u3001\u975e\u9759\u6001\u3001\u8fd4\u56de\u503c\u4e3a ",(0,a.kt)("inlineCode",{parentName:"li"},"void")," \u4e14\u65b9\u6cd5\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"IServiceCollection")," \u7c7b\u578b\uff0c\u90a3\u4e48\u4ed6\u5c31\u662f\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"li"},"ConfigureServices")," \u65b9\u6cd5"),(0,a.kt)("li",{parentName:"ul"},"\u4efb\u4f55\u516c\u5f00\u3001\u975e\u9759\u6001\u3001\u8fd4\u56de\u503c\u4e3a ",(0,a.kt)("inlineCode",{parentName:"li"},"void")," \u4e14\u65b9\u6cd5\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"IApplicationBuilder")," \u7c7b\u578b\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"IWebHostEnvironment")," \u7c7b\u578b\uff0c\u90a3\u4e48\u4ed6\u5c31\u662f\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"li"},"Configure")," \u65b9\u6cd5")),(0,a.kt)("p",null,"\u6240\u4ee5\uff0c\u6211\u4eec\u53ef\u4ee5\u81ea\u7531\u7684\u7f16\u5199\u65b9\u6cd5\uff0c\u53ea\u8981\u9075\u5faa\u7ea6\u5b9a\u5373\u53ef\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,7,12,18,23}",showLineNumbers:!0,"":!0,"{5,7,12,18,23}":!0},"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.EntityFramework.Core\n{\n public class MyStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddDataValidation();\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n app.UseSwagger();\n }\n\n // \u53ef\u4ee5\u968f\u610f\u5b9a\u4e49\u540d\u5b57\u548c\u65b9\u6cd5\n public void XXXXName(IServiceCollection services)\n {\n }\n\n // \u53ef\u4ee5\u968f\u610f\u5b9a\u4e49\u540d\u5b57\u548c\u65b9\u6cd5\n public void ZZZName(IApplicationBuilder app, IWebHostEnvironment env)\n {\n }\n }\n}\n")),(0,a.kt)("h3",{id:"3123-appstartup-\u914d\u7f6e\u987a\u5e8f"},"3.1.2.3 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AppStartup")," \u914d\u7f6e\u987a\u5e8f"),(0,a.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u914d\u7f6e\u987a\u5e8f\u7531\u6240\u5728\u7a0b\u5e8f\u96c6\u7684\u540d\u79f0\u8fdb\u884c\u6b63\u5e8f\u8c03\u7528\uff0c\u5982\u679c\u6211\u4eec\u9700\u8981\u914d\u7f6e\u6267\u884c\u987a\u5e8f\uff0c\u53ea\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u6d3e\u751f\u7c7b\u4e2d\u8d34 ",(0,a.kt)("inlineCode",{parentName:"p"},"[AppStartup(order)]")," \u7279\u6027\u5373\u53ef\u3002"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"order")," \u6570\u503c\u8d8a\u5927\uff0c\u8d8a\u5728\u524d\u9762\u8c03\u7528\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppStartup(10)]\n public class FirstStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n }\n }\n}\n")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppStartup(9)]\n public class SecondStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n }\n }\n}\n")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"FirstStartup")," \u4f1a\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"SecondStartup")," \u4e4b\u524d\u8c03\u7528\u3002"),(0,a.kt)("h3",{id:"3124-appstartup-\u65b9\u6cd5\u8c03\u7528\u987a\u5e8f"},"3.1.2.4 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AppStartup")," \u65b9\u6cd5\u8c03\u7528\u987a\u5e8f"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u65b9\u6cd5\u8c03\u7528\u987a\u5e8f\u548c\u65b9\u6cd5\u7684\u4e66\u5199\u5148\u540e\u6709\u5173\uff0c\u8d8a\u5728\u524d\u9762\u7684\u65b9\u6cd5\u8d8a\u5148\u8c03\u7528\u3002"),(0,a.kt)("h2",{id:"313-startup-\u914d\u7f6e\u6700\u4f73\u5b9e\u8df5"},"3.1.3 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Startup")," \u914d\u7f6e\u6700\u4f73\u5b9e\u8df5"),(0,a.kt)("admonition",{type:"important"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"v3.6.3+")," \u8bf4\u660e"),(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion v3.6.3+")," \u7248\u672c\u4e4b\u540e\u65e0\u9700\u521b\u5efa\u7a7a ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7c7b\uff0c\u5185\u90e8\u5df2\u5b9e\u73b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"FakeStartup")," \u6a21\u5f0f\u3002")),(0,a.kt)("p",null,"\u5efa\u8bae ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u542f\u52a8\u5c42\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4fdd\u6301\u4e3a\u7a7a\u65b9\u6cd5\u4f53\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {9-11,13-15} title="Furion.Web.Entry\\Startup.cs"',showLineNumbers:!0,"{9-11,13-15}":!0,title:'"Furion.Web.Entry\\Startup.cs"'},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.Web.Entry\n{\n public class Startup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n }\n }\n}\n")),(0,a.kt)("p",null,"\u5c06\u6240\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web \u5e94\u7528\u5c42")," \u914d\u7f6e\u8fc1\u79fb\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Web.Core.Startup.cs")," \u4e2d\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="Furion.Web.Core\\Startup.cs"',showLineNumbers:!0,"":!0,title:'"Furion.Web.Core\\Startup.cs"'},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Furion.Web.Core\n{\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddCorsAccessor();\n\n services.AddControllers().AddInject();\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n if (env.IsDevelopment())\n {\n app.UseDeveloperExceptionPage();\n }\n\n app.UseHttpsRedirection();\n\n app.UseRouting();\n\n app.UseCorsAccessor();\n\n app.UseAuthentication();\n app.UseAuthorization();\n\n app.UseInject();\n\n app.UseEndpoints(endpoints =>\n {\n endpoints.MapControllers();\n });\n }\n }\n}\n")),(0,a.kt)("p",null,"\u8fd9\u6837\uff0c\u540e\u7eed\u66f4\u6362 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web \u5e94\u7528\u5c42")," \u4e5f\u65e0\u9700\u91cd\u65b0\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")),(0,a.kt)("h2",{id:"314-\u6784\u9020\u51fd\u6570\u6ce8\u5165\u8bf4\u660e"},"3.1.4 \u6784\u9020\u51fd\u6570\u6ce8\u5165\u8bf4\u660e"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"AppStartup")," \u7684\u6d3e\u751f\u7c7b\u5e76\u672a\u63d0\u4f9b\u4f9d\u8d56\u6ce8\u5165\u7684\u529f\u80fd\uff0c\u4e5f\u5373\u662f\u65e0\u6cd5\u901a\u8fc7\u6784\u9020\u51fd\u6570\u8fdb\u884c\u6ce8\u5165\u670d\u52a1"),"\u3002\u539f\u56e0\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u662f\u4e2a\u7a7a\u7c7b\uff0c\u76ee\u7684\u662f\u7528\u6765\u67e5\u627e ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup")," \u7684\u3002"),(0,a.kt)("p",null,"\u90a3\u5982\u4f55\u50cf ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e00\u6837\u4f7f\u7528\u670d\u52a1\u5462\uff1f"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u83b7\u53d6\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"li"},"IConfiguration")," \u5b9e\u4f8b\uff1a\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"li"},"App.Configuration")),(0,a.kt)("li",{parentName:"ul"},"\u89e3\u6790\u670d\u52a1\uff1a\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"li"},"App.GetService()")," \u6216 ",(0,a.kt)("inlineCode",{parentName:"li"},"app.ApplicationServices.GetService()"))),(0,a.kt)("admonition",{type:"important"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u5173\u4e8e ",(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Configure")," \u65b9\u6cd5\u6ce8\u5165"),(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u9488\u5bf9 ",(0,a.kt)("inlineCode",{parentName:"p"},"Configure")," \u65b9\u6cd5\u63d0\u4f9b\u4e86\u53c2\u6570\u89e3\u6790\u6ce8\u5165\u529f\u80fd\uff0c\u4e5f\u5c31\u662f\u53ea\u8981\u5728\u65b9\u6cd5\u4e2d\u58f0\u660e\u63a5\u53e3\u53c2\u6570\u5373\u53ef\u81ea\u52a8\u6ce8\u5165\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,2}",showLineNumbers:!0,"":!0,"{1,2}":!0},"// app \u548c env \u4f1a\u81ea\u52a8\u6ce8\u5165\npublic void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n{\n}\n"))),(0,a.kt)("h2",{id:"315-\u5173\u4e8e-appsettingsjson"},"3.1.5 \u5173\u4e8e ",(0,a.kt)("inlineCode",{parentName:"h2"},"appsettings.json")),(0,a.kt)("p",null,"\u5728\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u914d\u7f6e\u653e\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u4e2d\u914d\u7f6e\uff0c\u4f46\u662f\u8fd9\u6837\u7684\u65b9\u5f0f\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u914d\u7f6e\u4e00\u6837\u7684\u9053\u7406\uff0c\u4e00\u65e6\u6211\u4eec\u66f4\u6362\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web \u5e94\u7528\u5c42"),"\uff0c\u90a3\u4e48 ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u53c8\u8981\u91cd\u65b0\u914d\u7f6e\u4e00\u6b21\u3002"),(0,a.kt)("p",null,"\u6240\u4ee5\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u66f4\u52a0\u7075\u6d3b\u7684\u65b9\u5f0f\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json"),"\uff0c",(0,a.kt)("strong",{parentName:"p"},"\u53ea\u9700\u8981\u5728\u4efb\u4f55\u9879\u76ee\u5c42\u6839\u76ee\u5f55\u4e0b\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"strong"},".json")," \u6587\u4ef6\u5373\u53ef\u3002",(0,a.kt)("inlineCode",{parentName:"strong"},"Furion")," \u6846\u67b6\u6700\u540e\u4f1a\u81ea\u52a8\u5408\u5e76\u6240\u6709\u5206\u6563\u7684\u914d\u7f6e\u6587\u4ef6\u3002")),(0,a.kt)("p",null,"\u5982\u6211\u4eec\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.EntityFramework.Core")," \u5c42\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"dbsettings.json")," \u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers title="Furion.EntityFramework.Core\\dbsettings.json"',showLineNumbers:!0,"":!0,title:'"Furion.EntityFramework.Core\\dbsettings.json"'},'{\n "ConnectionStrings": {\n "DbConnectionString": "Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;",\n "Sqlite3ConnectionString": "Data Source=./Furion.db"\n }\n}\n')),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u65e0\u9700\u5728 ",(0,a.kt)("inlineCode",{parentName:"strong"},"appsettings.json")," \u4e2d\u914d\u7f6e"),"\uff0c\u4e0b\u9762\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u9ed8\u8ba4\u4ee3\u7801:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "Logging": {\n "LogLevel": {\n "Default": "Information",\n "Microsoft": "Warning",\n "Microsoft.Hosting.Lifetime": "Information",\n "Microsoft.EntityFrameworkCore": "Information"\n }\n },\n "AllowedHosts": "*"\n}\n')),(0,a.kt)("p",null,"\u8fd9\u6837\u6211\u4eec\u628a\u914d\u7f6e\u6587\u4ef6\u5206\u6563\u5728\u4e0d\u540c\u9879\u76ee\u5c42\u4e4b\u540e\uff0c\u5c31\u53ef\u4ee5\u5b9e\u73b0\u5171\u7528\u548c\u5171\u4eab\u4e86\u3002"),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"\u5176\u4ed6\u5c42\u7684\u914d\u7f6e\u6587\u4ef6\u4e0d\u80fd\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u547d\u540d\uff0c\u4f1a\u5bfc\u81f4\u8986\u76d6\u542f\u52a8\u5c42\u7684\u914d\u7f6e\u3002"),(0,a.kt)("p",{parentName:"admonition"},"\u53e6\u5916\uff0c\u5728\u5176\u4ed6\u5c42\u521b\u5efa\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"*.json")," \u6587\u4ef6\u5fc5\u987b\u8bbe\u7f6e\u6587\u4ef6\u5c5e\u6027\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u59cb\u7ec8\u590d\u5236\u6216\u8f83\u65b0\u590d\u5236"),"\u3002")),(0,a.kt)("h2",{id:"316-\u53cd\u9988\u4e0e\u5efa\u8bae"},"3.1.6 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return u},kt:function(){return m}});var i=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function p(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=i.createContext({}),s=function(e){var n=i.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):p(p({},n),e)),t},u=function(e){var n=s(e.components);return i.createElement(l.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},d=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,l=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),d=s(t),m=r,k=d["".concat(l,".").concat(m)]||d[m]||c[m]||a;return t?i.createElement(k,p(p({ref:n},u),{},{components:t})):i.createElement(k,p({ref:n},u))}));function m(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,p=new Array(a);p[0]=d;var o={};for(var l in n)hasOwnProperty.call(n,l)&&(o[l]=n[l]);o.originalType=e,o.mdxType="string"==typeof e?e:r,p[1]=o;for(var s=2;s=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=i.createContext({}),s=function(e){var n=i.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):p(p({},n),e)),t},u=function(e){var n=s(e.components);return i.createElement(l.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},d=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,l=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),d=s(t),m=r,k=d["".concat(l,".").concat(m)]||d[m]||c[m]||a;return t?i.createElement(k,p(p({ref:n},u),{},{components:t})):i.createElement(k,p({ref:n},u))}));function m(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,p=new Array(a);p[0]=d;var o={};for(var l in n)hasOwnProperty.call(n,l)&&(o[l]=n[l]);o.originalType=e,o.mdxType="string"==typeof e?e:r,p[1]=o;for(var s=2;sStartup \u7c7b",id:"311-startup-\u7c7b",level:2},{value:"3.1.1.1 Startup \u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5",id:"3111-startup-\u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5",level:3},{value:"3.1.2 AppStartup",id:"312-appstartup",level:2},{value:"3.1.2.1 \u5982\u4f55\u914d\u7f6e AppStartup",id:"3121-\u5982\u4f55\u914d\u7f6e-appstartup",level:3},{value:"3.1.2.2 AppStartup \u7ea6\u5b9a",id:"3122-appstartup-\u7ea6\u5b9a",level:3},{value:"3.1.2.3 AppStartup \u914d\u7f6e\u987a\u5e8f",id:"3123-appstartup-\u914d\u7f6e\u987a\u5e8f",level:3},{value:"3.1.2.4 AppStartup \u65b9\u6cd5\u8c03\u7528\u987a\u5e8f",id:"3124-appstartup-\u65b9\u6cd5\u8c03\u7528\u987a\u5e8f",level:3},{value:"3.1.3 Startup \u914d\u7f6e\u6700\u4f73\u5b9e\u8df5",id:"313-startup-\u914d\u7f6e\u6700\u4f73\u5b9e\u8df5",level:2},{value:"3.1.4 \u6784\u9020\u51fd\u6570\u6ce8\u5165\u8bf4\u660e",id:"314-\u6784\u9020\u51fd\u6570\u6ce8\u5165\u8bf4\u660e",level:2},{value:"3.1.5 \u5173\u4e8e appsettings.json",id:"315-\u5173\u4e8e-appsettingsjson",level:2},{value:"3.1.6 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"316-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:c};function m(e){var n=e.components,t=(0,r.Z)(e,p);return(0,a.kt)("wrapper",(0,i.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"311-startup-\u7c7b"},"3.1.1 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Startup")," \u7c7b"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Startup")," \u7c7b\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u7a0b\u5e8f\u542f\u52a8\u9ed8\u8ba4\u8c03\u7528\u7684\u7c7b\uff0c\u8be5\u7c7b\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u914d\u7f6e\uff1a"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},".NET5")," \u65b9\u5f0f"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {18} title="Furion.Web.Entry\\Program.cs"',showLineNumbers:!0,"":!0,"{18}":!0,title:'"Furion.Web.Entry\\Program.cs"'},"using Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Furion.Web.Entry\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args)\n {\n return Host.CreateDefaultBuilder(args)\n .ConfigureWebHostDefaults(webBuilder =>\n {\n webBuilder.UseStartup();\n });\n }\n }\n}\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},".NET6 \u65b9\u5f0f")),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET6")," \u4e2d\u5fae\u8f6f\u5df2\u4e0d\u518d\u63a8\u8350 ",(0,a.kt)("inlineCode",{parentName:"p"},"UseStartup()")," \u65b9\u5f0f\u3002"),(0,a.kt)("h3",{id:"3111-startup-\u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5"},"3.1.1.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Startup")," \u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Startup")," \u9ed8\u8ba4\u6709\u4e24\u4e2a\u91cd\u8981\u7684\u65b9\u6cd5:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ConfigureServices"),"\uff1a\u914d\u7f6e\u5e94\u7528\u6240\u9700\u670d\u52a1\uff0c\u5728\u8be5\u65b9\u6cd5\u4e2d\u53ef\u4ee5\u6dfb\u52a0\u5e94\u7528\u6240\u9700\u8981\u7684\u529f\u80fd\u6216\u670d\u52a1"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Configure"),"\uff1a\u914d\u7f6e\u5e94\u7528\u8bf7\u6c42\u5904\u7406\u7ba1\u9053")),(0,a.kt)("p",null,"\u9ed8\u8ba4\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {9,13} title="Furion.Web.Entry\\Startup.cs"',showLineNumbers:!0,"":!0,"{9,13}":!0,title:'"Furion.Web.Entry\\Startup.cs"'},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.Web.Entry\n{\n public class Startup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n }\n }\n}\n")),(0,a.kt)("p",null,"\u5728\u8fd9\u91cc\uff0c\u4e0d\u6253\u7b97\u8be6\u7ec6\u8bb2 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup")," \u7c7b\u7684\u5177\u4f53\u529f\u80fd\u548c\u4f5c\u7528\u3002"),(0,a.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/startup?view=aspnetcore-3.1"},"ASP.NET Core - Startup \u7c7b")," \u7ae0\u8282\u3002")),(0,a.kt)("h2",{id:"312-appstartup"},"3.1.2 ",(0,a.kt)("inlineCode",{parentName:"h2"},"AppStartup")),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u63d0\u4f9b\u4e86\u66f4\u4e3a\u7075\u6d3b\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup")," \u7c7b\u914d\u7f6e\u65b9\u5f0f\uff0c",(0,a.kt)("strong",{parentName:"p"},"\u65e0\u9700\u5728 ",(0,a.kt)("inlineCode",{parentName:"strong"},"Web \u542f\u7528\u5c42")," \u4e2d\u914d\u7f6e\uff0c\u53ef\u5c06\u914d\u7f6e\u653e\u5230\u4efb\u4f55\u9879\u76ee\u5c42\u3002")),(0,a.kt)("p",null,"\u53ef\u80fd\u4f1a\u6709\u8bfb\u8005\u6709\u7591\u95ee\uff0c\u4e3a\u4ec0\u4e48\u8981\u591a\u6b64\u4e00\u4e3e\u5462\uff1f\u539f\u56e0\u6709\u51e0\u70b9\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Startup")," \u7c7b\u9ed8\u8ba4\u548c ",(0,a.kt)("inlineCode",{parentName:"li"},"Web \u5e94\u7528\u5c42")," \u7ed1\u5b9a\u5728\u4e00\u8d77\uff0c\u8fd9\u6837\u5c31\u4f1a\u5bfc\u81f4\u5982\u679c\u6211\u521b\u5efa\u4e86\u65b0\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"Web \u5e94\u7528\u5c42"),"\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"Startup")," \u53c8\u8981\u91cd\u65b0\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},"\u968f\u7740\u4e1a\u52a1\u7684\u589e\u957f\uff0c\u9700\u8981\u96c6\u6210\u8d8a\u6765\u8d8a\u591a\u7684\u7b2c\u4e09\u65b9\u670d\u52a1\uff0c\u8fd9\u65f6\u5019 ",(0,a.kt)("inlineCode",{parentName:"li"},"Startup")," \u7c7b\u5c31\u4f1a\u53d8\u5f97\u8d8a\u6765\u8d8a\u81c3\u80bf\uff0c\u96be\u4ee5\u7ef4\u62a4"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Startup")," \u7c7b\u65e0\u6cd5\u4e0e\u5176\u4ed6\u9879\u76ee\u7c7b\u578b\u8fdb\u884c\u5171\u7528")),(0,a.kt)("p",null,"\u6240\u4ee5\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u66f4\u52a0\u7075\u6d3b\u7684\u914d\u7f6e\u65b9\u5f0f\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup"),"\u3002"),(0,a.kt)("admonition",{title:"\u6ce8\u610f\u4e8b\u9879",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c ",(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u7684\u6d3e\u751f\u7c7b\u6240\u5728\u7684\u9879\u76ee\u5c42\u6ca1\u6709\u88ab\u542f\u52a8\u5c42\u76f4\u63a5\u6216\u95f4\u63a5\u6dfb\u52a0\u5f15\u7528\uff0c\u90a3\u4e48\u8fd9\u4e2a ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u5c31\u4f1a\u88ab\u5ffd\u7565\uff0c\u4e5f\u5c31\u662f\u4e0d\u4f1a\u81ea\u52a8\u8f7d\u5165\u6ce8\u518c\u3002")),(0,a.kt)("h3",{id:"3121-\u5982\u4f55\u914d\u7f6e-appstartup"},"3.1.2.1 \u5982\u4f55\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"h3"},"AppStartup")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u662f\u4e00\u4e2a\u62bd\u8c61\u7684\u7a7a\u7c7b\uff0c\u6ca1\u6709\u4efb\u4f55\u5b9a\u4e49\u6210\u5458\u3002\u6b63\u662f\u56e0\u4e3a\u8fd9\u6837\uff0c\u624d\u63d0\u4f9b\u66f4\u52a0\u7075\u6d3b\u7684\u914d\u7f6e\u65b9\u5f0f\u3002"),(0,a.kt)("h3",{id:"3122-appstartup-\u7ea6\u5b9a"},"3.1.2.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AppStartup")," \u7ea6\u5b9a"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u6d3e\u751f\u7c7b\u53ea\u6709\u4e24\u4e2a\u5c0f\u7ea6\u5b9a\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u4efb\u4f55\u516c\u5f00\u3001\u975e\u9759\u6001\u3001\u8fd4\u56de\u503c\u4e3a ",(0,a.kt)("inlineCode",{parentName:"li"},"void")," \u4e14\u65b9\u6cd5\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"IServiceCollection")," \u7c7b\u578b\uff0c\u90a3\u4e48\u4ed6\u5c31\u662f\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"li"},"ConfigureServices")," \u65b9\u6cd5"),(0,a.kt)("li",{parentName:"ul"},"\u4efb\u4f55\u516c\u5f00\u3001\u975e\u9759\u6001\u3001\u8fd4\u56de\u503c\u4e3a ",(0,a.kt)("inlineCode",{parentName:"li"},"void")," \u4e14\u65b9\u6cd5\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"IApplicationBuilder")," \u7c7b\u578b\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"IWebHostEnvironment")," \u7c7b\u578b\uff0c\u90a3\u4e48\u4ed6\u5c31\u662f\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"li"},"Configure")," \u65b9\u6cd5")),(0,a.kt)("p",null,"\u6240\u4ee5\uff0c\u6211\u4eec\u53ef\u4ee5\u81ea\u7531\u7684\u7f16\u5199\u65b9\u6cd5\uff0c\u53ea\u8981\u9075\u5faa\u7ea6\u5b9a\u5373\u53ef\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,7,12,18,23}",showLineNumbers:!0,"":!0,"{5,7,12,18,23}":!0},"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.EntityFramework.Core\n{\n public class MyStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddDataValidation();\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n app.UseSwagger();\n }\n\n // \u53ef\u4ee5\u968f\u610f\u5b9a\u4e49\u540d\u5b57\u548c\u65b9\u6cd5\n public void XXXXName(IServiceCollection services)\n {\n }\n\n // \u53ef\u4ee5\u968f\u610f\u5b9a\u4e49\u540d\u5b57\u548c\u65b9\u6cd5\n public void ZZZName(IApplicationBuilder app, IWebHostEnvironment env)\n {\n }\n }\n}\n")),(0,a.kt)("h3",{id:"3123-appstartup-\u914d\u7f6e\u987a\u5e8f"},"3.1.2.3 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AppStartup")," \u914d\u7f6e\u987a\u5e8f"),(0,a.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u914d\u7f6e\u987a\u5e8f\u7531\u6240\u5728\u7a0b\u5e8f\u96c6\u7684\u540d\u79f0\u8fdb\u884c\u6b63\u5e8f\u8c03\u7528\uff0c\u5982\u679c\u6211\u4eec\u9700\u8981\u914d\u7f6e\u6267\u884c\u987a\u5e8f\uff0c\u53ea\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u6d3e\u751f\u7c7b\u4e2d\u8d34 ",(0,a.kt)("inlineCode",{parentName:"p"},"[AppStartup(order)]")," \u7279\u6027\u5373\u53ef\u3002"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"order")," \u6570\u503c\u8d8a\u5927\uff0c\u8d8a\u5728\u524d\u9762\u8c03\u7528\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppStartup(10)]\n public class FirstStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n }\n }\n}\n")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppStartup(9)]\n public class SecondStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n }\n }\n}\n")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"FirstStartup")," \u4f1a\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"SecondStartup")," \u4e4b\u524d\u8c03\u7528\u3002"),(0,a.kt)("h3",{id:"3124-appstartup-\u65b9\u6cd5\u8c03\u7528\u987a\u5e8f"},"3.1.2.4 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AppStartup")," \u65b9\u6cd5\u8c03\u7528\u987a\u5e8f"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u65b9\u6cd5\u8c03\u7528\u987a\u5e8f\u548c\u65b9\u6cd5\u7684\u4e66\u5199\u5148\u540e\u6709\u5173\uff0c\u8d8a\u5728\u524d\u9762\u7684\u65b9\u6cd5\u8d8a\u5148\u8c03\u7528\u3002"),(0,a.kt)("h2",{id:"313-startup-\u914d\u7f6e\u6700\u4f73\u5b9e\u8df5"},"3.1.3 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Startup")," \u914d\u7f6e\u6700\u4f73\u5b9e\u8df5"),(0,a.kt)("admonition",{type:"important"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"v3.6.3+")," \u8bf4\u660e"),(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion v3.6.3+")," \u7248\u672c\u4e4b\u540e\u65e0\u9700\u521b\u5efa\u7a7a ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7c7b\uff0c\u5185\u90e8\u5df2\u5b9e\u73b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"FakeStartup")," \u6a21\u5f0f\u3002")),(0,a.kt)("p",null,"\u5efa\u8bae ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u542f\u52a8\u5c42\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4fdd\u6301\u4e3a\u7a7a\u65b9\u6cd5\u4f53\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {9-11,13-15} title="Furion.Web.Entry\\Startup.cs"',showLineNumbers:!0,"{9-11,13-15}":!0,title:'"Furion.Web.Entry\\Startup.cs"'},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.Web.Entry\n{\n public class Startup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n }\n }\n}\n")),(0,a.kt)("p",null,"\u5c06\u6240\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web \u5e94\u7528\u5c42")," \u914d\u7f6e\u8fc1\u79fb\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Web.Core.Startup.cs")," \u4e2d\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="Furion.Web.Core\\Startup.cs"',showLineNumbers:!0,"":!0,title:'"Furion.Web.Core\\Startup.cs"'},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Furion.Web.Core\n{\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddCorsAccessor();\n\n services.AddControllers().AddInject();\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n if (env.IsDevelopment())\n {\n app.UseDeveloperExceptionPage();\n }\n\n app.UseHttpsRedirection();\n\n app.UseRouting();\n\n app.UseCorsAccessor();\n\n app.UseAuthentication();\n app.UseAuthorization();\n\n app.UseInject();\n\n app.UseEndpoints(endpoints =>\n {\n endpoints.MapControllers();\n });\n }\n }\n}\n")),(0,a.kt)("p",null,"\u8fd9\u6837\uff0c\u540e\u7eed\u66f4\u6362 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web \u5e94\u7528\u5c42")," \u4e5f\u65e0\u9700\u91cd\u65b0\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")),(0,a.kt)("h2",{id:"314-\u6784\u9020\u51fd\u6570\u6ce8\u5165\u8bf4\u660e"},"3.1.4 \u6784\u9020\u51fd\u6570\u6ce8\u5165\u8bf4\u660e"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"AppStartup")," \u7684\u6d3e\u751f\u7c7b\u5e76\u672a\u63d0\u4f9b\u4f9d\u8d56\u6ce8\u5165\u7684\u529f\u80fd\uff0c\u4e5f\u5373\u662f\u65e0\u6cd5\u901a\u8fc7\u6784\u9020\u51fd\u6570\u8fdb\u884c\u6ce8\u5165\u670d\u52a1"),"\u3002\u539f\u56e0\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u662f\u4e2a\u7a7a\u7c7b\uff0c\u76ee\u7684\u662f\u7528\u6765\u67e5\u627e ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup")," \u7684\u3002"),(0,a.kt)("p",null,"\u90a3\u5982\u4f55\u50cf ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e00\u6837\u4f7f\u7528\u670d\u52a1\u5462\uff1f"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u83b7\u53d6\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"li"},"IConfiguration")," \u5b9e\u4f8b\uff1a\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"li"},"App.Configuration")),(0,a.kt)("li",{parentName:"ul"},"\u89e3\u6790\u670d\u52a1\uff1a\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"li"},"App.GetService()")," \u6216 ",(0,a.kt)("inlineCode",{parentName:"li"},"app.ApplicationServices.GetService()"))),(0,a.kt)("admonition",{type:"important"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u5173\u4e8e ",(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Configure")," \u65b9\u6cd5\u6ce8\u5165"),(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"AppStartup")," \u9488\u5bf9 ",(0,a.kt)("inlineCode",{parentName:"p"},"Configure")," \u65b9\u6cd5\u63d0\u4f9b\u4e86\u53c2\u6570\u89e3\u6790\u6ce8\u5165\u529f\u80fd\uff0c\u4e5f\u5c31\u662f\u53ea\u8981\u5728\u65b9\u6cd5\u4e2d\u58f0\u660e\u63a5\u53e3\u53c2\u6570\u5373\u53ef\u81ea\u52a8\u6ce8\u5165\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,2}",showLineNumbers:!0,"":!0,"{1,2}":!0},"// app \u548c env \u4f1a\u81ea\u52a8\u6ce8\u5165\npublic void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n{\n}\n"))),(0,a.kt)("h2",{id:"315-\u5173\u4e8e-appsettingsjson"},"3.1.5 \u5173\u4e8e ",(0,a.kt)("inlineCode",{parentName:"h2"},"appsettings.json")),(0,a.kt)("p",null,"\u5728\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u914d\u7f6e\u653e\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u4e2d\u914d\u7f6e\uff0c\u4f46\u662f\u8fd9\u6837\u7684\u65b9\u5f0f\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u914d\u7f6e\u4e00\u6837\u7684\u9053\u7406\uff0c\u4e00\u65e6\u6211\u4eec\u66f4\u6362\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web \u5e94\u7528\u5c42"),"\uff0c\u90a3\u4e48 ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u53c8\u8981\u91cd\u65b0\u914d\u7f6e\u4e00\u6b21\u3002"),(0,a.kt)("p",null,"\u6240\u4ee5\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u66f4\u52a0\u7075\u6d3b\u7684\u65b9\u5f0f\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json"),"\uff0c",(0,a.kt)("strong",{parentName:"p"},"\u53ea\u9700\u8981\u5728\u4efb\u4f55\u9879\u76ee\u5c42\u6839\u76ee\u5f55\u4e0b\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"strong"},".json")," \u6587\u4ef6\u5373\u53ef\u3002",(0,a.kt)("inlineCode",{parentName:"strong"},"Furion")," \u6846\u67b6\u6700\u540e\u4f1a\u81ea\u52a8\u5408\u5e76\u6240\u6709\u5206\u6563\u7684\u914d\u7f6e\u6587\u4ef6\u3002")),(0,a.kt)("p",null,"\u5982\u6211\u4eec\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.EntityFramework.Core")," \u5c42\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"dbsettings.json")," \u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers title="Furion.EntityFramework.Core\\dbsettings.json"',showLineNumbers:!0,"":!0,title:'"Furion.EntityFramework.Core\\dbsettings.json"'},'{\n "ConnectionStrings": {\n "DbConnectionString": "Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;",\n "Sqlite3ConnectionString": "Data Source=./Furion.db"\n }\n}\n')),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u65e0\u9700\u5728 ",(0,a.kt)("inlineCode",{parentName:"strong"},"appsettings.json")," \u4e2d\u914d\u7f6e"),"\uff0c\u4e0b\u9762\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u9ed8\u8ba4\u4ee3\u7801:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "Logging": {\n "LogLevel": {\n "Default": "Information",\n "Microsoft": "Warning",\n "Microsoft.Hosting.Lifetime": "Information",\n "Microsoft.EntityFrameworkCore": "Information"\n }\n },\n "AllowedHosts": "*"\n}\n')),(0,a.kt)("p",null,"\u8fd9\u6837\u6211\u4eec\u628a\u914d\u7f6e\u6587\u4ef6\u5206\u6563\u5728\u4e0d\u540c\u9879\u76ee\u5c42\u4e4b\u540e\uff0c\u5c31\u53ef\u4ee5\u5b9e\u73b0\u5171\u7528\u548c\u5171\u4eab\u4e86\u3002"),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"\u5176\u4ed6\u5c42\u7684\u914d\u7f6e\u6587\u4ef6\u4e0d\u80fd\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u547d\u540d\uff0c\u4f1a\u5bfc\u81f4\u8986\u76d6\u542f\u52a8\u5c42\u7684\u914d\u7f6e\u3002"),(0,a.kt)("p",{parentName:"admonition"},"\u53e6\u5916\uff0c\u5728\u5176\u4ed6\u5c42\u521b\u5efa\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"*.json")," \u6587\u4ef6\u5fc5\u987b\u8bbe\u7f6e\u6587\u4ef6\u5c5e\u6027\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u59cb\u7ec8\u590d\u5236\u6216\u8f83\u65b0\u590d\u5236"),"\u3002")),(0,a.kt)("h2",{id:"316-\u53cd\u9988\u4e0e\u5efa\u8bae"},"3.1.6 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/7c5dd5ef.9634009c.js b/handbook/build/assets/js/7c5dd5ef.9634009c.js deleted file mode 100644 index 5ad11aac85..0000000000 --- a/handbook/build/assets/js/7c5dd5ef.9634009c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[3043],{137:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return s},default:function(){return d},frontMatter:function(){return i},metadata:function(){return p},toc:function(){return c}});var r=n(3117),o=n(102),a=(n(7294),n(3905)),l=["components"],i={id:"oops",title:"4. Oops \u9759\u6001\u7c7b",sidebar_label:"4. Oops \u9759\u6001\u7c7b"},s=void 0,p={unversionedId:"global/oops",id:"global/oops",title:"4. Oops \u9759\u6001\u7c7b",description:"4.1 \u629b\u51fa\u5b57\u7b26\u4e32\u5f02\u5e38",source:"@site/docs/global/oops.mdx",sourceDirName:"global",slug:"/global/oops",permalink:"/furion/docs/global/oops",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/global/oops.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1658202770,formattedLastUpdatedAt:"Jul 19, 2022",frontMatter:{id:"oops",title:"4. Oops \u9759\u6001\u7c7b",sidebar_label:"4. Oops \u9759\u6001\u7c7b"},sidebar:"global",previous:{title:"3. DataValidator \u9759\u6001\u7c7b",permalink:"/furion/docs/global/datavalidator"},next:{title:"5. LinqExpression \u9759\u6001\u7c7b",permalink:"/furion/docs/global/linqexpression"}},u={},c=[{value:"4.1 \u629b\u51fa\u5b57\u7b26\u4e32\u5f02\u5e38",id:"41-\u629b\u51fa\u5b57\u7b26\u4e32\u5f02\u5e38",level:2},{value:"4.2 \u6307\u5b9a\u7c7b\u578b\u7684\u5f02\u5e38",id:"42-\u6307\u5b9a\u7c7b\u578b\u7684\u5f02\u5e38",level:2},{value:"4.3 \u72b6\u6001\u7801\u5f02\u5e38",id:"43-\u72b6\u6001\u7801\u5f02\u5e38",level:2},{value:"4.4 \u72b6\u6001\u7801\u5f02\u5e38",id:"44-\u72b6\u6001\u7801\u5f02\u5e38",level:2},{value:"4.5 \u5f02\u5e38\u65b9\u6cd5\u91cd\u8bd5",id:"45-\u5f02\u5e38\u65b9\u6cd5\u91cd\u8bd5",level:2},{value:"4.6 \u629b\u51fa\u4e1a\u52a1\u5f02\u5e38",id:"46-\u629b\u51fa\u4e1a\u52a1\u5f02\u5e38",level:2}],m={toc:c};function d(e){var t=e.components,n=(0,o.Z)(e,l);return(0,a.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"41-\u629b\u51fa\u5b57\u7b26\u4e32\u5f02\u5e38"},"4.1 \u629b\u51fa\u5b57\u7b26\u4e32\u5f02\u5e38"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'throw Oops.Oh("\u5f02\u5e38\u6d88\u606f");\nthrow Oops.Oh("\u5f02\u5e38\u6d88\u606f\uff1a{0}", "\u51fa\u9519\u4e86");\n')),(0,a.kt)("h2",{id:"42-\u6307\u5b9a\u7c7b\u578b\u7684\u5f02\u5e38"},"4.2 \u6307\u5b9a\u7c7b\u578b\u7684\u5f02\u5e38"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'throw Oops.Oh("\u5f02\u5e38\u6d88\u606f", typeof(ArgumentNullException));\nthrow Oops.Oh("\u5f02\u5e38\u6d88\u606f\uff1a{0}", typeof(ArgumentNullException), "\u51fa\u9519\u4e86");\n')),(0,a.kt)("h2",{id:"43-\u72b6\u6001\u7801\u5f02\u5e38"},"4.3 \u72b6\u6001\u7801\u5f02\u5e38"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'throw Oops.Oh(1000);\nthrow Oops.Oh(1000, "\u51fa\u9519\u4e86");\n')),(0,a.kt)("h2",{id:"44-\u72b6\u6001\u7801\u5f02\u5e38"},"4.4 \u72b6\u6001\u7801\u5f02\u5e38"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'throw Oops.Oh(1000, typeof(ArgumentNullException));\nthrow Oops.Oh(1000, typeof(ArgumentNullException), "\u51fa\u9519\u4e86");\n')),(0,a.kt)("h2",{id:"45-\u5f02\u5e38\u65b9\u6cd5\u91cd\u8bd5"},"4.5 \u5f02\u5e38\u65b9\u6cd5\u91cd\u8bd5"),(0,a.kt)("admonition",{title:"\u8c03\u6574\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"v2.17.0+")," \u7248\u672c\u4e0b\u9762\u65b9\u6cd5\u8bf7\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Retry.Invoke()/Retry.InvokeAsync()")," \u66ff\u4ee3\u3002")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"Oops.Retry(() => {\n // Do.....\n}, 3, 1000);\n\n// \u5e26\u8fd4\u56de\u503c\nvar value = Oops.Retry(() => {\n // Do.....\n}, 3, 1000);\n\n// \u53ea\u6709\u7279\u5b9a\u5f02\u5e38\u624d\u76d1\u542c\nOops.Retry(() => {\n\n}, 3, 1000, typeof(ArgumentNullException));\n")),(0,a.kt)("h2",{id:"46-\u629b\u51fa\u4e1a\u52a1\u5f02\u5e38"},"4.6 \u629b\u51fa\u4e1a\u52a1\u5f02\u5e38"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'throw Oops.Bah("\u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef");\nthrow Oops.Bah(1000);\n')))}d.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return u},kt:function(){return d}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},u=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,s=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),m=p(n),d=o,f=m["".concat(s,".").concat(d)]||m[d]||c[d]||a;return n?r.createElement(f,l(l({ref:t},u),{},{components:n})):r.createElement(f,l({ref:t},u))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,l=new Array(a);l[0]=m;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:o,l[1]=i;for(var p=2;p=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},u=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,s=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),m=p(n),d=o,f=m["".concat(s,".").concat(d)]||m[d]||c[d]||a;return n?r.createElement(f,l(l({ref:t},u),{},{components:n})):r.createElement(f,l({ref:t},u))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,l=new Array(a);l[0]=m;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:o,l[1]=i;for(var p=2;p {\n // Do.....\n}, 3, 1000);\n\n// \u5e26\u8fd4\u56de\u503c\nvar value = Oops.Retry(() => {\n // Do.....\n}, 3, 1000);\n\n// \u53ea\u6709\u7279\u5b9a\u5f02\u5e38\u624d\u76d1\u542c\nOops.Retry(() => {\n\n}, 3, 1000, typeof(ArgumentNullException));\n")),(0,a.kt)("h2",{id:"46-\u629b\u51fa\u4e1a\u52a1\u5f02\u5e38"},"4.6 \u629b\u51fa\u4e1a\u52a1\u5f02\u5e38"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'throw Oops.Bah("\u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef");\nthrow Oops.Bah(1000);\n')))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/7c6b08dc.85addf76.js b/handbook/build/assets/js/7c6b08dc.85addf76.js new file mode 100644 index 0000000000..b3667887c9 --- /dev/null +++ b/handbook/build/assets/js/7c6b08dc.85addf76.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4507],{3905:function(e,t,n){n.d(t,{Zo:function(){return c},kt:function(){return d}});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),m=p(n),d=a,f=m["".concat(s,".").concat(d)]||m[d]||u[d]||o;return n?r.createElement(f,i(i({ref:t},c),{},{components:n})):r.createElement(f,i({ref:t},c))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var p=2;pContentType \u6216 Mime",id:"135-\u83b7\u53d6\u6587\u4ef6-contenttype-\u6216-mime",level:2},{value:"13.6 \u521d\u59cb\u5316\u6587\u4ef6 ContentType \u63d0\u4f9b\u5668",id:"136-\u521d\u59cb\u5316\u6587\u4ef6-contenttype-\u63d0\u4f9b\u5668",level:2}],m={toc:u};function d(e){var t=e.components,n=(0,a.Z)(e,i);return(0,o.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"131-\u83b7\u53d6\u7269\u7406\u6587\u4ef6\u63d0\u4f9b\u5668"},"13.1 \u83b7\u53d6\u7269\u7406\u6587\u4ef6\u63d0\u4f9b\u5668"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var fileProvider = FS.GetPhysicalFileProvider(@"c:/test");\n')),(0,o.kt)("h2",{id:"132-\u83b7\u53d6\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6\u63d0\u4f9b\u5668"},"13.2 \u83b7\u53d6\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6\u63d0\u4f9b\u5668"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var fileProvider = FS.GetEmbeddedFileProvider(Assembly.GetEntryAssembly());\n")),(0,o.kt)("h2",{id:"133-\u83b7\u53d6\u6587\u4ef6\u63d0\u4f9b\u5668"},"13.3 \u83b7\u53d6\u6587\u4ef6\u63d0\u4f9b\u5668"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var fileProvider = FS.GetFileProvider(FileProviderTypes.Physical, @"c:/test");\n')),(0,o.kt)("h2",{id:"134-\u7279\u522b\u6ce8\u610f"},"13.4 \u7279\u522b\u6ce8\u610f"),(0,o.kt)("p",null,"\u4f7f\u7528\u8be5\u529f\u80fd\u9700\u786e\u4fdd ",(0,o.kt)("inlineCode",{parentName:"p"},"services.AddVirtualFileServer()")," \u5df2\u6ce8\u518c\u3002\u6846\u67b6\u63d0\u4f9b\u4e24\u79cd\u65b9\u5f0f\u63a7\u5236\u8be5\u670d\u52a1\u6ce8\u518c\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"AppSettings")," \u914d\u7f6e"),"\uff08\u63a8\u8350\u65b9\u5f0f\uff09")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "AppSettings": {\n "EnabledVirtualFileServer": true\n }\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u4ee5\u4e0a\u914d\u7f6e\u9ed8\u8ba4\u5f00\u542f\uff0c\u65e0\u9700\u914d\u7f6e\u3002")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"`\u624b\u52a8\u6ce8\u518c"))),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddVirtualFileServer();\n")),(0,o.kt)("h2",{id:"135-\u83b7\u53d6\u6587\u4ef6-contenttype-\u6216-mime"},"13.5 \u83b7\u53d6\u6587\u4ef6 ",(0,o.kt)("inlineCode",{parentName:"h2"},"ContentType")," \u6216 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Mime")),(0,o.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"warning"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 3.3.1 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var success = FS.TryGetContentType("image.png", out var contentType); // image/png\n')),(0,o.kt)("h2",{id:"136-\u521d\u59cb\u5316\u6587\u4ef6-contenttype-\u63d0\u4f9b\u5668"},"13.6 \u521d\u59cb\u5316\u6587\u4ef6 ",(0,o.kt)("inlineCode",{parentName:"h2"},"ContentType")," \u63d0\u4f9b\u5668"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var provider = FS.InitialContentTypeProvider();\n\n// \u53ef\u4ee5\u5728 Startup.cs \u4e2d\u6dfb\u52a0\u9759\u6001\u914d\u7f6e\napp.UseStaticFiles(new StaticFileOptions {\n ContentTypeProvider = provider\n})\n")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/7c6b08dc.897bee85.js b/handbook/build/assets/js/7c6b08dc.897bee85.js deleted file mode 100644 index 912a67b03c..0000000000 --- a/handbook/build/assets/js/7c6b08dc.897bee85.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4507],{6898:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return s},default:function(){return d},frontMatter:function(){return l},metadata:function(){return p},toc:function(){return u}});var r=n(3117),a=n(102),o=(n(7294),n(3905)),i=["components"],l={id:"fs",title:"13. FS \u9759\u6001\u7c7b",sidebar_label:"13. FS \u9759\u6001\u7c7b"},s=void 0,p={unversionedId:"global/fs",id:"global/fs",title:"13. FS \u9759\u6001\u7c7b",description:"13.1 \u83b7\u53d6\u7269\u7406\u6587\u4ef6\u63d0\u4f9b\u5668",source:"@site/docs/global/fs.mdx",sourceDirName:"global",slug:"/global/fs",permalink:"/furion/docs/global/fs",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/global/fs.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1654746241,formattedLastUpdatedAt:"Jun 9, 2022",frontMatter:{id:"fs",title:"13. FS \u9759\u6001\u7c7b",sidebar_label:"13. FS \u9759\u6001\u7c7b"},sidebar:"global",previous:{title:"12. SpareTime \u9759\u6001\u7c7b",permalink:"/furion/docs/global/sparetime"},next:{title:"14. JWTEncryption \u9759\u6001\u7c7b",permalink:"/furion/docs/global/jwt"}},c={},u=[{value:"13.1 \u83b7\u53d6\u7269\u7406\u6587\u4ef6\u63d0\u4f9b\u5668",id:"131-\u83b7\u53d6\u7269\u7406\u6587\u4ef6\u63d0\u4f9b\u5668",level:2},{value:"13.2 \u83b7\u53d6\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6\u63d0\u4f9b\u5668",id:"132-\u83b7\u53d6\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6\u63d0\u4f9b\u5668",level:2},{value:"13.3 \u83b7\u53d6\u6587\u4ef6\u63d0\u4f9b\u5668",id:"133-\u83b7\u53d6\u6587\u4ef6\u63d0\u4f9b\u5668",level:2},{value:"13.4 \u7279\u522b\u6ce8\u610f",id:"134-\u7279\u522b\u6ce8\u610f",level:2},{value:"13.5 \u83b7\u53d6\u6587\u4ef6 ContentType \u6216 Mime",id:"135-\u83b7\u53d6\u6587\u4ef6-contenttype-\u6216-mime",level:2},{value:"13.6 \u521d\u59cb\u5316\u6587\u4ef6 ContentType \u63d0\u4f9b\u5668",id:"136-\u521d\u59cb\u5316\u6587\u4ef6-contenttype-\u63d0\u4f9b\u5668",level:2}],m={toc:u};function d(e){var t=e.components,n=(0,a.Z)(e,i);return(0,o.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"131-\u83b7\u53d6\u7269\u7406\u6587\u4ef6\u63d0\u4f9b\u5668"},"13.1 \u83b7\u53d6\u7269\u7406\u6587\u4ef6\u63d0\u4f9b\u5668"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var fileProvider = FS.GetPhysicalFileProvider(@"c:/test");\n')),(0,o.kt)("h2",{id:"132-\u83b7\u53d6\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6\u63d0\u4f9b\u5668"},"13.2 \u83b7\u53d6\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6\u63d0\u4f9b\u5668"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var fileProvider = FS.GetEmbeddedFileProvider(Assembly.GetEntryAssembly());\n")),(0,o.kt)("h2",{id:"133-\u83b7\u53d6\u6587\u4ef6\u63d0\u4f9b\u5668"},"13.3 \u83b7\u53d6\u6587\u4ef6\u63d0\u4f9b\u5668"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var fileProvider = FS.GetFileProvider(FileProviderTypes.Physical, @"c:/test");\n')),(0,o.kt)("h2",{id:"134-\u7279\u522b\u6ce8\u610f"},"13.4 \u7279\u522b\u6ce8\u610f"),(0,o.kt)("p",null,"\u4f7f\u7528\u8be5\u529f\u80fd\u9700\u786e\u4fdd ",(0,o.kt)("inlineCode",{parentName:"p"},"services.AddVirtualFileServer()")," \u5df2\u6ce8\u518c\u3002\u6846\u67b6\u63d0\u4f9b\u4e24\u79cd\u65b9\u5f0f\u63a7\u5236\u8be5\u670d\u52a1\u6ce8\u518c\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"AppSettings")," \u914d\u7f6e"),"\uff08\u63a8\u8350\u65b9\u5f0f\uff09")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "AppSettings": {\n "EnabledVirtualFileServer": true\n }\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u4ee5\u4e0a\u914d\u7f6e\u9ed8\u8ba4\u5f00\u542f\uff0c\u65e0\u9700\u914d\u7f6e\u3002")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"`\u624b\u52a8\u6ce8\u518c"))),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddVirtualFileServer();\n")),(0,o.kt)("h2",{id:"135-\u83b7\u53d6\u6587\u4ef6-contenttype-\u6216-mime"},"13.5 \u83b7\u53d6\u6587\u4ef6 ",(0,o.kt)("inlineCode",{parentName:"h2"},"ContentType")," \u6216 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Mime")),(0,o.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"warning"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 3.3.1 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var success = FS.TryGetContentType("image.png", out var contentType); // image/png\n')),(0,o.kt)("h2",{id:"136-\u521d\u59cb\u5316\u6587\u4ef6-contenttype-\u63d0\u4f9b\u5668"},"13.6 \u521d\u59cb\u5316\u6587\u4ef6 ",(0,o.kt)("inlineCode",{parentName:"h2"},"ContentType")," \u63d0\u4f9b\u5668"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var provider = FS.InitialContentTypeProvider();\n\n// \u53ef\u4ee5\u5728 Startup.cs \u4e2d\u6dfb\u52a0\u9759\u6001\u914d\u7f6e\napp.UseStaticFiles(new StaticFileOptions {\n ContentTypeProvider = provider\n})\n")))}d.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return c},kt:function(){return d}});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),m=p(n),d=a,f=m["".concat(s,".").concat(d)]||m[d]||u[d]||o;return n?r.createElement(f,i(i({ref:t},c),{},{components:n})):r.createElement(f,i({ref:t},c))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var p=2;p=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=r.createContext({}),s=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},c=function(e){var n=s(e.components);return r.createElement(l.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),d=s(t),m=i,g=d["".concat(l,".").concat(m)]||d[m]||u[m]||o;return t?r.createElement(g,a(a({ref:n},c),{},{components:t})):r.createElement(g,a({ref:n},c))}));function m(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var o=t.length,a=new Array(o);a[0]=d;var p={};for(var l in n)hasOwnProperty.call(n,l)&&(p[l]=n[l]);p.originalType=e,p.mdxType="string"==typeof e?e:i,a[1]=p;for(var s=2;sWeb \u9879\u76ee",id:"21-\u521b\u5efa-web-\u9879\u76ee",level:2},{value:"2.1.1 \u521b\u5efa ASP.NET Core Web \u5e94\u7528\u7a0b\u5e8f",id:"211-\u521b\u5efa-aspnet-core-web-\u5e94\u7528\u7a0b\u5e8f",level:3},{value:"2.2 \u6dfb\u52a0 Furion \u4f9d\u8d56\u5305",id:"22-\u6dfb\u52a0-furion-\u4f9d\u8d56\u5305",level:2},{value:"2.3 Furion \u57fa\u672c\u914d\u7f6e",id:"23-furion-\u57fa\u672c\u914d\u7f6e",level:2},{value:"2.3.1 Program.cs \u6dfb\u52a0 Inject()",id:"231-programcs-\u6dfb\u52a0-inject",level:3},{value:"2.3.2 \u5728 Startup.cs \u4e2d\u6dfb\u52a0\u4e24\u4e2a Inject()",id:"232-\u5728-startupcs-\u4e2d\u6dfb\u52a0\u4e24\u4e2a-inject",level:3},{value:"2.4 \u542f\u52a8\u6d4f\u89c8\u5668",id:"24-\u542f\u52a8\u6d4f\u89c8\u5668",level:2}],m={toc:d};function g(e){var n=e.components,t=(0,i.Z)(e,p);return(0,o.kt)("wrapper",(0,r.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{title:"\u5c3d\u5feb\u5347\u7ea7",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"\u622a\u81f3 ",(0,o.kt)("strong",{parentName:"p"},"2022 \u5e74 05 \u6708 31 \u65e5"),"\uff0c\u5fae\u8f6f\u5df2\u7ecf\u505c\u6b62\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},".NET5")," \u7684\u6280\u672f\u652f\u6301\uff0c\u6240\u4ee5\u8bf7\u5c3d\u5feb\u5347\u7ea7\u5230 ",(0,o.kt)("inlineCode",{parentName:"p"},".NET6")," \u7248\u672c\uff0c\u8be6\u7ec6\u5347\u7ea7\u53ef\u67e5\u9605 \u3010",(0,o.kt)("a",{parentName:"p",href:"/furion/docs/net5-to-net6"},".NET5 \u5347\u7ea7 .NET6"),"\u3011")),(0,o.kt)("admonition",{title:"\u63a8\u8350\u4f7f\u7528\u811a\u624b\u67b6",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u5b98\u65b9\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u65b9\u4fbf\u7684\u811a\u624b\u67b6\uff0c\u53ef\u4ee5\u5feb\u901f\u7684\u521b\u5efa\u591a\u5c42\u67b6\u6784\u9879\u76ee\u3002"),(0,o.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u4f7f\u7528 \u300a",(0,o.kt)("a",{parentName:"p",href:"/furion/docs/template"},"2.2 \u5b98\u65b9\u811a\u624b\u67b6"),"\u300b\u4ee3\u66ff\u672c\u7ae0\u8282\u529f\u80fd\u3002")),(0,o.kt)("admonition",{title:"\u5165\u95e8\u6761\u4ef6",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u5bf9 ",(0,o.kt)("inlineCode",{parentName:"p"},".NET Core/ASP.NET Core")," \u6709\u4e00\u5b9a\u57fa\u7840\u4e86\u89e3\uff0c\u8fd8\u672a\u63a5\u89e6\u7684\u53ef\u5148\u770b ",(0,o.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/?view=aspnetcore-5.0&tabs=windows"},"\u3010ASP.NET Core \u57fa\u7840\u3011"))),(0,o.kt)("h2",{id:"21-\u521b\u5efa-web-\u9879\u76ee"},"2.1 \u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"h2"},"Web")," \u9879\u76ee"),(0,o.kt)("admonition",{title:"\u73af\u5883\u8981\u6c42",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e4b\u524d\u5148\u786e\u4fdd\u5b89\u88c5\u4e86\u6700\u65b0\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},".NET 5 SDK")," \u5e76\u5347\u7ea7 ",(0,o.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019")," \u81f3\u6700\u65b0\u7248\u3002")),(0,o.kt)("h3",{id:"211-\u521b\u5efa-aspnet-core-web-\u5e94\u7528\u7a0b\u5e8f"},"2.1.1 \u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"h3"},"ASP.NET Core Web \u5e94\u7528\u7a0b\u5e8f")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u6253\u5f00 ",(0,o.kt)("inlineCode",{parentName:"li"},"Visual Studio 2019")," \u5e76\u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"li"},"Web")," \u9879\u76ee")),(0,o.kt)("img",{src:(0,a.Z)("img/rm1.png")}),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u914d\u7f6e\u9879\u76ee\u540d\u79f0")),(0,o.kt)("img",{src:(0,a.Z)("img/rm2.png")}),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u9009\u62e9 ",(0,o.kt)("inlineCode",{parentName:"li"},"WebAPI")," \u9879\u76ee")),(0,o.kt)("img",{src:(0,a.Z)("img/rm3.png")}),(0,o.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"warning"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u5df2\u7ecf\u5185\u7f6e\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"Swagger")," \u89c4\u8303\u5316\u5e93\uff0c\u6240\u4ee5\u521b\u5efa\u65f6",(0,o.kt)("strong",{parentName:"p"},"\u65e0\u9700\u52fe\u9009")," ",(0,o.kt)("inlineCode",{parentName:"p"},"Enable OpenAPI support")," \u9009\u9879\u3002\u5426\u5219\u63d0\u793a\u7248\u672c\u4e0d\u4e00\u81f4\u4ea7\u751f\u51b2\u7a81\u3002")),(0,o.kt)("h2",{id:"22-\u6dfb\u52a0-furion-\u4f9d\u8d56\u5305"},"2.2 \u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Furion")," \u4f9d\u8d56\u5305"),(0,o.kt)("img",{src:(0,a.Z)("img/rm4.png")}),(0,o.kt)("h2",{id:"23-furion-\u57fa\u672c\u914d\u7f6e"},"2.3 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Furion")," \u57fa\u672c\u914d\u7f6e"),(0,o.kt)("h3",{id:"231-programcs-\u6dfb\u52a0-inject"},"2.3.1 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Program.cs")," \u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Inject()")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {18}",showLineNumbers:!0,"":!0,"{18}":!0},"using Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Hosting;\n\nnamespace FurionStart\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args) =>\n Host.CreateDefaultBuilder(args)\n .ConfigureWebHostDefaults(webBuilder =>\n {\n webBuilder\n .Inject() // \u6dfb\u52a0\u8fd9\u4e00\u884c\n .UseStartup();\n });\n }\n}\n")),(0,o.kt)("h3",{id:"232-\u5728-startupcs-\u4e2d\u6dfb\u52a0\u4e24\u4e2a-inject"},"2.3.2 \u5728 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Startup.cs")," \u4e2d\u6dfb\u52a0\u4e24\u4e2a ",(0,o.kt)("inlineCode",{parentName:"h3"},"Inject()")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {20,37}",showLineNumbers:!0,"":!0,"{20,37}":!0},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace FurionStart\n{\n public class Startup\n {\n public Startup(IConfiguration configuration)\n {\n Configuration = configuration;\n }\n\n public IConfiguration Configuration { get; }\n\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddControllers().AddInject(); // \u6dfb\u52a0 AddInject();\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n if (env.IsDevelopment())\n {\n app.UseDeveloperExceptionPage();\n }\n\n app.UseHttpsRedirection();\n\n app.UseRouting();\n\n app.UseAuthorization();\n\n // \u6dfb\u52a0\u8fd9\u4e00\u884c\uff0c\u5982\u679c\u662f MVC\u548cAPI\u5171\u5b58\u9879\u76ee\uff0c\u65e0\u9700\u6dfb\u52a0 string.Empty\n app.UseInject(string.Empty);\n\n app.UseEndpoints(endpoints =>\n {\n endpoints.MapControllers();\n });\n }\n }\n}\n")),(0,o.kt)("admonition",{title:"\u5c0f\u63d0\u9192",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c ",(0,o.kt)("inlineCode",{parentName:"p"},"app.UseInject()")," \u4e0d\u8f93\u5165\u53c2\u6570\uff0c\u5219\u9ed8\u8ba4\u5730\u5740\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"/api"),"\uff0c\u5982\u679c\u8f93\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"string.Empty")," \u5219\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"/")," \u76ee\u5f55\u3002\u5982\u679c\u8f93\u5165\u4efb\u610f\u5b57\u7b26\u4e32\uff0c\u5219\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"/\u4efb\u610f\u5b57\u7b26\u4e32")," \u76ee\u5f55\u3002")),(0,o.kt)("h2",{id:"24-\u542f\u52a8\u6d4f\u89c8\u5668"},"2.4 \u542f\u52a8\u6d4f\u89c8\u5668"),(0,o.kt)("p",null,"\u542f\u52a8\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u3002"),(0,o.kt)("img",{src:(0,a.Z)("img/rm5.png")}),(0,o.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019")," \u521b\u5efa\u7684\u9879\u76ee\u4f1a\u81ea\u52a8\u914d\u7f6e\u4e86\u542f\u52a8\u9875\uff0c\u5982\u679c\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"F5")," \u8fd0\u884c\uff0c\u53ef\u80fd\u4e0d\u4f1a\u81ea\u52a8\u6253\u5f00\u9996\u9875\uff0c\u8fd9\u65f6\u5019\u6211\u4eec\u53ea\u9700\u8981\u914d\u7f6e ",(0,o.kt)("inlineCode",{parentName:"p"},"launchSettings.json")," \u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"launchUrl")," \u5373\u53ef\uff1a"),(0,o.kt)("img",{src:(0,a.Z)("img/rm6.png")})))}g.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/7d1915d2.c1af54c4.js b/handbook/build/assets/js/7d1915d2.c1af54c4.js deleted file mode 100644 index 6bbf564ab8..0000000000 --- a/handbook/build/assets/js/7d1915d2.c1af54c4.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[9173],{2955:function(e,n,t){t.r(n),t.d(n,{assets:function(){return u},contentTitle:function(){return s},default:function(){return g},frontMatter:function(){return l},metadata:function(){return c},toc:function(){return d}});var r=t(3117),i=t(102),o=(t(7294),t(3905)),a=t(1402),p=["components"],l={id:"get-start",title:"2.1 ASP.NET 5 \u96c6\u6210",sidebar_label:"2.1 ASP.NET 5 \u96c6\u6210"},s=void 0,c={unversionedId:"get-start",id:"get-start",title:"2.1 ASP.NET 5 \u96c6\u6210",description:"\u622a\u81f3 2022 \u5e74 05 \u6708 31 \u65e5\uff0c\u5fae\u8f6f\u5df2\u7ecf\u505c\u6b62\u4e86 .NET5 \u7684\u6280\u672f\u652f\u6301\uff0c\u6240\u4ee5\u8bf7\u5c3d\u5feb\u5347\u7ea7\u5230 .NET6 \u7248\u672c\uff0c\u8be6\u7ec6\u5347\u7ea7\u53ef\u67e5\u9605 \u3010.NET5 \u5347\u7ea7 .NET6\u3011",source:"@site/docs/get-start.mdx",sourceDirName:".",slug:"/get-start",permalink:"/furion/docs/get-start",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/get-start.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1655877540,formattedLastUpdatedAt:"Jun 22, 2022",frontMatter:{id:"get-start",title:"2.1 ASP.NET 5 \u96c6\u6210",sidebar_label:"2.1 ASP.NET 5 \u96c6\u6210"},sidebar:"docs",previous:{title:"2.0 \u5165\u95e8\u6307\u5357 \u2728",permalink:"/furion/docs/serverun"},next:{title:"2.1 ASP.NET 6 \u96c6\u6210",permalink:"/furion/docs/get-start-net6"}},u={},d=[{value:"2.1 \u521b\u5efa Web \u9879\u76ee",id:"21-\u521b\u5efa-web-\u9879\u76ee",level:2},{value:"2.1.1 \u521b\u5efa ASP.NET Core Web \u5e94\u7528\u7a0b\u5e8f",id:"211-\u521b\u5efa-aspnet-core-web-\u5e94\u7528\u7a0b\u5e8f",level:3},{value:"2.2 \u6dfb\u52a0 Furion \u4f9d\u8d56\u5305",id:"22-\u6dfb\u52a0-furion-\u4f9d\u8d56\u5305",level:2},{value:"2.3 Furion \u57fa\u672c\u914d\u7f6e",id:"23-furion-\u57fa\u672c\u914d\u7f6e",level:2},{value:"2.3.1 Program.cs \u6dfb\u52a0 Inject()",id:"231-programcs-\u6dfb\u52a0-inject",level:3},{value:"2.3.2 \u5728 Startup.cs \u4e2d\u6dfb\u52a0\u4e24\u4e2a Inject()",id:"232-\u5728-startupcs-\u4e2d\u6dfb\u52a0\u4e24\u4e2a-inject",level:3},{value:"2.4 \u542f\u52a8\u6d4f\u89c8\u5668",id:"24-\u542f\u52a8\u6d4f\u89c8\u5668",level:2}],m={toc:d};function g(e){var n=e.components,t=(0,i.Z)(e,p);return(0,o.kt)("wrapper",(0,r.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{title:"\u5c3d\u5feb\u5347\u7ea7",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"\u622a\u81f3 ",(0,o.kt)("strong",{parentName:"p"},"2022 \u5e74 05 \u6708 31 \u65e5"),"\uff0c\u5fae\u8f6f\u5df2\u7ecf\u505c\u6b62\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},".NET5")," \u7684\u6280\u672f\u652f\u6301\uff0c\u6240\u4ee5\u8bf7\u5c3d\u5feb\u5347\u7ea7\u5230 ",(0,o.kt)("inlineCode",{parentName:"p"},".NET6")," \u7248\u672c\uff0c\u8be6\u7ec6\u5347\u7ea7\u53ef\u67e5\u9605 \u3010",(0,o.kt)("a",{parentName:"p",href:"/furion/docs/net5-to-net6"},".NET5 \u5347\u7ea7 .NET6"),"\u3011")),(0,o.kt)("admonition",{title:"\u63a8\u8350\u4f7f\u7528\u811a\u624b\u67b6",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u5b98\u65b9\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u65b9\u4fbf\u7684\u811a\u624b\u67b6\uff0c\u53ef\u4ee5\u5feb\u901f\u7684\u521b\u5efa\u591a\u5c42\u67b6\u6784\u9879\u76ee\u3002"),(0,o.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u4f7f\u7528 \u300a",(0,o.kt)("a",{parentName:"p",href:"/furion/docs/template"},"2.2 \u5b98\u65b9\u811a\u624b\u67b6"),"\u300b\u4ee3\u66ff\u672c\u7ae0\u8282\u529f\u80fd\u3002")),(0,o.kt)("admonition",{title:"\u5165\u95e8\u6761\u4ef6",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u5bf9 ",(0,o.kt)("inlineCode",{parentName:"p"},".NET Core/ASP.NET Core")," \u6709\u4e00\u5b9a\u57fa\u7840\u4e86\u89e3\uff0c\u8fd8\u672a\u63a5\u89e6\u7684\u53ef\u5148\u770b ",(0,o.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/?view=aspnetcore-5.0&tabs=windows"},"\u3010ASP.NET Core \u57fa\u7840\u3011"))),(0,o.kt)("h2",{id:"21-\u521b\u5efa-web-\u9879\u76ee"},"2.1 \u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"h2"},"Web")," \u9879\u76ee"),(0,o.kt)("admonition",{title:"\u73af\u5883\u8981\u6c42",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e4b\u524d\u5148\u786e\u4fdd\u5b89\u88c5\u4e86\u6700\u65b0\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},".NET 5 SDK")," \u5e76\u5347\u7ea7 ",(0,o.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019")," \u81f3\u6700\u65b0\u7248\u3002")),(0,o.kt)("h3",{id:"211-\u521b\u5efa-aspnet-core-web-\u5e94\u7528\u7a0b\u5e8f"},"2.1.1 \u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"h3"},"ASP.NET Core Web \u5e94\u7528\u7a0b\u5e8f")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u6253\u5f00 ",(0,o.kt)("inlineCode",{parentName:"li"},"Visual Studio 2019")," \u5e76\u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"li"},"Web")," \u9879\u76ee")),(0,o.kt)("img",{src:(0,a.Z)("img/rm1.png")}),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u914d\u7f6e\u9879\u76ee\u540d\u79f0")),(0,o.kt)("img",{src:(0,a.Z)("img/rm2.png")}),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u9009\u62e9 ",(0,o.kt)("inlineCode",{parentName:"li"},"WebAPI")," \u9879\u76ee")),(0,o.kt)("img",{src:(0,a.Z)("img/rm3.png")}),(0,o.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"warning"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u5df2\u7ecf\u5185\u7f6e\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"Swagger")," \u89c4\u8303\u5316\u5e93\uff0c\u6240\u4ee5\u521b\u5efa\u65f6",(0,o.kt)("strong",{parentName:"p"},"\u65e0\u9700\u52fe\u9009")," ",(0,o.kt)("inlineCode",{parentName:"p"},"Enable OpenAPI support")," \u9009\u9879\u3002\u5426\u5219\u63d0\u793a\u7248\u672c\u4e0d\u4e00\u81f4\u4ea7\u751f\u51b2\u7a81\u3002")),(0,o.kt)("h2",{id:"22-\u6dfb\u52a0-furion-\u4f9d\u8d56\u5305"},"2.2 \u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Furion")," \u4f9d\u8d56\u5305"),(0,o.kt)("img",{src:(0,a.Z)("img/rm4.png")}),(0,o.kt)("h2",{id:"23-furion-\u57fa\u672c\u914d\u7f6e"},"2.3 ",(0,o.kt)("inlineCode",{parentName:"h2"},"Furion")," \u57fa\u672c\u914d\u7f6e"),(0,o.kt)("h3",{id:"231-programcs-\u6dfb\u52a0-inject"},"2.3.1 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Program.cs")," \u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Inject()")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {18}",showLineNumbers:!0,"":!0,"{18}":!0},"using Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Hosting;\n\nnamespace FurionStart\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args) =>\n Host.CreateDefaultBuilder(args)\n .ConfigureWebHostDefaults(webBuilder =>\n {\n webBuilder\n .Inject() // \u6dfb\u52a0\u8fd9\u4e00\u884c\n .UseStartup();\n });\n }\n}\n")),(0,o.kt)("h3",{id:"232-\u5728-startupcs-\u4e2d\u6dfb\u52a0\u4e24\u4e2a-inject"},"2.3.2 \u5728 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Startup.cs")," \u4e2d\u6dfb\u52a0\u4e24\u4e2a ",(0,o.kt)("inlineCode",{parentName:"h3"},"Inject()")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {20,37}",showLineNumbers:!0,"":!0,"{20,37}":!0},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace FurionStart\n{\n public class Startup\n {\n public Startup(IConfiguration configuration)\n {\n Configuration = configuration;\n }\n\n public IConfiguration Configuration { get; }\n\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddControllers().AddInject(); // \u6dfb\u52a0 AddInject();\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n if (env.IsDevelopment())\n {\n app.UseDeveloperExceptionPage();\n }\n\n app.UseHttpsRedirection();\n\n app.UseRouting();\n\n app.UseAuthorization();\n\n // \u6dfb\u52a0\u8fd9\u4e00\u884c\uff0c\u5982\u679c\u662f MVC\u548cAPI\u5171\u5b58\u9879\u76ee\uff0c\u65e0\u9700\u6dfb\u52a0 string.Empty\n app.UseInject(string.Empty);\n\n app.UseEndpoints(endpoints =>\n {\n endpoints.MapControllers();\n });\n }\n }\n}\n")),(0,o.kt)("admonition",{title:"\u5c0f\u63d0\u9192",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c ",(0,o.kt)("inlineCode",{parentName:"p"},"app.UseInject()")," \u4e0d\u8f93\u5165\u53c2\u6570\uff0c\u5219\u9ed8\u8ba4\u5730\u5740\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"/api"),"\uff0c\u5982\u679c\u8f93\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"string.Empty")," \u5219\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"/")," \u76ee\u5f55\u3002\u5982\u679c\u8f93\u5165\u4efb\u610f\u5b57\u7b26\u4e32\uff0c\u5219\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"/\u4efb\u610f\u5b57\u7b26\u4e32")," \u76ee\u5f55\u3002")),(0,o.kt)("h2",{id:"24-\u542f\u52a8\u6d4f\u89c8\u5668"},"2.4 \u542f\u52a8\u6d4f\u89c8\u5668"),(0,o.kt)("p",null,"\u542f\u52a8\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u3002"),(0,o.kt)("img",{src:(0,a.Z)("img/rm5.png")}),(0,o.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019")," \u521b\u5efa\u7684\u9879\u76ee\u4f1a\u81ea\u52a8\u914d\u7f6e\u4e86\u542f\u52a8\u9875\uff0c\u5982\u679c\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"F5")," \u8fd0\u884c\uff0c\u53ef\u80fd\u4e0d\u4f1a\u81ea\u52a8\u6253\u5f00\u9996\u9875\uff0c\u8fd9\u65f6\u5019\u6211\u4eec\u53ea\u9700\u8981\u914d\u7f6e ",(0,o.kt)("inlineCode",{parentName:"p"},"launchSettings.json")," \u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"launchUrl")," \u5373\u53ef\uff1a"),(0,o.kt)("img",{src:(0,a.Z)("img/rm6.png")})))}g.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return c},kt:function(){return m}});var r=t(7294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function a(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=r.createContext({}),s=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},c=function(e){var n=s(e.components);return r.createElement(l.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),d=s(t),m=i,g=d["".concat(l,".").concat(m)]||d[m]||u[m]||o;return t?r.createElement(g,a(a({ref:n},c),{},{components:t})):r.createElement(g,a({ref:n},c))}));function m(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var o=t.length,a=new Array(o);a[0]=d;var p={};for(var l in n)hasOwnProperty.call(n,l)&&(p[l]=n[l]);p.originalType=e,p.mdxType="string"==typeof e?e:i,a[1]=p;for(var s=2;s=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},s=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=o,f=d["".concat(u,".").concat(m)]||d[m]||c[m]||i;return n?r.createElement(f,a(a({ref:t},s),{},{components:n})):r.createElement(f,a({ref:t},s))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var p=2;p.NET 6 Preview 6 SDK",id:"\u5b89\u88c5-net-6-preview-6-sdk",level:2},{value:"\u65e7\u9879\u76ee\u5347\u7ea7",id:"\u65e7\u9879\u76ee\u5347\u7ea7",level:2},{value:"\u65b0\u9879\u76ee\u4f7f\u7528",id:"\u65b0\u9879\u76ee\u4f7f\u7528",level:2},{value:"\u5347\u7ea7 Visual Studio 2019",id:"\u5347\u7ea7-visual-studio-2019",level:3},{value:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:3},{value:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",level:3}],d={toc:c};function m(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"2021 \u5e74 07 \u6708 15 \u65e5\uff0c\u5fae\u8f6f\u53d1\u5e03\u4e86 ",(0,i.kt)("inlineCode",{parentName:"strong"},".NET 6 Preview 6")," \u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5728\u5f53\u5929\u7b2c\u4e00\u65f6\u95f4\u9002\u914d\u4e86\u8be5\u7248\u672c\uff0c\u5e76\u53d1\u5e03 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v3.0.0-rc.1")," \u7248\u672c\u3002")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/tree/3.0.0-rc.1/"},"Furion .NET 6 Preview 6 \u6e90\u7801\u5730\u5740")),(0,i.kt)("h2",{id:"\u5b89\u88c5-net-6-preview-6-sdk"},"\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h2"},".NET 6 Preview 6 SDK")),(0,i.kt)("p",null,"\u5c1d\u9c9c\u4e4b\u524d\uff0c\u9996\u5148\u5148\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 6 SDK"),"\uff0c\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/download/dotnet/6.0"},"https://dotnet.microsoft.com/download/dotnet/6.0")),(0,i.kt)("p",null,"\u4e0b\u8f7d\u5bf9\u5e94\u7cfb\u7edf\u548c\u5904\u7406\u5668\u7248\u672c\u5373\u53ef\u3002"),(0,i.kt)("h2",{id:"\u65e7\u9879\u76ee\u5347\u7ea7"},"\u65e7\u9879\u76ee\u5347\u7ea7"),(0,i.kt)("p",null,"\u7f16\u8f91\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},".csproj")," \u9879\u76ee\uff0c\u4fee\u6539 ",(0,i.kt)("inlineCode",{parentName:"p"},"net5.0")," \u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"net6.0"),"\u3002"),(0,i.kt)("p",null,"\u540c\u65f6\u5347\u7ea7\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"Microsoft")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\u4e3a\u6700\u65b0\u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6700\u65b0\u7248\u672c\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"v3.0.0-rc.1"),"\u3002"),(0,i.kt)("h2",{id:"\u65b0\u9879\u76ee\u4f7f\u7528"},"\u65b0\u9879\u76ee\u4f7f\u7528"),(0,i.kt)("h3",{id:"\u5347\u7ea7-visual-studio-2019"},"\u5347\u7ea7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Visual Studio 2019")),(0,i.kt)("p",null,"\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 6")," \u652f\u6301\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview 16.11.0 Preview 3.0")," \u7248\u672c\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u662f ",(0,i.kt)("inlineCode",{parentName:"strong"},"Preview")," \u6700\u65b0\u7248\u672c"),"\u3002\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16"},"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16")),(0,i.kt)("p",null,"\u5df2\u7ecf\u5b89\u88c5\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview")," \u7248\u672c\u7684\u670b\u53cb\u76f4\u63a5\u5347\u7ea7\u5230\u6700\u65b0\u7248\u5373\u53ef\u3002"),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio Code")," \u5f00\u53d1\uff0c\u53ef\u5ffd\u7565\u6b64\u9009\u9879\u3002")),(0,i.kt)("h3",{id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion v3.0.0-rc.1")," \u76ee\u524d\u63d0\u4f9b\u4e86\u6240\u6709\u7c7b\u578b\u7684\u811a\u624b\u67b6\uff0c\u7248\u672c\u53f7\u7edf\u4e00 ",(0,i.kt)("inlineCode",{parentName:"p"},"3.0.0-rc.1"),"\u3002"),(0,i.kt)("p",null,"\u5b89\u88c5\u811a\u624b\u67b6\uff0c\u6253\u5f00 ",(0,i.kt)("inlineCode",{parentName:"p"},"CMD/Powershell")," \u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new --install Furion.Template.Api::3.0.0-rc.1\n")),(0,i.kt)("p",null,"\u521b\u5efa\u9879\u76ee"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new furionapi -n FurionNET6\n")),(0,i.kt)("h3",{id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"},"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"),(0,i.kt)("p",null,"\u6253\u5f00\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u5373\u53ef\u3002"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/7dd08b1c.cbbe1161.js b/handbook/build/assets/js/7dd08b1c.cbbe1161.js deleted file mode 100644 index ce21ffad22..0000000000 --- a/handbook/build/assets/js/7dd08b1c.cbbe1161.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4640],{2370:function(e,t,n){n.r(t),n.d(t,{assets:function(){return s},contentTitle:function(){return u},default:function(){return m},frontMatter:function(){return l},metadata:function(){return p},toc:function(){return c}});var r=n(3117),o=n(102),i=(n(7294),n(3905)),a=(n(1402),["components"]),l={slug:"net6-preview6",title:"4. .NET 6 Preview 6 \u5c1d\u9c9c",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5",".net6"]},u=void 0,p={permalink:"/furion/blog/net6-preview6",editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/blog/2021-07-15-net6-preview6.mdx",source:"@site/blog/2021-07-15-net6-preview6.mdx",title:"4. .NET 6 Preview 6 \u5c1d\u9c9c",description:"",date:"2021-07-15T00:00:00.000Z",formattedDate:"July 15, 2021",tags:[{label:"furion",permalink:"/furion/blog/tags/furion"},{label:"furos",permalink:"/furion/blog/tags/furos"},{label:".net",permalink:"/furion/blog/tags/net"},{label:".netcore",permalink:"/furion/blog/tags/netcore"},{label:".net5",permalink:"/furion/blog/tags/net-5"},{label:".net6",permalink:"/furion/blog/tags/net-6"}],readingTime:1.485,hasTruncateMarker:!1,authors:[{name:"dotNET China",title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",url:"https://www.chinadot.net",imageURL:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png"}],frontMatter:{slug:"net6-preview6",title:"4. .NET 6 Preview 6 \u5c1d\u9c9c",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5",".net6"]},prevItem:{title:"5. \u5728\u63a7\u5236\u53f0\u4e2d\u4f7f\u7528",permalink:"/furion/blog/console"},nextItem:{title:"3. .NET 6 Preview 5 \u5c1d\u9c9c",permalink:"/furion/blog/net6-preview5"}},s={authorsImageUrls:[void 0]},c=[{value:"\u5b89\u88c5 .NET 6 Preview 6 SDK",id:"\u5b89\u88c5-net-6-preview-6-sdk",level:2},{value:"\u65e7\u9879\u76ee\u5347\u7ea7",id:"\u65e7\u9879\u76ee\u5347\u7ea7",level:2},{value:"\u65b0\u9879\u76ee\u4f7f\u7528",id:"\u65b0\u9879\u76ee\u4f7f\u7528",level:2},{value:"\u5347\u7ea7 Visual Studio 2019",id:"\u5347\u7ea7-visual-studio-2019",level:3},{value:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:3},{value:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",level:3}],d={toc:c};function m(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"2021 \u5e74 07 \u6708 15 \u65e5\uff0c\u5fae\u8f6f\u53d1\u5e03\u4e86 ",(0,i.kt)("inlineCode",{parentName:"strong"},".NET 6 Preview 6")," \u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5728\u5f53\u5929\u7b2c\u4e00\u65f6\u95f4\u9002\u914d\u4e86\u8be5\u7248\u672c\uff0c\u5e76\u53d1\u5e03 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v3.0.0-rc.1")," \u7248\u672c\u3002")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/tree/3.0.0-rc.1/"},"Furion .NET 6 Preview 6 \u6e90\u7801\u5730\u5740")),(0,i.kt)("h2",{id:"\u5b89\u88c5-net-6-preview-6-sdk"},"\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h2"},".NET 6 Preview 6 SDK")),(0,i.kt)("p",null,"\u5c1d\u9c9c\u4e4b\u524d\uff0c\u9996\u5148\u5148\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 6 SDK"),"\uff0c\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/download/dotnet/6.0"},"https://dotnet.microsoft.com/download/dotnet/6.0")),(0,i.kt)("p",null,"\u4e0b\u8f7d\u5bf9\u5e94\u7cfb\u7edf\u548c\u5904\u7406\u5668\u7248\u672c\u5373\u53ef\u3002"),(0,i.kt)("h2",{id:"\u65e7\u9879\u76ee\u5347\u7ea7"},"\u65e7\u9879\u76ee\u5347\u7ea7"),(0,i.kt)("p",null,"\u7f16\u8f91\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},".csproj")," \u9879\u76ee\uff0c\u4fee\u6539 ",(0,i.kt)("inlineCode",{parentName:"p"},"net5.0")," \u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"net6.0"),"\u3002"),(0,i.kt)("p",null,"\u540c\u65f6\u5347\u7ea7\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"Microsoft")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\u4e3a\u6700\u65b0\u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6700\u65b0\u7248\u672c\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"v3.0.0-rc.1"),"\u3002"),(0,i.kt)("h2",{id:"\u65b0\u9879\u76ee\u4f7f\u7528"},"\u65b0\u9879\u76ee\u4f7f\u7528"),(0,i.kt)("h3",{id:"\u5347\u7ea7-visual-studio-2019"},"\u5347\u7ea7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Visual Studio 2019")),(0,i.kt)("p",null,"\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 6")," \u652f\u6301\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview 16.11.0 Preview 3.0")," \u7248\u672c\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u662f ",(0,i.kt)("inlineCode",{parentName:"strong"},"Preview")," \u6700\u65b0\u7248\u672c"),"\u3002\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16"},"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16")),(0,i.kt)("p",null,"\u5df2\u7ecf\u5b89\u88c5\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview")," \u7248\u672c\u7684\u670b\u53cb\u76f4\u63a5\u5347\u7ea7\u5230\u6700\u65b0\u7248\u5373\u53ef\u3002"),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio Code")," \u5f00\u53d1\uff0c\u53ef\u5ffd\u7565\u6b64\u9009\u9879\u3002")),(0,i.kt)("h3",{id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion v3.0.0-rc.1")," \u76ee\u524d\u63d0\u4f9b\u4e86\u6240\u6709\u7c7b\u578b\u7684\u811a\u624b\u67b6\uff0c\u7248\u672c\u53f7\u7edf\u4e00 ",(0,i.kt)("inlineCode",{parentName:"p"},"3.0.0-rc.1"),"\u3002"),(0,i.kt)("p",null,"\u5b89\u88c5\u811a\u624b\u67b6\uff0c\u6253\u5f00 ",(0,i.kt)("inlineCode",{parentName:"p"},"CMD/Powershell")," \u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new --install Furion.Template.Api::3.0.0-rc.1\n")),(0,i.kt)("p",null,"\u521b\u5efa\u9879\u76ee"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new furionapi -n FurionNET6\n")),(0,i.kt)("h3",{id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"},"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"),(0,i.kt)("p",null,"\u6253\u5f00\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u5373\u53ef\u3002"))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return m}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},s=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=o,f=d["".concat(u,".").concat(m)]||d[m]||c[m]||i;return n?r.createElement(f,a(a({ref:t},s),{},{components:n})):r.createElement(f,a({ref:t},s))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var p=2;p=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},s=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=o,f=d["".concat(u,".").concat(m)]||d[m]||c[m]||i;return n?r.createElement(f,a(a({ref:t},s),{},{components:n})):r.createElement(f,a({ref:t},s))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var p=2;p.NET 6 Preview 6 SDK",id:"\u5b89\u88c5-net-6-preview-6-sdk",level:2},{value:"\u65e7\u9879\u76ee\u5347\u7ea7",id:"\u65e7\u9879\u76ee\u5347\u7ea7",level:2},{value:"\u65b0\u9879\u76ee\u4f7f\u7528",id:"\u65b0\u9879\u76ee\u4f7f\u7528",level:2},{value:"\u5347\u7ea7 Visual Studio 2019",id:"\u5347\u7ea7-visual-studio-2019",level:3},{value:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:3},{value:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",level:3}],d={toc:c};function m(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"2021 \u5e74 07 \u6708 15 \u65e5\uff0c\u5fae\u8f6f\u53d1\u5e03\u4e86 ",(0,i.kt)("inlineCode",{parentName:"strong"},".NET 6 Preview 6")," \u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5728\u5f53\u5929\u7b2c\u4e00\u65f6\u95f4\u9002\u914d\u4e86\u8be5\u7248\u672c\uff0c\u5e76\u53d1\u5e03 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v3.0.0-rc.1")," \u7248\u672c\u3002")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/tree/3.0.0-rc.1/"},"Furion .NET 6 Preview 6 \u6e90\u7801\u5730\u5740")),(0,i.kt)("h2",{id:"\u5b89\u88c5-net-6-preview-6-sdk"},"\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h2"},".NET 6 Preview 6 SDK")),(0,i.kt)("p",null,"\u5c1d\u9c9c\u4e4b\u524d\uff0c\u9996\u5148\u5148\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 6 SDK"),"\uff0c\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/download/dotnet/6.0"},"https://dotnet.microsoft.com/download/dotnet/6.0")),(0,i.kt)("p",null,"\u4e0b\u8f7d\u5bf9\u5e94\u7cfb\u7edf\u548c\u5904\u7406\u5668\u7248\u672c\u5373\u53ef\u3002"),(0,i.kt)("h2",{id:"\u65e7\u9879\u76ee\u5347\u7ea7"},"\u65e7\u9879\u76ee\u5347\u7ea7"),(0,i.kt)("p",null,"\u7f16\u8f91\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},".csproj")," \u9879\u76ee\uff0c\u4fee\u6539 ",(0,i.kt)("inlineCode",{parentName:"p"},"net5.0")," \u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"net6.0"),"\u3002"),(0,i.kt)("p",null,"\u540c\u65f6\u5347\u7ea7\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"Microsoft")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\u4e3a\u6700\u65b0\u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6700\u65b0\u7248\u672c\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"v3.0.0-rc.1"),"\u3002"),(0,i.kt)("h2",{id:"\u65b0\u9879\u76ee\u4f7f\u7528"},"\u65b0\u9879\u76ee\u4f7f\u7528"),(0,i.kt)("h3",{id:"\u5347\u7ea7-visual-studio-2019"},"\u5347\u7ea7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Visual Studio 2019")),(0,i.kt)("p",null,"\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 6")," \u652f\u6301\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview 16.11.0 Preview 3.0")," \u7248\u672c\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u662f ",(0,i.kt)("inlineCode",{parentName:"strong"},"Preview")," \u6700\u65b0\u7248\u672c"),"\u3002\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16"},"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16")),(0,i.kt)("p",null,"\u5df2\u7ecf\u5b89\u88c5\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview")," \u7248\u672c\u7684\u670b\u53cb\u76f4\u63a5\u5347\u7ea7\u5230\u6700\u65b0\u7248\u5373\u53ef\u3002"),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio Code")," \u5f00\u53d1\uff0c\u53ef\u5ffd\u7565\u6b64\u9009\u9879\u3002")),(0,i.kt)("h3",{id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion v3.0.0-rc.1")," \u76ee\u524d\u63d0\u4f9b\u4e86\u6240\u6709\u7c7b\u578b\u7684\u811a\u624b\u67b6\uff0c\u7248\u672c\u53f7\u7edf\u4e00 ",(0,i.kt)("inlineCode",{parentName:"p"},"3.0.0-rc.1"),"\u3002"),(0,i.kt)("p",null,"\u5b89\u88c5\u811a\u624b\u67b6\uff0c\u6253\u5f00 ",(0,i.kt)("inlineCode",{parentName:"p"},"CMD/Powershell")," \u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new --install Furion.Template.Api::3.0.0-rc.1\n")),(0,i.kt)("p",null,"\u521b\u5efa\u9879\u76ee"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new furionapi -n FurionNET6\n")),(0,i.kt)("h3",{id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"},"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"),(0,i.kt)("p",null,"\u6253\u5f00\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u5373\u53ef\u3002"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/800036d7.c5090b95.js b/handbook/build/assets/js/800036d7.c5090b95.js deleted file mode 100644 index ce815d78c7..0000000000 --- a/handbook/build/assets/js/800036d7.c5090b95.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[7350],{7653:function(e,t,n){n.r(t),n.d(t,{assets:function(){return s},contentTitle:function(){return u},default:function(){return m},frontMatter:function(){return l},metadata:function(){return p},toc:function(){return c}});var r=n(3117),o=n(102),i=(n(7294),n(3905)),a=(n(1402),["components"]),l={slug:"net6-preview6",title:"4. .NET 6 Preview 6 \u5c1d\u9c9c",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5",".net6"]},u=void 0,p={permalink:"/furion/blog/net6-preview6",editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/blog/2021-07-15-net6-preview6.mdx",source:"@site/blog/2021-07-15-net6-preview6.mdx",title:"4. .NET 6 Preview 6 \u5c1d\u9c9c",description:"",date:"2021-07-15T00:00:00.000Z",formattedDate:"July 15, 2021",tags:[{label:"furion",permalink:"/furion/blog/tags/furion"},{label:"furos",permalink:"/furion/blog/tags/furos"},{label:".net",permalink:"/furion/blog/tags/net"},{label:".netcore",permalink:"/furion/blog/tags/netcore"},{label:".net5",permalink:"/furion/blog/tags/net-5"},{label:".net6",permalink:"/furion/blog/tags/net-6"}],readingTime:1.485,hasTruncateMarker:!1,authors:[{name:"dotNET China",title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",url:"https://www.chinadot.net",imageURL:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png"}],frontMatter:{slug:"net6-preview6",title:"4. .NET 6 Preview 6 \u5c1d\u9c9c",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5",".net6"]},prevItem:{title:"5. \u5728\u63a7\u5236\u53f0\u4e2d\u4f7f\u7528",permalink:"/furion/blog/console"},nextItem:{title:"3. .NET 6 Preview 5 \u5c1d\u9c9c",permalink:"/furion/blog/net6-preview5"}},s={authorsImageUrls:[void 0]},c=[{value:"\u5b89\u88c5 .NET 6 Preview 6 SDK",id:"\u5b89\u88c5-net-6-preview-6-sdk",level:2},{value:"\u65e7\u9879\u76ee\u5347\u7ea7",id:"\u65e7\u9879\u76ee\u5347\u7ea7",level:2},{value:"\u65b0\u9879\u76ee\u4f7f\u7528",id:"\u65b0\u9879\u76ee\u4f7f\u7528",level:2},{value:"\u5347\u7ea7 Visual Studio 2019",id:"\u5347\u7ea7-visual-studio-2019",level:3},{value:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:3},{value:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",level:3}],d={toc:c};function m(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"2021 \u5e74 07 \u6708 15 \u65e5\uff0c\u5fae\u8f6f\u53d1\u5e03\u4e86 ",(0,i.kt)("inlineCode",{parentName:"strong"},".NET 6 Preview 6")," \u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5728\u5f53\u5929\u7b2c\u4e00\u65f6\u95f4\u9002\u914d\u4e86\u8be5\u7248\u672c\uff0c\u5e76\u53d1\u5e03 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v3.0.0-rc.1")," \u7248\u672c\u3002")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/tree/3.0.0-rc.1/"},"Furion .NET 6 Preview 6 \u6e90\u7801\u5730\u5740")),(0,i.kt)("h2",{id:"\u5b89\u88c5-net-6-preview-6-sdk"},"\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h2"},".NET 6 Preview 6 SDK")),(0,i.kt)("p",null,"\u5c1d\u9c9c\u4e4b\u524d\uff0c\u9996\u5148\u5148\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 6 SDK"),"\uff0c\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/download/dotnet/6.0"},"https://dotnet.microsoft.com/download/dotnet/6.0")),(0,i.kt)("p",null,"\u4e0b\u8f7d\u5bf9\u5e94\u7cfb\u7edf\u548c\u5904\u7406\u5668\u7248\u672c\u5373\u53ef\u3002"),(0,i.kt)("h2",{id:"\u65e7\u9879\u76ee\u5347\u7ea7"},"\u65e7\u9879\u76ee\u5347\u7ea7"),(0,i.kt)("p",null,"\u7f16\u8f91\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},".csproj")," \u9879\u76ee\uff0c\u4fee\u6539 ",(0,i.kt)("inlineCode",{parentName:"p"},"net5.0")," \u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"net6.0"),"\u3002"),(0,i.kt)("p",null,"\u540c\u65f6\u5347\u7ea7\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"Microsoft")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\u4e3a\u6700\u65b0\u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6700\u65b0\u7248\u672c\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"v3.0.0-rc.1"),"\u3002"),(0,i.kt)("h2",{id:"\u65b0\u9879\u76ee\u4f7f\u7528"},"\u65b0\u9879\u76ee\u4f7f\u7528"),(0,i.kt)("h3",{id:"\u5347\u7ea7-visual-studio-2019"},"\u5347\u7ea7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Visual Studio 2019")),(0,i.kt)("p",null,"\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 6")," \u652f\u6301\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview 16.11.0 Preview 3.0")," \u7248\u672c\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u662f ",(0,i.kt)("inlineCode",{parentName:"strong"},"Preview")," \u6700\u65b0\u7248\u672c"),"\u3002\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16"},"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16")),(0,i.kt)("p",null,"\u5df2\u7ecf\u5b89\u88c5\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview")," \u7248\u672c\u7684\u670b\u53cb\u76f4\u63a5\u5347\u7ea7\u5230\u6700\u65b0\u7248\u5373\u53ef\u3002"),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio Code")," \u5f00\u53d1\uff0c\u53ef\u5ffd\u7565\u6b64\u9009\u9879\u3002")),(0,i.kt)("h3",{id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion v3.0.0-rc.1")," \u76ee\u524d\u63d0\u4f9b\u4e86\u6240\u6709\u7c7b\u578b\u7684\u811a\u624b\u67b6\uff0c\u7248\u672c\u53f7\u7edf\u4e00 ",(0,i.kt)("inlineCode",{parentName:"p"},"3.0.0-rc.1"),"\u3002"),(0,i.kt)("p",null,"\u5b89\u88c5\u811a\u624b\u67b6\uff0c\u6253\u5f00 ",(0,i.kt)("inlineCode",{parentName:"p"},"CMD/Powershell")," \u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new --install Furion.Template.Api::3.0.0-rc.1\n")),(0,i.kt)("p",null,"\u521b\u5efa\u9879\u76ee"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new furionapi -n FurionNET6\n")),(0,i.kt)("h3",{id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"},"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"),(0,i.kt)("p",null,"\u6253\u5f00\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u5373\u53ef\u3002"))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return m}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},s=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=o,f=d["".concat(u,".").concat(m)]||d[m]||c[m]||i;return n?r.createElement(f,a(a({ref:t},s),{},{components:n})):r.createElement(f,a({ref:t},s))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var p=2;p=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var p=i.createContext({}),m=function(e){var n=i.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},s=function(e){var n=m(e.components);return i.createElement(p.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},d=i.forwardRef((function(e,n){var t=e.components,a=e.mdxType,r=e.originalType,p=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=m(t),k=a,c=d["".concat(p,".").concat(k)]||d[k]||u[k]||r;return t?i.createElement(c,l(l({ref:n},s),{},{components:t})):i.createElement(c,l({ref:n},s))}));function k(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var r=t.length,l=new Array(r);l[0]=d;var o={};for(var p in n)hasOwnProperty.call(n,p)&&(o[p]=n[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var m=2;m=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var p=i.createContext({}),m=function(e){var n=i.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},s=function(e){var n=m(e.components);return i.createElement(p.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},d=i.forwardRef((function(e,n){var t=e.components,a=e.mdxType,r=e.originalType,p=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=m(t),k=a,c=d["".concat(p,".").concat(k)]||d[k]||u[k]||r;return t?i.createElement(c,l(l({ref:n},s),{},{components:t})):i.createElement(c,l({ref:n},s))}));function k(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var r=t.length,l=new Array(r);l[0]=d;var o={};for(var p in n)hasOwnProperty.call(n,p)&&(o[p]=n[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var m=2;m=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},l=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,c=e.parentName,l=u(e,["components","mdxType","originalType","parentName"]),d=p(r),f=o,m=d["".concat(c,".").concat(f)]||d[f]||s[f]||i;return r?n.createElement(m,a(a({ref:t},l),{},{components:r})):n.createElement(m,a({ref:t},l))}));function f(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=d;var u={};for(var c in t)hasOwnProperty.call(t,c)&&(u[c]=t[c]);u.originalType=e,u.mdxType="string"==typeof e?e:o,a[1]=u;for(var p=2;p=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},l=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,c=e.parentName,l=u(e,["components","mdxType","originalType","parentName"]),d=p(r),f=o,m=d["".concat(c,".").concat(f)]||d[f]||s[f]||i;return r?n.createElement(m,a(a({ref:t},l),{},{components:r})):n.createElement(m,a({ref:t},l))}));function f(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=d;var u={};for(var c in t)hasOwnProperty.call(t,c)&&(u[c]=t[c]);u.originalType=e,u.mdxType="string"==typeof e?e:o,a[1]=u;for(var p=2;p=0||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}var l=r.createContext({}),c=function(t){var e=r.useContext(l),n=e;return t&&(n="function"==typeof t?t(e):i(i({},e),t)),n},u=function(t){var e=c(t.components);return r.createElement(l.Provider,{value:e},t.children)},s={inlineCode:"code",wrapper:function(t){var e=t.children;return r.createElement(r.Fragment,{},e)}},d=r.forwardRef((function(t,e){var n=t.components,o=t.mdxType,a=t.originalType,l=t.parentName,u=p(t,["components","mdxType","originalType","parentName"]),d=c(n),m=o,h=d["".concat(l,".").concat(m)]||d[m]||s[m]||a;return n?r.createElement(h,i(i({ref:e},u),{},{components:n})):r.createElement(h,i({ref:e},u))}));function m(t,e){var n=arguments,o=e&&e.mdxType;if("string"==typeof t||o){var a=n.length,i=new Array(a);i[0]=d;var p={};for(var l in e)hasOwnProperty.call(e,l)&&(p[l]=e[l]);p.originalType=t,p.mdxType="string"==typeof t?t:o,i[1]=p;for(var c=2;cControllerBase \u6d3e\u751f\u7c7b\u4e2d",id:"\u5728-controllerbase-\u6d3e\u751f\u7c7b\u4e2d",level:3},{value:"\u901a\u8fc7\u6ce8\u5165 IHttpContextAccessor",id:"\u901a\u8fc7\u6ce8\u5165-ihttpcontextaccessor",level:3},{value:"\u901a\u8fc7 App.HttpContext",id:"\u901a\u8fc7-apphttpcontext",level:3},{value:"HttpContext \u62d3\u5c55\u65b9\u6cd5",id:"httpcontext-\u62d3\u5c55\u65b9\u6cd5",level:2},{value:"\u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027",id:"\u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027",level:3},{value:"\u8bbe\u7f6e Swagger \u81ea\u52a8\u6388\u6743",id:"\u8bbe\u7f6e-swagger-\u81ea\u52a8\u6388\u6743",level:3},{value:"\u9000\u51fa Swagger \u6388\u6743",id:"\u9000\u51fa-swagger-\u6388\u6743",level:3},{value:"\u83b7\u53d6\u672c\u5730 IP \u5730\u5740",id:"\u83b7\u53d6\u672c\u5730-ip-\u5730\u5740",level:3},{value:"\u83b7\u53d6\u5ba2\u6237\u7aef IP \u5730\u5740",id:"\u83b7\u53d6\u5ba2\u6237\u7aef-ip-\u5730\u5740",level:3}],d={toc:s};function m(t){var e=t.components,n=(0,o.Z)(t,i);return(0,a.kt)("wrapper",(0,r.Z)({},d,n,{components:e,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"httpcontext-\u91cd\u5927\u8c03\u6574"},"HttpContext \u91cd\u5927\u8c03\u6574"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET")," \u7684\u65f6\u4ee3\uff0c\u6211\u4eec\u901a\u5e38\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5168\u5c40\u9759\u6001\u7c7b\u83b7\u53d6\u8bf7\u6c42\u4e0a\u4e0b\u6587\uff0c\u4f46\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u4e2d\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u662f\u4e00\u4e2a\u975e\u9759\u6001\u7684\u62bd\u8c61\u7c7b\uff0c\u65e0\u6cd5\u624b\u52a8\u521b\u5efa\uff0c\u4e5f\u65e0\u6cd5\u901a\u8fc7\u9759\u6001\u83b7\u53d6\u3002"),(0,a.kt)("p",null,"\u867d\u7136\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u4e2d\u65e0\u6cd5\u76f4\u63a5\u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5bf9\u8c61\u3002\u4f46\u662f\u5fae\u8f6f\u4e5f\u63d0\u4f9b\u4e86\u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"p"},"IHttpContextAccessor")," \u65b9\u5f0f\u83b7\u53d6\u3002"),(0,a.kt)("h2",{id:"httpcontext-\u591a\u79cd\u83b7\u53d6\u65b9\u5f0f"},"HttpContext \u591a\u79cd\u83b7\u53d6\u65b9\u5f0f"),(0,a.kt)("h3",{id:"\u5728-controllerbase-\u6d3e\u751f\u7c7b\u4e2d"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"h3"},"ControllerBase")," \u6d3e\u751f\u7c7b\u4e2d"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ControllerBase")," \u6d3e\u751f\u7c7b\u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u76f4\u63a5\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5c5e\u6027\u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5bf9\u8c61\u3002"),(0,a.kt)("h3",{id:"\u901a\u8fc7\u6ce8\u5165-ihttpcontextaccessor"},"\u901a\u8fc7\u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"h3"},"IHttpContextAccessor")),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u5df2\u7ecf\u6ce8\u518c\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"IHttpContextAccessor")," \u670d\u52a1\uff0c\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u6784\u9020\u51fd\u6570\u6ce8\u5165\u8be5\u5bf9\u8c61\u83b7\u53d6\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5}",showLineNumbers:!0,"":!0,"{3,5}":!0},"public class AppService\n{\n public AppService(IHttpContextAccessor httpContextAccessor)\n {\n var httpContext = httpContextAccessor.HttpContext;\n }\n}\n")),(0,a.kt)("h3",{id:"\u901a\u8fc7-apphttpcontext"},"\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"h3"},"App.HttpContext")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"App")," \u9759\u6001\u7c7b\u4e5f\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"App.HttpContext")," \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5bf9\u8c61\u3002"),(0,a.kt)("h2",{id:"httpcontext-\u62d3\u5c55\u65b9\u6cd5"},(0,a.kt)("inlineCode",{parentName:"h2"},"HttpContext")," \u62d3\u5c55\u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e5f\u63d0\u4f9b\u4e86\u4e00\u4e9b\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u62d3\u5c55\u65b9\u6cd5"),(0,a.kt)("h3",{id:"\u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027"},"\u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var attribute = httpContext.GetMetadata();\n")),(0,a.kt)("h3",{id:"\u8bbe\u7f6e-swagger-\u81ea\u52a8\u6388\u6743"},"\u8bbe\u7f6e ",(0,a.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u81ea\u52a8\u6388\u6743"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'httpContext.SigninToSwagger("\u4f60\u7684token");\n')),(0,a.kt)("h3",{id:"\u9000\u51fa-swagger-\u6388\u6743"},"\u9000\u51fa ",(0,a.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u6388\u6743"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"httpContext.SignoutToSwagger();\n")),(0,a.kt)("h3",{id:"\u83b7\u53d6\u672c\u5730-ip-\u5730\u5740"},"\u83b7\u53d6\u672c\u5730 IP \u5730\u5740"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var ipv4 = httpContext.GetLocalIpAddressToIPv4();\nvar ipv6 = httpContext.GetLocalIpAddressToIPv6();\n")),(0,a.kt)("h3",{id:"\u83b7\u53d6\u5ba2\u6237\u7aef-ip-\u5730\u5740"},"\u83b7\u53d6\u5ba2\u6237\u7aef IP \u5730\u5740"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var ipv4 = httpContext.GetRemoteIpAddressToIPv4();\nvar ipv6 = httpContext.GetRemoteIpAddressToIPv6();\n")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/861b6d56.f4a2fc6e.js b/handbook/build/assets/js/861b6d56.f4a2fc6e.js deleted file mode 100644 index d1246e9ca9..0000000000 --- a/handbook/build/assets/js/861b6d56.f4a2fc6e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[7555],{5451:function(t,e,n){n.r(e),n.d(e,{assets:function(){return u},contentTitle:function(){return l},default:function(){return m},frontMatter:function(){return p},metadata:function(){return c},toc:function(){return s}});var r=n(3117),o=n(102),a=(n(7294),n(3905)),i=(n(1402),["components"]),p={slug:"httpcontext",title:"1. HttpContext \u5e94\u7528",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5","httpcontext"]},l=void 0,c={permalink:"/furion/blog/httpcontext",editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/blog/2021-02-01-httpcontext.mdx",source:"@site/blog/2021-02-01-httpcontext.mdx",title:"1. HttpContext \u5e94\u7528",description:"",date:"2021-02-01T00:00:00.000Z",formattedDate:"February 1, 2021",tags:[{label:"furion",permalink:"/furion/blog/tags/furion"},{label:"furos",permalink:"/furion/blog/tags/furos"},{label:".net",permalink:"/furion/blog/tags/net"},{label:".netcore",permalink:"/furion/blog/tags/netcore"},{label:".net5",permalink:"/furion/blog/tags/net-5"},{label:"httpcontext",permalink:"/furion/blog/tags/httpcontext"}],readingTime:1.545,hasTruncateMarker:!0,authors:[{name:"dotNET China",title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",url:"https://www.chinadot.net",imageURL:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png"}],frontMatter:{slug:"httpcontext",title:"1. HttpContext \u5e94\u7528",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5","httpcontext"]},prevItem:{title:"2. \u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d",permalink:"/furion/blog/fileupload-download"}},u={authorsImageUrls:[void 0]},s=[{value:"HttpContext \u91cd\u5927\u8c03\u6574",id:"httpcontext-\u91cd\u5927\u8c03\u6574",level:2},{value:"HttpContext \u591a\u79cd\u83b7\u53d6\u65b9\u5f0f",id:"httpcontext-\u591a\u79cd\u83b7\u53d6\u65b9\u5f0f",level:2},{value:"\u5728 ControllerBase \u6d3e\u751f\u7c7b\u4e2d",id:"\u5728-controllerbase-\u6d3e\u751f\u7c7b\u4e2d",level:3},{value:"\u901a\u8fc7\u6ce8\u5165 IHttpContextAccessor",id:"\u901a\u8fc7\u6ce8\u5165-ihttpcontextaccessor",level:3},{value:"\u901a\u8fc7 App.HttpContext",id:"\u901a\u8fc7-apphttpcontext",level:3},{value:"HttpContext \u62d3\u5c55\u65b9\u6cd5",id:"httpcontext-\u62d3\u5c55\u65b9\u6cd5",level:2},{value:"\u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027",id:"\u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027",level:3},{value:"\u8bbe\u7f6e Swagger \u81ea\u52a8\u6388\u6743",id:"\u8bbe\u7f6e-swagger-\u81ea\u52a8\u6388\u6743",level:3},{value:"\u9000\u51fa Swagger \u6388\u6743",id:"\u9000\u51fa-swagger-\u6388\u6743",level:3},{value:"\u83b7\u53d6\u672c\u5730 IP \u5730\u5740",id:"\u83b7\u53d6\u672c\u5730-ip-\u5730\u5740",level:3},{value:"\u83b7\u53d6\u5ba2\u6237\u7aef IP \u5730\u5740",id:"\u83b7\u53d6\u5ba2\u6237\u7aef-ip-\u5730\u5740",level:3}],d={toc:s};function m(t){var e=t.components,n=(0,o.Z)(t,i);return(0,a.kt)("wrapper",(0,r.Z)({},d,n,{components:e,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"httpcontext-\u91cd\u5927\u8c03\u6574"},"HttpContext \u91cd\u5927\u8c03\u6574"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET")," \u7684\u65f6\u4ee3\uff0c\u6211\u4eec\u901a\u5e38\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5168\u5c40\u9759\u6001\u7c7b\u83b7\u53d6\u8bf7\u6c42\u4e0a\u4e0b\u6587\uff0c\u4f46\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u4e2d\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u662f\u4e00\u4e2a\u975e\u9759\u6001\u7684\u62bd\u8c61\u7c7b\uff0c\u65e0\u6cd5\u624b\u52a8\u521b\u5efa\uff0c\u4e5f\u65e0\u6cd5\u901a\u8fc7\u9759\u6001\u83b7\u53d6\u3002"),(0,a.kt)("p",null,"\u867d\u7136\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u4e2d\u65e0\u6cd5\u76f4\u63a5\u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5bf9\u8c61\u3002\u4f46\u662f\u5fae\u8f6f\u4e5f\u63d0\u4f9b\u4e86\u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"p"},"IHttpContextAccessor")," \u65b9\u5f0f\u83b7\u53d6\u3002"),(0,a.kt)("h2",{id:"httpcontext-\u591a\u79cd\u83b7\u53d6\u65b9\u5f0f"},"HttpContext \u591a\u79cd\u83b7\u53d6\u65b9\u5f0f"),(0,a.kt)("h3",{id:"\u5728-controllerbase-\u6d3e\u751f\u7c7b\u4e2d"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"h3"},"ControllerBase")," \u6d3e\u751f\u7c7b\u4e2d"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"ControllerBase")," \u6d3e\u751f\u7c7b\u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u76f4\u63a5\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5c5e\u6027\u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5bf9\u8c61\u3002"),(0,a.kt)("h3",{id:"\u901a\u8fc7\u6ce8\u5165-ihttpcontextaccessor"},"\u901a\u8fc7\u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"h3"},"IHttpContextAccessor")),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u5df2\u7ecf\u6ce8\u518c\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"IHttpContextAccessor")," \u670d\u52a1\uff0c\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u6784\u9020\u51fd\u6570\u6ce8\u5165\u8be5\u5bf9\u8c61\u83b7\u53d6\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5}",showLineNumbers:!0,"":!0,"{3,5}":!0},"public class AppService\n{\n public AppService(IHttpContextAccessor httpContextAccessor)\n {\n var httpContext = httpContextAccessor.HttpContext;\n }\n}\n")),(0,a.kt)("h3",{id:"\u901a\u8fc7-apphttpcontext"},"\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"h3"},"App.HttpContext")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"App")," \u9759\u6001\u7c7b\u4e5f\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"App.HttpContext")," \u83b7\u53d6 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u5bf9\u8c61\u3002"),(0,a.kt)("h2",{id:"httpcontext-\u62d3\u5c55\u65b9\u6cd5"},(0,a.kt)("inlineCode",{parentName:"h2"},"HttpContext")," \u62d3\u5c55\u65b9\u6cd5"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e5f\u63d0\u4f9b\u4e86\u4e00\u4e9b\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpContext")," \u62d3\u5c55\u65b9\u6cd5"),(0,a.kt)("h3",{id:"\u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027"},"\u83b7\u53d6\u5f53\u524d\u8bf7\u6c42\u7684\u7279\u6027"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var attribute = httpContext.GetMetadata();\n")),(0,a.kt)("h3",{id:"\u8bbe\u7f6e-swagger-\u81ea\u52a8\u6388\u6743"},"\u8bbe\u7f6e ",(0,a.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u81ea\u52a8\u6388\u6743"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'httpContext.SigninToSwagger("\u4f60\u7684token");\n')),(0,a.kt)("h3",{id:"\u9000\u51fa-swagger-\u6388\u6743"},"\u9000\u51fa ",(0,a.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u6388\u6743"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"httpContext.SignoutToSwagger();\n")),(0,a.kt)("h3",{id:"\u83b7\u53d6\u672c\u5730-ip-\u5730\u5740"},"\u83b7\u53d6\u672c\u5730 IP \u5730\u5740"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var ipv4 = httpContext.GetLocalIpAddressToIPv4();\nvar ipv6 = httpContext.GetLocalIpAddressToIPv6();\n")),(0,a.kt)("h3",{id:"\u83b7\u53d6\u5ba2\u6237\u7aef-ip-\u5730\u5740"},"\u83b7\u53d6\u5ba2\u6237\u7aef IP \u5730\u5740"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var ipv4 = httpContext.GetRemoteIpAddressToIPv4();\nvar ipv6 = httpContext.GetRemoteIpAddressToIPv6();\n")))}m.isMDXComponent=!0},3905:function(t,e,n){n.d(e,{Zo:function(){return u},kt:function(){return m}});var r=n(7294);function o(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function a(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function i(t){for(var e=1;e=0||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}var l=r.createContext({}),c=function(t){var e=r.useContext(l),n=e;return t&&(n="function"==typeof t?t(e):i(i({},e),t)),n},u=function(t){var e=c(t.components);return r.createElement(l.Provider,{value:e},t.children)},s={inlineCode:"code",wrapper:function(t){var e=t.children;return r.createElement(r.Fragment,{},e)}},d=r.forwardRef((function(t,e){var n=t.components,o=t.mdxType,a=t.originalType,l=t.parentName,u=p(t,["components","mdxType","originalType","parentName"]),d=c(n),m=o,h=d["".concat(l,".").concat(m)]||d[m]||s[m]||a;return n?r.createElement(h,i(i({ref:e},u),{},{components:n})):r.createElement(h,i({ref:e},u))}));function m(t,e){var n=arguments,o=e&&e.mdxType;if("string"==typeof t||o){var a=n.length,i=new Array(a);i[0]=d;var p={};for(var l in e)hasOwnProperty.call(e,l)&&(p[l]=e[l]);p.originalType=t,p.mdxType="string"==typeof t?t:o,i[1]=p;for(var c=2;cMapster \u4f7f\u7528",id:"133-mapster-\u4f7f\u7528",level:2},{value:"13.3.1 \u5feb\u901f\u5165\u95e8",id:"1331-\u5feb\u901f\u5165\u95e8",level:3},{value:"13.3.2 \u81ea\u5b9a\u4e49\u6620\u5c04\u89c4\u5219",id:"1332-\u81ea\u5b9a\u4e49\u6620\u5c04\u89c4\u5219",level:3},{value:"13.3.3 \u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f",id:"1333-\u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f",level:3},{value:"13.3.4 \u548c EFCore \u914d\u5408",id:"1334-\u548c-efcore-\u914d\u5408",level:3},{value:"13.4 \u5168\u5c40\u9ed8\u8ba4\u914d\u7f6e",id:"134-\u5168\u5c40\u9ed8\u8ba4\u914d\u7f6e",level:2},{value:"13.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"135-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:u};function c(e){var t=e.components,n=(0,a.Z)(e,p);return(0,i.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{type:"important"},(0,i.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Mapster")," \u4ee5\u5916\u7684\u62d3\u5c55\u8bf4\u660e"),(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Mapster")," \u7684\u62d3\u5c55 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion.Extras.ObjectMapper.Mapster"),"\uff0c\u5982\u9700\u4f7f\u7528\u7b2c\u4e09\u65b9\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"AutoMapper")," \u5219\u65e0\u9700\u5b89\u88c5\u6b64\u62d3\u5c55\u3002")),(0,i.kt)("h2",{id:"131-\u5bf9\u8c61\u6620\u5c04"},"13.1 \u5bf9\u8c61\u6620\u5c04"),(0,i.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u5c31\u662f\u5c06\u4e00\u4e2a\u5bf9\u8c61\u7684\u6570\u636e\u6839\u636e\u7279\u5b9a\u89c4\u5219\u6279\u91cf\u6620\u5c04\u5230\u53e6\u4e00\u4e2a\u5bf9\u8c61\u4e2d\uff0c\u51cf\u5c11\u624b\u5de5\u64cd\u4f5c\u548c\u964d\u4f4e\u4eba\u4e3a\u51fa\u9519\u7387\u3002\u5982\u5c06 ",(0,i.kt)("inlineCode",{parentName:"p"},"DTO")," \u5bf9\u8c61\u6620\u5c04\u5230 ",(0,i.kt)("inlineCode",{parentName:"p"},"Entity")," \u5b9e\u4f53\u4e2d\uff0c\u53cd\u4e4b\u4ea6\u7136\u3002"),(0,i.kt)("h2",{id:"132-\u5148\u770b\u4f8b\u5b50"},"13.2 \u5148\u770b\u4f8b\u5b50"),(0,i.kt)("p",null,"\u5728\u8fc7\u53bb\uff0c\u6211\u4eec\u9700\u8981\u5c06\u4e00\u4e2a\u5bf9\u8c61\u7684\u503c\u8f6c\u6362\u5230\u53e6\u4e00\u4e2a\u5bf9\u8c61\u4e2d\uff0c\u6211\u4eec\u9700\u8981\u8fd9\u6837\u505a\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var entity = repository.Find(1);\n\nvar dto = new Dto();\ndto.Id = entity.Id;\ndto.Name = entity.Name;\ndto.Age = entity.Age;\ndto.Address = entity.Address;\ndto.FullName = entity.FirstName + entity.LastName;\ndto.IdCard = entity.IdCard.Replace("1234", "****");\n')),(0,i.kt)("p",null,"\u4e0a\u9762\u7684\u4f8b\u5b50\u4f3c\u4e4e\u6ca1\u6709\u4efb\u4f55\u95ee\u9898\uff0c\u4f46\u662f\u5982\u679c\u5f88\u591a\u5730\u65b9\u9700\u8981\u8fd9\u6837\u7684\u8d4b\u503c\u64cd\u4f5c\u3001\u6216\u8005\u76f8\u540c\u7684\u8d4b\u503c\u64cd\u4f5c\u5728\u591a\u4e2a\u5730\u65b9\u4f7f\u7528\uff0c\u53c8\u6216\u8005\u4e00\u4e2a\u7c7b\u4e2d\u542b\u6709\u975e\u5e38\u591a\u7684\u5c5e\u6027\u6216\u81ea\u5b9a\u4e49\u8d4b\u503c\u64cd\u4f5c\u3002\u90a3\u4e48\u8fd9\u6837\u7684\u64cd\u4f5c\u6548\u7387\u6781\u4f4e\uff0c\u5bb9\u6613\u51fa\u9519\uff0c\u4e14\u4ee3\u7801\u975e\u5e38\u81c3\u80bf\u548c\u5197\u4f59\u3002"),(0,i.kt)("p",null,"\u6240\u4ee5\uff0c\u5b9e\u73b0\u81ea\u52a8\u6620\u5c04\u8d4b\u503c\u548c\u652f\u6301\u7279\u6b8a\u914d\u7f6e\u7684\u9700\u6c42\u5c31\u6709\u4e86\u3002\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},"C#")," \u5e73\u53f0\u6709\u4e24\u4e2a\u4f18\u79c0\u7684\u5bf9\u8c61\u6620\u5c04\u5de5\u5177\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"Mapster")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"AutoMapper"),"\u3002",(0,i.kt)("strong",{parentName:"p"},"\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u63a8\u8350\u4f7f\u7528 ",(0,i.kt)("a",{parentName:"strong",href:"https://github.com/MapsterMapper/Mapster"},"Mapster"),"\uff0c",(0,i.kt)("a",{parentName:"strong",href:"https://github.com/MapsterMapper/Mapster"},"Mapster")," \u662f\u4e00\u6b3e\u6781\u6613\u4f7f\u7528\u4e14\u8d85\u9ad8\u6027\u80fd\u7684\u5bf9\u8c61\u6620\u5c04\u6846\u67b6\u3002")),(0,i.kt)("h2",{id:"133-mapster-\u4f7f\u7528"},"13.3 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Mapster")," \u4f7f\u7528"),(0,i.kt)("p",null,"\u73b0\u5728\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"Mapster")," \u63d0\u4f9b\u7684\u5bf9\u8c61\u6620\u5c04\u65b9\u6cd5\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"Adapt")," \u65b9\u6cd5\u6539\u9020\u4e0a\u9762\u7684\u4f8b\u5b50\uff1a"),(0,i.kt)("admonition",{title:"\u5b89\u88c5\u62d3\u5c55\u5305",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion.Core")," \u5c42\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion.Extras.ObjectMapper.Mapster")," \u62d3\u5c55\u5305\uff0c\u65e0\u9700\u624b\u52a8\u8c03\u7528\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4f1a\u81ea\u52a8\u52a0\u8f7d\u5e76\u8c03\u7528\u3002")),(0,i.kt)("h3",{id:"1331-\u5feb\u901f\u5165\u95e8"},"13.3.1 \u5feb\u901f\u5165\u95e8"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var entity = repository.Find(1);\nvar dto = entity.Adapt();\n")),(0,i.kt)("p",null,"\u4ec5\u4ec5\u4e00\u884c\u4ee3\u7801\u5c31\u53ef\u4ee5\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"p"},"entity -> dto")," \u7684\u8f6c\u6362\uff0c\u5982\u679c\u6d89\u53ca\u5230\u8d4b\u503c\u7684\u590d\u5236\u64cd\u4f5c\uff0c\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"dto.FullName")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"dto.IdCard"),"\uff0c\u6211\u4eec\u53ea\u9700\u8981\u81ea\u5b9a\u4e49\u6620\u5c04\u89c4\u5219\u7c7b\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"1332-\u81ea\u5b9a\u4e49\u6620\u5c04\u89c4\u5219"},"13.3.2 \u81ea\u5b9a\u4e49\u6620\u5c04\u89c4\u5219"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,6,10-12}",showLineNumbers:!0,"":!0,"{1,6,10-12}":!0},'using Mapster;\nusing System;\n\nnamespace Furion.Application\n{\n public class Mapper : IRegister\n {\n public void Register(TypeAdapterConfig config)\n {\n config.ForType()\n .Map(dest => dest.FullName, src => src.FirstName + src.LastName)\n .Map(dest => dest.IdCard, src => src.IdCard.Replace("1234", "****"));\n }\n }\n}\n')),(0,i.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u8be5\u6620\u5c04\u6587\u4ef6 ",(0,i.kt)("inlineCode",{parentName:"p"},"Mapper.cs")," \u53ef\u4ee5\u653e\u5728\u4efb\u4f55\u9879\u76ee\u6216\u6587\u4ef6\u5939\u4e2d\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4f1a\u5728\u7a0b\u5e8f\u542f\u52a8\u7684\u65f6\u5019\u81ea\u52a8\u626b\u63cf\u5e76\u6ce8\u5165\u914d\u7f6e\u3002")),(0,i.kt)("h3",{id:"1333-\u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f"},"13.3.3 \u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Mapster")," \u9664\u4e86\u63d0\u4f9b ",(0,i.kt)("inlineCode",{parentName:"p"},"Adapt")," \u62d3\u5c55\u65b9\u6cd5\u4ee5\u5916\uff0c\u540c\u65f6\u8fd8\u63d0\u4f9b\u4f9d\u8d56\u6ce8\u5165\u7684\u65b9\u5f0f\u3002"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public Person(IMapper mapper)\n{\n var dto = _mapper.Map(entity);\n}\n")),(0,i.kt)("h3",{id:"1334-\u548c-efcore-\u914d\u5408"},"13.3.4 \u548c ",(0,i.kt)("inlineCode",{parentName:"h3"},"EFCore")," \u914d\u5408"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Mapster")," \u8fd8\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"ProjectToType")," Linq \u62d3\u5c55\u65b9\u6cd5\u51cf\u5c11\u6211\u4eec\u624b\u52a8 ",(0,i.kt)("inlineCode",{parentName:"p"},"Select")," \u64cd\u4f5c\uff0c\u5982\uff1a"),(0,i.kt)("p",null,"\u6b63\u5e38\u7684\u64cd\u4f5c\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var destinations = context.Sources\n .Select(p => new Destination {\n Id = p.Id,\n Name = p.Name,\n Surname = p.Surname,\n ....\n })\n .ToList();\n")),(0,i.kt)("p",null,"\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Mapster")," \u4e4b\u540e\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0}," var destinations = context.Sources.ProjectToType().ToList();\n")),(0,i.kt)("h2",{id:"134-\u5168\u5c40\u9ed8\u8ba4\u914d\u7f6e"},"13.4 \u5168\u5c40\u9ed8\u8ba4\u914d\u7f6e"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u5168\u5c40\u9ed8\u8ba4\u6620\u5c04\u914d\u7f6e\u9009\u9879 ",(0,i.kt)("inlineCode",{parentName:"p"},"TypeAdapterConfig.GlobalSettings.Default"),"\uff0c\u53ef\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup")," \u4e2d\u914d\u7f6e\u5373\u53ef\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"TypeAdapterConfig.GlobalSettings.Default\n .PreserveReference(true);\n")),(0,i.kt)("h2",{id:"135-\u53cd\u9988\u4e0e\u5efa\u8bae"},"13.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,i.kt)("hr",null),(0,i.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"p"},"Mapster")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/MapsterMapper/Mapster/wiki"},"Mapster - Wiki")," \u6587\u6863\u3002")))}c.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return d},kt:function(){return c}});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function p(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=r.createContext({}),s=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):p(p({},t),e)),n},d=function(e){var t=s(e.components);return r.createElement(l.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,l=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),m=s(n),c=a,k=m["".concat(l,".").concat(c)]||m[c]||u[c]||i;return n?r.createElement(k,p(p({ref:t},d),{},{components:n})):r.createElement(k,p({ref:t},d))}));function c(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,p=new Array(i);p[0]=m;var o={};for(var l in t)hasOwnProperty.call(t,l)&&(o[l]=t[l]);o.originalType=e,o.mdxType="string"==typeof e?e:a,p[1]=o;for(var s=2;s=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=r.createContext({}),s=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):p(p({},t),e)),n},d=function(e){var t=s(e.components);return r.createElement(l.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,l=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),m=s(n),c=a,k=m["".concat(l,".").concat(c)]||m[c]||u[c]||i;return n?r.createElement(k,p(p({ref:t},d),{},{components:n})):r.createElement(k,p({ref:t},d))}));function c(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,p=new Array(i);p[0]=m;var o={};for(var l in t)hasOwnProperty.call(t,l)&&(o[l]=t[l]);o.originalType=e,o.mdxType="string"==typeof e?e:a,p[1]=o;for(var s=2;sMapster \u4f7f\u7528",id:"133-mapster-\u4f7f\u7528",level:2},{value:"13.3.1 \u5feb\u901f\u5165\u95e8",id:"1331-\u5feb\u901f\u5165\u95e8",level:3},{value:"13.3.2 \u81ea\u5b9a\u4e49\u6620\u5c04\u89c4\u5219",id:"1332-\u81ea\u5b9a\u4e49\u6620\u5c04\u89c4\u5219",level:3},{value:"13.3.3 \u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f",id:"1333-\u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f",level:3},{value:"13.3.4 \u548c EFCore \u914d\u5408",id:"1334-\u548c-efcore-\u914d\u5408",level:3},{value:"13.4 \u5168\u5c40\u9ed8\u8ba4\u914d\u7f6e",id:"134-\u5168\u5c40\u9ed8\u8ba4\u914d\u7f6e",level:2},{value:"13.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"135-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:u};function c(e){var t=e.components,n=(0,a.Z)(e,p);return(0,i.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{type:"important"},(0,i.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Mapster")," \u4ee5\u5916\u7684\u62d3\u5c55\u8bf4\u660e"),(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Mapster")," \u7684\u62d3\u5c55 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion.Extras.ObjectMapper.Mapster"),"\uff0c\u5982\u9700\u4f7f\u7528\u7b2c\u4e09\u65b9\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"AutoMapper")," \u5219\u65e0\u9700\u5b89\u88c5\u6b64\u62d3\u5c55\u3002")),(0,i.kt)("h2",{id:"131-\u5bf9\u8c61\u6620\u5c04"},"13.1 \u5bf9\u8c61\u6620\u5c04"),(0,i.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u5c31\u662f\u5c06\u4e00\u4e2a\u5bf9\u8c61\u7684\u6570\u636e\u6839\u636e\u7279\u5b9a\u89c4\u5219\u6279\u91cf\u6620\u5c04\u5230\u53e6\u4e00\u4e2a\u5bf9\u8c61\u4e2d\uff0c\u51cf\u5c11\u624b\u5de5\u64cd\u4f5c\u548c\u964d\u4f4e\u4eba\u4e3a\u51fa\u9519\u7387\u3002\u5982\u5c06 ",(0,i.kt)("inlineCode",{parentName:"p"},"DTO")," \u5bf9\u8c61\u6620\u5c04\u5230 ",(0,i.kt)("inlineCode",{parentName:"p"},"Entity")," \u5b9e\u4f53\u4e2d\uff0c\u53cd\u4e4b\u4ea6\u7136\u3002"),(0,i.kt)("h2",{id:"132-\u5148\u770b\u4f8b\u5b50"},"13.2 \u5148\u770b\u4f8b\u5b50"),(0,i.kt)("p",null,"\u5728\u8fc7\u53bb\uff0c\u6211\u4eec\u9700\u8981\u5c06\u4e00\u4e2a\u5bf9\u8c61\u7684\u503c\u8f6c\u6362\u5230\u53e6\u4e00\u4e2a\u5bf9\u8c61\u4e2d\uff0c\u6211\u4eec\u9700\u8981\u8fd9\u6837\u505a\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var entity = repository.Find(1);\n\nvar dto = new Dto();\ndto.Id = entity.Id;\ndto.Name = entity.Name;\ndto.Age = entity.Age;\ndto.Address = entity.Address;\ndto.FullName = entity.FirstName + entity.LastName;\ndto.IdCard = entity.IdCard.Replace("1234", "****");\n')),(0,i.kt)("p",null,"\u4e0a\u9762\u7684\u4f8b\u5b50\u4f3c\u4e4e\u6ca1\u6709\u4efb\u4f55\u95ee\u9898\uff0c\u4f46\u662f\u5982\u679c\u5f88\u591a\u5730\u65b9\u9700\u8981\u8fd9\u6837\u7684\u8d4b\u503c\u64cd\u4f5c\u3001\u6216\u8005\u76f8\u540c\u7684\u8d4b\u503c\u64cd\u4f5c\u5728\u591a\u4e2a\u5730\u65b9\u4f7f\u7528\uff0c\u53c8\u6216\u8005\u4e00\u4e2a\u7c7b\u4e2d\u542b\u6709\u975e\u5e38\u591a\u7684\u5c5e\u6027\u6216\u81ea\u5b9a\u4e49\u8d4b\u503c\u64cd\u4f5c\u3002\u90a3\u4e48\u8fd9\u6837\u7684\u64cd\u4f5c\u6548\u7387\u6781\u4f4e\uff0c\u5bb9\u6613\u51fa\u9519\uff0c\u4e14\u4ee3\u7801\u975e\u5e38\u81c3\u80bf\u548c\u5197\u4f59\u3002"),(0,i.kt)("p",null,"\u6240\u4ee5\uff0c\u5b9e\u73b0\u81ea\u52a8\u6620\u5c04\u8d4b\u503c\u548c\u652f\u6301\u7279\u6b8a\u914d\u7f6e\u7684\u9700\u6c42\u5c31\u6709\u4e86\u3002\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},"C#")," \u5e73\u53f0\u6709\u4e24\u4e2a\u4f18\u79c0\u7684\u5bf9\u8c61\u6620\u5c04\u5de5\u5177\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"Mapster")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"AutoMapper"),"\u3002",(0,i.kt)("strong",{parentName:"p"},"\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u63a8\u8350\u4f7f\u7528 ",(0,i.kt)("a",{parentName:"strong",href:"https://github.com/MapsterMapper/Mapster"},"Mapster"),"\uff0c",(0,i.kt)("a",{parentName:"strong",href:"https://github.com/MapsterMapper/Mapster"},"Mapster")," \u662f\u4e00\u6b3e\u6781\u6613\u4f7f\u7528\u4e14\u8d85\u9ad8\u6027\u80fd\u7684\u5bf9\u8c61\u6620\u5c04\u6846\u67b6\u3002")),(0,i.kt)("h2",{id:"133-mapster-\u4f7f\u7528"},"13.3 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Mapster")," \u4f7f\u7528"),(0,i.kt)("p",null,"\u73b0\u5728\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"Mapster")," \u63d0\u4f9b\u7684\u5bf9\u8c61\u6620\u5c04\u65b9\u6cd5\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"Adapt")," \u65b9\u6cd5\u6539\u9020\u4e0a\u9762\u7684\u4f8b\u5b50\uff1a"),(0,i.kt)("admonition",{title:"\u5b89\u88c5\u62d3\u5c55\u5305",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion.Core")," \u5c42\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion.Extras.ObjectMapper.Mapster")," \u62d3\u5c55\u5305\uff0c\u65e0\u9700\u624b\u52a8\u8c03\u7528\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4f1a\u81ea\u52a8\u52a0\u8f7d\u5e76\u8c03\u7528\u3002")),(0,i.kt)("h3",{id:"1331-\u5feb\u901f\u5165\u95e8"},"13.3.1 \u5feb\u901f\u5165\u95e8"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var entity = repository.Find(1);\nvar dto = entity.Adapt();\n")),(0,i.kt)("p",null,"\u4ec5\u4ec5\u4e00\u884c\u4ee3\u7801\u5c31\u53ef\u4ee5\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"p"},"entity -> dto")," \u7684\u8f6c\u6362\uff0c\u5982\u679c\u6d89\u53ca\u5230\u8d4b\u503c\u7684\u590d\u5236\u64cd\u4f5c\uff0c\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"dto.FullName")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"dto.IdCard"),"\uff0c\u6211\u4eec\u53ea\u9700\u8981\u81ea\u5b9a\u4e49\u6620\u5c04\u89c4\u5219\u7c7b\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"1332-\u81ea\u5b9a\u4e49\u6620\u5c04\u89c4\u5219"},"13.3.2 \u81ea\u5b9a\u4e49\u6620\u5c04\u89c4\u5219"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,6,10-12}",showLineNumbers:!0,"":!0,"{1,6,10-12}":!0},'using Mapster;\nusing System;\n\nnamespace Furion.Application\n{\n public class Mapper : IRegister\n {\n public void Register(TypeAdapterConfig config)\n {\n config.ForType()\n .Map(dest => dest.FullName, src => src.FirstName + src.LastName)\n .Map(dest => dest.IdCard, src => src.IdCard.Replace("1234", "****"));\n }\n }\n}\n')),(0,i.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u8be5\u6620\u5c04\u6587\u4ef6 ",(0,i.kt)("inlineCode",{parentName:"p"},"Mapper.cs")," \u53ef\u4ee5\u653e\u5728\u4efb\u4f55\u9879\u76ee\u6216\u6587\u4ef6\u5939\u4e2d\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4f1a\u5728\u7a0b\u5e8f\u542f\u52a8\u7684\u65f6\u5019\u81ea\u52a8\u626b\u63cf\u5e76\u6ce8\u5165\u914d\u7f6e\u3002")),(0,i.kt)("h3",{id:"1333-\u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f"},"13.3.3 \u4f9d\u8d56\u6ce8\u5165\u65b9\u5f0f"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Mapster")," \u9664\u4e86\u63d0\u4f9b ",(0,i.kt)("inlineCode",{parentName:"p"},"Adapt")," \u62d3\u5c55\u65b9\u6cd5\u4ee5\u5916\uff0c\u540c\u65f6\u8fd8\u63d0\u4f9b\u4f9d\u8d56\u6ce8\u5165\u7684\u65b9\u5f0f\u3002"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public Person(IMapper mapper)\n{\n var dto = _mapper.Map(entity);\n}\n")),(0,i.kt)("h3",{id:"1334-\u548c-efcore-\u914d\u5408"},"13.3.4 \u548c ",(0,i.kt)("inlineCode",{parentName:"h3"},"EFCore")," \u914d\u5408"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Mapster")," \u8fd8\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"ProjectToType")," Linq \u62d3\u5c55\u65b9\u6cd5\u51cf\u5c11\u6211\u4eec\u624b\u52a8 ",(0,i.kt)("inlineCode",{parentName:"p"},"Select")," \u64cd\u4f5c\uff0c\u5982\uff1a"),(0,i.kt)("p",null,"\u6b63\u5e38\u7684\u64cd\u4f5c\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var destinations = context.Sources\n .Select(p => new Destination {\n Id = p.Id,\n Name = p.Name,\n Surname = p.Surname,\n ....\n })\n .ToList();\n")),(0,i.kt)("p",null,"\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Mapster")," \u4e4b\u540e\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0}," var destinations = context.Sources.ProjectToType().ToList();\n")),(0,i.kt)("h2",{id:"134-\u5168\u5c40\u9ed8\u8ba4\u914d\u7f6e"},"13.4 \u5168\u5c40\u9ed8\u8ba4\u914d\u7f6e"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u5168\u5c40\u9ed8\u8ba4\u6620\u5c04\u914d\u7f6e\u9009\u9879 ",(0,i.kt)("inlineCode",{parentName:"p"},"TypeAdapterConfig.GlobalSettings.Default"),"\uff0c\u53ef\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Startup")," \u4e2d\u914d\u7f6e\u5373\u53ef\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"TypeAdapterConfig.GlobalSettings.Default\n .PreserveReference(true);\n")),(0,i.kt)("h2",{id:"135-\u53cd\u9988\u4e0e\u5efa\u8bae"},"13.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,i.kt)("hr",null),(0,i.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"p"},"Mapster")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/MapsterMapper/Mapster/wiki"},"Mapster - Wiki")," \u6587\u6863\u3002")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/8968961d.e90ecda8.js b/handbook/build/assets/js/8968961d.e90ecda8.js deleted file mode 100644 index acc33b7b32..0000000000 --- a/handbook/build/assets/js/8968961d.e90ecda8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[2710],{7886:function(e,n,t){t.r(n),t.d(n,{assets:function(){return p},contentTitle:function(){return l},default:function(){return m},frontMatter:function(){return s},metadata:function(){return u},toc:function(){return c}});var r=t(3117),a=t(102),o=(t(7294),t(3905)),i=["components"],s={id:"dbcontext-delete",title:"9.8 \u5220\u9664\u64cd\u4f5c",sidebar_label:"9.8 \u5220\u9664\u64cd\u4f5c"},l=void 0,u={unversionedId:"dbcontext-delete",id:"dbcontext-delete",title:"9.8 \u5220\u9664\u64cd\u4f5c",description:"\u4ee5\u4e0b\u5185\u5bb9\u5305\u542b Exists \u5355\u8bcd\u7684\u5728 Furion 2.6.0 + \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002",source:"@site/docs/dbcontext-delete.mdx",sourceDirName:".",slug:"/dbcontext-delete",permalink:"/furion/docs/dbcontext-delete",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-delete.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"dbcontext-delete",title:"9.8 \u5220\u9664\u64cd\u4f5c",sidebar_label:"9.8 \u5220\u9664\u64cd\u4f5c"},sidebar:"docs",previous:{title:"9.7 \u65b0\u589e\u6216\u66f4\u65b0\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-add-or-update"},next:{title:"9.9 \u6279\u91cf\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-batch"}},p={},c=[{value:"9.8.1 \u5220\u9664\u4e00\u4e2a\u5b9e\u4f53\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09",id:"981-\u5220\u9664\u4e00\u4e2a\u5b9e\u4f53\u4e0d\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.8.2 \u5220\u9664\u4e00\u4e2a\u5b9e\u4f53\uff08\u7acb\u5373\u63d0\u4ea4\uff09",id:"982-\u5220\u9664\u4e00\u4e2a\u5b9e\u4f53\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.8.3 \u6839\u636e\u4e3b\u952e\u5220\u9664\u8bb0\u5f55\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09",id:"983-\u6839\u636e\u4e3b\u952e\u5220\u9664\u8bb0\u5f55\u4e0d\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.8.4 \u6839\u636e\u4e3b\u952e\u5220\u9664\u8bb0\u5f55\uff08\u7acb\u5373\u63d0\u4ea4\uff09",id:"984-\u6839\u636e\u4e3b\u952e\u5220\u9664\u8bb0\u5f55\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.8.5 \u6570\u636e\u5b58\u5728\u624d\u6839\u636e\u4e3b\u952e\u5220\u9664\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09",id:"985-\u6570\u636e\u5b58\u5728\u624d\u6839\u636e\u4e3b\u952e\u5220\u9664\u4e0d\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.8.6 \u6570\u636e\u5b58\u5728\u624d\u6839\u636e\u4e3b\u952e\u5220\u9664\uff08\u7acb\u5373\u63d0\u4ea4\uff09",id:"986-\u6570\u636e\u5b58\u5728\u624d\u6839\u636e\u4e3b\u952e\u5220\u9664\u7acb\u5373\u63d0\u4ea4",level:2},{value:"9.8.7 \u5047\u5220\u9664/\u8f6f\u5220\u9664",id:"987-\u5047\u5220\u9664\u8f6f\u5220\u9664",level:2},{value:"9.8.7.1 \u6dfb\u52a0 [FakeDelete] \u6807\u8bb0",id:"9871-\u6dfb\u52a0-fakedelete-\u6807\u8bb0",level:3},{value:"9.8.7.2 \u5047\u5220\u9664\u4f7f\u7528",id:"9872-\u5047\u5220\u9664\u4f7f\u7528",level:3},{value:"9.8.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"988-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:c};function m(e){var n=e.components,t=(0,a.Z)(e,i);return(0,o.kt)("wrapper",(0,r.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{title:"\u529f\u80fd\u79fb\u9664\u58f0\u660e",type:"warning"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u5305\u542b ",(0,o.kt)("inlineCode",{parentName:"p"},"Exists")," \u5355\u8bcd\u7684\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 2.6.0 +")," \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002")),(0,o.kt)("h2",{id:"981-\u5220\u9664\u4e00\u4e2a\u5b9e\u4f53\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.8.1 \u5220\u9664\u4e00\u4e2a\u5b9e\u4f53\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.Delete(user);\n\n// \u793a\u4f8b\u4e8c\nuser.Delete();\n\n// \u793a\u4f8b\u4e09\nrepository.ChangeEntityState(user, EntityState.Deleted);\n\n// \u793a\u4f8b\u56db\nrepository.Entities.Remove(user);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.DeleteAsync(user);\n\n// \u793a\u4f8b\u4e8c\nawait user.DeleteAsync();\n")),(0,o.kt)("h2",{id:"982-\u5220\u9664\u4e00\u4e2a\u5b9e\u4f53\u7acb\u5373\u63d0\u4ea4"},"9.8.2 \u5220\u9664\u4e00\u4e2a\u5b9e\u4f53\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.DeleteNow(user);\n\n// \u793a\u4f8b\u4e8c\nuser.DeleteNow();\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.DeleteNowAsync(user);\n\n// \u793a\u4f8b\u4e8c\nawait user.DeleteNowAsync();\n")),(0,o.kt)("h2",{id:"983-\u6839\u636e\u4e3b\u952e\u5220\u9664\u8bb0\u5f55\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.8.3 \u6839\u636e\u4e3b\u952e\u5220\u9664\u8bb0\u5f55\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.Delete(1);\n\n// \u793a\u4f8b\u4e8c\nuser.Delete(1);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.DeleteAsync(1);\n\n// \u793a\u4f8b\u4e8c\nawait user.DeleteAsync(1);\n")),(0,o.kt)("h2",{id:"984-\u6839\u636e\u4e3b\u952e\u5220\u9664\u8bb0\u5f55\u7acb\u5373\u63d0\u4ea4"},"9.8.4 \u6839\u636e\u4e3b\u952e\u5220\u9664\u8bb0\u5f55\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.DeleteNow(1);\n\n// \u793a\u4f8b\u4e8c\nuser.DeleteNow(1);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.DeleteNowAsync(1);\n\n// \u793a\u4f8b\u4e8c\nawait user.DeleteNowAsync(1);\n")),(0,o.kt)("h2",{id:"985-\u6570\u636e\u5b58\u5728\u624d\u6839\u636e\u4e3b\u952e\u5220\u9664\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.8.5 \u6570\u636e\u5b58\u5728\u624d\u6839\u636e\u4e3b\u952e\u5220\u9664\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.DeleteExists(1);\n\n// \u793a\u4f8b\u4e8c\nuser.DeleteExists(1);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.DeleteExistsAsync(1);\n\n// \u793a\u4f8b\u4e8c\nawait user.DeleteExistsAsync(1);\n")),(0,o.kt)("h2",{id:"986-\u6570\u636e\u5b58\u5728\u624d\u6839\u636e\u4e3b\u952e\u5220\u9664\u7acb\u5373\u63d0\u4ea4"},"9.8.6 \u6570\u636e\u5b58\u5728\u624d\u6839\u636e\u4e3b\u952e\u5220\u9664\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.DeleteExistsNow(1);\n\n// \u793a\u4f8b\u4e8c\nuser.DeleteExistsNow(1);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.DeleteExistsNowAsync(1);\n\n// \u793a\u4f8b\u4e8c\nawait user.DeleteExistsNowAsync(1);\n")),(0,o.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u6240\u6709\u5e26 ",(0,o.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u8868\u793a\u7acb\u5373\u63d0\u4ea4\u5230\u6570\u636e\u5e93\uff0c\u4e5f\u5c31\u662f\u7acb\u5373\u8c03\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216 ",(0,o.kt)("inlineCode",{parentName:"p"},"SaveChangesAsync"),"\u3002")),(0,o.kt)("h2",{id:"987-\u5047\u5220\u9664\u8f6f\u5220\u9664"},"9.8.7 \u5047\u5220\u9664/\u8f6f\u5220\u9664"),(0,o.kt)("admonition",{title:"\u529f\u80fd\u79fb\u9664\u58f0\u660e",type:"warning"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 2.10 +")," \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u53ef\u4ee5\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"[FakeDelete]")," \u7279\u6027\u6807\u8bb0\u5047\u5220\u9664\u7279\u6027\uff0c\u5982\uff1a"),(0,o.kt)("h3",{id:"9871-\u6dfb\u52a0-fakedelete-\u6807\u8bb0"},"9.8.7.1 \u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"h3"},"[FakeDelete]")," \u6807\u8bb0"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public class Model: IEntity\n{\n [FakeDelete(true)] // \u8bbe\u7f6e\u5047\u5220\u9664\u7684\u503c\n public bool IsDeleted { get; set; }\n}\n")),(0,o.kt)("admonition",{type:"note"},(0,o.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"[FakeDelete]"),(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("strong",{parentName:"p"},"[FakeDelete]")," \u5c5e\u6027\u62e5\u6709\u5e26\u4e00\u4e2a\u53c2\u6570\u7684\u6784\u9020\u51fd\u6570\uff0c\u8fd9\u4e2a\u53c2\u6570\u662f\u5047\u5220\u9664\u7684\u503c")),(0,o.kt)("h3",{id:"9872-\u5047\u5220\u9664\u4f7f\u7528"},"9.8.7.2 \u5047\u5220\u9664\u4f7f\u7528"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.FakeDelete(entity);\n\n// \u793a\u4f8b\u4e8c\nrepository.FakeDeleteNow(entity);\n\n// \u793a\u4f8b\u4e09\nrepository.FakeDelete(1);\n\n// \u793a\u4f8b\u56db\nrepository.FakeDeleteNow(1);\n\n// \u793a\u4f8b\u4e94\nentity.FakeDelete();\n\n// \u793a\u4f8b\u516d\nrepository.UpdateInclude(user, u => u.IsDeleted);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.FakeDeleteAsync(entity);\n\n// \u793a\u4f8b\u4e8c\nawait repository.FakeDeleteNowAsync(entity);\n\n// \u793a\u4f8b\u4e09\nawait repository.FakeDeleteAsync(1);\n\n// \u793a\u4f8b\u56db\nawait repository.FakeDeleteNowAsync(1);\n\n// \u793a\u4f8b\u4e94\nawait entity.FakeDeleteAsync();\n\n// \u793a\u4f8b\u516d\nawait repository.UpdateIncludeAsync(user, u => u.IsDeleted);\n")),(0,o.kt)("h2",{id:"988-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.8.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return p},kt:function(){return m}});var r=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function i(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=r.createContext({}),u=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},p=function(e){var n=u(e.components);return r.createElement(l.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=u(t),m=a,y=d["".concat(l,".").concat(m)]||d[m]||c[m]||o;return t?r.createElement(y,i(i({ref:n},p),{},{components:t})):r.createElement(y,i({ref:n},p))}));function m(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var o=t.length,i=new Array(o);i[0]=d;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:a,i[1]=s;for(var u=2;u=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=r.createContext({}),u=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},p=function(e){var n=u(e.components);return r.createElement(l.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=u(t),m=a,y=d["".concat(l,".").concat(m)]||d[m]||c[m]||o;return t?r.createElement(y,i(i({ref:n},p),{},{components:t})):r.createElement(y,i({ref:n},p))}));function m(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var o=t.length,i=new Array(o);i[0]=d;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:a,i[1]=s;for(var u=2;u[FakeDelete] \u6807\u8bb0",id:"9871-\u6dfb\u52a0-fakedelete-\u6807\u8bb0",level:3},{value:"9.8.7.2 \u5047\u5220\u9664\u4f7f\u7528",id:"9872-\u5047\u5220\u9664\u4f7f\u7528",level:3},{value:"9.8.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"988-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:c};function m(e){var n=e.components,t=(0,a.Z)(e,i);return(0,o.kt)("wrapper",(0,r.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{title:"\u529f\u80fd\u79fb\u9664\u58f0\u660e",type:"warning"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u5305\u542b ",(0,o.kt)("inlineCode",{parentName:"p"},"Exists")," \u5355\u8bcd\u7684\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 2.6.0 +")," \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002")),(0,o.kt)("h2",{id:"981-\u5220\u9664\u4e00\u4e2a\u5b9e\u4f53\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.8.1 \u5220\u9664\u4e00\u4e2a\u5b9e\u4f53\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.Delete(user);\n\n// \u793a\u4f8b\u4e8c\nuser.Delete();\n\n// \u793a\u4f8b\u4e09\nrepository.ChangeEntityState(user, EntityState.Deleted);\n\n// \u793a\u4f8b\u56db\nrepository.Entities.Remove(user);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.DeleteAsync(user);\n\n// \u793a\u4f8b\u4e8c\nawait user.DeleteAsync();\n")),(0,o.kt)("h2",{id:"982-\u5220\u9664\u4e00\u4e2a\u5b9e\u4f53\u7acb\u5373\u63d0\u4ea4"},"9.8.2 \u5220\u9664\u4e00\u4e2a\u5b9e\u4f53\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.DeleteNow(user);\n\n// \u793a\u4f8b\u4e8c\nuser.DeleteNow();\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.DeleteNowAsync(user);\n\n// \u793a\u4f8b\u4e8c\nawait user.DeleteNowAsync();\n")),(0,o.kt)("h2",{id:"983-\u6839\u636e\u4e3b\u952e\u5220\u9664\u8bb0\u5f55\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.8.3 \u6839\u636e\u4e3b\u952e\u5220\u9664\u8bb0\u5f55\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.Delete(1);\n\n// \u793a\u4f8b\u4e8c\nuser.Delete(1);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.DeleteAsync(1);\n\n// \u793a\u4f8b\u4e8c\nawait user.DeleteAsync(1);\n")),(0,o.kt)("h2",{id:"984-\u6839\u636e\u4e3b\u952e\u5220\u9664\u8bb0\u5f55\u7acb\u5373\u63d0\u4ea4"},"9.8.4 \u6839\u636e\u4e3b\u952e\u5220\u9664\u8bb0\u5f55\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.DeleteNow(1);\n\n// \u793a\u4f8b\u4e8c\nuser.DeleteNow(1);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.DeleteNowAsync(1);\n\n// \u793a\u4f8b\u4e8c\nawait user.DeleteNowAsync(1);\n")),(0,o.kt)("h2",{id:"985-\u6570\u636e\u5b58\u5728\u624d\u6839\u636e\u4e3b\u952e\u5220\u9664\u4e0d\u7acb\u5373\u63d0\u4ea4"},"9.8.5 \u6570\u636e\u5b58\u5728\u624d\u6839\u636e\u4e3b\u952e\u5220\u9664\uff08\u4e0d\u7acb\u5373\u63d0\u4ea4\uff09"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.DeleteExists(1);\n\n// \u793a\u4f8b\u4e8c\nuser.DeleteExists(1);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.DeleteExistsAsync(1);\n\n// \u793a\u4f8b\u4e8c\nawait user.DeleteExistsAsync(1);\n")),(0,o.kt)("h2",{id:"986-\u6570\u636e\u5b58\u5728\u624d\u6839\u636e\u4e3b\u952e\u5220\u9664\u7acb\u5373\u63d0\u4ea4"},"9.8.6 \u6570\u636e\u5b58\u5728\u624d\u6839\u636e\u4e3b\u952e\u5220\u9664\uff08\u7acb\u5373\u63d0\u4ea4\uff09"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.DeleteExistsNow(1);\n\n// \u793a\u4f8b\u4e8c\nuser.DeleteExistsNow(1);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.DeleteExistsNowAsync(1);\n\n// \u793a\u4f8b\u4e8c\nawait user.DeleteExistsNowAsync(1);\n")),(0,o.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u6240\u6709\u5e26 ",(0,o.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u8868\u793a\u7acb\u5373\u63d0\u4ea4\u5230\u6570\u636e\u5e93\uff0c\u4e5f\u5c31\u662f\u7acb\u5373\u8c03\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216 ",(0,o.kt)("inlineCode",{parentName:"p"},"SaveChangesAsync"),"\u3002")),(0,o.kt)("h2",{id:"987-\u5047\u5220\u9664\u8f6f\u5220\u9664"},"9.8.7 \u5047\u5220\u9664/\u8f6f\u5220\u9664"),(0,o.kt)("admonition",{title:"\u529f\u80fd\u79fb\u9664\u58f0\u660e",type:"warning"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion 2.10 +")," \u7248\u672c\u4e2d\u5df2\u79fb\u9664\u3002")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u53ef\u4ee5\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"[FakeDelete]")," \u7279\u6027\u6807\u8bb0\u5047\u5220\u9664\u7279\u6027\uff0c\u5982\uff1a"),(0,o.kt)("h3",{id:"9871-\u6dfb\u52a0-fakedelete-\u6807\u8bb0"},"9.8.7.1 \u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"h3"},"[FakeDelete]")," \u6807\u8bb0"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public class Model: IEntity\n{\n [FakeDelete(true)] // \u8bbe\u7f6e\u5047\u5220\u9664\u7684\u503c\n public bool IsDeleted { get; set; }\n}\n")),(0,o.kt)("admonition",{type:"note"},(0,o.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"[FakeDelete]"),(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("strong",{parentName:"p"},"[FakeDelete]")," \u5c5e\u6027\u62e5\u6709\u5e26\u4e00\u4e2a\u53c2\u6570\u7684\u6784\u9020\u51fd\u6570\uff0c\u8fd9\u4e2a\u53c2\u6570\u662f\u5047\u5220\u9664\u7684\u503c")),(0,o.kt)("h3",{id:"9872-\u5047\u5220\u9664\u4f7f\u7528"},"9.8.7.2 \u5047\u5220\u9664\u4f7f\u7528"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nrepository.FakeDelete(entity);\n\n// \u793a\u4f8b\u4e8c\nrepository.FakeDeleteNow(entity);\n\n// \u793a\u4f8b\u4e09\nrepository.FakeDelete(1);\n\n// \u793a\u4f8b\u56db\nrepository.FakeDeleteNow(1);\n\n// \u793a\u4f8b\u4e94\nentity.FakeDelete();\n\n// \u793a\u4f8b\u516d\nrepository.UpdateInclude(user, u => u.IsDeleted);\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nawait repository.FakeDeleteAsync(entity);\n\n// \u793a\u4f8b\u4e8c\nawait repository.FakeDeleteNowAsync(entity);\n\n// \u793a\u4f8b\u4e09\nawait repository.FakeDeleteAsync(1);\n\n// \u793a\u4f8b\u56db\nawait repository.FakeDeleteNowAsync(1);\n\n// \u793a\u4f8b\u4e94\nawait entity.FakeDeleteAsync();\n\n// \u793a\u4f8b\u516d\nawait repository.UpdateIncludeAsync(user, u => u.IsDeleted);\n")),(0,o.kt)("h2",{id:"988-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.8.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/8a0794d9.a10e91de.js b/handbook/build/assets/js/8a0794d9.a10e91de.js new file mode 100644 index 0000000000..df90bd1ef0 --- /dev/null +++ b/handbook/build/assets/js/8a0794d9.a10e91de.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[2362],{3905:function(t,e,a){a.d(e,{Zo:function(){return u},kt:function(){return c}});var n=a(7294);function r(t,e,a){return e in t?Object.defineProperty(t,e,{value:a,enumerable:!0,configurable:!0,writable:!0}):t[e]=a,t}function i(t,e){var a=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),a.push.apply(a,n)}return a}function l(t){for(var e=1;e=0||(r[a]=t[a]);return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(t,a)&&(r[a]=t[a])}return r}var o=n.createContext({}),g=function(t){var e=n.useContext(o),a=e;return t&&(a="function"==typeof t?t(e):l(l({},e),t)),a},u=function(t){var e=g(t.components);return n.createElement(o.Provider,{value:e},t.children)},s={inlineCode:"code",wrapper:function(t){var e=t.children;return n.createElement(n.Fragment,{},e)}},m=n.forwardRef((function(t,e){var a=t.components,r=t.mdxType,i=t.originalType,o=t.parentName,u=p(t,["components","mdxType","originalType","parentName"]),m=g(a),c=r,k=m["".concat(o,".").concat(c)]||m[c]||s[c]||i;return a?n.createElement(k,l(l({ref:e},u),{},{components:a})):n.createElement(k,l({ref:e},u))}));function c(t,e){var a=arguments,r=e&&e.mdxType;if("string"==typeof t||r){var i=a.length,l=new Array(i);l[0]=m;var p={};for(var o in e)hasOwnProperty.call(e,o)&&(p[o]=e[o]);p.originalType=t,p.mdxType="string"==typeof t?t:r,l[1]=p;for(var g=2;gFurion + EFCore",id:"furion--efcore",level:4},{value:"Furion + SqlSugar",id:"furion--sqlsugar",level:4},{value:"\ud83c\udf4e \u6846\u67b6\u7279\u70b9",id:"-\u6846\u67b6\u7279\u70b9",level:2},{value:"\ud83e\udd5d \u529f\u80fd\u6a21\u5757",id:"-\u529f\u80fd\u6a21\u5757",level:2},{value:"\ud83e\udd50 \u6846\u67b6\u4f9d\u8d56",id:"-\u6846\u67b6\u4f9d\u8d56",level:2},{value:"\ud83e\udd57 \u73af\u5883\u8981\u6c42",id:"-\u73af\u5883\u8981\u6c42",level:2},{value:"\ud83e\udd6a \u652f\u6301\u5e73\u53f0",id:"-\u652f\u6301\u5e73\u53f0",level:2},{value:"\ud83c\udf56 \u5173\u4e8e\u6027\u80fd",id:"-\u5173\u4e8e\u6027\u80fd",level:2},{value:"\ud83c\udf7b \u8d21\u732e\u4ee3\u7801",id:"-\u8d21\u732e\u4ee3\u7801",level:2}],c={toc:m};function k(t){var e=t.components,a=(0,r.Z)(t,p);return(0,i.kt)("wrapper",(0,n.Z)({},c,a,{components:e,mdxType:"MDXLayout"}),(0,i.kt)("img",{src:(0,l.Z)("img/furionlogo.png"),height:"80",style:{margin:"0 auto",display:"block"}}),(0,i.kt)("div",{style:{textAlign:"center",marginTop:25}},(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/stargazers"},(0,i.kt)("img",{parentName:"a",src:"https://gitee.com/dotnetchina/Furion/badge/star.svg?theme=gvp",alt:"star"}))," ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/members"},(0,i.kt)("img",{parentName:"a",src:"https://gitee.com/dotnetchina/Furion/badge/fork.svg?theme=gvp",alt:"fork"}))," ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/MonkSoul/Furion/stargazers"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/github/stars/MonkSoul/Furion?logo=github",alt:"GitHub stars"}))," ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/MonkSoul/Furion/network"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/github/forks/MonkSoul/Furion?logo=github",alt:"GitHub forks"}))," ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/MonkSoul/Furion/blob/main/LICENSE"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/badge/license-MIT-orange",alt:"GitHub license"}))," ",(0,i.kt)("a",{parentName:"p",href:"https://www.nuget.org/packages/Furion"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.svg?cacheSeconds=10800",alt:"nuget"})))),(0,i.kt)("div",{style:{textAlign:"center"}},(0,i.kt)("p",null,"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002")),(0,i.kt)("h2",{id:"-\u5e8f\u8a00"},"\ud83d\udc90 \u5e8f\u8a00"),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u65e0\u79c1\u5949\u732e\u4e0d\u662f\u5929\u65b9\u591c\u8c2d\uff0c\u6709\u65f6\u5019\uff0c\u6211\u4eec\u4e5f\u53ef\u4ee5\u505a\u5230\u3002")),(0,i.kt)("h2",{id:"-\u540d\u5b57\u7684\u7531\u6765"},"\ud83c\udf55 \u540d\u5b57\u7684\u7531\u6765"),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u6545\u4e8b\u662f\u8fd9\u6837\u5b50\u7684\uff1a"),(0,i.kt)("p",{parentName:"blockquote"},"\u81ea\u5fae\u8f6f\u5ba3\u5e03 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 5")," \u5e73\u53f0\u6d88\u606f\u4e4b\u540e\uff0c\u5c31\u7422\u78e8\u7740\u5f00\u53d1\u4e00\u4e2a\u57fa\u4e8e ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 5")," \u5e73\u53f0\u7684\u5f00\u53d1\u6846\u67b6\uff0c\u60f3\u505a\u7b2c\u4e00\u4e2a\u5403 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 5")," \u8783\u87f9\u5c1d\u9c9c\u4e4b\u4eba\u3002"),(0,i.kt)("p",{parentName:"blockquote"},"\u4e00\u5f00\u59cb\u60f3\u5230\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Lazier")," \u4f5c\u4e3a\u6846\u67b6\u7684\u540d\u79f0\uff0c\u4e2d\u6587\u6709 ",(0,i.kt)("strong",{parentName:"p"},"\u66f4\u61d2")," \u7684\u610f\u601d\u3002\u7b26\u5408\u6211\u7684 \u201c\u4e00\u5207\u4ece\u7b80\uff0c\u53ea\u4e3a\u4e86\u66f4\u61d2\u201d \u7684\u5f00\u53d1\u7406\u5ff5\u3002"),(0,i.kt)("p",{parentName:"blockquote"},"\u4f46\u662f ",(0,i.kt)("strong",{parentName:"p"},"\u66f4\u61d2")," \u548c ",(0,i.kt)("strong",{parentName:"p"},"\u66f4\u70c2")," \u4e2d\u6587\u8bfb\u97f3\u76f8\u8fd1\u4e14\u6ca1\u6709\u7279\u8272\uff0c\u800c\u4e14\u5bd3\u610f\u4e5f\u4e0d\u662f\u5f88\u597d\uff0c\u5bf9\u6b64\u6362\u540d\u95ee\u9898\u82e6\u607c\u4e86\u597d\u4e9b\u5929\u3002"),(0,i.kt)("p",{parentName:"blockquote"},"\u521a\u597d\u6709\u4e00\u6b21\u5728 QQ \u7fa4\u4e2d\u65e0\u610f\u95f4\u5237\u5230\u4e86\u7fa4\u53cb\u53d1\u7684 ",(0,i.kt)("strong",{parentName:"p"},"\u201c\u5148\u77e5\u201d")," \u5355\u8bcd\uff1a",(0,i.kt)("strong",{parentName:"p"},"\u201c",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion [fu:r\u026a\u0259n]"),"\u201d"),"\uff0c\u5c31\u90a3\u4e00\u523b\uff0c\u5c31\u8ba4\u5b9a\u5b83\u4e86\uff01"),(0,i.kt)("p",{parentName:"blockquote"},(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e2d\u6587\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5148\u77e5")," \u7684\u610f\u601d\uff0c\u6070\u597d\u7b26\u5408\u6211\u521b\u9020\u6846\u67b6\u7684\u521d\u8877\u3002\u6240\u4ee5\uff0c",(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"Furion"))," \u5c31\u8bde\u751f\u4e86\u3002")),(0,i.kt)("h2",{id:"-\u6587\u6863\u5730\u5740"},"\ud83c\udf5f \u6587\u6863\u5730\u5740"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u56fd\u5185\u6587\u6863\uff1a",(0,i.kt)("a",{parentName:"li",href:"https://dotnetchina.gitee.io/furion"},"https://dotnetchina.gitee.io/furion")),(0,i.kt)("li",{parentName:"ul"},"\u56fd\u5916\u6587\u6863\uff1a",(0,i.kt)("a",{parentName:"li",href:"https://furion.icu"},"https://furion.icu"))),(0,i.kt)("h2",{id:"-\u5f00\u6e90\u5730\u5740"},"\ud83c\udf2d \u5f00\u6e90\u5730\u5740"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Gitee\uff1a",(0,i.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion"},"https://gitee.com/dotnetchina/Furion")),(0,i.kt)("li",{parentName:"ul"},"GitHub\uff1a",(0,i.kt)("a",{parentName:"li",href:"https://github.com/monksoul/Furion"},"https://github.com/monksoul/Furion")),(0,i.kt)("li",{parentName:"ul"},"Nuget\uff1a",(0,i.kt)("a",{parentName:"li",href:"https://www.nuget.org/packages/Furion"},"https://www.nuget.org/packages/Furion"))),(0,i.kt)("h2",{id:"-\u6846\u67b6\u62d3\u5c55\u5305"},"\ud83e\udd65 \u6846\u67b6\u62d3\u5c55\u5305"),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:"center"},"\u5305\u7c7b\u578b"),(0,i.kt)("th",{parentName:"tr",align:null},"\u540d\u79f0"),(0,i.kt)("th",{parentName:"tr",align:"center"},"\u7248\u672c"),(0,i.kt)("th",{parentName:"tr",align:null},"\u63cf\u8ff0"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion \u6838\u5fc3\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Pure"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Pure"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Pure"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Pure.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion \u7eaf\u51c0\u7248\u5305\uff08\u4e0d\u542b EFCore\uff09")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.Authentication.JwtBearer"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Extras.Authentication.JwtBearer"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.Authentication.JwtBearer"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Extras.Authentication.JwtBearer.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion Jwt \u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DependencyModel.CodeAnalysis"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Extras.DependencyModel.CodeAnalysis"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DependencyModel.CodeAnalysis"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Extras.DependencyModel.CodeAnalysis.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion CodeAnalysis \u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.ObjectMapper.Mapster"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Extras.ObjectMapper.Mapster"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.ObjectMapper.Mapster"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Extras.ObjectMapper.Mapster.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion Mapster \u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DatabaseAccessor.SqlSugar"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Extras.DatabaseAccessor.SqlSugar"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DatabaseAccessor.SqlSugar"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Extras.DatabaseAccessor.SqlSugar.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion SqlSugar \u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DatabaseAccessor.Dapper"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Extras.DatabaseAccessor.Dapper"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DatabaseAccessor.Dapper"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Extras.DatabaseAccessor.Dapper.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion Dapper \u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DatabaseAccessor.MongoDB"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Extras.DatabaseAccessor.MongoDB"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DatabaseAccessor.MongoDB"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Extras.DatabaseAccessor.MongoDB.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion MongoDB \u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.Logging.Serilog"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Extras.Logging.Serilog"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.Logging.Serilog"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Extras.Logging.Serilog.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion Serilog \u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Xunit"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Xunit"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Xunit"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Xunit.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion Xunit \u5355\u5143\u6d4b\u8bd5\u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Pure.Xunit"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Pure.Xunit"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Pure.Xunit"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Pure.Xunit.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion \u7eaf\u51c0\u7248\u5305 Xunit \u5355\u5143\u6d4b\u8bd5\u62d3\u5c55\u5305\uff08\u4e0d\u542b EFCore\uff09")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Tools.CommandLine"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Tools.CommandLine"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Tools.CommandLine"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Tools.CommandLine.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion Tools \u547d\u4ee4\u884c\u53c2\u6570\u89e3\u6790")))),(0,i.kt)("h2",{id:"-\u6846\u67b6\u811a\u624b\u67b6"},"\ud83c\udf44 \u6846\u67b6\u811a\u624b\u67b6"),(0,i.kt)("h4",{id:"furion--efcore"},(0,i.kt)("inlineCode",{parentName:"h4"},"Furion + EFCore")),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:"center"},"\u6a21\u677f\u7c7b\u578b"),(0,i.kt)("th",{parentName:"tr",align:null},"\u540d\u79f0"),(0,i.kt)("th",{parentName:"tr",align:"center"},"\u7248\u672c"),(0,i.kt)("th",{parentName:"tr",align:null},"\u63cf\u8ff0"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Mvc/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Template.Mvc"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Mvc/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Mvc.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Mvc \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Api/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Template.Api"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Api/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Api.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"WebApi \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.App/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Template.App"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.App/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.App.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Mvc/WebApi \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Razor/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Template.Razor"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Razor/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Razor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"RazorPages \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.RazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Template.RazorWithWebApi"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.RazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.RazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"RazorPages/WebApi \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Blazor/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Template.Blazor"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Blazor/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Blazor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Blazor \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.BlazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Template.BlazorWithWebApi"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.BlazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.BlazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Blazor/WebApi \u6a21\u677f")))),(0,i.kt)("h4",{id:"furion--sqlsugar"},(0,i.kt)("inlineCode",{parentName:"h4"},"Furion + SqlSugar")),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:"center"},"\u6a21\u677f\u7c7b\u578b"),(0,i.kt)("th",{parentName:"tr",align:null},"\u540d\u79f0"),(0,i.kt)("th",{parentName:"tr",align:"center"},"\u7248\u672c"),(0,i.kt)("th",{parentName:"tr",align:null},"\u63cf\u8ff0"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Mvc/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Mvc"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Mvc/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Mvc.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Mvc \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Api/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Api"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Api/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Api.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"WebApi \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.App/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.App"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.App/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.App.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Mvc/WebApi \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Razor/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Razor"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Razor/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Razor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"RazorPages \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.RazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.RazorWithWebApi"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.RazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.RazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"RazorPages/WebApi \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Blazor/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Blazor"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Blazor/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Blazor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Blazor \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.BlazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.BlazorWithWebApi"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.BlazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.BlazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Blazor/WebApi \u6a21\u677f")))),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("a",{parentName:"strong",href:"https://dotnetchina.gitee.io/furion/docs/template"},"\u5982\u4f55\u4f7f\u7528\u811a\u624b\u67b6"))),(0,i.kt)("h2",{id:"-\u6846\u67b6\u7279\u70b9"},"\ud83c\udf4e \u6846\u67b6\u7279\u70b9"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u5168\u65b0\u9762\u8c8c\uff1a\u57fa\u4e8e ",(0,i.kt)("inlineCode",{parentName:"li"},".NET5+")," \u5e73\u53f0\uff0c\u6ca1\u6709\u5386\u53f2\u5305\u88b1"),(0,i.kt)("li",{parentName:"ul"},"\u6781\u5c11\u4f9d\u8d56\uff1a\u6846\u67b6\u53ea\u4f9d\u8d56\u4e24\u4e2a\u7b2c\u4e09\u65b9\u5305"),(0,i.kt)("li",{parentName:"ul"},"\u6781\u6613\u5165\u95e8\uff1a\u53ea\u9700\u8981\u4e00\u4e2a ",(0,i.kt)("inlineCode",{parentName:"li"},"Inject()")," \u5373\u53ef\u5b8c\u6210\u914d\u7f6e"),(0,i.kt)("li",{parentName:"ul"},"\u6781\u901f\u5f00\u53d1\uff1a\u5185\u7f6e\u4e30\u5bcc\u7684\u4f01\u4e1a\u5e94\u7528\u5f00\u53d1\u529f\u80fd"),(0,i.kt)("li",{parentName:"ul"},"\u6781\u5176\u7075\u6d3b\uff1a\u8f7b\u677e\u9762\u5bf9\u591a\u53d8\u590d\u6742\u7684\u9700\u6c42"),(0,i.kt)("li",{parentName:"ul"},"\u6781\u6613\u7ef4\u62a4\uff1a\u91c7\u7528\u72ec\u7279\u7684\u67b6\u6784\u601d\u60f3\uff0c\u53ea\u4e3a\u957f\u4e45\u7ef4\u62a4\u8bbe\u8ba1"),(0,i.kt)("li",{parentName:"ul"},"\u5b8c\u6574\u6587\u6863\uff1a\u63d0\u4f9b\u5b8c\u5584\u7684\u5f00\u53d1\u6587\u6863"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u8de8\u5168\u5e73\u53f0\uff1a\u652f\u6301\u6240\u6709\u4e3b\u6d41\u64cd\u4f5c\u7cfb\u7edf\u53ca .NET \u5168\u90e8\u9879\u76ee\u7c7b\u578b"))),(0,i.kt)("h2",{id:"-\u529f\u80fd\u6a21\u5757"},"\ud83e\udd5d \u529f\u80fd\u6a21\u5757"),(0,i.kt)("img",{src:(0,l.Z)("img/functions.png")}),(0,i.kt)("h2",{id:"-\u6846\u67b6\u4f9d\u8d56"},"\ud83e\udd50 \u6846\u67b6\u4f9d\u8d56"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e3a\u4e86\u8ffd\u6c42\u6781\u901f\u5165\u95e8\uff0c\u6781\u81f4\u6027\u80fd\uff0c\u5c3d\u53ef\u80fd\u7684\u4e0d\u4f7f\u7528\u6216\u51cf\u5c11\u7b2c\u4e09\u65b9\u4f9d\u8d56\u3002\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4ec5\u96c6\u6210\u4e86\u4ee5\u4e0b\u4e24\u4e2a\u4f9d\u8d56\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/MiniProfiler/dotnet"},"MiniProfiler"),"\uff1a\u6027\u80fd\u5206\u6790\u548c\u76d1\u542c\u5fc5\u5907"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/domaindrivendev/Swashbuckle.AspNetCore"},"Swashbuckle"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Swagger")," \u63a5\u53e3\u6587\u6863")),(0,i.kt)("p",null,"\u9ebb\u96c0\u867d\u5c0f\u4e94\u810f\u4ff1\u5168\u3002",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u5373\u4f7f\u53ea\u96c6\u6210\u4e86\u8fd9\u4e24\u4e2a\u4f9d\u8d56\uff0c\u4f46\u662f\u4e3b\u6d41\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"AOP")," \u9762\u5411\u5207\u9762\u7f16\u7a0b\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"\u4e8b\u4ef6\u603b\u7ebf"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"\u6570\u636e\u9a8c\u8bc1"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"\u6570\u636e\u5e93\u64cd\u4f5c")," \u7b49\u7b49\u4e00\u4e2a\u90fd\u4e0d\u5c11\u3002"),(0,i.kt)("h2",{id:"-\u73af\u5883\u8981\u6c42"},"\ud83e\udd57 \u73af\u5883\u8981\u6c42"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Visual Studio 2019 16.8 +"),(0,i.kt)("li",{parentName:"ul"},".NET 5 SDK +"),(0,i.kt)("li",{parentName:"ul"},".Net Standard 2.1 +")),(0,i.kt)("h2",{id:"-\u652f\u6301\u5e73\u53f0"},"\ud83e\udd6a \u652f\u6301\u5e73\u53f0"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u8fd0\u884c\u73af\u5883",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"Windows"),(0,i.kt)("li",{parentName:"ul"},"Linux"),(0,i.kt)("li",{parentName:"ul"},"MacOS/MacOS M1 CPU"),(0,i.kt)("li",{parentName:"ul"},"Docker/K8S/K3S/Rancher"),(0,i.kt)("li",{parentName:"ul"},"Xamarin/MAUI"))),(0,i.kt)("li",{parentName:"ul"},"\u6570\u636e\u5e93",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"SqlServer"),(0,i.kt)("li",{parentName:"ul"},"Sqlite"),(0,i.kt)("li",{parentName:"ul"},"Azure Cosmos"),(0,i.kt)("li",{parentName:"ul"},"MySql"),(0,i.kt)("li",{parentName:"ul"},"MariaDB"),(0,i.kt)("li",{parentName:"ul"},"PostgreSQL"),(0,i.kt)("li",{parentName:"ul"},"InMemoryDatabase"),(0,i.kt)("li",{parentName:"ul"},"Oracle"),(0,i.kt)("li",{parentName:"ul"},"Firebird"),(0,i.kt)("li",{parentName:"ul"},"\u8fbe\u68a6\u6570\u636e\u5e93"),(0,i.kt)("li",{parentName:"ul"},"MongoDB"))),(0,i.kt)("li",{parentName:"ul"},"\u5e94\u7528\u90e8\u7f72",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"Kestrel"),(0,i.kt)("li",{parentName:"ul"},"Nginx"),(0,i.kt)("li",{parentName:"ul"},"Jexus"),(0,i.kt)("li",{parentName:"ul"},"IIS"),(0,i.kt)("li",{parentName:"ul"},"Apache"),(0,i.kt)("li",{parentName:"ul"},"PM2"),(0,i.kt)("li",{parentName:"ul"},"Supervisor"),(0,i.kt)("li",{parentName:"ul"},"\u72ec\u7acb\u53d1\u5e03/\u5355\u6587\u4ef6"),(0,i.kt)("li",{parentName:"ul"},"\u5bb9\u5668\uff08Docker/K8S/K3S/Rancher/PodMan\uff09")))),(0,i.kt)("h2",{id:"-\u5173\u4e8e\u6027\u80fd"},"\ud83c\udf56 \u5173\u4e8e\u6027\u80fd"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u76ee\u524d\u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 16.8")," \u81ea\u5e26\u6027\u80fd\u6d4b\u8bd5\u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"JMeter")," \u8fdb\u884c\u6d4b\u8bd5\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u53ea\u8d34\u90e8\u5206\u6d4b\u8bd5\u56fe\uff0c\u6d4b\u8bd5\u7ed3\u679c\u5982\u4e0b\uff1a"),(0,i.kt)("img",{src:(0,l.Z)("img/xncs.png")}),(0,i.kt)("h2",{id:"-\u8d21\u732e\u4ee3\u7801"},"\ud83c\udf7b \u8d21\u732e\u4ee3\u7801"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u9075\u5faa ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/blob/net6/LICENSE"},"MIT")," \u5f00\u6e90\u534f\u8bae\uff0c\u6b22\u8fce\u5927\u5bb6\u63d0\u4ea4 ",(0,i.kt)("inlineCode",{parentName:"p"},"PR")," \u6216 ",(0,i.kt)("inlineCode",{parentName:"p"},"Issue"),"\u3002"),(0,i.kt)("p",null,"\u5982\u679c\u8981\u4e3a\u9879\u76ee\u505a\u51fa\u8d21\u732e\uff0c\u8bf7\u67e5\u770b ",(0,i.kt)("a",{parentName:"p",href:"/docs/contribute"},"\u8d21\u732e\u6307\u5357"),"\u3002\u611f\u8c22\u6bcf\u4e00\u4f4d\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u8d21\u732e\u4ee3\u7801\u7684\u670b\u53cb\u3002"))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/8a0794d9.ccc96964.js b/handbook/build/assets/js/8a0794d9.ccc96964.js deleted file mode 100644 index 0d6ba16873..0000000000 --- a/handbook/build/assets/js/8a0794d9.ccc96964.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[2362],{7753:function(t,e,a){a.r(e),a.d(e,{assets:function(){return s},contentTitle:function(){return g},default:function(){return k},frontMatter:function(){return o},metadata:function(){return u},toc:function(){return m}});var n=a(3117),r=a(102),i=(a(7294),a(3905)),l=a(1402),p=["components"],o={id:"introduce",title:"1.1 \u4ecb\u7ecd",sidebar_label:"1.1 \u4ecb\u7ecd",slug:"/"},g=void 0,u={unversionedId:"introduce",id:"introduce",title:"1.1 \u4ecb\u7ecd",description:"",source:"@site/docs/introduce.mdx",sourceDirName:".",slug:"/",permalink:"/furion/docs/",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/introduce.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1659326900,formattedLastUpdatedAt:"Aug 1, 2022",frontMatter:{id:"introduce",title:"1.1 \u4ecb\u7ecd",sidebar_label:"1.1 \u4ecb\u7ecd",slug:"/"},sidebar:"docs",next:{title:"1.2 \u5173\u4e8e\u4f5c\u8005",permalink:"/furion/docs/author"}},s={},m=[{value:"\ud83d\udc90 \u5e8f\u8a00",id:"-\u5e8f\u8a00",level:2},{value:"\ud83c\udf55 \u540d\u5b57\u7684\u7531\u6765",id:"-\u540d\u5b57\u7684\u7531\u6765",level:2},{value:"\ud83c\udf5f \u6587\u6863\u5730\u5740",id:"-\u6587\u6863\u5730\u5740",level:2},{value:"\ud83c\udf2d \u5f00\u6e90\u5730\u5740",id:"-\u5f00\u6e90\u5730\u5740",level:2},{value:"\ud83e\udd65 \u6846\u67b6\u62d3\u5c55\u5305",id:"-\u6846\u67b6\u62d3\u5c55\u5305",level:2},{value:"\ud83c\udf44 \u6846\u67b6\u811a\u624b\u67b6",id:"-\u6846\u67b6\u811a\u624b\u67b6",level:2},{value:"Furion + EFCore",id:"furion--efcore",level:4},{value:"Furion + SqlSugar",id:"furion--sqlsugar",level:4},{value:"\ud83c\udf4e \u6846\u67b6\u7279\u70b9",id:"-\u6846\u67b6\u7279\u70b9",level:2},{value:"\ud83e\udd5d \u529f\u80fd\u6a21\u5757",id:"-\u529f\u80fd\u6a21\u5757",level:2},{value:"\ud83e\udd50 \u6846\u67b6\u4f9d\u8d56",id:"-\u6846\u67b6\u4f9d\u8d56",level:2},{value:"\ud83e\udd57 \u73af\u5883\u8981\u6c42",id:"-\u73af\u5883\u8981\u6c42",level:2},{value:"\ud83e\udd6a \u652f\u6301\u5e73\u53f0",id:"-\u652f\u6301\u5e73\u53f0",level:2},{value:"\ud83c\udf56 \u5173\u4e8e\u6027\u80fd",id:"-\u5173\u4e8e\u6027\u80fd",level:2},{value:"\ud83c\udf7b \u8d21\u732e\u4ee3\u7801",id:"-\u8d21\u732e\u4ee3\u7801",level:2}],c={toc:m};function k(t){var e=t.components,a=(0,r.Z)(t,p);return(0,i.kt)("wrapper",(0,n.Z)({},c,a,{components:e,mdxType:"MDXLayout"}),(0,i.kt)("img",{src:(0,l.Z)("img/furionlogo.png"),height:"80",style:{margin:"0 auto",display:"block"}}),(0,i.kt)("div",{style:{textAlign:"center",marginTop:25}},(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/stargazers"},(0,i.kt)("img",{parentName:"a",src:"https://gitee.com/dotnetchina/Furion/badge/star.svg?theme=gvp",alt:"star"}))," ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/members"},(0,i.kt)("img",{parentName:"a",src:"https://gitee.com/dotnetchina/Furion/badge/fork.svg?theme=gvp",alt:"fork"}))," ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/MonkSoul/Furion/stargazers"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/github/stars/MonkSoul/Furion?logo=github",alt:"GitHub stars"}))," ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/MonkSoul/Furion/network"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/github/forks/MonkSoul/Furion?logo=github",alt:"GitHub forks"}))," ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/MonkSoul/Furion/blob/main/LICENSE"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/badge/license-MIT-orange",alt:"GitHub license"}))," ",(0,i.kt)("a",{parentName:"p",href:"https://www.nuget.org/packages/Furion"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.svg?cacheSeconds=10800",alt:"nuget"})))),(0,i.kt)("div",{style:{textAlign:"center"}},(0,i.kt)("p",null,"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002")),(0,i.kt)("h2",{id:"-\u5e8f\u8a00"},"\ud83d\udc90 \u5e8f\u8a00"),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u65e0\u79c1\u5949\u732e\u4e0d\u662f\u5929\u65b9\u591c\u8c2d\uff0c\u6709\u65f6\u5019\uff0c\u6211\u4eec\u4e5f\u53ef\u4ee5\u505a\u5230\u3002")),(0,i.kt)("h2",{id:"-\u540d\u5b57\u7684\u7531\u6765"},"\ud83c\udf55 \u540d\u5b57\u7684\u7531\u6765"),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u6545\u4e8b\u662f\u8fd9\u6837\u5b50\u7684\uff1a"),(0,i.kt)("p",{parentName:"blockquote"},"\u81ea\u5fae\u8f6f\u5ba3\u5e03 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 5")," \u5e73\u53f0\u6d88\u606f\u4e4b\u540e\uff0c\u5c31\u7422\u78e8\u7740\u5f00\u53d1\u4e00\u4e2a\u57fa\u4e8e ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 5")," \u5e73\u53f0\u7684\u5f00\u53d1\u6846\u67b6\uff0c\u60f3\u505a\u7b2c\u4e00\u4e2a\u5403 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 5")," \u8783\u87f9\u5c1d\u9c9c\u4e4b\u4eba\u3002"),(0,i.kt)("p",{parentName:"blockquote"},"\u4e00\u5f00\u59cb\u60f3\u5230\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Lazier")," \u4f5c\u4e3a\u6846\u67b6\u7684\u540d\u79f0\uff0c\u4e2d\u6587\u6709 ",(0,i.kt)("strong",{parentName:"p"},"\u66f4\u61d2")," \u7684\u610f\u601d\u3002\u7b26\u5408\u6211\u7684 \u201c\u4e00\u5207\u4ece\u7b80\uff0c\u53ea\u4e3a\u4e86\u66f4\u61d2\u201d \u7684\u5f00\u53d1\u7406\u5ff5\u3002"),(0,i.kt)("p",{parentName:"blockquote"},"\u4f46\u662f ",(0,i.kt)("strong",{parentName:"p"},"\u66f4\u61d2")," \u548c ",(0,i.kt)("strong",{parentName:"p"},"\u66f4\u70c2")," \u4e2d\u6587\u8bfb\u97f3\u76f8\u8fd1\u4e14\u6ca1\u6709\u7279\u8272\uff0c\u800c\u4e14\u5bd3\u610f\u4e5f\u4e0d\u662f\u5f88\u597d\uff0c\u5bf9\u6b64\u6362\u540d\u95ee\u9898\u82e6\u607c\u4e86\u597d\u4e9b\u5929\u3002"),(0,i.kt)("p",{parentName:"blockquote"},"\u521a\u597d\u6709\u4e00\u6b21\u5728 QQ \u7fa4\u4e2d\u65e0\u610f\u95f4\u5237\u5230\u4e86\u7fa4\u53cb\u53d1\u7684 ",(0,i.kt)("strong",{parentName:"p"},"\u201c\u5148\u77e5\u201d")," \u5355\u8bcd\uff1a",(0,i.kt)("strong",{parentName:"p"},"\u201c",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion [fu:r\u026a\u0259n]"),"\u201d"),"\uff0c\u5c31\u90a3\u4e00\u523b\uff0c\u5c31\u8ba4\u5b9a\u5b83\u4e86\uff01"),(0,i.kt)("p",{parentName:"blockquote"},(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e2d\u6587\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5148\u77e5")," \u7684\u610f\u601d\uff0c\u6070\u597d\u7b26\u5408\u6211\u521b\u9020\u6846\u67b6\u7684\u521d\u8877\u3002\u6240\u4ee5\uff0c",(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("inlineCode",{parentName:"strong"},"Furion"))," \u5c31\u8bde\u751f\u4e86\u3002")),(0,i.kt)("h2",{id:"-\u6587\u6863\u5730\u5740"},"\ud83c\udf5f \u6587\u6863\u5730\u5740"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u56fd\u5185\u6587\u6863\uff1a",(0,i.kt)("a",{parentName:"li",href:"https://dotnetchina.gitee.io/furion"},"https://dotnetchina.gitee.io/furion")),(0,i.kt)("li",{parentName:"ul"},"\u56fd\u5916\u6587\u6863\uff1a",(0,i.kt)("a",{parentName:"li",href:"https://furion.icu"},"https://furion.icu"))),(0,i.kt)("h2",{id:"-\u5f00\u6e90\u5730\u5740"},"\ud83c\udf2d \u5f00\u6e90\u5730\u5740"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Gitee\uff1a",(0,i.kt)("a",{parentName:"li",href:"https://gitee.com/dotnetchina/Furion"},"https://gitee.com/dotnetchina/Furion")),(0,i.kt)("li",{parentName:"ul"},"GitHub\uff1a",(0,i.kt)("a",{parentName:"li",href:"https://github.com/monksoul/Furion"},"https://github.com/monksoul/Furion")),(0,i.kt)("li",{parentName:"ul"},"Nuget\uff1a",(0,i.kt)("a",{parentName:"li",href:"https://www.nuget.org/packages/Furion"},"https://www.nuget.org/packages/Furion"))),(0,i.kt)("h2",{id:"-\u6846\u67b6\u62d3\u5c55\u5305"},"\ud83e\udd65 \u6846\u67b6\u62d3\u5c55\u5305"),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:"center"},"\u5305\u7c7b\u578b"),(0,i.kt)("th",{parentName:"tr",align:null},"\u540d\u79f0"),(0,i.kt)("th",{parentName:"tr",align:"center"},"\u7248\u672c"),(0,i.kt)("th",{parentName:"tr",align:null},"\u63cf\u8ff0"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion \u6838\u5fc3\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Pure"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Pure"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Pure"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Pure.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion \u7eaf\u51c0\u7248\u5305\uff08\u4e0d\u542b EFCore\uff09")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.Authentication.JwtBearer"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Extras.Authentication.JwtBearer"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.Authentication.JwtBearer"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Extras.Authentication.JwtBearer.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion Jwt \u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DependencyModel.CodeAnalysis"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Extras.DependencyModel.CodeAnalysis"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DependencyModel.CodeAnalysis"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Extras.DependencyModel.CodeAnalysis.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion CodeAnalysis \u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.ObjectMapper.Mapster"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Extras.ObjectMapper.Mapster"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.ObjectMapper.Mapster"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Extras.ObjectMapper.Mapster.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion Mapster \u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DatabaseAccessor.SqlSugar"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Extras.DatabaseAccessor.SqlSugar"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DatabaseAccessor.SqlSugar"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Extras.DatabaseAccessor.SqlSugar.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion SqlSugar \u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DatabaseAccessor.Dapper"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Extras.DatabaseAccessor.Dapper"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DatabaseAccessor.Dapper"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Extras.DatabaseAccessor.Dapper.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion Dapper \u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DatabaseAccessor.MongoDB"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Extras.DatabaseAccessor.MongoDB"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.DatabaseAccessor.MongoDB"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Extras.DatabaseAccessor.MongoDB.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion MongoDB \u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.Logging.Serilog"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Extras.Logging.Serilog"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Extras.Logging.Serilog"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Extras.Logging.Serilog.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion Serilog \u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Xunit"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Xunit"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Xunit"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Xunit.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion Xunit \u5355\u5143\u6d4b\u8bd5\u62d3\u5c55\u5305")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Pure.Xunit"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Pure.Xunit"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Pure.Xunit"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Pure.Xunit.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion \u7eaf\u51c0\u7248\u5305 Xunit \u5355\u5143\u6d4b\u8bd5\u62d3\u5c55\u5305\uff08\u4e0d\u542b EFCore\uff09")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Tools.CommandLine"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-blue?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Tools.CommandLine"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Tools.CommandLine"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Tools.CommandLine.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion Tools \u547d\u4ee4\u884c\u53c2\u6570\u89e3\u6790")))),(0,i.kt)("h2",{id:"-\u6846\u67b6\u811a\u624b\u67b6"},"\ud83c\udf44 \u6846\u67b6\u811a\u624b\u67b6"),(0,i.kt)("h4",{id:"furion--efcore"},(0,i.kt)("inlineCode",{parentName:"h4"},"Furion + EFCore")),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:"center"},"\u6a21\u677f\u7c7b\u578b"),(0,i.kt)("th",{parentName:"tr",align:null},"\u540d\u79f0"),(0,i.kt)("th",{parentName:"tr",align:"center"},"\u7248\u672c"),(0,i.kt)("th",{parentName:"tr",align:null},"\u63cf\u8ff0"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Mvc/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Template.Mvc"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Mvc/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Mvc.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Mvc \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Api/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Template.Api"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Api/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Api.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"WebApi \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.App/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Template.App"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.App/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.App.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Mvc/WebApi \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Razor/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Template.Razor"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Razor/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Razor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"RazorPages \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.RazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Template.RazorWithWebApi"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.RazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.RazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"RazorPages/WebApi \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Blazor/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Template.Blazor"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.Blazor/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.Blazor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Blazor \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.BlazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.Template.BlazorWithWebApi"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.Template.BlazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.Template.BlazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Blazor/WebApi \u6a21\u677f")))),(0,i.kt)("h4",{id:"furion--sqlsugar"},(0,i.kt)("inlineCode",{parentName:"h4"},"Furion + SqlSugar")),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:"center"},"\u6a21\u677f\u7c7b\u578b"),(0,i.kt)("th",{parentName:"tr",align:null},"\u540d\u79f0"),(0,i.kt)("th",{parentName:"tr",align:"center"},"\u7248\u672c"),(0,i.kt)("th",{parentName:"tr",align:null},"\u63cf\u8ff0"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Mvc/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Mvc"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Mvc/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Mvc.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Mvc \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Api/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Api"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Api/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Api.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"WebApi \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.App/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.App"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.App/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.App.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Mvc/WebApi \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Razor/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Razor"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Razor/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Razor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"RazorPages \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.RazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.RazorWithWebApi"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.RazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.RazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"RazorPages/WebApi \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Blazor/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.Blazor"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.Blazor/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.Blazor.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Blazor \u6a21\u677f")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.BlazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://shields.io/badge/-Nuget-yellow?cacheSeconds=604800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Furion.SqlSugar.Template.BlazorWithWebApi"),(0,i.kt)("td",{parentName:"tr",align:"center"},(0,i.kt)("a",{parentName:"td",href:"https://www.nuget.org/packages/Furion.SqlSugar.Template.BlazorWithWebApi/"},(0,i.kt)("img",{parentName:"a",src:"https://img.shields.io/nuget/v/Furion.SqlSugar.Template.BlazorWithWebApi.svg?cacheSeconds=10800",alt:"nuget"}))),(0,i.kt)("td",{parentName:"tr",align:null},"Blazor/WebApi \u6a21\u677f")))),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("a",{parentName:"strong",href:"https://dotnetchina.gitee.io/furion/docs/template"},"\u5982\u4f55\u4f7f\u7528\u811a\u624b\u67b6"))),(0,i.kt)("h2",{id:"-\u6846\u67b6\u7279\u70b9"},"\ud83c\udf4e \u6846\u67b6\u7279\u70b9"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u5168\u65b0\u9762\u8c8c\uff1a\u57fa\u4e8e ",(0,i.kt)("inlineCode",{parentName:"li"},".NET5+")," \u5e73\u53f0\uff0c\u6ca1\u6709\u5386\u53f2\u5305\u88b1"),(0,i.kt)("li",{parentName:"ul"},"\u6781\u5c11\u4f9d\u8d56\uff1a\u6846\u67b6\u53ea\u4f9d\u8d56\u4e24\u4e2a\u7b2c\u4e09\u65b9\u5305"),(0,i.kt)("li",{parentName:"ul"},"\u6781\u6613\u5165\u95e8\uff1a\u53ea\u9700\u8981\u4e00\u4e2a ",(0,i.kt)("inlineCode",{parentName:"li"},"Inject()")," \u5373\u53ef\u5b8c\u6210\u914d\u7f6e"),(0,i.kt)("li",{parentName:"ul"},"\u6781\u901f\u5f00\u53d1\uff1a\u5185\u7f6e\u4e30\u5bcc\u7684\u4f01\u4e1a\u5e94\u7528\u5f00\u53d1\u529f\u80fd"),(0,i.kt)("li",{parentName:"ul"},"\u6781\u5176\u7075\u6d3b\uff1a\u8f7b\u677e\u9762\u5bf9\u591a\u53d8\u590d\u6742\u7684\u9700\u6c42"),(0,i.kt)("li",{parentName:"ul"},"\u6781\u6613\u7ef4\u62a4\uff1a\u91c7\u7528\u72ec\u7279\u7684\u67b6\u6784\u601d\u60f3\uff0c\u53ea\u4e3a\u957f\u4e45\u7ef4\u62a4\u8bbe\u8ba1"),(0,i.kt)("li",{parentName:"ul"},"\u5b8c\u6574\u6587\u6863\uff1a\u63d0\u4f9b\u5b8c\u5584\u7684\u5f00\u53d1\u6587\u6863"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u8de8\u5168\u5e73\u53f0\uff1a\u652f\u6301\u6240\u6709\u4e3b\u6d41\u64cd\u4f5c\u7cfb\u7edf\u53ca .NET \u5168\u90e8\u9879\u76ee\u7c7b\u578b"))),(0,i.kt)("h2",{id:"-\u529f\u80fd\u6a21\u5757"},"\ud83e\udd5d \u529f\u80fd\u6a21\u5757"),(0,i.kt)("img",{src:(0,l.Z)("img/functions.png")}),(0,i.kt)("h2",{id:"-\u6846\u67b6\u4f9d\u8d56"},"\ud83e\udd50 \u6846\u67b6\u4f9d\u8d56"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e3a\u4e86\u8ffd\u6c42\u6781\u901f\u5165\u95e8\uff0c\u6781\u81f4\u6027\u80fd\uff0c\u5c3d\u53ef\u80fd\u7684\u4e0d\u4f7f\u7528\u6216\u51cf\u5c11\u7b2c\u4e09\u65b9\u4f9d\u8d56\u3002\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4ec5\u96c6\u6210\u4e86\u4ee5\u4e0b\u4e24\u4e2a\u4f9d\u8d56\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/MiniProfiler/dotnet"},"MiniProfiler"),"\uff1a\u6027\u80fd\u5206\u6790\u548c\u76d1\u542c\u5fc5\u5907"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/domaindrivendev/Swashbuckle.AspNetCore"},"Swashbuckle"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Swagger")," \u63a5\u53e3\u6587\u6863")),(0,i.kt)("p",null,"\u9ebb\u96c0\u867d\u5c0f\u4e94\u810f\u4ff1\u5168\u3002",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u5373\u4f7f\u53ea\u96c6\u6210\u4e86\u8fd9\u4e24\u4e2a\u4f9d\u8d56\uff0c\u4f46\u662f\u4e3b\u6d41\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"AOP")," \u9762\u5411\u5207\u9762\u7f16\u7a0b\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"\u4e8b\u4ef6\u603b\u7ebf"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"\u6570\u636e\u9a8c\u8bc1"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"\u6570\u636e\u5e93\u64cd\u4f5c")," \u7b49\u7b49\u4e00\u4e2a\u90fd\u4e0d\u5c11\u3002"),(0,i.kt)("h2",{id:"-\u73af\u5883\u8981\u6c42"},"\ud83e\udd57 \u73af\u5883\u8981\u6c42"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Visual Studio 2019 16.8 +"),(0,i.kt)("li",{parentName:"ul"},".NET 5 SDK +"),(0,i.kt)("li",{parentName:"ul"},".Net Standard 2.1 +")),(0,i.kt)("h2",{id:"-\u652f\u6301\u5e73\u53f0"},"\ud83e\udd6a \u652f\u6301\u5e73\u53f0"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u8fd0\u884c\u73af\u5883",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"Windows"),(0,i.kt)("li",{parentName:"ul"},"Linux"),(0,i.kt)("li",{parentName:"ul"},"MacOS/MacOS M1 CPU"),(0,i.kt)("li",{parentName:"ul"},"Docker/K8S/K3S/Rancher"),(0,i.kt)("li",{parentName:"ul"},"Xamarin/MAUI"))),(0,i.kt)("li",{parentName:"ul"},"\u6570\u636e\u5e93",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"SqlServer"),(0,i.kt)("li",{parentName:"ul"},"Sqlite"),(0,i.kt)("li",{parentName:"ul"},"Azure Cosmos"),(0,i.kt)("li",{parentName:"ul"},"MySql"),(0,i.kt)("li",{parentName:"ul"},"MariaDB"),(0,i.kt)("li",{parentName:"ul"},"PostgreSQL"),(0,i.kt)("li",{parentName:"ul"},"InMemoryDatabase"),(0,i.kt)("li",{parentName:"ul"},"Oracle"),(0,i.kt)("li",{parentName:"ul"},"Firebird"),(0,i.kt)("li",{parentName:"ul"},"\u8fbe\u68a6\u6570\u636e\u5e93"),(0,i.kt)("li",{parentName:"ul"},"MongoDB"))),(0,i.kt)("li",{parentName:"ul"},"\u5e94\u7528\u90e8\u7f72",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"Kestrel"),(0,i.kt)("li",{parentName:"ul"},"Nginx"),(0,i.kt)("li",{parentName:"ul"},"Jexus"),(0,i.kt)("li",{parentName:"ul"},"IIS"),(0,i.kt)("li",{parentName:"ul"},"Apache"),(0,i.kt)("li",{parentName:"ul"},"PM2"),(0,i.kt)("li",{parentName:"ul"},"Supervisor"),(0,i.kt)("li",{parentName:"ul"},"\u72ec\u7acb\u53d1\u5e03/\u5355\u6587\u4ef6"),(0,i.kt)("li",{parentName:"ul"},"\u5bb9\u5668\uff08Docker/K8S/K3S/Rancher/PodMan\uff09")))),(0,i.kt)("h2",{id:"-\u5173\u4e8e\u6027\u80fd"},"\ud83c\udf56 \u5173\u4e8e\u6027\u80fd"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u76ee\u524d\u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 16.8")," \u81ea\u5e26\u6027\u80fd\u6d4b\u8bd5\u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"JMeter")," \u8fdb\u884c\u6d4b\u8bd5\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u53ea\u8d34\u90e8\u5206\u6d4b\u8bd5\u56fe\uff0c\u6d4b\u8bd5\u7ed3\u679c\u5982\u4e0b\uff1a"),(0,i.kt)("img",{src:(0,l.Z)("img/xncs.png")}),(0,i.kt)("h2",{id:"-\u8d21\u732e\u4ee3\u7801"},"\ud83c\udf7b \u8d21\u732e\u4ee3\u7801"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u9075\u5faa ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/blob/net6/LICENSE"},"MIT")," \u5f00\u6e90\u534f\u8bae\uff0c\u6b22\u8fce\u5927\u5bb6\u63d0\u4ea4 ",(0,i.kt)("inlineCode",{parentName:"p"},"PR")," \u6216 ",(0,i.kt)("inlineCode",{parentName:"p"},"Issue"),"\u3002"),(0,i.kt)("p",null,"\u5982\u679c\u8981\u4e3a\u9879\u76ee\u505a\u51fa\u8d21\u732e\uff0c\u8bf7\u67e5\u770b ",(0,i.kt)("a",{parentName:"p",href:"/docs/contribute"},"\u8d21\u732e\u6307\u5357"),"\u3002\u611f\u8c22\u6bcf\u4e00\u4f4d\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u8d21\u732e\u4ee3\u7801\u7684\u670b\u53cb\u3002"))}k.isMDXComponent=!0},3905:function(t,e,a){a.d(e,{Zo:function(){return u},kt:function(){return c}});var n=a(7294);function r(t,e,a){return e in t?Object.defineProperty(t,e,{value:a,enumerable:!0,configurable:!0,writable:!0}):t[e]=a,t}function i(t,e){var a=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),a.push.apply(a,n)}return a}function l(t){for(var e=1;e=0||(r[a]=t[a]);return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(t,a)&&(r[a]=t[a])}return r}var o=n.createContext({}),g=function(t){var e=n.useContext(o),a=e;return t&&(a="function"==typeof t?t(e):l(l({},e),t)),a},u=function(t){var e=g(t.components);return n.createElement(o.Provider,{value:e},t.children)},s={inlineCode:"code",wrapper:function(t){var e=t.children;return n.createElement(n.Fragment,{},e)}},m=n.forwardRef((function(t,e){var a=t.components,r=t.mdxType,i=t.originalType,o=t.parentName,u=p(t,["components","mdxType","originalType","parentName"]),m=g(a),c=r,k=m["".concat(o,".").concat(c)]||m[c]||s[c]||i;return a?n.createElement(k,l(l({ref:e},u),{},{components:a})):n.createElement(k,l({ref:e},u))}));function c(t,e){var a=arguments,r=e&&e.mdxType;if("string"==typeof t||r){var i=a.length,l=new Array(i);l[0]=m;var p={};for(var o in e)hasOwnProperty.call(e,o)&&(p[o]=e[o]);p.originalType=t,p.mdxType="string"==typeof t?t:r,l[1]=p;for(var g=2;gHttpContext",id:"16-\u83b7\u53d6-httpcontext",level:2},{value:"1.7 \u83b7\u53d6\u767b\u5f55\u7684 User \u5bf9\u8c61",id:"17-\u83b7\u53d6\u767b\u5f55\u7684-user-\u5bf9\u8c61",level:2},{value:"1.8 \u83b7\u53d6\u670d\u52a1\u63d0\u4f9b\u5668",id:"18-\u83b7\u53d6\u670d\u52a1\u63d0\u4f9b\u5668",level:2},{value:"1.9 \u89e3\u6790\u670d\u52a1",id:"19-\u89e3\u6790\u670d\u52a1",level:2},{value:"1.10 \u83b7\u53d6\u9009\u9879\u914d\u7f6e",id:"110-\u83b7\u53d6\u9009\u9879\u914d\u7f6e",level:2},{value:"1.11 \u6253\u5370\u6570\u636e\u5230 MiniProfiler",id:"111-\u6253\u5370\u6570\u636e\u5230-miniprofiler",level:2},{value:"1.12 \u83b7\u53d6\u5e94\u7528\u540d\u79f0",id:"112-\u83b7\u53d6\u5e94\u7528\u540d\u79f0",level:2},{value:"1.13 \u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6839\u76ee\u5f55",id:"113-\u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6839\u76ee\u5f55",level:2},{value:"1.14 \u83b7\u53d6\u7f51\u7ad9\u6839\u76ee\u5f55 wwwroot \u76ee\u5f55",id:"114-\u83b7\u53d6\u7f51\u7ad9\u6839\u76ee\u5f55-wwwroot-\u76ee\u5f55",level:2},{value:"1.15 \u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6240\u5728\u7a0b\u5e8f\u96c6",id:"115-\u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6240\u5728\u7a0b\u5e8f\u96c6",level:2},{value:"1.16 \u83b7\u53d6\u542f\u52a8\u9879\u76ee bin \u76ee\u5f55",id:"116-\u83b7\u53d6\u542f\u52a8\u9879\u76ee-bin-\u76ee\u5f55",level:2},{value:"1.17 \u83b7\u53d6\u73af\u5883\u53d8\u91cf\u540d",id:"117-\u83b7\u53d6\u73af\u5883\u53d8\u91cf\u540d",level:2},{value:"1.18 \u5224\u65ad\u7cfb\u7edf\u73af\u5883",id:"118-\u5224\u65ad\u7cfb\u7edf\u73af\u5883",level:2},{value:"1.19 \u83b7\u53d6\u670d\u52a1\u5668\u4fe1\u606f",id:"119-\u83b7\u53d6\u670d\u52a1\u5668\u4fe1\u606f",level:2},{value:"1.20 \u83b7\u53d6\u6846\u67b6\u5e95\u5c42\u6240\u6709\u672a\u6258\u7ba1\u5bf9\u8c61",id:"120-\u83b7\u53d6\u6846\u67b6\u5e95\u5c42\u6240\u6709\u672a\u6258\u7ba1\u5bf9\u8c61",level:2},{value:"1.21 \u624b\u52a8\u91ca\u653e\u975e\u6258\u7ba1\u5bf9\u8c61",id:"121-\u624b\u52a8\u91ca\u653e\u975e\u6258\u7ba1\u5bf9\u8c61",level:2},{value:"1.22 \u5224\u65ad\u662f\u5426\u662f\u5355\u6587\u4ef6\u73af\u5883",id:"122-\u5224\u65ad\u662f\u5426\u662f\u5355\u6587\u4ef6\u73af\u5883",level:2}],m={toc:c};function v(e){var n=e.components,t=(0,a.Z)(e,o);return(0,i.kt)("wrapper",(0,r.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"11-\u83b7\u53d6\u5168\u5c40\u914d\u7f6e"},"1.1 \u83b7\u53d6\u5168\u5c40\u914d\u7f6e"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var settings = App.Settings;\n")),(0,i.kt)("h2",{id:"12-\u83b7\u53d6\u914d\u7f6e\u5bf9\u8c61"},"1.2 \u83b7\u53d6\u914d\u7f6e\u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u83b7\u53d6 IConfiguration \u5bf9\u8c61\nvar configuration = App.Configuration;\nvar value = configuration["xxx:xxx"];\n\n// \u83b7\u53d6\u6307\u5b9a\u8282\u70b9\u503c\u5e76\u8f6c\u6210 T \u7c7b\u578b\nvar data = App.GetConfig("key:key2");\n\n// \u91cd\u8f7d/\u5237\u65b0\u914d\u7f6e\uff08v2.17+ \u7248\u672c\u5df2\u79fb\u9664\uff09\nApp.Configuration.Reload();\n')),(0,i.kt)("h2",{id:"13-\u83b7\u53d6\u73af\u5883\u5bf9\u8c61"},"1.3 \u83b7\u53d6\u73af\u5883\u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var webHostEnvironment = App.HostEnvironment;\n")),(0,i.kt)("h2",{id:"14-\u83b7\u53d6\u9879\u76ee\u6240\u6709\u7a0b\u5e8f\u96c6"},"1.4 \u83b7\u53d6\u9879\u76ee\u6240\u6709\u7a0b\u5e8f\u96c6"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var assemblies = App.Assemblies;\n")),(0,i.kt)("h2",{id:"15-\u83b7\u53d6\u9879\u76ee\u6240\u6709\u6709\u6548\u7c7b\u578b"},"1.5 \u83b7\u53d6\u9879\u76ee\u6240\u6709\u6709\u6548\u7c7b\u578b"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var types = App.EffectiveTypes;\n")),(0,i.kt)("h2",{id:"16-\u83b7\u53d6-httpcontext"},"1.6 \u83b7\u53d6 ",(0,i.kt)("inlineCode",{parentName:"h2"},"HttpContext")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var httpContext = App.HttpContext;\n")),(0,i.kt)("h2",{id:"17-\u83b7\u53d6\u767b\u5f55\u7684-user-\u5bf9\u8c61"},"1.7 \u83b7\u53d6\u767b\u5f55\u7684 ",(0,i.kt)("inlineCode",{parentName:"h2"},"User")," \u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var contextUser = App.User;\n\n// \u83b7\u53d6 `Jwt` \u5b58\u50a8\u7684\u4fe1\u606f\nvar userId = App.User?.FindFirstValue("\u952e");\n')),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u5f15\u5165 ",(0,i.kt)("inlineCode",{parentName:"strong"},"System.Security.Claims")," \u547d\u540d\u7a7a\u95f4")),(0,i.kt)("h2",{id:"18-\u83b7\u53d6\u670d\u52a1\u63d0\u4f9b\u5668"},"1.8 \u83b7\u53d6\u670d\u52a1\u63d0\u4f9b\u5668"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var serviceProvider = App.ServiceProvider;\n\n// \u83b7\u53d6\u6839\u670d\u52a1\uff0c\u901a\u5e38\u7528\u6765\u89e3\u6790\u5355\u4f8b\u548c\u77ac\u65f6\u7684\uff0c\u53ef\u4f18\u5316\u6027\u80fd\nvar rootService = App.RootServices;\n")),(0,i.kt)("h2",{id:"19-\u89e3\u6790\u670d\u52a1"},"1.9 \u89e3\u6790\u670d\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var service = App.GetService([IServiceProvider]);\nvar service2 = App.GetService(typeof(TService), [IServiceProvider]);\n\nvar service3 = App.GetRequiredService([IServiceProvider]);\nvar service4 = App.GetRequiredService(typeof(TService), [IServiceProvider]);\n")),(0,i.kt)("h2",{id:"110-\u83b7\u53d6\u9009\u9879\u914d\u7f6e"},"1.10 \u83b7\u53d6\u9009\u9879\u914d\u7f6e"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var options = App.GetOptions([IServiceProvider]);\nvar options2 = App.GetOptionsMonitor([IServiceProvider]);\nvar options3 = App.GetOptionsSnapshot([IServiceProvider]);\n")),(0,i.kt)("h2",{id:"111-\u6253\u5370\u6570\u636e\u5230-miniprofiler"},"1.11 \u6253\u5370\u6570\u636e\u5230 ",(0,i.kt)("inlineCode",{parentName:"h2"},"MiniProfiler")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'App.PrintToMiniProfiler("\u5206\u7c7b", "\u72b6\u6001", "\u8981\u6253\u5370\u7684\u6d88\u606f");\n')),(0,i.kt)("h2",{id:"112-\u83b7\u53d6\u5e94\u7528\u540d\u79f0"},"1.12 \u83b7\u53d6\u5e94\u7528\u540d\u79f0"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var applicationName = App.HostEnvironment.ApplicationName;\n")),(0,i.kt)("h2",{id:"113-\u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6839\u76ee\u5f55"},"1.13 \u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6839\u76ee\u5f55"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var webRootPath = App.HostEnvironment.ContentRootPath;\n")),(0,i.kt)("h2",{id:"114-\u83b7\u53d6\u7f51\u7ad9\u6839\u76ee\u5f55-wwwroot-\u76ee\u5f55"},"1.14 \u83b7\u53d6\u7f51\u7ad9\u6839\u76ee\u5f55 ",(0,i.kt)("inlineCode",{parentName:"h2"},"wwwroot")," \u76ee\u5f55"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var wwwroot = App.WebHostEnvironment.WebRootPath;\n")),(0,i.kt)("h2",{id:"115-\u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6240\u5728\u7a0b\u5e8f\u96c6"},"1.15 \u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6240\u5728\u7a0b\u5e8f\u96c6"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var webAssembly = Assembly.GetEntryAssembly();\n")),(0,i.kt)("h2",{id:"116-\u83b7\u53d6\u542f\u52a8\u9879\u76ee-bin-\u76ee\u5f55"},"1.16 \u83b7\u53d6\u542f\u52a8\u9879\u76ee ",(0,i.kt)("inlineCode",{parentName:"h2"},"bin")," \u76ee\u5f55"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var binPath = AppContext.BaseDirectory;\n")),(0,i.kt)("h2",{id:"117-\u83b7\u53d6\u73af\u5883\u53d8\u91cf\u540d"},"1.17 \u83b7\u53d6\u73af\u5883\u53d8\u91cf\u540d"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var environmentName = App.HostEnvironment.EnvironmentName;\n")),(0,i.kt)("h2",{id:"118-\u5224\u65ad\u7cfb\u7edf\u73af\u5883"},"1.18 \u5224\u65ad\u7cfb\u7edf\u73af\u5883"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u5224\u65ad\u662f\u5426\u5f00\u53d1\u73af\u5883\nvar isDevelopment = App.HostEnvironment.IsDevelopment();\n\n// \u5224\u65ad\u662f\u5426\u751f\u4ea7\u73af\u5883\nvar isProduction = App.HostEnvironment.IsProduction();\n\n// \u5224\u65ad\u662f\u5426 Stage \u73af\u5883\nvar isStaging = App.HostEnvironment.IsStaging();\n\n// \u5224\u65ad\u662f\u5426\u662f\u7279\u5b9a\u73af\u5883\uff0c\u6bd4\u5982\u81ea\u5b9a\u4e49\u6d4b\u8bd5\u73af\u5883\nvar isTest = App.HostEnvironment.IsEnvironment("TestEnvironment");\n')),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\uff0c\u9700\u5f15\u7528 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Microsoft.Extensions.Hosting")," \u547d\u540d\u7a7a\u95f4")),(0,i.kt)("h2",{id:"119-\u83b7\u53d6\u670d\u52a1\u5668\u4fe1\u606f"},"1.19 \u83b7\u53d6\u670d\u52a1\u5668\u4fe1\u606f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u83b7\u53d6\u7cfb\u7edf\u67b6\u6784\nvar osArchitecture = RuntimeInformation.OSArchitecture; // => X64\n\n// \u83b7\u53d6\u7cfb\u7edf\u540d\u79f0\nvar osDescription = RuntimeInformation.OSDescription; // => Windows 10 \u4f01\u4e1a\u7248\n\n// \u83b7\u53d6\u8fdb\u7a0b\u67b6\u6784\nvar processArchitecture = RuntimeInformation.ProcessArchitecture; // => X64\n\n// \u662f\u5426\u662f64\u4f4d\u64cd\u4f5c\u7cfb\u7edf\nvar is64BitOperatingSystem = Environment.Is64BitOperatingSystem; // => True\n")),(0,i.kt)("h2",{id:"120-\u83b7\u53d6\u6846\u67b6\u5e95\u5c42\u6240\u6709\u672a\u6258\u7ba1\u5bf9\u8c61"},"1.20 \u83b7\u53d6\u6846\u67b6\u5e95\u5c42\u6240\u6709\u672a\u6258\u7ba1\u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var objs = App.UnmanagedObjects;\n")),(0,i.kt)("h2",{id:"121-\u624b\u52a8\u91ca\u653e\u975e\u6258\u7ba1\u5bf9\u8c61"},"1.21 \u624b\u52a8\u91ca\u653e\u975e\u6258\u7ba1\u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"App.DisposeUnmanagedObjects(); // \u901a\u5e38\u5728\u975e `Web` \u73af\u5883\u4e2d\u624b\u52a8\u5904\u7406\u91ca\u653e\u65f6\u673a\n")),(0,i.kt)("h2",{id:"122-\u5224\u65ad\u662f\u5426\u662f\u5355\u6587\u4ef6\u73af\u5883"},"1.22 \u5224\u65ad\u662f\u5426\u662f\u5355\u6587\u4ef6\u73af\u5883"),(0,i.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 3.6.8 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"bool isSingleFileEnviroment = App.SingleFileEnvironment;\n")))}v.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return u},kt:function(){return v}});var r=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function o(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=r.createContext({}),p=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},u=function(e){var n=p(e.components);return r.createElement(l.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},m=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),m=p(t),v=a,d=m["".concat(l,".").concat(v)]||m[v]||c[v]||i;return t?r.createElement(d,o(o({ref:n},u),{},{components:t})):r.createElement(d,o({ref:n},u))}));function v(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,o=new Array(i);o[0]=m;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var p=2;p=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=r.createContext({}),p=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},u=function(e){var n=p(e.components);return r.createElement(l.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},m=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),m=p(t),v=a,d=m["".concat(l,".").concat(v)]||m[v]||c[v]||i;return t?r.createElement(d,o(o({ref:n},u),{},{components:t})):r.createElement(d,o({ref:n},u))}));function v(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,o=new Array(i);o[0]=m;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var p=2;pHttpContext",id:"16-\u83b7\u53d6-httpcontext",level:2},{value:"1.7 \u83b7\u53d6\u767b\u5f55\u7684 User \u5bf9\u8c61",id:"17-\u83b7\u53d6\u767b\u5f55\u7684-user-\u5bf9\u8c61",level:2},{value:"1.8 \u83b7\u53d6\u670d\u52a1\u63d0\u4f9b\u5668",id:"18-\u83b7\u53d6\u670d\u52a1\u63d0\u4f9b\u5668",level:2},{value:"1.9 \u89e3\u6790\u670d\u52a1",id:"19-\u89e3\u6790\u670d\u52a1",level:2},{value:"1.10 \u83b7\u53d6\u9009\u9879\u914d\u7f6e",id:"110-\u83b7\u53d6\u9009\u9879\u914d\u7f6e",level:2},{value:"1.11 \u6253\u5370\u6570\u636e\u5230 MiniProfiler",id:"111-\u6253\u5370\u6570\u636e\u5230-miniprofiler",level:2},{value:"1.12 \u83b7\u53d6\u5e94\u7528\u540d\u79f0",id:"112-\u83b7\u53d6\u5e94\u7528\u540d\u79f0",level:2},{value:"1.13 \u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6839\u76ee\u5f55",id:"113-\u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6839\u76ee\u5f55",level:2},{value:"1.14 \u83b7\u53d6\u7f51\u7ad9\u6839\u76ee\u5f55 wwwroot \u76ee\u5f55",id:"114-\u83b7\u53d6\u7f51\u7ad9\u6839\u76ee\u5f55-wwwroot-\u76ee\u5f55",level:2},{value:"1.15 \u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6240\u5728\u7a0b\u5e8f\u96c6",id:"115-\u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6240\u5728\u7a0b\u5e8f\u96c6",level:2},{value:"1.16 \u83b7\u53d6\u542f\u52a8\u9879\u76ee bin \u76ee\u5f55",id:"116-\u83b7\u53d6\u542f\u52a8\u9879\u76ee-bin-\u76ee\u5f55",level:2},{value:"1.17 \u83b7\u53d6\u73af\u5883\u53d8\u91cf\u540d",id:"117-\u83b7\u53d6\u73af\u5883\u53d8\u91cf\u540d",level:2},{value:"1.18 \u5224\u65ad\u7cfb\u7edf\u73af\u5883",id:"118-\u5224\u65ad\u7cfb\u7edf\u73af\u5883",level:2},{value:"1.19 \u83b7\u53d6\u670d\u52a1\u5668\u4fe1\u606f",id:"119-\u83b7\u53d6\u670d\u52a1\u5668\u4fe1\u606f",level:2},{value:"1.20 \u83b7\u53d6\u6846\u67b6\u5e95\u5c42\u6240\u6709\u672a\u6258\u7ba1\u5bf9\u8c61",id:"120-\u83b7\u53d6\u6846\u67b6\u5e95\u5c42\u6240\u6709\u672a\u6258\u7ba1\u5bf9\u8c61",level:2},{value:"1.21 \u624b\u52a8\u91ca\u653e\u975e\u6258\u7ba1\u5bf9\u8c61",id:"121-\u624b\u52a8\u91ca\u653e\u975e\u6258\u7ba1\u5bf9\u8c61",level:2},{value:"1.22 \u5224\u65ad\u662f\u5426\u662f\u5355\u6587\u4ef6\u73af\u5883",id:"122-\u5224\u65ad\u662f\u5426\u662f\u5355\u6587\u4ef6\u73af\u5883",level:2}],m={toc:c};function v(e){var n=e.components,t=(0,a.Z)(e,o);return(0,i.kt)("wrapper",(0,r.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"11-\u83b7\u53d6\u5168\u5c40\u914d\u7f6e"},"1.1 \u83b7\u53d6\u5168\u5c40\u914d\u7f6e"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var settings = App.Settings;\n")),(0,i.kt)("h2",{id:"12-\u83b7\u53d6\u914d\u7f6e\u5bf9\u8c61"},"1.2 \u83b7\u53d6\u914d\u7f6e\u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u83b7\u53d6 IConfiguration \u5bf9\u8c61\nvar configuration = App.Configuration;\nvar value = configuration["xxx:xxx"];\n\n// \u83b7\u53d6\u6307\u5b9a\u8282\u70b9\u503c\u5e76\u8f6c\u6210 T \u7c7b\u578b\nvar data = App.GetConfig("key:key2");\n\n// \u91cd\u8f7d/\u5237\u65b0\u914d\u7f6e\uff08v2.17+ \u7248\u672c\u5df2\u79fb\u9664\uff09\nApp.Configuration.Reload();\n')),(0,i.kt)("h2",{id:"13-\u83b7\u53d6\u73af\u5883\u5bf9\u8c61"},"1.3 \u83b7\u53d6\u73af\u5883\u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var webHostEnvironment = App.HostEnvironment;\n")),(0,i.kt)("h2",{id:"14-\u83b7\u53d6\u9879\u76ee\u6240\u6709\u7a0b\u5e8f\u96c6"},"1.4 \u83b7\u53d6\u9879\u76ee\u6240\u6709\u7a0b\u5e8f\u96c6"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var assemblies = App.Assemblies;\n")),(0,i.kt)("h2",{id:"15-\u83b7\u53d6\u9879\u76ee\u6240\u6709\u6709\u6548\u7c7b\u578b"},"1.5 \u83b7\u53d6\u9879\u76ee\u6240\u6709\u6709\u6548\u7c7b\u578b"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var types = App.EffectiveTypes;\n")),(0,i.kt)("h2",{id:"16-\u83b7\u53d6-httpcontext"},"1.6 \u83b7\u53d6 ",(0,i.kt)("inlineCode",{parentName:"h2"},"HttpContext")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var httpContext = App.HttpContext;\n")),(0,i.kt)("h2",{id:"17-\u83b7\u53d6\u767b\u5f55\u7684-user-\u5bf9\u8c61"},"1.7 \u83b7\u53d6\u767b\u5f55\u7684 ",(0,i.kt)("inlineCode",{parentName:"h2"},"User")," \u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var contextUser = App.User;\n\n// \u83b7\u53d6 `Jwt` \u5b58\u50a8\u7684\u4fe1\u606f\nvar userId = App.User?.FindFirstValue("\u952e");\n')),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u5f15\u5165 ",(0,i.kt)("inlineCode",{parentName:"strong"},"System.Security.Claims")," \u547d\u540d\u7a7a\u95f4")),(0,i.kt)("h2",{id:"18-\u83b7\u53d6\u670d\u52a1\u63d0\u4f9b\u5668"},"1.8 \u83b7\u53d6\u670d\u52a1\u63d0\u4f9b\u5668"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var serviceProvider = App.ServiceProvider;\n\n// \u83b7\u53d6\u6839\u670d\u52a1\uff0c\u901a\u5e38\u7528\u6765\u89e3\u6790\u5355\u4f8b\u548c\u77ac\u65f6\u7684\uff0c\u53ef\u4f18\u5316\u6027\u80fd\nvar rootService = App.RootServices;\n")),(0,i.kt)("h2",{id:"19-\u89e3\u6790\u670d\u52a1"},"1.9 \u89e3\u6790\u670d\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var service = App.GetService([IServiceProvider]);\nvar service2 = App.GetService(typeof(TService), [IServiceProvider]);\n\nvar service3 = App.GetRequiredService([IServiceProvider]);\nvar service4 = App.GetRequiredService(typeof(TService), [IServiceProvider]);\n")),(0,i.kt)("h2",{id:"110-\u83b7\u53d6\u9009\u9879\u914d\u7f6e"},"1.10 \u83b7\u53d6\u9009\u9879\u914d\u7f6e"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var options = App.GetOptions([IServiceProvider]);\nvar options2 = App.GetOptionsMonitor([IServiceProvider]);\nvar options3 = App.GetOptionsSnapshot([IServiceProvider]);\n")),(0,i.kt)("h2",{id:"111-\u6253\u5370\u6570\u636e\u5230-miniprofiler"},"1.11 \u6253\u5370\u6570\u636e\u5230 ",(0,i.kt)("inlineCode",{parentName:"h2"},"MiniProfiler")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'App.PrintToMiniProfiler("\u5206\u7c7b", "\u72b6\u6001", "\u8981\u6253\u5370\u7684\u6d88\u606f");\n')),(0,i.kt)("h2",{id:"112-\u83b7\u53d6\u5e94\u7528\u540d\u79f0"},"1.12 \u83b7\u53d6\u5e94\u7528\u540d\u79f0"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var applicationName = App.HostEnvironment.ApplicationName;\n")),(0,i.kt)("h2",{id:"113-\u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6839\u76ee\u5f55"},"1.13 \u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6839\u76ee\u5f55"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var webRootPath = App.HostEnvironment.ContentRootPath;\n")),(0,i.kt)("h2",{id:"114-\u83b7\u53d6\u7f51\u7ad9\u6839\u76ee\u5f55-wwwroot-\u76ee\u5f55"},"1.14 \u83b7\u53d6\u7f51\u7ad9\u6839\u76ee\u5f55 ",(0,i.kt)("inlineCode",{parentName:"h2"},"wwwroot")," \u76ee\u5f55"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var wwwroot = App.WebHostEnvironment.WebRootPath;\n")),(0,i.kt)("h2",{id:"115-\u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6240\u5728\u7a0b\u5e8f\u96c6"},"1.15 \u83b7\u53d6\u542f\u52a8\u9879\u76ee\u6240\u5728\u7a0b\u5e8f\u96c6"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var webAssembly = Assembly.GetEntryAssembly();\n")),(0,i.kt)("h2",{id:"116-\u83b7\u53d6\u542f\u52a8\u9879\u76ee-bin-\u76ee\u5f55"},"1.16 \u83b7\u53d6\u542f\u52a8\u9879\u76ee ",(0,i.kt)("inlineCode",{parentName:"h2"},"bin")," \u76ee\u5f55"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var binPath = AppContext.BaseDirectory;\n")),(0,i.kt)("h2",{id:"117-\u83b7\u53d6\u73af\u5883\u53d8\u91cf\u540d"},"1.17 \u83b7\u53d6\u73af\u5883\u53d8\u91cf\u540d"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var environmentName = App.HostEnvironment.EnvironmentName;\n")),(0,i.kt)("h2",{id:"118-\u5224\u65ad\u7cfb\u7edf\u73af\u5883"},"1.18 \u5224\u65ad\u7cfb\u7edf\u73af\u5883"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u5224\u65ad\u662f\u5426\u5f00\u53d1\u73af\u5883\nvar isDevelopment = App.HostEnvironment.IsDevelopment();\n\n// \u5224\u65ad\u662f\u5426\u751f\u4ea7\u73af\u5883\nvar isProduction = App.HostEnvironment.IsProduction();\n\n// \u5224\u65ad\u662f\u5426 Stage \u73af\u5883\nvar isStaging = App.HostEnvironment.IsStaging();\n\n// \u5224\u65ad\u662f\u5426\u662f\u7279\u5b9a\u73af\u5883\uff0c\u6bd4\u5982\u81ea\u5b9a\u4e49\u6d4b\u8bd5\u73af\u5883\nvar isTest = App.HostEnvironment.IsEnvironment("TestEnvironment");\n')),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\uff0c\u9700\u5f15\u7528 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Microsoft.Extensions.Hosting")," \u547d\u540d\u7a7a\u95f4")),(0,i.kt)("h2",{id:"119-\u83b7\u53d6\u670d\u52a1\u5668\u4fe1\u606f"},"1.19 \u83b7\u53d6\u670d\u52a1\u5668\u4fe1\u606f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u83b7\u53d6\u7cfb\u7edf\u67b6\u6784\nvar osArchitecture = RuntimeInformation.OSArchitecture; // => X64\n\n// \u83b7\u53d6\u7cfb\u7edf\u540d\u79f0\nvar osDescription = RuntimeInformation.OSDescription; // => Windows 10 \u4f01\u4e1a\u7248\n\n// \u83b7\u53d6\u8fdb\u7a0b\u67b6\u6784\nvar processArchitecture = RuntimeInformation.ProcessArchitecture; // => X64\n\n// \u662f\u5426\u662f64\u4f4d\u64cd\u4f5c\u7cfb\u7edf\nvar is64BitOperatingSystem = Environment.Is64BitOperatingSystem; // => True\n")),(0,i.kt)("h2",{id:"120-\u83b7\u53d6\u6846\u67b6\u5e95\u5c42\u6240\u6709\u672a\u6258\u7ba1\u5bf9\u8c61"},"1.20 \u83b7\u53d6\u6846\u67b6\u5e95\u5c42\u6240\u6709\u672a\u6258\u7ba1\u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var objs = App.UnmanagedObjects;\n")),(0,i.kt)("h2",{id:"121-\u624b\u52a8\u91ca\u653e\u975e\u6258\u7ba1\u5bf9\u8c61"},"1.21 \u624b\u52a8\u91ca\u653e\u975e\u6258\u7ba1\u5bf9\u8c61"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"App.DisposeUnmanagedObjects(); // \u901a\u5e38\u5728\u975e `Web` \u73af\u5883\u4e2d\u624b\u52a8\u5904\u7406\u91ca\u653e\u65f6\u673a\n")),(0,i.kt)("h2",{id:"122-\u5224\u65ad\u662f\u5426\u662f\u5355\u6587\u4ef6\u73af\u5883"},"1.22 \u5224\u65ad\u662f\u5426\u662f\u5355\u6587\u4ef6\u73af\u5883"),(0,i.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 3.6.8 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"bool isSingleFileEnviroment = App.SingleFileEnvironment;\n")))}v.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/8d45ae1b.6981b7a2.js b/handbook/build/assets/js/8d45ae1b.d16db555.js similarity index 71% rename from handbook/build/assets/js/8d45ae1b.6981b7a2.js rename to handbook/build/assets/js/8d45ae1b.d16db555.js index 10e7eae406..c6fa570cc0 100644 --- a/handbook/build/assets/js/8d45ae1b.6981b7a2.js +++ b/handbook/build/assets/js/8d45ae1b.d16db555.js @@ -1 +1 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4723],{4390:function(n){n.exports=JSON.parse('{"label":".net","permalink":"/furion/blog/tags/net","allTagsPath":"/furion/blog/tags","count":7}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4723],{6971:function(n){n.exports=JSON.parse('{"label":".net","permalink":"/furion/blog/tags/net","allTagsPath":"/furion/blog/tags","count":7}')}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/8dcbe064.ecefcb93.js b/handbook/build/assets/js/8dcbe064.ecefcb93.js deleted file mode 100644 index 5b83c1a2ac..0000000000 --- a/handbook/build/assets/js/8dcbe064.ecefcb93.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[7896],{7309:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return l},default:function(){return m},frontMatter:function(){return s},metadata:function(){return c},toc:function(){return p}});var r=n(3117),i=n(102),a=(n(7294),n(3905)),o=["components"],s={id:"validationTypemessagesettings",title:"3. \u9a8c\u8bc1\u6d88\u606f\u914d\u7f6e",sidebar_label:"3. \u9a8c\u8bc1\u6d88\u606f\u914d\u7f6e"},l=void 0,c={unversionedId:"settings/validationTypemessagesettings",id:"settings/validationTypemessagesettings",title:"3. \u9a8c\u8bc1\u6d88\u606f\u914d\u7f6e",description:"\u5982\u9700\u7f16\u5199\u914d\u7f6e\u7684\u65f6\u5019\u63d0\u4f9b\u667a\u80fd\u63d0\u793a\u548c\u6821\u9a8c\uff0c\u53ef\u67e5\u770b \u30102.7 JSON Schema \u4f7f\u7528\u3011",source:"@site/docs/settings/validationTypemessagesettings.mdx",sourceDirName:"settings",slug:"/settings/validationTypemessagesettings",permalink:"/furion/docs/settings/validationTypemessagesettings",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/settings/validationTypemessagesettings.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1656403543,formattedLastUpdatedAt:"Jun 28, 2022",frontMatter:{id:"validationTypemessagesettings",title:"3. \u9a8c\u8bc1\u6d88\u606f\u914d\u7f6e",sidebar_label:"3. \u9a8c\u8bc1\u6d88\u606f\u914d\u7f6e"},sidebar:"settings",previous:{title:"2. \u8de8\u57df\u914d\u7f6e",permalink:"/furion/docs/settings/corsaccessorsettings"},next:{title:"4. \u4f9d\u8d56\u6ce8\u5165\u914d\u7f6e",permalink:"/furion/docs/settings/dependencyinjectionsettings"}},u={},p=[{value:"3.1 \u5173\u4e8e\u914d\u7f6e",id:"31-\u5173\u4e8e\u914d\u7f6e",level:2},{value:"3.2 \u914d\u7f6e\u4fe1\u606f",id:"32-\u914d\u7f6e\u4fe1\u606f",level:2},{value:"3.3 \u914d\u7f6e\u793a\u4f8b",id:"33-\u914d\u7f6e\u793a\u4f8b",level:2}],d={toc:p};function m(e){var t=e.components,n=(0,i.Z)(e,o);return(0,a.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{title:"\u914d\u7f6e\u667a\u80fd\u63d0\u793a\u548c\u6821\u9a8c",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u9700\u7f16\u5199\u914d\u7f6e\u7684\u65f6\u5019\u63d0\u4f9b\u667a\u80fd\u63d0\u793a\u548c\u6821\u9a8c\uff0c\u53ef\u67e5\u770b \u3010",(0,a.kt)("a",{parentName:"p",href:"../jsonschema"},"2.7 JSON Schema \u4f7f\u7528"),"\u3011"),(0,a.kt)("p",{parentName:"admonition"},"\u53ea\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u5934\u90e8\u6dfb\u52a0\u4e0b\u5217\u914d\u7f6e\u5373\u53ef\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},'{\n "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"\n}\n'))),(0,a.kt)("h2",{id:"31-\u5173\u4e8e\u914d\u7f6e"},"3.1 \u5173\u4e8e\u914d\u7f6e"),(0,a.kt)("p",null,"\u9a8c\u8bc1\u6d88\u606f\u914d\u7f6e\u6307\u7684\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6570\u636e\u6821\u9a8c\u4e2d\u9a8c\u8bc1\u7c7b\u578b\u9ed8\u8ba4\u6d88\u606f\u914d\u7f6e\u9009\u9879\u3002"),(0,a.kt)("h2",{id:"32-\u914d\u7f6e\u4fe1\u606f"},"3.2 \u914d\u7f6e\u4fe1\u606f"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ValidationTypeMessageSettings"),"\uff1a\u914d\u7f6e\u6839\u8282\u70b9",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Definitions"),"\uff1a\u914d\u7f6e\u9a8c\u8bc1\u7c7b\u578b\u5bf9\u5e94\u7684\u6d88\u606f\u7c7b\u578b\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"[\u7c7b\u578b\u540d\u79f0\uff0c\u7c7b\u578b\u6d88\u606f][]")," \u7c7b\u578b\uff0c\u5982\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},'["Required", "\u503c\u4e0d\u80fd\u4e3a\u7a7a\u6216Null"]'))))),(0,a.kt)("h2",{id:"33-\u914d\u7f6e\u793a\u4f8b"},"3.3 \u914d\u7f6e\u793a\u4f8b"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "ValidationTypeMessageSettings": {\n "Definitions": [\n ["Required", "\u503c\u4e0d\u80fd\u4e3a\u7a7a\u6216Null"],\n ["Numeric", "\u5fc5\u987b\u662f\u6570\u503c\u7c7b\u578b"],\n ["StrongPassword", "\u5bc6\u7801\u592a\u7b80\u5355\u4e86!!!"]\n ]\n }\n}\n')))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return u},kt:function(){return m}});var r=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},u=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,a=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),d=c(n),m=i,f=d["".concat(l,".").concat(m)]||d[m]||p[m]||a;return n?r.createElement(f,o(o({ref:t},u),{},{components:n})):r.createElement(f,o({ref:t},u))}));function m(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=n.length,o=new Array(a);o[0]=d;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:i,o[1]=s;for(var c=2;c=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},u=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,a=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),d=c(n),m=i,f=d["".concat(l,".").concat(m)]||d[m]||p[m]||a;return n?r.createElement(f,o(o({ref:t},u),{},{components:n})):r.createElement(f,o({ref:t},u))}));function m(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=n.length,o=new Array(a);o[0]=d;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:i,o[1]=s;for(var c=2;c=0||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}var p=r.createContext({}),u=function(t){var e=r.useContext(p),n=e;return t&&(n="function"==typeof t?t(e):i(i({},e),t)),n},c=function(t){var e=u(t.components);return r.createElement(p.Provider,{value:e},t.children)},f={inlineCode:"code",wrapper:function(t){var e=t.children;return r.createElement(r.Fragment,{},e)}},s=r.forwardRef((function(t,e){var n=t.components,o=t.mdxType,a=t.originalType,p=t.parentName,c=l(t,["components","mdxType","originalType","parentName"]),s=u(n),m=o,h=s["".concat(p,".").concat(m)]||s[m]||f[m]||a;return n?r.createElement(h,i(i({ref:e},c),{},{components:n})):r.createElement(h,i({ref:e},c))}));function m(t,e){var n=arguments,o=e&&e.mdxType;if("string"==typeof t||o){var a=n.length,i=new Array(a);i[0]=s;var l={};for(var p in e)hasOwnProperty.call(e,p)&&(l[p]=e[p]);l.originalType=t,l.mdxType="string"==typeof t?t:o,i[1]=l;for(var u=2;u=0||(o[n]=t[n]);return o}(t,e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}var p=r.createContext({}),u=function(t){var e=r.useContext(p),n=e;return t&&(n="function"==typeof t?t(e):i(i({},e),t)),n},c=function(t){var e=u(t.components);return r.createElement(p.Provider,{value:e},t.children)},f={inlineCode:"code",wrapper:function(t){var e=t.children;return r.createElement(r.Fragment,{},e)}},s=r.forwardRef((function(t,e){var n=t.components,o=t.mdxType,a=t.originalType,p=t.parentName,c=l(t,["components","mdxType","originalType","parentName"]),s=u(n),m=o,h=s["".concat(p,".").concat(m)]||s[m]||f[m]||a;return n?r.createElement(h,i(i({ref:e},c),{},{components:n})):r.createElement(h,i({ref:e},c))}));function m(t,e){var n=arguments,o=e&&e.mdxType;if("string"==typeof t||o){var a=n.length,i=new Array(a);i[0]=s;var l={};for(var p in e)hasOwnProperty.call(e,p)&&(l[p]=e[p]);l.originalType=t,l.mdxType="string"==typeof t?t:o,i[1]=l;for(var u=2;u=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var c=a.createContext({}),s=function(e){var t=a.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d=function(e){var t=s(e.components);return a.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,l=e.originalType,c=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),u=s(n),v=r,f=u["".concat(c,".").concat(v)]||u[v]||m[v]||l;return n?a.createElement(f,i(i({ref:t},d),{},{components:n})):a.createElement(f,i({ref:t},d))}));function v(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=n.length,i=new Array(l);i[0]=u;var o={};for(var c in t)hasOwnProperty.call(t,c)&&(o[c]=t[c]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var s=2;s0,s=!!(t||n||l);return o||s?a.createElement("footer",{className:(0,d.Z)(L.k.docs.docFooter,"docusaurus-mt-lg")},o&&a.createElement(P,{tags:i}),s&&a.createElement(I,{editUrl:t,lastUpdatedAt:n,lastUpdatedBy:l,formattedLastUpdatedAt:r})):null}var B=n(6043),S=n(3743),V=n(102),D="tocCollapsibleButton_TO0P",R="tocCollapsibleButtonExpanded_MG3E",z=["collapsed"];function F(e){var t=e.collapsed,n=(0,V.Z)(e,z);return a.createElement("button",(0,u.Z)({type:"button"},n,{className:(0,d.Z)("clean-btn",D,!t&&R,n.className)}),a.createElement(v.Z,{id:"theme.TOCCollapsible.toggleButtonLabel",description:"The label used by the button on the collapsible TOC component"},"On this page"))}var q="tocCollapsible_ETCw",G="tocCollapsibleContent_vkbj",J="tocCollapsibleExpanded_sAul";function X(e){var t=e.toc,n=e.className,r=e.minHeadingLevel,l=e.maxHeadingLevel,i=(0,B.u)({initialState:!0}),o=i.collapsed,c=i.toggleCollapsed;return a.createElement("div",{className:(0,d.Z)(q,!o&&J,n)},a.createElement(F,{collapsed:o,onClick:c}),a.createElement(B.z,{lazy:!0,className:G,collapsed:o},a.createElement(S.Z,{toc:t,minHeadingLevel:r,maxHeadingLevel:l})))}var Q="tocMobile_ITEo";function W(){var e=c(),t=e.toc,n=e.frontMatter;return a.createElement(X,{toc:t,minHeadingLevel:n.toc_min_heading_level,maxHeadingLevel:n.toc_max_heading_level,className:(0,d.Z)(L.k.docs.docTocMobile,Q)})}var K=n(541);function Y(){var e=c(),t=e.toc,n=e.frontMatter;return a.createElement(K.Z,{toc:t,minHeadingLevel:n.toc_min_heading_level,maxHeadingLevel:n.toc_max_heading_level,className:L.k.docs.docTocDesktop})}var $=n(2503),ee=n(5042);function te(e){var t,n,r,l,i=e.children,o=(t=c(),n=t.metadata,r=t.frontMatter,l=t.contentTitle,r.hide_title||void 0!==l?null:n.title);return a.createElement("div",{className:(0,d.Z)(L.k.docs.docMarkdown,"markdown")},o&&a.createElement("header",null,a.createElement($.Z,{as:"h1"},o)),a.createElement(ee.Z,null,i))}var ne=n(4575),ae=n(8596),re=n(4996);function le(e){return a.createElement("svg",(0,u.Z)({viewBox:"0 0 24 24"},e),a.createElement("path",{d:"M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z",fill:"currentColor"}))}var ie={breadcrumbsContainer:"breadcrumbsContainer_Z_bl",breadcrumbHomeIcon:"breadcrumbHomeIcon_OVgt"};function oe(e){var t=e.children,n=e.href,r="breadcrumbs__link";return e.isLast?a.createElement("span",{className:r,itemProp:"name"},t):n?a.createElement(g.Z,{className:r,href:n,itemProp:"item"},a.createElement("span",{itemProp:"name"},t)):a.createElement("span",{className:r},t)}function ce(e){var t=e.children,n=e.active,r=e.index,l=e.addMicrodata;return a.createElement("li",(0,u.Z)({},l&&{itemScope:!0,itemProp:"itemListElement",itemType:"https://schema.org/ListItem"},{className:(0,d.Z)("breadcrumbs__item",{"breadcrumbs__item--active":n})}),t,a.createElement("meta",{itemProp:"position",content:String(r+1)}))}function se(){var e=(0,re.Z)("/");return a.createElement("li",{className:"breadcrumbs__item"},a.createElement(g.Z,{"aria-label":(0,v.I)({id:"theme.docs.breadcrumbs.home",message:"Home page",description:"The ARIA label for the home page in the breadcrumbs"}),className:(0,d.Z)("breadcrumbs__link",ie.breadcrumbsItemLink),href:e},a.createElement(le,{className:ie.breadcrumbHomeIcon})))}function de(){var e=(0,ne.s1)(),t=(0,ae.Ns)();return e?a.createElement("nav",{className:(0,d.Z)(L.k.docs.docBreadcrumbs,ie.breadcrumbsContainer),"aria-label":(0,v.I)({id:"theme.docs.breadcrumbs.navAriaLabel",message:"Breadcrumbs",description:"The ARIA label for the breadcrumbs"})},a.createElement("ul",{className:"breadcrumbs",itemScope:!0,itemType:"https://schema.org/BreadcrumbList"},t&&a.createElement(se,null),e.map((function(t,n){var r=n===e.length-1;return a.createElement(ce,{key:n,active:r,index:n,addMicrodata:!!t.href},a.createElement(oe,{href:t.href,isLast:r},t.label))})))):null}var me="docItemContainer_Djhp",ue="docItemCol_VOVn";function ve(e){var t,n,r,l,i,o,s=e.children,u=(t=c(),n=t.frontMatter,r=t.toc,l=(0,m.i)(),i=n.hide_table_of_contents,o=!i&&r.length>0,{hidden:i,mobile:o?a.createElement(W,null):void 0,desktop:!o||"desktop"!==l&&"ssr"!==l?void 0:a.createElement(Y,null)});return a.createElement("div",{className:"row"},a.createElement("div",{className:(0,d.Z)("col",!u.hidden&&ue)},a.createElement(C,null),a.createElement("div",{className:me},a.createElement("article",null,a.createElement(de,null),a.createElement(T,null),u.mobile,a.createElement(te,null,s),a.createElement(j,null)),a.createElement(b,null))),u.desktop&&a.createElement("div",{className:"col col--3"},u.desktop))}function fe(e){var t="docs-doc-id-"+e.content.metadata.unversionedId,n=e.content;return a.createElement(o,{content:e.content},a.createElement(r.FG,{className:t},a.createElement(s,null),a.createElement(ve,null,a.createElement(n,null))))}},4881:function(e,t,n){n.d(t,{Z:function(){return u}});var a=n(7294),r=n(5999),l=n(5281),i=n(3117),o=n(102),c=n(4334),s="iconEdit_Z9Sw",d=["className"];function m(e){var t=e.className,n=(0,o.Z)(e,d);return a.createElement("svg",(0,i.Z)({fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,c.Z)(s,t),"aria-hidden":"true"},n),a.createElement("g",null,a.createElement("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})))}function u(e){var t=e.editUrl;return a.createElement("a",{href:t,target:"_blank",rel:"noreferrer noopener",className:l.k.common.editThisPage},a.createElement(m,null),a.createElement(r.Z,{id:"theme.common.editThisPage",description:"The link label to edit the current page"},"Edit this page"))}},5042:function(e,t,n){n.d(t,{Z:function(){return i}});var a=n(7294),r=n(3905),l=n(1414);function i(e){var t=e.children;return a.createElement(r.Zo,{components:l.Z},t)}},2244:function(e,t,n){n.d(t,{Z:function(){return i}});var a=n(7294),r=n(4334),l=n(9960);function i(e){var t=e.permalink,n=e.title,i=e.subLabel,o=e.isNext;return a.createElement(l.Z,{className:(0,r.Z)("pagination-nav__link",o?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t},i&&a.createElement("div",{className:"pagination-nav__sublabel"},i),a.createElement("div",{className:"pagination-nav__label"},n))}},3743:function(e,t,n){n.d(t,{Z:function(){return h}});var a=n(3117),r=n(102),l=n(7294),i=n(6668),o=["parentIndex"];function c(e){var t=e.map((function(e){return Object.assign({},e,{parentIndex:-1,children:[]})})),n=Array(7).fill(-1);t.forEach((function(e,t){var a=n.slice(2,e.level);e.parentIndex=Math.max.apply(Math,a),n[e.level]=t}));var a=[];return t.forEach((function(e){var n=e.parentIndex,l=(0,r.Z)(e,o);n>=0?t[n].children.push(l):a.push(l)})),a}function s(e){var t=e.toc,n=e.minHeadingLevel,a=e.maxHeadingLevel;return t.flatMap((function(e){var t=s({toc:e.children,minHeadingLevel:n,maxHeadingLevel:a});return function(e){return e.level>=n&&e.level<=a}(e)?[Object.assign({},e,{children:t})]:t}))}function d(e){var t=e.getBoundingClientRect();return t.top===t.bottom?d(e.parentNode):t}function m(e,t){var n,a,r=t.anchorTopOffset,l=e.find((function(e){return d(e).top>=r}));return l?function(e){return e.top>0&&e.bottom {\n var services = scope.ServiceProvider;\n});\n\n// \u5f02\u6b65\nawait Scope.CreateAsync(async (factory, scope) => {\n var services = scope.ServiceProvider;\n await _calcService.GetAsync();\n // ...\n})\n")),(0,a.kt)("admonition",{title:"\u6570\u636e\u5e93\u64cd\u4f5c\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f5c\u7528\u57df\u4e2d\u5bf9",(0,a.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u6709\u4efb\u4f55\u53d8\u66f4\u64cd\u4f5c"),"\uff0c\u9700\u624b\u52a8\u8c03\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216\u5e26 ",(0,a.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u65b9\u6cd5\u3002\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Scoped.CreateUow(handler)")," \u4ee3\u66ff\u3002")),(0,a.kt)("h2",{id:"112-\u521b\u5efa\u4e00\u4e2a\u5e26\u5de5\u4f5c\u5355\u5143\u7684\u4f5c\u7528\u57df"},"11.2 \u521b\u5efa\u4e00\u4e2a\u5e26\u5de5\u4f5c\u5355\u5143\u7684\u4f5c\u7528\u57df"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u540c\u6b65\nScoped.CreateUow((factory, scope) => {\n var services = scope.ServiceProvider;\n});\n\n// \u5f02\u6b65\nawait Scope.CreateUowAsync(await (factory, scope) => {\n var services = scope.ServiceProvider;\n await _calcService.GetAsync();\n // ...\n});\n")),(0,a.kt)("p",null,"\u6b64\u65b9\u6cd5\u5c06\u5728\u6267\u884c\u5b8c\u6bd5\u4e4b\u540e\u81ea\u52a8\u8c03\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"SaveChanges()")),(0,a.kt)("h2",{id:"113-\u521b\u5efa\u4e00\u4e2a\u4f9d\u8d56\u6ce8\u5165\u4f5c\u7528\u57df\u8303\u56f4\u5e26\u8fd4\u56de\u503c"},"11.3 \u521b\u5efa\u4e00\u4e2a\u4f9d\u8d56\u6ce8\u5165\u4f5c\u7528\u57df\u8303\u56f4\uff08\u5e26\u8fd4\u56de\u503c\uff09"),(0,a.kt)("admonition",{title:"\u79fb\u9664\u58f0\u660e",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion v2.18+")," \u7248\u672c\u79fb\u9664\u5e26\u8fd4\u56de\u503c\u7684\u4f5c\u7528\u57df\uff08\u8be5\u65b9\u6cd5\u5c5e\u4e8e\u591a\u4f59\u64cd\u4f5c\uff09")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'var obj = Scoped.CreateRef((factory, scope) => {\n var services = scope.ServiceProvider;\n return "\u8fd4\u56de\u503c";\n});\n')),(0,a.kt)("h2",{id:"114-\u521b\u5efa\u4e00\u4e2a\u5e26\u5de5\u4f5c\u5355\u5143\u7684\u4f5c\u7528\u57df\u5e26\u8fd4\u56de\u503c"},"11.4 \u521b\u5efa\u4e00\u4e2a\u5e26\u5de5\u4f5c\u5355\u5143\u7684\u4f5c\u7528\u57df\uff08\u5e26\u8fd4\u56de\u503c\uff09"),(0,a.kt)("admonition",{title:"\u79fb\u9664\u58f0\u660e",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion v2.18+")," \u7248\u672c\u79fb\u9664\u5e26\u8fd4\u56de\u503c\u7684\u4f5c\u7528\u57df\uff08\u8be5\u65b9\u6cd5\u5c5e\u4e8e\u591a\u4f59\u64cd\u4f5c\uff09")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var obj = Scoped.CreateUowRef((factory, scope) => {\n var services = scope.ServiceProvider;\n return "\u8fd4\u56de\u503c";\n});\n')))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return l},kt:function(){return m}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=r.createContext({}),s=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},l=function(e){var t=s(e.components);return r.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,p=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),d=s(n),m=o,f=d["".concat(p,".").concat(m)]||d[m]||u[m]||a;return n?r.createElement(f,i(i({ref:t},l),{},{components:n})):r.createElement(f,i({ref:t},l))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=d;var c={};for(var p in t)hasOwnProperty.call(t,p)&&(c[p]=t[p]);c.originalType=e,c.mdxType="string"==typeof e?e:o,i[1]=c;for(var s=2;s=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=r.createContext({}),s=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},l=function(e){var t=s(e.components);return r.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,p=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),d=s(n),m=o,f=d["".concat(p,".").concat(m)]||d[m]||u[m]||a;return n?r.createElement(f,i(i({ref:t},l),{},{components:n})):r.createElement(f,i({ref:t},l))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=d;var c={};for(var p in t)hasOwnProperty.call(t,p)&&(c[p]=t[p]);c.originalType=e,c.mdxType="string"==typeof e?e:o,i[1]=c;for(var s=2;s {\n var services = scope.ServiceProvider;\n});\n\n// \u5f02\u6b65\nawait Scoped.CreateAsync(async (factory, scope) => {\n var services = scope.ServiceProvider;\n await _calcService.GetAsync();\n // ...\n})\n")),(0,a.kt)("admonition",{title:"\u6570\u636e\u5e93\u64cd\u4f5c\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f5c\u7528\u57df\u4e2d\u5bf9",(0,a.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u6709\u4efb\u4f55\u53d8\u66f4\u64cd\u4f5c"),"\uff0c\u9700\u624b\u52a8\u8c03\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216\u5e26 ",(0,a.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u65b9\u6cd5\u3002\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Scoped.CreateUow(handler)")," \u4ee3\u66ff\u3002")),(0,a.kt)("h2",{id:"112-\u521b\u5efa\u4e00\u4e2a\u5e26\u5de5\u4f5c\u5355\u5143\u7684\u4f5c\u7528\u57df"},"11.2 \u521b\u5efa\u4e00\u4e2a\u5e26\u5de5\u4f5c\u5355\u5143\u7684\u4f5c\u7528\u57df"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u540c\u6b65\nScoped.CreateUow((factory, scope) => {\n var services = scope.ServiceProvider;\n});\n\n// \u5f02\u6b65\nawait Scope.CreateUowAsync(await (factory, scope) => {\n var services = scope.ServiceProvider;\n await _calcService.GetAsync();\n // ...\n});\n")),(0,a.kt)("p",null,"\u6b64\u65b9\u6cd5\u5c06\u5728\u6267\u884c\u5b8c\u6bd5\u4e4b\u540e\u81ea\u52a8\u8c03\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"SaveChanges()")),(0,a.kt)("h2",{id:"113-\u521b\u5efa\u4e00\u4e2a\u4f9d\u8d56\u6ce8\u5165\u4f5c\u7528\u57df\u8303\u56f4\u5e26\u8fd4\u56de\u503c"},"11.3 \u521b\u5efa\u4e00\u4e2a\u4f9d\u8d56\u6ce8\u5165\u4f5c\u7528\u57df\u8303\u56f4\uff08\u5e26\u8fd4\u56de\u503c\uff09"),(0,a.kt)("admonition",{title:"\u79fb\u9664\u58f0\u660e",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion v2.18+")," \u7248\u672c\u79fb\u9664\u5e26\u8fd4\u56de\u503c\u7684\u4f5c\u7528\u57df\uff08\u8be5\u65b9\u6cd5\u5c5e\u4e8e\u591a\u4f59\u64cd\u4f5c\uff09")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'var obj = Scoped.CreateRef((factory, scope) => {\n var services = scope.ServiceProvider;\n return "\u8fd4\u56de\u503c";\n});\n')),(0,a.kt)("h2",{id:"114-\u521b\u5efa\u4e00\u4e2a\u5e26\u5de5\u4f5c\u5355\u5143\u7684\u4f5c\u7528\u57df\u5e26\u8fd4\u56de\u503c"},"11.4 \u521b\u5efa\u4e00\u4e2a\u5e26\u5de5\u4f5c\u5355\u5143\u7684\u4f5c\u7528\u57df\uff08\u5e26\u8fd4\u56de\u503c\uff09"),(0,a.kt)("admonition",{title:"\u79fb\u9664\u58f0\u660e",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion v2.18+")," \u7248\u672c\u79fb\u9664\u5e26\u8fd4\u56de\u503c\u7684\u4f5c\u7528\u57df\uff08\u8be5\u65b9\u6cd5\u5c5e\u4e8e\u591a\u4f59\u64cd\u4f5c\uff09")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var obj = Scoped.CreateUowRef((factory, scope) => {\n var services = scope.ServiceProvider;\n return "\u8fd4\u56de\u503c";\n});\n')))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/934e2055.4d5ac78b.js b/handbook/build/assets/js/934e2055.4d5ac78b.js new file mode 100644 index 0000000000..768778e8d1 --- /dev/null +++ b/handbook/build/assets/js/934e2055.4d5ac78b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4918],{3905:function(e,n,t){t.d(n,{Zo:function(){return s},kt:function(){return m}});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function l(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var p=a.createContext({}),d=function(e){var n=a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},s=function(e){var n=d(e.components);return a.createElement(p.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},c=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,p=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),c=d(t),m=r,C=c["".concat(p,".").concat(m)]||c[m]||u[m]||i;return t?a.createElement(C,l(l({ref:n},s),{},{components:t})):a.createElement(C,l({ref:n},s))}));function m(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,l=new Array(i);l[0]=c;var o={};for(var p in n)hasOwnProperty.call(n,p)&&(o[p]=n[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,l[1]=o;for(var d=2;dIPC",id:"331-\u4ec0\u4e48\u662f-ipc",level:2},{value:"33.2 \u5b9e\u73b0 IPC \u901a\u4fe1\u65b9\u5f0f",id:"332-\u5b9e\u73b0-ipc-\u901a\u4fe1\u65b9\u5f0f",level:2},{value:"33.3 IPC \u901a\u4fe1\u6a21\u5f0f",id:"333-ipc-\u901a\u4fe1\u6a21\u5f0f",level:2},{value:"33.4 \u8fdb\u7a0b\u5185\u901a\u4fe1\uff08\u7ebf\u7a0b\u95f4\uff09",id:"334-\u8fdb\u7a0b\u5185\u901a\u4fe1\u7ebf\u7a0b\u95f4",level:2},{value:"33.4.1 \u4e86\u89e3 Channel",id:"3341-\u4e86\u89e3-channel",level:3},{value:"33.4.2 \u5e38\u89c4\u4f7f\u7528",id:"3342-\u5e38\u89c4\u4f7f\u7528",level:3},{value:"\u521b\u5efa ChannelHandler<TMessage> \u7ba1\u9053\u5904\u7406\u7a0b\u5e8f",id:"\u521b\u5efa-channelhandlertmessage-\u7ba1\u9053\u5904\u7406\u7a0b\u5e8f",level:4},{value:"\u4f7f\u7528 ChannelContext<TMessage, THandler> \u53d1\u9001\u6d88\u606f",id:"\u4f7f\u7528-channelcontexttmessage-thandler-\u53d1\u9001\u6d88\u606f",level:4},{value:"33.4.3 \u5b9e\u73b0\u591a\u8ba2\u9605",id:"3343-\u5b9e\u73b0\u591a\u8ba2\u9605",level:3},{value:"33.4.4 \u66f4\u591a Channel \u77e5\u8bc6",id:"3344-\u66f4\u591a-channel-\u77e5\u8bc6",level:3},{value:"33.4.5 CallContext \u65b9\u5f0f",id:"3345-callcontext-\u65b9\u5f0f",level:3},{value:"34.5 \u8fdb\u7a0b\u5916\u901a\u4fe1\uff08\u5171\u4eab\u5185\u5b58\uff09",id:"345-\u8fdb\u7a0b\u5916\u901a\u4fe1\u5171\u4eab\u5185\u5b58",level:2},{value:"33.6 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"336-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:u};function m(e){var n=e.components,t=(0,r.Z)(e,l);return(0,i.kt)("wrapper",(0,a.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"331-\u4ec0\u4e48\u662f-ipc"},"33.1 \u4ec0\u4e48\u662f ",(0,i.kt)("inlineCode",{parentName:"h2"},"IPC")),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u5f15\u7528\u767e\u5ea6\u767e\u79d1"),(0,i.kt)("p",{parentName:"blockquote"},"IPC\uff08Inter-Process Communication\uff0c\u8fdb\u7a0b\u95f4\u901a\u4fe1\uff09\u3002\u8fdb\u7a0b\u95f4\u901a\u4fe1\u662f\u6307\u4e24\u4e2a\u8fdb\u7a0b\u7684\u6570\u636e\u4e4b\u95f4\u4ea7\u751f\u4ea4\u4e92\u3002")),(0,i.kt)("p",null,"\u901a\u4fd7\u70b9\u8bf4\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"IPC")," \u53ef\u4ee5\u5b9e\u73b0\u4e0d\u540c\u5e94\u7528\u7a0b\u5e8f\u95f4\u901a\u4fe1\uff08\u4ea4\u4e92\u6570\u636e\uff09\u3002"),(0,i.kt)("h2",{id:"332-\u5b9e\u73b0-ipc-\u901a\u4fe1\u65b9\u5f0f"},"33.2 \u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"h2"},"IPC")," \u901a\u4fe1\u65b9\u5f0f"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u534a\u53cc\u5de5 Unix \u7ba1\u9053"),(0,i.kt)("li",{parentName:"ul"},"FIFOs(\u547d\u540d\u7ba1\u9053)"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u6d88\u606f\u961f\u5217"),"\uff08\u5e38\u7528\u6a21\u5f0f\uff09"),(0,i.kt)("li",{parentName:"ul"},"\u4fe1\u53f7\u91cf"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u5171\u4eab\u5185\u5b58"),"\uff08\u5e38\u7528\u6a21\u5f0f\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Furion")," \u6846\u67b6\u9ed8\u8ba4\u5b9e\u73b0\u65b9\u5f0f\uff09"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u7f51\u7edc Socket"),"\uff08\u5e38\u7528\u6a21\u5f0f\uff09")),(0,i.kt)("h2",{id:"333-ipc-\u901a\u4fe1\u6a21\u5f0f"},"33.3 ",(0,i.kt)("inlineCode",{parentName:"h2"},"IPC")," \u901a\u4fe1\u6a21\u5f0f"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"IPC")," \u672c\u8eab\u6307\u7684\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"\u8fdb\u7a0b\u95f4")," \u901a\u4fe1\uff0c\u4f46 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u5c06\u5185\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"\u8fdb\u7a0b\u95f4/\u5185")," \u4e24\u79cd\u8fdb\u7a0b\u901a\u4fe1\u6a21\u5f0f\u3002"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"\u8fdb\u7a0b\u5185\u901a\u4fe1"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Furion")," \u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"li"},"Channel")," \u7ba1\u9053\u63d0\u4f9b\u8fdb\u7a0b\u5185\u901a\u4fe1"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"\u8fdb\u7a0b\u5916\u901a\u4fe1"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Furion")," \u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"li"},"MemoryMapperFile")," \u5171\u4eab\u5185\u5b58\u65b9\u5f0f\u5b9e\u73b0\u8fdb\u7a0b\u5916\u901a\u4fe1\uff08\u540e\u7eed\u7248\u672c\u5b8c\u5584\uff09")),(0,i.kt)("h2",{id:"334-\u8fdb\u7a0b\u5185\u901a\u4fe1\u7ebf\u7a0b\u95f4"},"33.4 \u8fdb\u7a0b\u5185\u901a\u4fe1\uff08\u7ebf\u7a0b\u95f4\uff09"),(0,i.kt)("p",null,"\u8fdb\u7a0b\u5185\u901a\u4fe1\u4fd7\u79f0\u7ebf\u7a0b\u95f4\u901a\u4fe1\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"C#")," \u63d0\u4f9b\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Channel\uff08\u7ba1\u9053\uff09")," + ",(0,i.kt)("inlineCode",{parentName:"p"},"Lazy")," + ",(0,i.kt)("inlineCode",{parentName:"p"},"Task.Factory")," \u5b9e\u73b0\u957f\u65f6\u95f4\u9ad8\u6027\u80fd\u7684\u7ebf\u7a0b\u95f4\u901a\u4fe1\u673a\u5236\u3002",(0,i.kt)("inlineCode",{parentName:"p"},"Channel")," \u7ba1\u9053\u4e5f\u662f\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},".NET/C#")," \u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u751f\u4ea7\u8005-\u8ba2\u9605\u8005")," \u6a21\u5f0f\u6700\u7b80\u6613\u4e14\u6700\u4e3a\u5f3a\u5927\u7684\u5b9e\u73b0\u3002"),(0,i.kt)("h3",{id:"3341-\u4e86\u89e3-channel"},"33.4.1 \u4e86\u89e3 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Channel")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Channel")," \u662f\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET Core 2.1+")," \u7248\u672c\u4e4b\u540e\u52a0\u5165\u3002",(0,i.kt)("inlineCode",{parentName:"p"},"Channel")," \u5e95\u5c42\u5b9e\u73b0\u662f\u4e00\u4e2a\u9ad8\u6548\u7684\u3001\u7ebf\u7a0b\u5b89\u5168\u7684\u961f\u5217\uff0c\u53ef\u4ee5\u5728\u7ebf\u7a0b\u4e4b\u95f4\u4f20\u9012\u6570\u636e\u3002"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Channel")," \u7684\u4e3b\u8981\u5e94\u7528\u573a\u666f\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"\u53d1\u5e03/\u8ba2\u9605\u3001\u89c2\u5bdf\u8005\u6a21\u5f0f")," \u4e2d\u4f7f\u7528\uff0c\u5982\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"\u4e8b\u4ef6\u603b\u7ebf")," \u5c31\u662f\u6700\u597d\u7684\u5b9e\u73b0\u65b9\u5f0f\u3002\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"Channel")," \u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u751f\u4ea7-\u6d88\u8d39")," \u673a\u5236\u53ef\u4ee5\u51cf\u5c11\u9879\u76ee\u95f4\u7684\u8026\u5408\uff0c\u63d0\u9ad8\u5e94\u7528\u541e\u5410\u91cf\u3002"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"ChannelContext")," \u5bc6\u5c01\u7c7b\uff0c\u63d0\u4f9b ",(0,i.kt)("inlineCode",{parentName:"p"},"UnBoundedChannel")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"BoundedChannel")," \u4e24\u79cd\u7ba1\u9053\u901a\u4fe1\u6a21\u5f0f\u3002"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"UnBoundedChannel"),"\uff1a\u5177\u6709\u65e0\u9650\u5bb9\u91cf\u7684 ",(0,i.kt)("inlineCode",{parentName:"li"},"Channel"),", \u751f\u4ea7\u8005\u53ef\u4ee5\u5168\u901f\u8fdb\u884c\u751f\u4ea7\u6570\u636e\uff0c\u4f46\u5982\u679c\u6d88\u8d39\u8005\u7684\u6d88\u8d39\u901f\u5ea6\u4f4e\u4e8e\u751f\u4ea7\u8005\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Channel")," \u7684\u8d44\u6e90\u4f7f\u7528\u4f1a\u65e0\u9650\u589e\u52a0\uff0c\u4f1a\u6709\u670d\u52a1\u5668\u8d44\u6e90\u8017\u5c3d\u7684\u53ef\u80fd\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"BoundedChannel"),"\uff1a\u5177\u6709\u6709\u9650\u5bb9\u91cf\u7684 ",(0,i.kt)("inlineCode",{parentName:"li"},"Channel"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Furion")," \u6846\u67b6\u9ed8\u8ba4\u4e3a ",(0,i.kt)("inlineCode",{parentName:"li"},"1000"),"\uff0c\u5230\u8fbe\u4e0a\u9650\u540e\uff0c\u751f\u4ea7\u8005\u8fdb\u5165\u7b49\u5f85\u5199\u5165\u76f4\u5230\u6709\u7a7a\u95f2\uff0c\u597d\u5904\u662f\u53ef\u4ee5\u63a7\u5236\u751f\u4ea7\u7684\u901f\u5ea6\uff0c\u63a7\u5236\u7cfb\u7edf\u8d44\u6e90\u7684\u4f7f\u7528\u3002",(0,i.kt)("strong",{parentName:"li"},"\uff08\u63a8\u8350\uff09"))),(0,i.kt)("h3",{id:"3342-\u5e38\u89c4\u4f7f\u7528"},"33.4.2 \u5e38\u89c4\u4f7f\u7528"),(0,i.kt)("h4",{id:"\u521b\u5efa-channelhandlertmessage-\u7ba1\u9053\u5904\u7406\u7a0b\u5e8f"},"\u521b\u5efa ",(0,i.kt)("inlineCode",{parentName:"h4"},"ChannelHandler")," \u7ba1\u9053\u5904\u7406\u7a0b\u5e8f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,10,17}",showLineNumbers:!0,"":!0,"{1,10,17}":!0},'using Furion.IPCChannel;\nusing System;\nusing System.Threading.Tasks;\n\nnamespace Furion.Core\n{\n /// \n /// \u521b\u5efa\u7ba1\u9053\u5904\u7406\u7a0b\u5e8f\uff08\u5904\u7406 String \u7c7b\u578b\u6d88\u606f\uff09\n /// \n public class MyChannelHandler : ChannelHandler\n {\n /// \n /// \u63a5\u53d7\u5230\u7ba1\u9053\u6d88\u606f\u540e\u5904\u7406\u7a0b\u5e8f\n /// \n /// \n /// \n public override Task InvokeAsync(string message)\n {\n Console.WriteLine(message);\n\n return Task.CompletedTask;\n }\n }\n}\n')),(0,i.kt)("admonition",{type:"note"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"}," ChannelHandler")," \u6cdb\u578b\u7c7b\u578b\u51b3\u5b9a\u4e86\u4f60\u8981\u63a5\u53d7\u90a3\u79cd\u7c7b\u578b\u7684\u6d88\u606f\uff0c\u4e0d\u540c\u7c7b\u578b\u6d88\u606f\u5c06\u4f1a\u81ea\u52a8\u8fc7\u6ee4\u7b5b\u9009\u3002")),(0,i.kt)("h4",{id:"\u4f7f\u7528-channelcontexttmessage-thandler-\u53d1\u9001\u6d88\u606f"},"\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"h4"},"ChannelContext")," \u53d1\u9001\u6d88\u606f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5-6}",showLineNumbers:!0,"":!0,"{5-6}":!0},'public async Task SendAsync()\n{\n for (int i = 0; i < 100; i++)\n {\n // \u4f7f\u7528\u6709\u9650\u5bb9\u91cf\u751f\u4ea7\u6570\u636e\n await ChannelContext.BoundedChannel.Writer.WriteAsync($"Loop {i} times.");\n }\n}\n')),(0,i.kt)("p",null,"\u4ee5\u4e0a\u4ee3\u7801\u4e5f\u53ef\u4ee5\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"ChannelContext.BoundedChannel.Writer.TryWrite()")," \u540c\u6b65\u5199\u5165\u3002"),(0,i.kt)("h3",{id:"3343-\u5b9e\u73b0\u591a\u8ba2\u9605"},"33.4.3 \u5b9e\u73b0\u591a\u8ba2\u9605"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u521d\u59cb\u5316\u4e86\u4e00\u4e2a\u957f\u65f6\u95f4\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Task")," \u4efb\u52a1\u8fdb\u884c\u6570\u636e\u68c0\u67e5\u53ca\u8ba2\u9605\uff0c\u5982\u9700\u5b9e\u73b0\u591a\u8ba2\u9605\u6a21\u5f0f\uff0c\u53ef\u521b\u5efa\u65b0\u7684\u8ba2\u9605\u4efb\u52a1\u5373\u53ef\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var reader = ChannelContext.BoundedChannel.Reader;\n\n// \u521b\u5efa\u957f\u65f6\u95f4\u7ebf\u7a0b\u7ba1\u9053\u8bfb\u53d6\u5668\n_ = Task.Factory.StartNew(async () =>\n {\n while (await reader.WaitToReadAsync())\n {\n if (!reader.TryRead(out var message)) continue;\n // \u9ed8\u8ba4\u91cd\u8bd5 3 \u6b21\uff08\u6bcf\u6b21\u95f4\u9694 1s\uff09\n await Retry.Invoke(async () => await Activator.CreateInstance().InvokeAsync(message), 3, 1000, finalThrow: false);\n }\n }, TaskCreationOptions.LongRunning);\n")),(0,i.kt)("h3",{id:"3344-\u66f4\u591a-channel-\u77e5\u8bc6"},"33.4.4 \u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"h3"},"Channel")," \u77e5\u8bc6"),(0,i.kt)("p",null,"\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://www.cnblogs.com/tiger-wang/p/14068973.html"},"Dotnet Core \u4e0b\u7684 Channel, \u4f60\u7528\u4e86\u5417\uff1f")," \u535a\u5ba2\u6559\u7a0b\uff08\ud83d\ude03 \u5199\u7684\u4e0d\u9519\uff09"),(0,i.kt)("h3",{id:"3345-callcontext-\u65b9\u5f0f"},"33.4.5 ",(0,i.kt)("inlineCode",{parentName:"h3"},"CallContext")," \u65b9\u5f0f"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion v2.18+")," \u7248\u672c\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"CallContext")," \u9759\u6001\u7c7b\uff0c\u5185\u90e8\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"AsyncLocal")," \u5b9e\u73b0\uff0c\u4e5f\u53ef\u4ee5\u5b9e\u73b0\u7ebf\u7a0b\u95f4\u901a\u4fe1\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'CallContext.SetLocalValue("name", "Furion");\nCallContext.GetLocalValue("name");\n\nCallContext.SetLocalValue("count", 1);\nCallContext.GetLocalValue("count");\n')),(0,i.kt)("h2",{id:"345-\u8fdb\u7a0b\u5916\u901a\u4fe1\u5171\u4eab\u5185\u5b58"},"34.5 \u8fdb\u7a0b\u5916\u901a\u4fe1\uff08\u5171\u4eab\u5185\u5b58\uff09"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u76ee\u524d\u6682\u672a\u63d0\u4f9b\u7684\u8fdb\u7a0b\u5916\u901a\u4fe1\u529f\u80fd\uff0c\u5c06\u5728\u540e\u7eed\u7248\u672c\u5b9e\u73b0\uff08\u4e3b\u8981\u662f\u6a21\u5757\u8bbe\u8ba1\u8fd8\u672a\u60f3\u597d\uff0c\u6280\u672f\u5df2\u5b9e\u73b0\uff09\u3002"),(0,i.kt)("p",null,"\u4e3b\u8981\u662f\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"MemoryMapperFile")," \u5b9e\u73b0\u5171\u4eab\u5185\u5b58\u8fbe\u5230\u8fdb\u7a0b\u5916\u901a\u4fe1\u529f\u80fd\uff0c",(0,i.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/dotnet/api/system.io.memorymappedfiles.memorymappedfile?view=net-5.0"},"\u4e86\u89e3\u66f4\u591a MemoryMapperFile")),(0,i.kt)("h2",{id:"336-\u53cd\u9988\u4e0e\u5efa\u8bae"},"33.6 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/934e2055.c48809ce.js b/handbook/build/assets/js/934e2055.c48809ce.js deleted file mode 100644 index 202d2d7c39..0000000000 --- a/handbook/build/assets/js/934e2055.c48809ce.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4918],{998:function(e,n,t){t.r(n),t.d(n,{assets:function(){return s},contentTitle:function(){return p},default:function(){return m},frontMatter:function(){return o},metadata:function(){return d},toc:function(){return u}});var a=t(3117),r=t(102),i=(t(7294),t(3905)),l=["components"],o={id:"ipc",title:"33. IPC \u8fdb\u7a0b\u901a\u4fe1",sidebar_label:"33. IPC \u8fdb\u7a0b\u901a\u4fe1"},p=void 0,d={unversionedId:"ipc",id:"ipc",title:"33. IPC \u8fdb\u7a0b\u901a\u4fe1",description:"33.1 \u4ec0\u4e48\u662f IPC",source:"@site/docs/ipc.mdx",sourceDirName:".",slug:"/ipc",permalink:"/furion/docs/ipc",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/ipc.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"ipc",title:"33. IPC \u8fdb\u7a0b\u901a\u4fe1",sidebar_label:"33. IPC \u8fdb\u7a0b\u901a\u4fe1"},sidebar:"docs",previous:{title:"32. \u4f1a\u8bdd\u548c\u72b6\u6001\u7ba1\u7406",permalink:"/furion/docs/sesssion-state"},next:{title:"34.1 \u5728 IIS \u90e8\u7f72",permalink:"/furion/docs/deploy-iis"}},s={},u=[{value:"33.1 \u4ec0\u4e48\u662f IPC",id:"331-\u4ec0\u4e48\u662f-ipc",level:2},{value:"33.2 \u5b9e\u73b0 IPC \u901a\u4fe1\u65b9\u5f0f",id:"332-\u5b9e\u73b0-ipc-\u901a\u4fe1\u65b9\u5f0f",level:2},{value:"33.3 IPC \u901a\u4fe1\u6a21\u5f0f",id:"333-ipc-\u901a\u4fe1\u6a21\u5f0f",level:2},{value:"33.4 \u8fdb\u7a0b\u5185\u901a\u4fe1\uff08\u7ebf\u7a0b\u95f4\uff09",id:"334-\u8fdb\u7a0b\u5185\u901a\u4fe1\u7ebf\u7a0b\u95f4",level:2},{value:"33.4.1 \u4e86\u89e3 Channel",id:"3341-\u4e86\u89e3-channel",level:3},{value:"33.4.2 \u5e38\u89c4\u4f7f\u7528",id:"3342-\u5e38\u89c4\u4f7f\u7528",level:3},{value:"\u521b\u5efa ChannelHandler<TMessage> \u7ba1\u9053\u5904\u7406\u7a0b\u5e8f",id:"\u521b\u5efa-channelhandlertmessage-\u7ba1\u9053\u5904\u7406\u7a0b\u5e8f",level:4},{value:"\u4f7f\u7528 ChannelContext<TMessage, THandler> \u53d1\u9001\u6d88\u606f",id:"\u4f7f\u7528-channelcontexttmessage-thandler-\u53d1\u9001\u6d88\u606f",level:4},{value:"33.4.3 \u5b9e\u73b0\u591a\u8ba2\u9605",id:"3343-\u5b9e\u73b0\u591a\u8ba2\u9605",level:3},{value:"33.4.4 \u66f4\u591a Channel \u77e5\u8bc6",id:"3344-\u66f4\u591a-channel-\u77e5\u8bc6",level:3},{value:"33.4.5 CallContext \u65b9\u5f0f",id:"3345-callcontext-\u65b9\u5f0f",level:3},{value:"34.5 \u8fdb\u7a0b\u5916\u901a\u4fe1\uff08\u5171\u4eab\u5185\u5b58\uff09",id:"345-\u8fdb\u7a0b\u5916\u901a\u4fe1\u5171\u4eab\u5185\u5b58",level:2},{value:"33.6 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"336-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:u};function m(e){var n=e.components,t=(0,r.Z)(e,l);return(0,i.kt)("wrapper",(0,a.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"331-\u4ec0\u4e48\u662f-ipc"},"33.1 \u4ec0\u4e48\u662f ",(0,i.kt)("inlineCode",{parentName:"h2"},"IPC")),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"\u5f15\u7528\u767e\u5ea6\u767e\u79d1"),(0,i.kt)("p",{parentName:"blockquote"},"IPC\uff08Inter-Process Communication\uff0c\u8fdb\u7a0b\u95f4\u901a\u4fe1\uff09\u3002\u8fdb\u7a0b\u95f4\u901a\u4fe1\u662f\u6307\u4e24\u4e2a\u8fdb\u7a0b\u7684\u6570\u636e\u4e4b\u95f4\u4ea7\u751f\u4ea4\u4e92\u3002")),(0,i.kt)("p",null,"\u901a\u4fd7\u70b9\u8bf4\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"IPC")," \u53ef\u4ee5\u5b9e\u73b0\u4e0d\u540c\u5e94\u7528\u7a0b\u5e8f\u95f4\u901a\u4fe1\uff08\u4ea4\u4e92\u6570\u636e\uff09\u3002"),(0,i.kt)("h2",{id:"332-\u5b9e\u73b0-ipc-\u901a\u4fe1\u65b9\u5f0f"},"33.2 \u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"h2"},"IPC")," \u901a\u4fe1\u65b9\u5f0f"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u534a\u53cc\u5de5 Unix \u7ba1\u9053"),(0,i.kt)("li",{parentName:"ul"},"FIFOs(\u547d\u540d\u7ba1\u9053)"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u6d88\u606f\u961f\u5217"),"\uff08\u5e38\u7528\u6a21\u5f0f\uff09"),(0,i.kt)("li",{parentName:"ul"},"\u4fe1\u53f7\u91cf"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u5171\u4eab\u5185\u5b58"),"\uff08\u5e38\u7528\u6a21\u5f0f\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Furion")," \u6846\u67b6\u9ed8\u8ba4\u5b9e\u73b0\u65b9\u5f0f\uff09"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u7f51\u7edc Socket"),"\uff08\u5e38\u7528\u6a21\u5f0f\uff09")),(0,i.kt)("h2",{id:"333-ipc-\u901a\u4fe1\u6a21\u5f0f"},"33.3 ",(0,i.kt)("inlineCode",{parentName:"h2"},"IPC")," \u901a\u4fe1\u6a21\u5f0f"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"IPC")," \u672c\u8eab\u6307\u7684\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"\u8fdb\u7a0b\u95f4")," \u901a\u4fe1\uff0c\u4f46 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u5c06\u5185\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"\u8fdb\u7a0b\u95f4/\u5185")," \u4e24\u79cd\u8fdb\u7a0b\u901a\u4fe1\u6a21\u5f0f\u3002"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"\u8fdb\u7a0b\u5185\u901a\u4fe1"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Furion")," \u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"li"},"Channel")," \u7ba1\u9053\u63d0\u4f9b\u8fdb\u7a0b\u5185\u901a\u4fe1"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"\u8fdb\u7a0b\u5916\u901a\u4fe1"),"\uff1a",(0,i.kt)("inlineCode",{parentName:"li"},"Furion")," \u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"li"},"MemoryMapperFile")," \u5171\u4eab\u5185\u5b58\u65b9\u5f0f\u5b9e\u73b0\u8fdb\u7a0b\u5916\u901a\u4fe1\uff08\u540e\u7eed\u7248\u672c\u5b8c\u5584\uff09")),(0,i.kt)("h2",{id:"334-\u8fdb\u7a0b\u5185\u901a\u4fe1\u7ebf\u7a0b\u95f4"},"33.4 \u8fdb\u7a0b\u5185\u901a\u4fe1\uff08\u7ebf\u7a0b\u95f4\uff09"),(0,i.kt)("p",null,"\u8fdb\u7a0b\u5185\u901a\u4fe1\u4fd7\u79f0\u7ebf\u7a0b\u95f4\u901a\u4fe1\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"C#")," \u63d0\u4f9b\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Channel\uff08\u7ba1\u9053\uff09")," + ",(0,i.kt)("inlineCode",{parentName:"p"},"Lazy")," + ",(0,i.kt)("inlineCode",{parentName:"p"},"Task.Factory")," \u5b9e\u73b0\u957f\u65f6\u95f4\u9ad8\u6027\u80fd\u7684\u7ebf\u7a0b\u95f4\u901a\u4fe1\u673a\u5236\u3002",(0,i.kt)("inlineCode",{parentName:"p"},"Channel")," \u7ba1\u9053\u4e5f\u662f\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},".NET/C#")," \u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u751f\u4ea7\u8005-\u8ba2\u9605\u8005")," \u6a21\u5f0f\u6700\u7b80\u6613\u4e14\u6700\u4e3a\u5f3a\u5927\u7684\u5b9e\u73b0\u3002"),(0,i.kt)("h3",{id:"3341-\u4e86\u89e3-channel"},"33.4.1 \u4e86\u89e3 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Channel")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Channel")," \u662f\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET Core 2.1+")," \u7248\u672c\u4e4b\u540e\u52a0\u5165\u3002",(0,i.kt)("inlineCode",{parentName:"p"},"Channel")," \u5e95\u5c42\u5b9e\u73b0\u662f\u4e00\u4e2a\u9ad8\u6548\u7684\u3001\u7ebf\u7a0b\u5b89\u5168\u7684\u961f\u5217\uff0c\u53ef\u4ee5\u5728\u7ebf\u7a0b\u4e4b\u95f4\u4f20\u9012\u6570\u636e\u3002"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Channel")," \u7684\u4e3b\u8981\u5e94\u7528\u573a\u666f\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"\u53d1\u5e03/\u8ba2\u9605\u3001\u89c2\u5bdf\u8005\u6a21\u5f0f")," \u4e2d\u4f7f\u7528\uff0c\u5982\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"\u4e8b\u4ef6\u603b\u7ebf")," \u5c31\u662f\u6700\u597d\u7684\u5b9e\u73b0\u65b9\u5f0f\u3002\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"Channel")," \u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u751f\u4ea7-\u6d88\u8d39")," \u673a\u5236\u53ef\u4ee5\u51cf\u5c11\u9879\u76ee\u95f4\u7684\u8026\u5408\uff0c\u63d0\u9ad8\u5e94\u7528\u541e\u5410\u91cf\u3002"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"ChannelContext")," \u5bc6\u5c01\u7c7b\uff0c\u63d0\u4f9b ",(0,i.kt)("inlineCode",{parentName:"p"},"UnBoundedChannel")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"BoundedChannel")," \u4e24\u79cd\u7ba1\u9053\u901a\u4fe1\u6a21\u5f0f\u3002"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"UnBoundedChannel"),"\uff1a\u5177\u6709\u65e0\u9650\u5bb9\u91cf\u7684 ",(0,i.kt)("inlineCode",{parentName:"li"},"Channel"),", \u751f\u4ea7\u8005\u53ef\u4ee5\u5168\u901f\u8fdb\u884c\u751f\u4ea7\u6570\u636e\uff0c\u4f46\u5982\u679c\u6d88\u8d39\u8005\u7684\u6d88\u8d39\u901f\u5ea6\u4f4e\u4e8e\u751f\u4ea7\u8005\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Channel")," \u7684\u8d44\u6e90\u4f7f\u7528\u4f1a\u65e0\u9650\u589e\u52a0\uff0c\u4f1a\u6709\u670d\u52a1\u5668\u8d44\u6e90\u8017\u5c3d\u7684\u53ef\u80fd\u3002"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"BoundedChannel"),"\uff1a\u5177\u6709\u6709\u9650\u5bb9\u91cf\u7684 ",(0,i.kt)("inlineCode",{parentName:"li"},"Channel"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Furion")," \u6846\u67b6\u9ed8\u8ba4\u4e3a ",(0,i.kt)("inlineCode",{parentName:"li"},"1000"),"\uff0c\u5230\u8fbe\u4e0a\u9650\u540e\uff0c\u751f\u4ea7\u8005\u8fdb\u5165\u7b49\u5f85\u5199\u5165\u76f4\u5230\u6709\u7a7a\u95f2\uff0c\u597d\u5904\u662f\u53ef\u4ee5\u63a7\u5236\u751f\u4ea7\u7684\u901f\u5ea6\uff0c\u63a7\u5236\u7cfb\u7edf\u8d44\u6e90\u7684\u4f7f\u7528\u3002",(0,i.kt)("strong",{parentName:"li"},"\uff08\u63a8\u8350\uff09"))),(0,i.kt)("h3",{id:"3342-\u5e38\u89c4\u4f7f\u7528"},"33.4.2 \u5e38\u89c4\u4f7f\u7528"),(0,i.kt)("h4",{id:"\u521b\u5efa-channelhandlertmessage-\u7ba1\u9053\u5904\u7406\u7a0b\u5e8f"},"\u521b\u5efa ",(0,i.kt)("inlineCode",{parentName:"h4"},"ChannelHandler")," \u7ba1\u9053\u5904\u7406\u7a0b\u5e8f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,10,17}",showLineNumbers:!0,"":!0,"{1,10,17}":!0},'using Furion.IPCChannel;\nusing System;\nusing System.Threading.Tasks;\n\nnamespace Furion.Core\n{\n /// \n /// \u521b\u5efa\u7ba1\u9053\u5904\u7406\u7a0b\u5e8f\uff08\u5904\u7406 String \u7c7b\u578b\u6d88\u606f\uff09\n /// \n public class MyChannelHandler : ChannelHandler\n {\n /// \n /// \u63a5\u53d7\u5230\u7ba1\u9053\u6d88\u606f\u540e\u5904\u7406\u7a0b\u5e8f\n /// \n /// \n /// \n public override Task InvokeAsync(string message)\n {\n Console.WriteLine(message);\n\n return Task.CompletedTask;\n }\n }\n}\n')),(0,i.kt)("admonition",{type:"note"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"}," ChannelHandler")," \u6cdb\u578b\u7c7b\u578b\u51b3\u5b9a\u4e86\u4f60\u8981\u63a5\u53d7\u90a3\u79cd\u7c7b\u578b\u7684\u6d88\u606f\uff0c\u4e0d\u540c\u7c7b\u578b\u6d88\u606f\u5c06\u4f1a\u81ea\u52a8\u8fc7\u6ee4\u7b5b\u9009\u3002")),(0,i.kt)("h4",{id:"\u4f7f\u7528-channelcontexttmessage-thandler-\u53d1\u9001\u6d88\u606f"},"\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"h4"},"ChannelContext")," \u53d1\u9001\u6d88\u606f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5-6}",showLineNumbers:!0,"":!0,"{5-6}":!0},'public async Task SendAsync()\n{\n for (int i = 0; i < 100; i++)\n {\n // \u4f7f\u7528\u6709\u9650\u5bb9\u91cf\u751f\u4ea7\u6570\u636e\n await ChannelContext.BoundedChannel.Writer.WriteAsync($"Loop {i} times.");\n }\n}\n')),(0,i.kt)("p",null,"\u4ee5\u4e0a\u4ee3\u7801\u4e5f\u53ef\u4ee5\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"ChannelContext.BoundedChannel.Writer.TryWrite()")," \u540c\u6b65\u5199\u5165\u3002"),(0,i.kt)("h3",{id:"3343-\u5b9e\u73b0\u591a\u8ba2\u9605"},"33.4.3 \u5b9e\u73b0\u591a\u8ba2\u9605"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u521d\u59cb\u5316\u4e86\u4e00\u4e2a\u957f\u65f6\u95f4\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"Task")," \u4efb\u52a1\u8fdb\u884c\u6570\u636e\u68c0\u67e5\u53ca\u8ba2\u9605\uff0c\u5982\u9700\u5b9e\u73b0\u591a\u8ba2\u9605\u6a21\u5f0f\uff0c\u53ef\u521b\u5efa\u65b0\u7684\u8ba2\u9605\u4efb\u52a1\u5373\u53ef\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var reader = ChannelContext.BoundedChannel.Reader;\n\n// \u521b\u5efa\u957f\u65f6\u95f4\u7ebf\u7a0b\u7ba1\u9053\u8bfb\u53d6\u5668\n_ = Task.Factory.StartNew(async () =>\n {\n while (await reader.WaitToReadAsync())\n {\n if (!reader.TryRead(out var message)) continue;\n // \u9ed8\u8ba4\u91cd\u8bd5 3 \u6b21\uff08\u6bcf\u6b21\u95f4\u9694 1s\uff09\n await Retry.Invoke(async () => await Activator.CreateInstance().InvokeAsync(message), 3, 1000, finalThrow: false);\n }\n }, TaskCreationOptions.LongRunning);\n")),(0,i.kt)("h3",{id:"3344-\u66f4\u591a-channel-\u77e5\u8bc6"},"33.4.4 \u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"h3"},"Channel")," \u77e5\u8bc6"),(0,i.kt)("p",null,"\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://www.cnblogs.com/tiger-wang/p/14068973.html"},"Dotnet Core \u4e0b\u7684 Channel, \u4f60\u7528\u4e86\u5417\uff1f")," \u535a\u5ba2\u6559\u7a0b\uff08\ud83d\ude03 \u5199\u7684\u4e0d\u9519\uff09"),(0,i.kt)("h3",{id:"3345-callcontext-\u65b9\u5f0f"},"33.4.5 ",(0,i.kt)("inlineCode",{parentName:"h3"},"CallContext")," \u65b9\u5f0f"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion v2.18+")," \u7248\u672c\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"CallContext")," \u9759\u6001\u7c7b\uff0c\u5185\u90e8\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"AsyncLocal")," \u5b9e\u73b0\uff0c\u4e5f\u53ef\u4ee5\u5b9e\u73b0\u7ebf\u7a0b\u95f4\u901a\u4fe1\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'CallContext.SetLocalValue("name", "Furion");\nCallContext.GetLocalValue("name");\n\nCallContext.SetLocalValue("count", 1);\nCallContext.GetLocalValue("count");\n')),(0,i.kt)("h2",{id:"345-\u8fdb\u7a0b\u5916\u901a\u4fe1\u5171\u4eab\u5185\u5b58"},"34.5 \u8fdb\u7a0b\u5916\u901a\u4fe1\uff08\u5171\u4eab\u5185\u5b58\uff09"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u76ee\u524d\u6682\u672a\u63d0\u4f9b\u7684\u8fdb\u7a0b\u5916\u901a\u4fe1\u529f\u80fd\uff0c\u5c06\u5728\u540e\u7eed\u7248\u672c\u5b9e\u73b0\uff08\u4e3b\u8981\u662f\u6a21\u5757\u8bbe\u8ba1\u8fd8\u672a\u60f3\u597d\uff0c\u6280\u672f\u5df2\u5b9e\u73b0\uff09\u3002"),(0,i.kt)("p",null,"\u4e3b\u8981\u662f\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"MemoryMapperFile")," \u5b9e\u73b0\u5171\u4eab\u5185\u5b58\u8fbe\u5230\u8fdb\u7a0b\u5916\u901a\u4fe1\u529f\u80fd\uff0c",(0,i.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/dotnet/api/system.io.memorymappedfiles.memorymappedfile?view=net-5.0"},"\u4e86\u89e3\u66f4\u591a MemoryMapperFile")),(0,i.kt)("h2",{id:"336-\u53cd\u9988\u4e0e\u5efa\u8bae"},"33.6 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return s},kt:function(){return m}});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function l(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var p=a.createContext({}),d=function(e){var n=a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},s=function(e){var n=d(e.components);return a.createElement(p.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},c=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,p=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),c=d(t),m=r,C=c["".concat(p,".").concat(m)]||c[m]||u[m]||i;return t?a.createElement(C,l(l({ref:n},s),{},{components:t})):a.createElement(C,l({ref:n},s))}));function m(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,l=new Array(i);l[0]=c;var o={};for(var p in n)hasOwnProperty.call(n,p)&&(o[p]=n[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,l[1]=o;for(var d=2;dJSON Schema",id:"271-\u5173\u4e8e-json-schema",level:2},{value:"2.7.2 \u5b66\u4e60 JSON Schema \u7f16\u5199",id:"272-\u5b66\u4e60-json-schema-\u7f16\u5199",level:2},{value:"2.7.3 \u6846\u67b6\u63d0\u4f9b",id:"273-\u6846\u67b6\u63d0\u4f9b",level:2},{value:"2.7.4 \u5982\u4f55\u4f7f\u7528",id:"274-\u5982\u4f55\u4f7f\u7528",level:2},{value:"2.7.5 JSON Schema \u5931\u6548\u89e3\u51b3",id:"275-json-schema-\u5931\u6548\u89e3\u51b3",level:2},{value:"2.7.5.1 Visual Studio",id:"2751-visual-studio",level:3},{value:"2.7.5.2 Visual Studio Code",id:"2752-visual-studio-code",level:3},{value:"2.7.6 \u5982\u4f55\u66f4\u65b0 JSON Schema",id:"276-\u5982\u4f55\u66f4\u65b0-json-schema",level:2},{value:"2.7.6.1 Visual Studio",id:"2761-visual-studio",level:3},{value:"2.7.6.2 Visual Studio Code",id:"2762-visual-studio-code",level:3},{value:"2.7.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"277-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:u};function h(e){var t=e.components,n=(0,i.Z)(e,s);return(0,o.kt)("wrapper",(0,a.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"271-\u5173\u4e8e-json-schema"},"2.7.1 \u5173\u4e8e ",(0,o.kt)("inlineCode",{parentName:"h2"},"JSON Schema")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"JSON Schema")," \u662f\u7528\u4e8e\u9a8c\u8bc1 ",(0,o.kt)("inlineCode",{parentName:"p"},"JSON")," \u6570\u636e\u7ed3\u6784\u7684\u5f3a\u5927\u5de5\u5177\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Schema")," \u53ef\u4ee5\u7406\u89e3\u4e3a\u6a21\u5f0f\u6216\u8005\u89c4\u5219\u3002"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u6709\u4e86 ",(0,o.kt)("inlineCode",{parentName:"strong"},"JSON Schema")," \u518d\u4e5f\u4e0d\u6015\u914d\u7f6e\u5199\u9519\u7684\u60c5\u51b5\u4e86\uff01")),(0,o.kt)("h2",{id:"272-\u5b66\u4e60-json-schema-\u7f16\u5199"},"2.7.2 \u5b66\u4e60 ",(0,o.kt)("inlineCode",{parentName:"h2"},"JSON Schema")," \u7f16\u5199"),(0,o.kt)("p",null,"\u4f5c\u4e3a\u4e00\u4e2a\u6846\u67b6\u63d0\u4f9b ",(0,o.kt)("inlineCode",{parentName:"p"},"JSON Schema")," \u662f\u975e\u5e38\u6709\u5fc5\u8981\u7684\uff0c\u53ef\u4ee5\u8ba9\u5f00\u53d1\u8005\u5728\u6dfb\u52a0\u914d\u7f6e\u7684\u65f6\u5019\u80fd\u591f\u6709\u667a\u80fd\u63d0\u793a\u548c\u6821\u9a8c\u529f\u80fd\uff0c\u5982\u679c\u60f3\u5b66\u4e60 ",(0,o.kt)("inlineCode",{parentName:"p"},"JSON Schema")," \u7f16\u5199\u53ef\u4ee5\u67e5\u770b\u4ee5\u4e0b\u6587\u6863\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://json-schema.apifox.cn/"},"https://json-schema.apifox.cn/")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://zhuanlan.zhihu.com/p/355175938"},"https://zhuanlan.zhihu.com/p/355175938"))),(0,o.kt)("p",null,"\u8fd9\u91cc\u4e5f\u63d0\u4f9b\u4e00\u4e2a\u975e\u5e38\u4fbf\u6377\u7684\u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"p"},"JSON Schema")," \u7684\u5728\u7ebf\u7f51\u7ad9\uff0c\u53ef\u4ee5\u6839\u636e ",(0,o.kt)("inlineCode",{parentName:"p"},"json")," \u6587\u4ef6\u5185\u5bb9\u81ea\u52a8\u751f\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"JSON Schema"),"\uff0c\u4e4b\u540e\u8fdb\u884c\u5c0f\u91cf\u4fee\u6539\u5373\u53ef\uff1a"),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"https://hellosean1025.github.io/json-schema-visual-editor/"},"https://hellosean1025.github.io/json-schema-visual-editor/")),(0,o.kt)("h2",{id:"273-\u6846\u67b6\u63d0\u4f9b"},"2.7.3 \u6846\u67b6\u63d0\u4f9b"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u5b8c\u6574\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u548c ",(0,o.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"JSON Schema")," \u6587\u4ef6\uff0c\u901a\u8fc7\u8be5\u6587\u4ef6\u53ef\u4ee5\u5728\u7f16\u5199\u914d\u7f6e\u6587\u4ef6\u65f6\u63d0\u4f9b\u5b8c\u6574\u7684\u667a\u80fd\u63d0\u793a\u548c\u6821\u9a8c\u3002"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"},"\u67e5\u770b ",(0,o.kt)("inlineCode",{parentName:"a"},"JSON Schema")," \u6e90\u7801\u5730\u5740"))),(0,o.kt)("h2",{id:"274-\u5982\u4f55\u4f7f\u7528"},"2.7.4 \u5982\u4f55\u4f7f\u7528"),(0,o.kt)("p",null,"\u4f7f\u7528\u65b9\u5f0f\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700\u8981\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u7684\u5934\u90e8\u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"p"},'"$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json",')," \u5373\u53ef\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},'{\n "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json",\n\n "Logging": {\n "LogLevel": {\n "Default": "Information",\n "Microsoft": "Warning",\n "Microsoft.Hosting.Lifetime": "Information",\n "Microsoft.EntityFrameworkCore": "Information",\n "Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"\n }\n },\n "AllowedHosts": "*"\n}\n')),(0,o.kt)("img",{src:(0,r.Z)("img/js1.png")}),(0,o.kt)("img",{src:(0,r.Z)("img/js2.png")}),(0,o.kt)("img",{src:(0,r.Z)("img/js3.png")}),(0,o.kt)("img",{src:(0,r.Z)("img/js4.png")}),(0,o.kt)("img",{src:(0,r.Z)("img/js7.png")}),(0,o.kt)("h2",{id:"275-json-schema-\u5931\u6548\u89e3\u51b3"},"2.7.5 ",(0,o.kt)("inlineCode",{parentName:"h2"},"JSON Schema")," \u5931\u6548\u89e3\u51b3"),(0,o.kt)("p",null,"\u5982\u679c\u6dfb\u52a0\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},'"$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json",')," \u4f9d\u7136\u65e0\u6cd5\u8fdb\u884c\u667a\u80fd\u63d0\u793a\u6821\u9a8c\uff0c\u53ef\u5c1d\u8bd5\u5173\u95ed ",(0,o.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u518d\u91cd\u65b0\u6253\u5f00\u3002"),(0,o.kt)("p",null,"\u5982\u679c\u4e0a\u9762\u6b65\u9aa4\u4f9d\u7136\u65e0\u6548\uff0c\u90a3\u4e48\u8fd8\u53ef\u4ee5\u901a\u8fc7\u4e0b\u9762\u65b9\u5f0f\uff1a"),(0,o.kt)("h3",{id:"2751-visual-studio"},"2.7.5.1 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Visual Studio")),(0,o.kt)("img",{src:(0,r.Z)("img/js5.png")}),(0,o.kt)("img",{src:(0,r.Z)("img/js6.png")}),(0,o.kt)("h3",{id:"2752-visual-studio-code"},"2.7.5.2 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Visual Studio Code")),(0,o.kt)("p",null,"\u91cd\u542f ",(0,o.kt)("inlineCode",{parentName:"p"},"Visual Studio Code")," \u5373\u53ef\u3002"),(0,o.kt)("h2",{id:"276-\u5982\u4f55\u66f4\u65b0-json-schema"},"2.7.6 \u5982\u4f55\u66f4\u65b0 ",(0,o.kt)("inlineCode",{parentName:"h2"},"JSON Schema")),(0,o.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"JSON Schema")," \u5728\u7b2c\u4e00\u6b21\u83b7\u53d6\u4e4b\u540e\u4f1a\u81ea\u52a8\u7f13\u5b58\u8d77\u6765\uff0c\u53ef\u80fd\u4f1a\u5bfc\u81f4 ",(0,o.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u63d0\u793a\u9519\u8bef\uff0c\u8fd9\u4e2a\u65f6\u5019\u53ea\u9700\u8981\u5220\u9664\u7f13\u5b58\u5373\u53ef\u3002"),(0,o.kt)("h3",{id:"2761-visual-studio"},"2.7.6.1 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Visual Studio")),(0,o.kt)("p",null,"\u6253\u5f00\u7535\u8111\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"\u8fd0\u884c")," \u5e76\u8f93\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"%AppData%"),"\uff0c\u4e4b\u540e\u8fdb\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"C:\\Users\\\u4f60\u7684\u7535\u8111\u7528\u6237\u540d\\AppData\\Local\\Microsoft\\VisualStudio")," \u4e0b"),(0,o.kt)("img",{src:(0,r.Z)("img/js8.png")}),(0,o.kt)("img",{src:(0,r.Z)("img/js9.png")}),(0,o.kt)("img",{src:(0,r.Z)("img/js10.png")}),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u4e4b\u540e\u5220\u9664 ",(0,o.kt)("inlineCode",{parentName:"strong"},"http/https")," \u5f00\u5934\u7684\u6587\u4ef6\u5373\u53ef\u3002")),(0,o.kt)("h3",{id:"2762-visual-studio-code"},"2.7.6.2 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Visual Studio Code")),(0,o.kt)("p",null,"\u540c\u4e0a\uff0c\u8fd0\u884c\u8fdb\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"%AppData%"),"\uff0c\u4e4b\u540e\u8fdb\u5165\u4e0b\u5217\u8def\u5f84\uff1a",(0,o.kt)("inlineCode",{parentName:"p"},"C:\\Users\\\u4f60\u7684\u7535\u8111\u7528\u6237\u540d\\AppData\\Roaming\\Code\\User\\globalStorage\\vscode.json-language-features\\json-schema-cache")),(0,o.kt)("img",{src:(0,r.Z)("img/js11.png")}),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u4e4b\u540e\u5220\u9664\u8fd9\u4e9b\u6587\u4ef6\u5373\u53ef\u3002")),(0,o.kt)("h2",{id:"277-\u53cd\u9988\u4e0e\u5efa\u8bae"},"2.7.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}h.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return c},kt:function(){return d}});var a=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function r(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var l=a.createContext({}),p=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},c=function(e){var t=p(e.components);return a.createElement(l.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=p(n),d=i,h=u["".concat(l,".").concat(d)]||u[d]||m[d]||o;return n?a.createElement(h,r(r({ref:t},c),{},{components:n})):a.createElement(h,r({ref:t},c))}));function d(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=n.length,r=new Array(o);r[0]=u;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:i,r[1]=s;for(var p=2;p=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var l=a.createContext({}),p=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},c=function(e){var t=p(e.components);return a.createElement(l.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=p(n),d=i,h=u["".concat(l,".").concat(d)]||u[d]||m[d]||o;return n?a.createElement(h,r(r({ref:t},c),{},{components:n})):a.createElement(h,r({ref:t},c))}));function d(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=n.length,r=new Array(o);r[0]=u;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:i,r[1]=s;for(var p=2;pJSON Schema",id:"271-\u5173\u4e8e-json-schema",level:2},{value:"2.7.2 \u5b66\u4e60 JSON Schema \u7f16\u5199",id:"272-\u5b66\u4e60-json-schema-\u7f16\u5199",level:2},{value:"2.7.3 \u6846\u67b6\u63d0\u4f9b",id:"273-\u6846\u67b6\u63d0\u4f9b",level:2},{value:"2.7.4 \u5982\u4f55\u4f7f\u7528",id:"274-\u5982\u4f55\u4f7f\u7528",level:2},{value:"2.7.5 JSON Schema \u5931\u6548\u89e3\u51b3",id:"275-json-schema-\u5931\u6548\u89e3\u51b3",level:2},{value:"2.7.5.1 Visual Studio",id:"2751-visual-studio",level:3},{value:"2.7.5.2 Visual Studio Code",id:"2752-visual-studio-code",level:3},{value:"2.7.6 \u5982\u4f55\u66f4\u65b0 JSON Schema",id:"276-\u5982\u4f55\u66f4\u65b0-json-schema",level:2},{value:"2.7.6.1 Visual Studio",id:"2761-visual-studio",level:3},{value:"2.7.6.2 Visual Studio Code",id:"2762-visual-studio-code",level:3},{value:"2.7.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"277-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:u};function h(e){var t=e.components,n=(0,i.Z)(e,s);return(0,o.kt)("wrapper",(0,a.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"271-\u5173\u4e8e-json-schema"},"2.7.1 \u5173\u4e8e ",(0,o.kt)("inlineCode",{parentName:"h2"},"JSON Schema")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"JSON Schema")," \u662f\u7528\u4e8e\u9a8c\u8bc1 ",(0,o.kt)("inlineCode",{parentName:"p"},"JSON")," \u6570\u636e\u7ed3\u6784\u7684\u5f3a\u5927\u5de5\u5177\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Schema")," \u53ef\u4ee5\u7406\u89e3\u4e3a\u6a21\u5f0f\u6216\u8005\u89c4\u5219\u3002"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u6709\u4e86 ",(0,o.kt)("inlineCode",{parentName:"strong"},"JSON Schema")," \u518d\u4e5f\u4e0d\u6015\u914d\u7f6e\u5199\u9519\u7684\u60c5\u51b5\u4e86\uff01")),(0,o.kt)("h2",{id:"272-\u5b66\u4e60-json-schema-\u7f16\u5199"},"2.7.2 \u5b66\u4e60 ",(0,o.kt)("inlineCode",{parentName:"h2"},"JSON Schema")," \u7f16\u5199"),(0,o.kt)("p",null,"\u4f5c\u4e3a\u4e00\u4e2a\u6846\u67b6\u63d0\u4f9b ",(0,o.kt)("inlineCode",{parentName:"p"},"JSON Schema")," \u662f\u975e\u5e38\u6709\u5fc5\u8981\u7684\uff0c\u53ef\u4ee5\u8ba9\u5f00\u53d1\u8005\u5728\u6dfb\u52a0\u914d\u7f6e\u7684\u65f6\u5019\u80fd\u591f\u6709\u667a\u80fd\u63d0\u793a\u548c\u6821\u9a8c\u529f\u80fd\uff0c\u5982\u679c\u60f3\u5b66\u4e60 ",(0,o.kt)("inlineCode",{parentName:"p"},"JSON Schema")," \u7f16\u5199\u53ef\u4ee5\u67e5\u770b\u4ee5\u4e0b\u6587\u6863\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://json-schema.apifox.cn/"},"https://json-schema.apifox.cn/")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://zhuanlan.zhihu.com/p/355175938"},"https://zhuanlan.zhihu.com/p/355175938"))),(0,o.kt)("p",null,"\u8fd9\u91cc\u4e5f\u63d0\u4f9b\u4e00\u4e2a\u975e\u5e38\u4fbf\u6377\u7684\u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"p"},"JSON Schema")," \u7684\u5728\u7ebf\u7f51\u7ad9\uff0c\u53ef\u4ee5\u6839\u636e ",(0,o.kt)("inlineCode",{parentName:"p"},"json")," \u6587\u4ef6\u5185\u5bb9\u81ea\u52a8\u751f\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"JSON Schema"),"\uff0c\u4e4b\u540e\u8fdb\u884c\u5c0f\u91cf\u4fee\u6539\u5373\u53ef\uff1a"),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"https://hellosean1025.github.io/json-schema-visual-editor/"},"https://hellosean1025.github.io/json-schema-visual-editor/")),(0,o.kt)("h2",{id:"273-\u6846\u67b6\u63d0\u4f9b"},"2.7.3 \u6846\u67b6\u63d0\u4f9b"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u5b8c\u6574\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u548c ",(0,o.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"JSON Schema")," \u6587\u4ef6\uff0c\u901a\u8fc7\u8be5\u6587\u4ef6\u53ef\u4ee5\u5728\u7f16\u5199\u914d\u7f6e\u6587\u4ef6\u65f6\u63d0\u4f9b\u5b8c\u6574\u7684\u667a\u80fd\u63d0\u793a\u548c\u6821\u9a8c\u3002"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"},"\u67e5\u770b ",(0,o.kt)("inlineCode",{parentName:"a"},"JSON Schema")," \u6e90\u7801\u5730\u5740"))),(0,o.kt)("h2",{id:"274-\u5982\u4f55\u4f7f\u7528"},"2.7.4 \u5982\u4f55\u4f7f\u7528"),(0,o.kt)("p",null,"\u4f7f\u7528\u65b9\u5f0f\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700\u8981\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u7684\u5934\u90e8\u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"p"},'"$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json",')," \u5373\u53ef\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},'{\n "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json",\n\n "Logging": {\n "LogLevel": {\n "Default": "Information",\n "Microsoft": "Warning",\n "Microsoft.Hosting.Lifetime": "Information",\n "Microsoft.EntityFrameworkCore": "Information",\n "Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"\n }\n },\n "AllowedHosts": "*"\n}\n')),(0,o.kt)("img",{src:(0,r.Z)("img/js1.png")}),(0,o.kt)("img",{src:(0,r.Z)("img/js2.png")}),(0,o.kt)("img",{src:(0,r.Z)("img/js3.png")}),(0,o.kt)("img",{src:(0,r.Z)("img/js4.png")}),(0,o.kt)("img",{src:(0,r.Z)("img/js7.png")}),(0,o.kt)("h2",{id:"275-json-schema-\u5931\u6548\u89e3\u51b3"},"2.7.5 ",(0,o.kt)("inlineCode",{parentName:"h2"},"JSON Schema")," \u5931\u6548\u89e3\u51b3"),(0,o.kt)("p",null,"\u5982\u679c\u6dfb\u52a0\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},'"$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json",')," \u4f9d\u7136\u65e0\u6cd5\u8fdb\u884c\u667a\u80fd\u63d0\u793a\u6821\u9a8c\uff0c\u53ef\u5c1d\u8bd5\u5173\u95ed ",(0,o.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u518d\u91cd\u65b0\u6253\u5f00\u3002"),(0,o.kt)("p",null,"\u5982\u679c\u4e0a\u9762\u6b65\u9aa4\u4f9d\u7136\u65e0\u6548\uff0c\u90a3\u4e48\u8fd8\u53ef\u4ee5\u901a\u8fc7\u4e0b\u9762\u65b9\u5f0f\uff1a"),(0,o.kt)("h3",{id:"2751-visual-studio"},"2.7.5.1 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Visual Studio")),(0,o.kt)("img",{src:(0,r.Z)("img/js5.png")}),(0,o.kt)("img",{src:(0,r.Z)("img/js6.png")}),(0,o.kt)("h3",{id:"2752-visual-studio-code"},"2.7.5.2 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Visual Studio Code")),(0,o.kt)("p",null,"\u91cd\u542f ",(0,o.kt)("inlineCode",{parentName:"p"},"Visual Studio Code")," \u5373\u53ef\u3002"),(0,o.kt)("h2",{id:"276-\u5982\u4f55\u66f4\u65b0-json-schema"},"2.7.6 \u5982\u4f55\u66f4\u65b0 ",(0,o.kt)("inlineCode",{parentName:"h2"},"JSON Schema")),(0,o.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"JSON Schema")," \u5728\u7b2c\u4e00\u6b21\u83b7\u53d6\u4e4b\u540e\u4f1a\u81ea\u52a8\u7f13\u5b58\u8d77\u6765\uff0c\u53ef\u80fd\u4f1a\u5bfc\u81f4 ",(0,o.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u63d0\u793a\u9519\u8bef\uff0c\u8fd9\u4e2a\u65f6\u5019\u53ea\u9700\u8981\u5220\u9664\u7f13\u5b58\u5373\u53ef\u3002"),(0,o.kt)("h3",{id:"2761-visual-studio"},"2.7.6.1 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Visual Studio")),(0,o.kt)("p",null,"\u6253\u5f00\u7535\u8111\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"\u8fd0\u884c")," \u5e76\u8f93\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"%AppData%"),"\uff0c\u4e4b\u540e\u8fdb\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"C:\\Users\\\u4f60\u7684\u7535\u8111\u7528\u6237\u540d\\AppData\\Local\\Microsoft\\VisualStudio")," \u4e0b"),(0,o.kt)("img",{src:(0,r.Z)("img/js8.png")}),(0,o.kt)("img",{src:(0,r.Z)("img/js9.png")}),(0,o.kt)("img",{src:(0,r.Z)("img/js10.png")}),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u4e4b\u540e\u5220\u9664 ",(0,o.kt)("inlineCode",{parentName:"strong"},"http/https")," \u5f00\u5934\u7684\u6587\u4ef6\u5373\u53ef\u3002")),(0,o.kt)("h3",{id:"2762-visual-studio-code"},"2.7.6.2 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Visual Studio Code")),(0,o.kt)("p",null,"\u540c\u4e0a\uff0c\u8fd0\u884c\u8fdb\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"%AppData%"),"\uff0c\u4e4b\u540e\u8fdb\u5165\u4e0b\u5217\u8def\u5f84\uff1a",(0,o.kt)("inlineCode",{parentName:"p"},"C:\\Users\\\u4f60\u7684\u7535\u8111\u7528\u6237\u540d\\AppData\\Roaming\\Code\\User\\globalStorage\\vscode.json-language-features\\json-schema-cache")),(0,o.kt)("img",{src:(0,r.Z)("img/js11.png")}),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u4e4b\u540e\u5220\u9664\u8fd9\u4e9b\u6587\u4ef6\u5373\u53ef\u3002")),(0,o.kt)("h2",{id:"277-\u53cd\u9988\u4e0e\u5efa\u8bae"},"2.7.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}h.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/9888.c11ad302.js b/handbook/build/assets/js/9888.c11ad302.js deleted file mode 100644 index 84b4bd150e..0000000000 --- a/handbook/build/assets/js/9888.c11ad302.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[9888],{9888:function(e,t,n){n.r(t),n.d(t,{default:function(){return fe}});var a=n(7294),r=n(4873),l=n(8875),i=a.createContext(null);function o(e){var t=e.children,n=function(e){return(0,a.useMemo)((function(){return{metadata:e.metadata,frontMatter:e.frontMatter,assets:e.assets,contentTitle:e.contentTitle,toc:e.toc}}),[e])}(e.content);return a.createElement(i.Provider,{value:n},t)}function c(){var e=(0,a.useContext)(i);if(null===e)throw new l.i6("DocProvider");return e}function s(){var e,t=c(),n=t.metadata,l=t.frontMatter,i=t.assets;return a.createElement(r.d,{title:n.title,description:n.description,keywords:l.keywords,image:null!=(e=i.image)?e:l.image})}var d=n(4334),m=n(4980),u=n(3117),v=n(1614),f=n(3500);function p(e){var t=e.previous,n=e.next;return a.createElement("nav",{className:"pagination-nav docusaurus-mt-lg","aria-label":(0,v.I)({id:"theme.docs.paginator.navAriaLabel",message:"Docs pages navigation",description:"The ARIA label for the docs pagination"})},t&&a.createElement(f.Z,(0,u.Z)({},t,{subLabel:a.createElement(v.Z,{id:"theme.docs.paginator.previous",description:"The label used to navigate to the previous doc"},"Previous")})),n&&a.createElement(f.Z,(0,u.Z)({},n,{subLabel:a.createElement(v.Z,{id:"theme.docs.paginator.next",description:"The label used to navigate to the next doc"},"Next"),isNext:!0})))}function b(){var e=c().metadata;return a.createElement(p,{previous:e.previous,next:e.next})}var h=n(6832),g=n(8746),E=n(4452),L=n(8015),N=n(4049),y=n(6141);var Z={unreleased:function(e){var t=e.siteTitle,n=e.versionMetadata;return a.createElement(v.Z,{id:"theme.docs.versions.unreleasedVersionLabel",description:"The label used to tell the user that he's browsing an unreleased doc version",values:{siteTitle:t,versionLabel:a.createElement("b",null,n.label)}},"This is unreleased documentation for {siteTitle} {versionLabel} version.")},unmaintained:function(e){var t=e.siteTitle,n=e.versionMetadata;return a.createElement(v.Z,{id:"theme.docs.versions.unmaintainedVersionLabel",description:"The label used to tell the user that he's browsing an unmaintained doc version",values:{siteTitle:t,versionLabel:a.createElement("b",null,n.label)}},"This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained.")}};function k(e){var t=Z[e.versionMetadata.banner];return a.createElement(t,e)}function _(e){var t=e.versionLabel,n=e.to,r=e.onClick;return a.createElement(v.Z,{id:"theme.docs.versions.latestVersionSuggestionLabel",description:"The label used to tell the user to check the latest version",values:{versionLabel:t,latestVersionLink:a.createElement("b",null,a.createElement(g.Z,{to:n,onClick:r},a.createElement(v.Z,{id:"theme.docs.versions.latestVersionLinkLabel",description:"The label used for the latest version suggestion link label"},"latest version")))}},"For up-to-date documentation, see the {latestVersionLink} ({versionLabel}).")}function x(e){var t,n=e.className,r=e.versionMetadata,l=(0,h.Z)().siteConfig.title,i=(0,E.gA)({failfast:!0}).pluginId,o=(0,N.J)(i).savePreferredVersionName,c=(0,E.Jo)(i),s=c.latestDocSuggestion,m=c.latestVersionSuggestion,u=null!=s?s:(t=m).docs.find((function(e){return e.id===t.mainDocId}));return a.createElement("div",{className:(0,d.Z)(n,L.k.docs.docVersionBanner,"alert alert--warning margin-bottom--md"),role:"alert"},a.createElement("div",null,a.createElement(k,{siteTitle:l,versionMetadata:r})),a.createElement("div",{className:"margin-top--md"},a.createElement(_,{versionLabel:m.label,to:u.path,onClick:function(){return o(m.name)}})))}function C(e){var t=e.className,n=(0,y.E)();return n.banner?a.createElement(x,{className:t,versionMetadata:n}):null}function T(e){var t=e.className,n=(0,y.E)();return n.badge?a.createElement("span",{className:(0,d.Z)(t,L.k.docs.docVersionBadge,"badge badge--secondary")},a.createElement(v.Z,{id:"theme.docs.versionBadge.label",values:{versionLabel:n.label}},"Version: {versionLabel}")):null}function w(e){var t=e.lastUpdatedAt,n=e.formattedLastUpdatedAt;return a.createElement(v.Z,{id:"theme.lastUpdated.atDate",description:"The words used to describe on which date a page has been last updated",values:{date:a.createElement("b",null,a.createElement("time",{dateTime:new Date(1e3*t).toISOString()},n))}}," on {date}")}function O(e){var t=e.lastUpdatedBy;return a.createElement(v.Z,{id:"theme.lastUpdated.byUser",description:"The words used to describe by who the page has been last updated",values:{user:a.createElement("b",null,t)}}," by {user}")}function H(e){var t=e.lastUpdatedAt,n=e.formattedLastUpdatedAt,r=e.lastUpdatedBy;return a.createElement("span",{className:L.k.common.lastUpdated},a.createElement(v.Z,{id:"theme.lastUpdated.lastUpdatedAtBy",description:"The sentence used to display when a page has been last updated, and by who",values:{atDate:t&&n?a.createElement(w,{lastUpdatedAt:t,formattedLastUpdatedAt:n}):"",byUser:r?a.createElement(O,{lastUpdatedBy:r}):""}},"Last updated{atDate}{byUser}"),!1)}var U=n(7612),A=n(8045),M="lastUpdated_vwxv";function P(e){return a.createElement("div",{className:(0,d.Z)(L.k.docs.docFooterTagsRow,"row margin-bottom--sm")},a.createElement("div",{className:"col"},a.createElement(A.Z,e)))}function I(e){var t=e.editUrl,n=e.lastUpdatedAt,r=e.lastUpdatedBy,l=e.formattedLastUpdatedAt;return a.createElement("div",{className:(0,d.Z)(L.k.docs.docFooterEditMetaRow,"row")},a.createElement("div",{className:"col"},t&&a.createElement(U.Z,{editUrl:t})),a.createElement("div",{className:(0,d.Z)("col",M)},(n||r)&&a.createElement(H,{lastUpdatedAt:n,formattedLastUpdatedAt:l,lastUpdatedBy:r})))}function j(){var e=c().metadata,t=e.editUrl,n=e.lastUpdatedAt,r=e.formattedLastUpdatedAt,l=e.lastUpdatedBy,i=e.tags,o=i.length>0,s=!!(t||n||l);return o||s?a.createElement("footer",{className:(0,d.Z)(L.k.docs.docFooter,"docusaurus-mt-lg")},o&&a.createElement(P,{tags:i}),s&&a.createElement(I,{editUrl:t,lastUpdatedAt:n,lastUpdatedBy:l,formattedLastUpdatedAt:r})):null}var B=n(7940),S=n(1351),V=n(102),D="tocCollapsibleButton_TO0P",R="tocCollapsibleButtonExpanded_MG3E",z=["collapsed"];function F(e){var t=e.collapsed,n=(0,V.Z)(e,z);return a.createElement("button",(0,u.Z)({type:"button"},n,{className:(0,d.Z)("clean-btn",D,!t&&R,n.className)}),a.createElement(v.Z,{id:"theme.TOCCollapsible.toggleButtonLabel",description:"The label used by the button on the collapsible TOC component"},"On this page"))}var q="tocCollapsible_ETCw",G="tocCollapsibleContent_vkbj",J="tocCollapsibleExpanded_sAul";function X(e){var t=e.toc,n=e.className,r=e.minHeadingLevel,l=e.maxHeadingLevel,i=(0,B.u)({initialState:!0}),o=i.collapsed,c=i.toggleCollapsed;return a.createElement("div",{className:(0,d.Z)(q,!o&&J,n)},a.createElement(F,{collapsed:o,onClick:c}),a.createElement(B.z,{lazy:!0,className:G,collapsed:o},a.createElement(S.Z,{toc:t,minHeadingLevel:r,maxHeadingLevel:l})))}var Q="tocMobile_ITEo";function W(){var e=c(),t=e.toc,n=e.frontMatter;return a.createElement(X,{toc:t,minHeadingLevel:n.toc_min_heading_level,maxHeadingLevel:n.toc_max_heading_level,className:(0,d.Z)(L.k.docs.docTocMobile,Q)})}var K=n(4613);function Y(){var e=c(),t=e.toc,n=e.frontMatter;return a.createElement(K.Z,{toc:t,minHeadingLevel:n.toc_min_heading_level,maxHeadingLevel:n.toc_max_heading_level,className:L.k.docs.docTocDesktop})}var $=n(4055),ee=n(2279);function te(e){var t,n,r,l,i=e.children,o=(t=c(),n=t.metadata,r=t.frontMatter,l=t.contentTitle,r.hide_title||void 0!==l?null:n.title);return a.createElement("div",{className:(0,d.Z)(L.k.docs.docMarkdown,"markdown")},o&&a.createElement("header",null,a.createElement($.Z,{as:"h1"},o)),a.createElement(ee.Z,null,i))}var ne=n(4714),ae=n(8407),re=n(1402);function le(e){return a.createElement("svg",(0,u.Z)({viewBox:"0 0 24 24"},e),a.createElement("path",{d:"M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z",fill:"currentColor"}))}var ie={breadcrumbsContainer:"breadcrumbsContainer_Z_bl",breadcrumbHomeIcon:"breadcrumbHomeIcon_OVgt"};function oe(e){var t=e.children,n=e.href,r="breadcrumbs__link";return e.isLast?a.createElement("span",{className:r,itemProp:"name"},t):n?a.createElement(g.Z,{className:r,href:n,itemProp:"item"},a.createElement("span",{itemProp:"name"},t)):a.createElement("span",{className:r},t)}function ce(e){var t=e.children,n=e.active,r=e.index,l=e.addMicrodata;return a.createElement("li",(0,u.Z)({},l&&{itemScope:!0,itemProp:"itemListElement",itemType:"https://schema.org/ListItem"},{className:(0,d.Z)("breadcrumbs__item",{"breadcrumbs__item--active":n})}),t,a.createElement("meta",{itemProp:"position",content:String(r+1)}))}function se(){var e=(0,re.Z)("/");return a.createElement("li",{className:"breadcrumbs__item"},a.createElement(g.Z,{"aria-label":(0,v.I)({id:"theme.docs.breadcrumbs.home",message:"Home page",description:"The ARIA label for the home page in the breadcrumbs"}),className:(0,d.Z)("breadcrumbs__link",ie.breadcrumbsItemLink),href:e},a.createElement(le,{className:ie.breadcrumbHomeIcon})))}function de(){var e=(0,ne.s1)(),t=(0,ae.Ns)();return e?a.createElement("nav",{className:(0,d.Z)(L.k.docs.docBreadcrumbs,ie.breadcrumbsContainer),"aria-label":(0,v.I)({id:"theme.docs.breadcrumbs.navAriaLabel",message:"Breadcrumbs",description:"The ARIA label for the breadcrumbs"})},a.createElement("ul",{className:"breadcrumbs",itemScope:!0,itemType:"https://schema.org/BreadcrumbList"},t&&a.createElement(se,null),e.map((function(t,n){var r=n===e.length-1;return a.createElement(ce,{key:n,active:r,index:n,addMicrodata:!!t.href},a.createElement(oe,{href:t.href,isLast:r},t.label))})))):null}var me="docItemContainer_Djhp",ue="docItemCol_VOVn";function ve(e){var t,n,r,l,i,o,s=e.children,u=(t=c(),n=t.frontMatter,r=t.toc,l=(0,m.i)(),i=n.hide_table_of_contents,o=!i&&r.length>0,{hidden:i,mobile:o?a.createElement(W,null):void 0,desktop:!o||"desktop"!==l&&"ssr"!==l?void 0:a.createElement(Y,null)});return a.createElement("div",{className:"row"},a.createElement("div",{className:(0,d.Z)("col",!u.hidden&&ue)},a.createElement(C,null),a.createElement("div",{className:me},a.createElement("article",null,a.createElement(de,null),a.createElement(T,null),u.mobile,a.createElement(te,null,s),a.createElement(j,null)),a.createElement(b,null))),u.desktop&&a.createElement("div",{className:"col col--3"},u.desktop))}function fe(e){var t="docs-doc-id-"+e.content.metadata.unversionedId,n=e.content;return a.createElement(o,{content:e.content},a.createElement(r.FG,{className:t},a.createElement(s,null),a.createElement(ve,null,a.createElement(n,null))))}},7612:function(e,t,n){n.d(t,{Z:function(){return u}});var a=n(7294),r=n(1614),l=n(8015),i=n(3117),o=n(102),c=n(4334),s="iconEdit_Z9Sw",d=["className"];function m(e){var t=e.className,n=(0,o.Z)(e,d);return a.createElement("svg",(0,i.Z)({fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,c.Z)(s,t),"aria-hidden":"true"},n),a.createElement("g",null,a.createElement("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})))}function u(e){var t=e.editUrl;return a.createElement("a",{href:t,target:"_blank",rel:"noreferrer noopener",className:l.k.common.editThisPage},a.createElement(m,null),a.createElement(r.Z,{id:"theme.common.editThisPage",description:"The link label to edit the current page"},"Edit this page"))}},2279:function(e,t,n){n.d(t,{Z:function(){return i}});var a=n(7294),r=n(3905),l=n(9363);function i(e){var t=e.children;return a.createElement(r.Zo,{components:l.Z},t)}},3500:function(e,t,n){n.d(t,{Z:function(){return i}});var a=n(7294),r=n(4334),l=n(8746);function i(e){var t=e.permalink,n=e.title,i=e.subLabel,o=e.isNext;return a.createElement(l.Z,{className:(0,r.Z)("pagination-nav__link",o?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t},i&&a.createElement("div",{className:"pagination-nav__sublabel"},i),a.createElement("div",{className:"pagination-nav__label"},n))}},1351:function(e,t,n){n.d(t,{Z:function(){return h}});var a=n(3117),r=n(102),l=n(7294),i=n(6793),o=["parentIndex"];function c(e){var t=e.map((function(e){return Object.assign({},e,{parentIndex:-1,children:[]})})),n=Array(7).fill(-1);t.forEach((function(e,t){var a=n.slice(2,e.level);e.parentIndex=Math.max.apply(Math,a),n[e.level]=t}));var a=[];return t.forEach((function(e){var n=e.parentIndex,l=(0,r.Z)(e,o);n>=0?t[n].children.push(l):a.push(l)})),a}function s(e){var t=e.toc,n=e.minHeadingLevel,a=e.maxHeadingLevel;return t.flatMap((function(e){var t=s({toc:e.children,minHeadingLevel:n,maxHeadingLevel:a});return function(e){return e.level>=n&&e.level<=a}(e)?[Object.assign({},e,{children:t})]:t}))}function d(e){var t=e.getBoundingClientRect();return t.top===t.bottom?d(e.parentNode):t}function m(e,t){var n,a,r=t.anchorTopOffset,l=e.find((function(e){return d(e).top>=r}));return l?function(e){return e.top>0&&e.bottom=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var c=a.createContext({}),s=function(e){var t=a.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d=function(e){var t=s(e.components);return a.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,l=e.originalType,c=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),u=s(n),v=r,f=u["".concat(c,".").concat(v)]||u[v]||m[v]||l;return n?a.createElement(f,i(i({ref:t},d),{},{components:n})):a.createElement(f,i({ref:t},d))}));function v(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=n.length,i=new Array(l);i[0]=u;var o={};for(var c in t)hasOwnProperty.call(t,c)&&(o[c]=t[c]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var s=2;s=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var u=a.createContext({}),s=function(e){var n=a.useContext(u),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},p=function(e){var n=s(e.components);return a.createElement(u.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,o=e.originalType,u=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),m=s(t),c=r,v=m["".concat(u,".").concat(c)]||m[c]||d[c]||o;return t?a.createElement(v,i(i({ref:n},p),{},{components:t})):a.createElement(v,i({ref:n},p))}));function c(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var o=t.length,i=new Array(o);i[0]=m;var l={};for(var u in n)hasOwnProperty.call(n,u)&&(l[u]=n[u]);l.originalType=e,l.mdxType="string"==typeof e?e:r,i[1]=l;for(var s=2;sSaveChanges \u4e8b\u4ef6",id:"9222-\u5173\u4e8e-savechanges-\u4e8b\u4ef6",level:2},{value:"9.22.3 \u5982\u4f55\u5b9e\u73b0",id:"9223-\u5982\u4f55\u5b9e\u73b0",level:2},{value:"9.22.3.1 \u6570\u636e\u5e93\u5ba1\u8ba1\u65e5\u5fd7",id:"92231-\u6570\u636e\u5e93\u5ba1\u8ba1\u65e5\u5fd7",level:3},{value:"9.22.3.2 \u6267\u884c sql \u5ba1\u8ba1\u65e5\u5fd7",id:"92232-\u6267\u884c-sql-\u5ba1\u8ba1\u65e5\u5fd7",level:3},{value:"9.22.3.3 \u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7",id:"92233-\u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7",level:3},{value:"9.22.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9224-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:d};function c(e){var n=e.components,t=(0,r.Z)(e,i);return(0,o.kt)("wrapper",(0,a.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"9221-\u5ba1\u8ba1\u65e5\u5fd7"},"9.22.1 \u5ba1\u8ba1\u65e5\u5fd7"),(0,o.kt)("p",null,"\u5728\u4e00\u4e2a\u4f01\u4e1a\u5e94\u7528\u7cfb\u7edf\u4e2d\uff0c\u7528\u6237\u5bf9\u7cfb\u7edf\u6240\u6709\u7684\u64cd\u4f5c\u5305\u62ec\u8bf7\u6c42\u3001\u6570\u636e\u5e93\u64cd\u4f5c\u7b49\u7b49\u90fd\u5e94\u8be5\u8bb0\u5f55\u8d77\u6765\uff0c\u90a3\u4e48\u8fd9\u4e9b\u65e5\u5fd7\u6211\u4eec\u79f0\u4e3a\u64cd\u4f5c\u65e5\u5fd7\uff0c\u4e5f\u53ef\u4ee5\u8bf4\u5ba1\u8ba1\u65e5\u5fd7\u3002"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u901a\u5e38\u6765\u8bf4\uff0c\u6211\u4eec\u5ba1\u8ba1\u65e5\u5fd7\u66f4\u591a\u6307\u7684\u662f\u6570\u636e\u5e93\u7684\u64cd\u4f5c\u8bb0\u5f55"),"\u3002"),(0,o.kt)("p",null,"\u5ba1\u8ba1\u65e5\u5fd7\u4e00\u822c\u4f1a\u8bb0\u5f55\u4ee5\u4e0b\u4e09\u4e2a\u64cd\u4f5c\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"\u65b0\u589e\u64cd\u4f5c"),"\uff1a\u8bb0\u5f55\u67d0\u67d0\u4eba\u5728\u67d0\u67d0\u65f6\u95f4\u5bf9\u54ea\u4e2a\u8868\u65b0\u589e\u4e86\u4ec0\u4e48\u6570\u636e"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"\u66f4\u65b0\u64cd\u4f5c"),"\uff1a\u8bb0\u5f55\u67d0\u67d0\u4eba\u5728\u67d0\u67d0\u65f6\u95f4\u5bf9\u54ea\u4e2a\u8868\u7684\u54ea\u4e9b\u6570\u636e\u505a\u4e86\u66f4\u6539\uff0c\u8bb0\u5f55\u66f4\u6539\u524d\u7684\u503c\u548c\u66f4\u6539\u540e\u7684\u503c"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"\u5220\u9664\u64cd\u4f5c"),"\uff1a\u8bb0\u5f55\u67d0\u67d0\u4eba\u5728\u67d0\u67d0\u65f6\u95f4\u5bf9\u54ea\u4e2a\u8868\u5220\u9664\u4e86\u4ec0\u4e48\u6570\u636e")),(0,o.kt)("h2",{id:"9222-\u5173\u4e8e-savechanges-\u4e8b\u4ef6"},"9.22.2 \u5173\u4e8e ",(0,o.kt)("inlineCode",{parentName:"h2"},"SaveChanges")," \u4e8b\u4ef6"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u4e3a\u6240\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u5b50\u7c7b\u90fd\u63d0\u4f9b\u4e86\u4e09\u4e2a\u53ef\u91cd\u5199\u7684\u65b9\u6cd5\uff0c\u8fd9\u4e09\u4e2a\u65b9\u6cd5\u5206\u522b\u7531\u4e09\u4e2a\u4e8b\u4ef6\u89e6\u53d1\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"\u63d0\u4ea4\u66f4\u6539\u4e4b\u524d SavingChanges \u4e8b\u4ef6"),"\uff1a\u89e6\u53d1 ",(0,o.kt)("inlineCode",{parentName:"li"},"void SavingChangesEvent(DbContextEventData eventData, InterceptionResult result)")," \u65b9\u6cd5"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"\u63d0\u4ea4\u66f4\u6539\u4e4b\u540e SavedChanges \u4e8b\u4ef6"),"\uff1a\u89e6\u53d1 ",(0,o.kt)("inlineCode",{parentName:"li"},"void SavedChangesEvent(SaveChangesCompletedEventData eventData, int result)")," \u65b9\u6cd5"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"\u63d0\u4ea4\u66f4\u6539\u5931\u8d25 SaveChangesFailed \u4e8b\u4ef6"),"\uff1a\u89e6\u53d1 ",(0,o.kt)("inlineCode",{parentName:"li"},"void SaveChangesFailedEvent(DbContextErrorEventData eventData)")," \u65b9\u6cd5")),(0,o.kt)("p",null,"\u901a\u8fc7\u8fd9\u4e09\u4e2a\u4e8b\u4ef6\u6211\u4eec\u5c31\u53ef\u4ee5\u6355\u83b7\u6240\u6709\u66f4\u6539\u7684\u5b9e\u4f53\u7136\u540e\u4fdd\u5b58\u5230\u6570\u636e\u5e93\u5ba1\u8ba1\u65e5\u5fd7\u4e2d\u3002"),(0,o.kt)("h2",{id:"9223-\u5982\u4f55\u5b9e\u73b0"},"9.22.3 \u5982\u4f55\u5b9e\u73b0"),(0,o.kt)("h3",{id:"92231-\u6570\u636e\u5e93\u5ba1\u8ba1\u65e5\u5fd7"},"9.22.3.1 \u6570\u636e\u5e93\u5ba1\u8ba1\u65e5\u5fd7"),(0,o.kt)("p",null,"\u6211\u4eec\u53ea\u9700\u8981\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u5b50\u7c7b\u4e2d\u91cd\u5199 ",(0,o.kt)("inlineCode",{parentName:"p"},"SavingChanges")," \u4e8b\u4ef6\u5bf9\u5e94\u65b9\u6cd5\u5373\u53ef\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {23}",showLineNumbers:!0,"":!0,"{23}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing System;\nusing System.Linq;\nusing System.Security.AccessControl;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurionDbContext : AppDbContext\n {\n public FurionDbContext(DbContextOptions options) : base(options)\n {\n }\n\n /// \n /// \u91cd\u5199\u4fdd\u5b58\u4e4b\u524d\u4e8b\u4ef6\n /// \n /// \n /// \n protected override void SavingChangesEvent(DbContextEventData eventData, InterceptionResult result)\n {\n // \u83b7\u53d6\u5f53\u524d\u4e8b\u4ef6\u5bf9\u5e94\u4e0a\u4e0b\u6587\n var dbContext = eventData.Context;\n\n // \u5f3a\u5236\u91cd\u65b0\u68c0\u67e5\u4e00\u8fb9\u5b9e\u4f53\u66f4\u6539\u4fe1\u606f\n // dbContext.ChangeTracker.DetectChanges();\n\n // \u83b7\u53d6\u6240\u6709\u66f4\u6539\uff0c\u5220\u9664\uff0c\u65b0\u589e\u7684\u5b9e\u4f53\uff0c\u4f46\u6392\u9664\u5ba1\u8ba1\u5b9e\u4f53\uff08\u907f\u514d\u6b7b\u5faa\u73af\uff09\n var entities = dbContext.ChangeTracker.Entries()\n .Where(u => u.Entity.GetType() != typeof(Audit) && (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added))\n .ToList();\n\n // \u901a\u8fc7\u8bf7\u6c42\u4e2d\u83b7\u53d6\u5f53\u524d\u64cd\u4f5c\u4eba\n var userId = App.GetService().HttpContext.Items["UserId"];\n\n // \u83b7\u53d6\u6240\u6709\u5df2\u66f4\u6539\u7684\u5b9e\u4f53\n foreach (var entity in entities)\n {\n // \u83b7\u53d6\u5b9e\u4f53\u7c7b\u578b\n var entityType = entity.Entity.GetType();\n\n // \u83b7\u53d6\u6240\u6709\u5b9e\u4f53\u6709\u6548\u5c5e\u6027\uff0c\u6392\u9664 [NotMapper] \u5c5e\u6027\n var props = entity.OriginalValues.Properties;\n\n // \u83b7\u53d6\u5b9e\u4f53\u5f53\u524d\uff08\u73b0\u5728\uff09\u7684\u503c\n var currentValues = entity.CurrentValues;\n\n // \u83b7\u53d6\u6570\u636e\u5e93\u4e2d\u5b9e\u4f53\u7684\u503c\n var databaseValues = entity.GetDatabaseValues();\n\n // \u904d\u5386\u6240\u6709\u5c5e\u6027\n foreach (var prop in props)\n {\n // \u83b7\u53d6\u5c5e\u6027\u540d\n var propName = prop.Name;\n\n // \u83b7\u53d6\u73b0\u5728\u7684\u5b9e\u4f53\u503c\n var newValue = currentValues[propName];\n\n object oldValue = null;\n // \u5982\u679c\u662f\u65b0\u589e\u6570\u636e\uff0c\u5219 databaseValues \u4e3a\u7a7a\uff0c\u6240\u4ee5\u9700\u8981\u5224\u65ad\u4e00\u4e0b\n if (databaseValues != null)\n {\n oldValue = databaseValues[propName];\n }\n\n // \u63d2\u5165\u5ba1\u8ba1\u65e5\u5fd7\u8868\uff0cAudit \u662f\u4f60\u81ea\u5b9a\u4e49\u7684\u5b9e\u4f53\n dbContext.Set().Add(new Audit\n {\n Table = entityType.Name, // \u8868\u540d\n Column = propName, // \u66f4\u65b0\u7684\u5217\n NewValue = newValue, // \u65b0\u503c\n OldValue = oldValue, // \u65e7\u503c\n CreatedTime = DateTime.Now, // \u64cd\u4f5c\u65f6\u95f4\n UserId = userId, // \u64cd\u4f5c\u4eba\n Operate = entity.State.ToString() // \u64cd\u4f5c\u65b9\u5f0f\uff1a\u65b0\u589e\u3001\u66f4\u65b0\u3001\u5220\u9664\n });\n }\n }\n }\n }\n}\n')),(0,o.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u5bf9\u6027\u80fd\u6709\u6240\u8981\u6c42\uff0c\u90a3\u4e48\u5efa\u8bae\u5ba1\u8ba1\u65e5\u5fd7\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"\u65e5\u5fd7\u7ec4\u4ef6")," \u5199\u5165\u6570\u636e\u5e93\uff0c\u5982\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"Nlog\u3001Log4Net")," \u8fd9\u4e9b\u7b49\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u63d2\u5165\u5ba1\u8ba1\u65e5\u5fd7\u8868\ndbContext.Set().Add(new Audit\n{\n Table = entityType.Name, // \u8868\u540d\n Column = propName, // \u66f4\u65b0\u7684\u5217\n newValue = newValue, // \u65b0\u503c\n OldValue = oldValue, // \u65e7\u503c\n CreatedTime = DateTime.Now, // \u64cd\u4f5c\u65f6\u95f4\n UserId = userId, // \u64cd\u4f5c\u4eba\n Operate = entity.State.ToString() // \u64cd\u4f5c\u65b9\u5f0f\uff1a\u65b0\u589e\u3001\u66f4\u65b0\u3001\u5220\u9664\n});\n")),(0,o.kt)("p",{parentName:"admonition"},"\u66ff\u6362\u4e3a\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"logger.Information(JsonConvert.SerializeObject(new Audit\n{\n Table = entityType.Name, // \u8868\u540d\n Column = propName, // \u66f4\u65b0\u7684\u5217\n newValue = newValue, // \u65b0\u503c\n OldValue = oldValue, // \u65e7\u503c\n CreatedTime = DateTime.Now, // \u64cd\u4f5c\u65f6\u95f4\n UserId = userId, // \u64cd\u4f5c\u4eba\n Operate = entity.State.ToString() // \u64cd\u4f5c\u65b9\u5f0f\uff1a\u65b0\u589e\u3001\u66f4\u65b0\u3001\u5220\u9664\n}));\n"))),(0,o.kt)("p",null,"\u901a\u8fc7\u4e0a\u9762\u7684\u4f8b\u5b50\uff0c\u6211\u4eec\u5c31\u53ef\u4ee5\u5bf9\u6570\u636e\u5e93\u6240\u6709\u7684\u65b0\u589e\u3001\u66f4\u65b0\u3001\u5220\u9664\u8fdb\u884c\u76d1\u63a7\u4e86\u3002"),(0,o.kt)("h3",{id:"92232-\u6267\u884c-sql-\u5ba1\u8ba1\u65e5\u5fd7"},"9.22.3.2 \u6267\u884c ",(0,o.kt)("inlineCode",{parentName:"h3"},"sql")," \u5ba1\u8ba1\u65e5\u5fd7"),(0,o.kt)("p",null,"\u4e3b\u8981\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"DbCommandInterceptor")," \u62e6\u622a\u5b9e\u73b0\uff0c\u5177\u4f53\u4f7f\u7528\u53ef\u67e5\u770b ",(0,o.kt)("a",{parentName:"p",href:"./dbcontext-Interceptor#92422-dbcommandinterceptor"},"\u6570\u636e\u5e93\u62e6\u622a\u5668 - DbCommandInterceptor"),"\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11}",showLineNumbers:!0,"":!0,"{11}":!0},"using Microsoft.EntityFrameworkCore.Diagnostics;\nusing System.Data.Common;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Furion.Web.Core\n{\n /// \n /// \u6267\u884c sql \u5ba1\u8ba1\n /// \n public sealed class SqlCommandAuditInterceptor : DbCommandInterceptor\n {\n public override InterceptionResult NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)\n {\n // \u83b7\u53d6\u6267\u884c\u7684 sql \u8bed\u53e5\n var sql = command.CommandText;\n\n // \u83b7\u53d6\u6267\u884c\u7684 sql \u7c7b\u578b\uff0c\u662f sql \u8bed\u53e5\uff0c\u8fd8\u662f\u5b58\u50a8\u8fc7\u7a0b\uff0c\u8fd8\u662f\u5176\u4ed6\n var type = command.CommandType;\n\n // \u83b7\u53d6 sql \u4f20\u9012\u7684\u547d\u4ee4\u53c2\u6570\n var parameters = command.Parameters;\n\n // \u5199\u65e5\u5fd7~~~~\n\n return base.NonQueryExecuting(command, eventData, result);\n }\n\n public override ValueTask> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n // \u83b7\u53d6\u6267\u884c\u7684 sql \u8bed\u53e5\n var sql = command.CommandText;\n\n // \u83b7\u53d6\u6267\u884c\u7684 sql \u7c7b\u578b\uff0c\u662f sql \u8bed\u53e5\uff0c\u8fd8\u662f\u5b58\u50a8\u8fc7\u7a0b\uff0c\u8fd8\u662f\u5176\u4ed6\n var type = command.CommandType;\n\n // \u83b7\u53d6 sql \u4f20\u9012\u7684\u547d\u4ee4\u53c2\u6570\n var parameters = command.Parameters;\n\n // \u5199\u65e5\u5fd7~~~~\n\n return base.NonQueryExecutingAsync(command, eventData, result, cancellationToken);\n }\n\n // \u5176\u4ed6 override\n }\n}\n")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u6ce8\u518c\u5ba1\u8ba1\u65e5\u5fd7")),(0,o.kt)("p",null,"\u53ea\u9700\u8981\u5728\u6ce8\u518c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u6307\u5b9a ",(0,o.kt)("inlineCode",{parentName:"p"},"interceptors")," \u53c2\u6570\u5373\u53ef"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// services.AddDb \u4e00\u6837\nservices.AddDbPool(interceptors: new IInterceptor[] {\n new SqlCommandAuditInterceptor()\n});\n")),(0,o.kt)("h3",{id:"92233-\u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7"},"9.22.3.3 \u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7"),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u9700\u5b9e\u73b0\u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7\u53ef\u67e5\u9605 \u3010",(0,o.kt)("a",{parentName:"p",href:"/furion/docs/audit"},"5.4 \u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7\u7ae0\u8282"),"\u3011")),(0,o.kt)("h2",{id:"9224-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.22.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/9b04aa07.e9458336.js b/handbook/build/assets/js/9b04aa07.e9458336.js deleted file mode 100644 index 3a8e273b07..0000000000 --- a/handbook/build/assets/js/9b04aa07.e9458336.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[6521],{4925:function(e,n,t){t.r(n),t.d(n,{assets:function(){return p},contentTitle:function(){return u},default:function(){return c},frontMatter:function(){return l},metadata:function(){return s},toc:function(){return d}});var a=t(3117),r=t(102),o=(t(7294),t(3905)),i=["components"],l={id:"dbcontext-audit",title:"9.22 \u5ba1\u8ba1\u65e5\u5fd7",sidebar_label:"9.22 \u5ba1\u8ba1\u65e5\u5fd7 (Audit)"},u=void 0,s={unversionedId:"dbcontext-audit",id:"dbcontext-audit",title:"9.22 \u5ba1\u8ba1\u65e5\u5fd7",description:"9.22.1 \u5ba1\u8ba1\u65e5\u5fd7",source:"@site/docs/dbcontext-audit.mdx",sourceDirName:".",slug:"/dbcontext-audit",permalink:"/furion/docs/dbcontext-audit",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-audit.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1658977221,formattedLastUpdatedAt:"Jul 28, 2022",frontMatter:{id:"dbcontext-audit",title:"9.22 \u5ba1\u8ba1\u65e5\u5fd7",sidebar_label:"9.22 \u5ba1\u8ba1\u65e5\u5fd7 (Audit)"},sidebar:"docs",previous:{title:"9.21 \u5b9e\u4f53\u79cd\u5b50\u6570\u636e",permalink:"/furion/docs/dbcontext-seed-data"},next:{title:"9.23 \u5b9e\u4f53/\u5168\u5c40\u67e5\u8be2\u7b5b\u9009\u5668",permalink:"/furion/docs/dbcontext-filter"}},p={},d=[{value:"9.22.1 \u5ba1\u8ba1\u65e5\u5fd7",id:"9221-\u5ba1\u8ba1\u65e5\u5fd7",level:2},{value:"9.22.2 \u5173\u4e8e SaveChanges \u4e8b\u4ef6",id:"9222-\u5173\u4e8e-savechanges-\u4e8b\u4ef6",level:2},{value:"9.22.3 \u5982\u4f55\u5b9e\u73b0",id:"9223-\u5982\u4f55\u5b9e\u73b0",level:2},{value:"9.22.3.1 \u6570\u636e\u5e93\u5ba1\u8ba1\u65e5\u5fd7",id:"92231-\u6570\u636e\u5e93\u5ba1\u8ba1\u65e5\u5fd7",level:3},{value:"9.22.3.2 \u6267\u884c sql \u5ba1\u8ba1\u65e5\u5fd7",id:"92232-\u6267\u884c-sql-\u5ba1\u8ba1\u65e5\u5fd7",level:3},{value:"9.22.3.3 \u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7",id:"92233-\u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7",level:3},{value:"9.22.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9224-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:d};function c(e){var n=e.components,t=(0,r.Z)(e,i);return(0,o.kt)("wrapper",(0,a.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"9221-\u5ba1\u8ba1\u65e5\u5fd7"},"9.22.1 \u5ba1\u8ba1\u65e5\u5fd7"),(0,o.kt)("p",null,"\u5728\u4e00\u4e2a\u4f01\u4e1a\u5e94\u7528\u7cfb\u7edf\u4e2d\uff0c\u7528\u6237\u5bf9\u7cfb\u7edf\u6240\u6709\u7684\u64cd\u4f5c\u5305\u62ec\u8bf7\u6c42\u3001\u6570\u636e\u5e93\u64cd\u4f5c\u7b49\u7b49\u90fd\u5e94\u8be5\u8bb0\u5f55\u8d77\u6765\uff0c\u90a3\u4e48\u8fd9\u4e9b\u65e5\u5fd7\u6211\u4eec\u79f0\u4e3a\u64cd\u4f5c\u65e5\u5fd7\uff0c\u4e5f\u53ef\u4ee5\u8bf4\u5ba1\u8ba1\u65e5\u5fd7\u3002"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u901a\u5e38\u6765\u8bf4\uff0c\u6211\u4eec\u5ba1\u8ba1\u65e5\u5fd7\u66f4\u591a\u6307\u7684\u662f\u6570\u636e\u5e93\u7684\u64cd\u4f5c\u8bb0\u5f55"),"\u3002"),(0,o.kt)("p",null,"\u5ba1\u8ba1\u65e5\u5fd7\u4e00\u822c\u4f1a\u8bb0\u5f55\u4ee5\u4e0b\u4e09\u4e2a\u64cd\u4f5c\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"\u65b0\u589e\u64cd\u4f5c"),"\uff1a\u8bb0\u5f55\u67d0\u67d0\u4eba\u5728\u67d0\u67d0\u65f6\u95f4\u5bf9\u54ea\u4e2a\u8868\u65b0\u589e\u4e86\u4ec0\u4e48\u6570\u636e"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"\u66f4\u65b0\u64cd\u4f5c"),"\uff1a\u8bb0\u5f55\u67d0\u67d0\u4eba\u5728\u67d0\u67d0\u65f6\u95f4\u5bf9\u54ea\u4e2a\u8868\u7684\u54ea\u4e9b\u6570\u636e\u505a\u4e86\u66f4\u6539\uff0c\u8bb0\u5f55\u66f4\u6539\u524d\u7684\u503c\u548c\u66f4\u6539\u540e\u7684\u503c"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"\u5220\u9664\u64cd\u4f5c"),"\uff1a\u8bb0\u5f55\u67d0\u67d0\u4eba\u5728\u67d0\u67d0\u65f6\u95f4\u5bf9\u54ea\u4e2a\u8868\u5220\u9664\u4e86\u4ec0\u4e48\u6570\u636e")),(0,o.kt)("h2",{id:"9222-\u5173\u4e8e-savechanges-\u4e8b\u4ef6"},"9.22.2 \u5173\u4e8e ",(0,o.kt)("inlineCode",{parentName:"h2"},"SaveChanges")," \u4e8b\u4ef6"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u4e3a\u6240\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u5b50\u7c7b\u90fd\u63d0\u4f9b\u4e86\u4e09\u4e2a\u53ef\u91cd\u5199\u7684\u65b9\u6cd5\uff0c\u8fd9\u4e09\u4e2a\u65b9\u6cd5\u5206\u522b\u7531\u4e09\u4e2a\u4e8b\u4ef6\u89e6\u53d1\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"\u63d0\u4ea4\u66f4\u6539\u4e4b\u524d SavingChanges \u4e8b\u4ef6"),"\uff1a\u89e6\u53d1 ",(0,o.kt)("inlineCode",{parentName:"li"},"void SavingChangesEvent(DbContextEventData eventData, InterceptionResult result)")," \u65b9\u6cd5"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"\u63d0\u4ea4\u66f4\u6539\u4e4b\u540e SavedChanges \u4e8b\u4ef6"),"\uff1a\u89e6\u53d1 ",(0,o.kt)("inlineCode",{parentName:"li"},"void SavedChangesEvent(SaveChangesCompletedEventData eventData, int result)")," \u65b9\u6cd5"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"\u63d0\u4ea4\u66f4\u6539\u5931\u8d25 SaveChangesFailed \u4e8b\u4ef6"),"\uff1a\u89e6\u53d1 ",(0,o.kt)("inlineCode",{parentName:"li"},"void SaveChangesFailedEvent(DbContextErrorEventData eventData)")," \u65b9\u6cd5")),(0,o.kt)("p",null,"\u901a\u8fc7\u8fd9\u4e09\u4e2a\u4e8b\u4ef6\u6211\u4eec\u5c31\u53ef\u4ee5\u6355\u83b7\u6240\u6709\u66f4\u6539\u7684\u5b9e\u4f53\u7136\u540e\u4fdd\u5b58\u5230\u6570\u636e\u5e93\u5ba1\u8ba1\u65e5\u5fd7\u4e2d\u3002"),(0,o.kt)("h2",{id:"9223-\u5982\u4f55\u5b9e\u73b0"},"9.22.3 \u5982\u4f55\u5b9e\u73b0"),(0,o.kt)("h3",{id:"92231-\u6570\u636e\u5e93\u5ba1\u8ba1\u65e5\u5fd7"},"9.22.3.1 \u6570\u636e\u5e93\u5ba1\u8ba1\u65e5\u5fd7"),(0,o.kt)("p",null,"\u6211\u4eec\u53ea\u9700\u8981\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u5b50\u7c7b\u4e2d\u91cd\u5199 ",(0,o.kt)("inlineCode",{parentName:"p"},"SavingChanges")," \u4e8b\u4ef6\u5bf9\u5e94\u65b9\u6cd5\u5373\u53ef\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {23}",showLineNumbers:!0,"":!0,"{23}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Infrastructure;\nusing System;\nusing System.Linq;\nusing System.Security.AccessControl;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurionDbContext : AppDbContext\n {\n public FurionDbContext(DbContextOptions options) : base(options)\n {\n }\n\n /// \n /// \u91cd\u5199\u4fdd\u5b58\u4e4b\u524d\u4e8b\u4ef6\n /// \n /// \n /// \n protected override void SavingChangesEvent(DbContextEventData eventData, InterceptionResult result)\n {\n // \u83b7\u53d6\u5f53\u524d\u4e8b\u4ef6\u5bf9\u5e94\u4e0a\u4e0b\u6587\n var dbContext = eventData.Context;\n\n // \u5f3a\u5236\u91cd\u65b0\u68c0\u67e5\u4e00\u8fb9\u5b9e\u4f53\u66f4\u6539\u4fe1\u606f\n // dbContext.ChangeTracker.DetectChanges();\n\n // \u83b7\u53d6\u6240\u6709\u66f4\u6539\uff0c\u5220\u9664\uff0c\u65b0\u589e\u7684\u5b9e\u4f53\uff0c\u4f46\u6392\u9664\u5ba1\u8ba1\u5b9e\u4f53\uff08\u907f\u514d\u6b7b\u5faa\u73af\uff09\n var entities = dbContext.ChangeTracker.Entries()\n .Where(u => u.Entity.GetType() != typeof(Audit) && (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added))\n .ToList();\n\n // \u901a\u8fc7\u8bf7\u6c42\u4e2d\u83b7\u53d6\u5f53\u524d\u64cd\u4f5c\u4eba\n var userId = App.GetService().HttpContext.Items["UserId"];\n\n // \u83b7\u53d6\u6240\u6709\u5df2\u66f4\u6539\u7684\u5b9e\u4f53\n foreach (var entity in entities)\n {\n // \u83b7\u53d6\u5b9e\u4f53\u7c7b\u578b\n var entityType = entity.Entity.GetType();\n\n // \u83b7\u53d6\u6240\u6709\u5b9e\u4f53\u6709\u6548\u5c5e\u6027\uff0c\u6392\u9664 [NotMapper] \u5c5e\u6027\n var props = entity.OriginalValues.Properties;\n\n // \u83b7\u53d6\u5b9e\u4f53\u5f53\u524d\uff08\u73b0\u5728\uff09\u7684\u503c\n var currentValues = entity.CurrentValues;\n\n // \u83b7\u53d6\u6570\u636e\u5e93\u4e2d\u5b9e\u4f53\u7684\u503c\n var databaseValues = entity.GetDatabaseValues();\n\n // \u904d\u5386\u6240\u6709\u5c5e\u6027\n foreach (var prop in props)\n {\n // \u83b7\u53d6\u5c5e\u6027\u540d\n var propName = prop.Name;\n\n // \u83b7\u53d6\u73b0\u5728\u7684\u5b9e\u4f53\u503c\n var newValue = currentValues[propName];\n\n object oldValue = null;\n // \u5982\u679c\u662f\u65b0\u589e\u6570\u636e\uff0c\u5219 databaseValues \u4e3a\u7a7a\uff0c\u6240\u4ee5\u9700\u8981\u5224\u65ad\u4e00\u4e0b\n if (databaseValues != null)\n {\n oldValue = databaseValues[propName];\n }\n\n // \u63d2\u5165\u5ba1\u8ba1\u65e5\u5fd7\u8868\uff0cAudit \u662f\u4f60\u81ea\u5b9a\u4e49\u7684\u5b9e\u4f53\n dbContext.Set().Add(new Audit\n {\n Table = entityType.Name, // \u8868\u540d\n Column = propName, // \u66f4\u65b0\u7684\u5217\n NewValue = newValue, // \u65b0\u503c\n OldValue = oldValue, // \u65e7\u503c\n CreatedTime = DateTime.Now, // \u64cd\u4f5c\u65f6\u95f4\n UserId = userId, // \u64cd\u4f5c\u4eba\n Operate = entity.State.ToString() // \u64cd\u4f5c\u65b9\u5f0f\uff1a\u65b0\u589e\u3001\u66f4\u65b0\u3001\u5220\u9664\n });\n }\n }\n }\n }\n}\n')),(0,o.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u5bf9\u6027\u80fd\u6709\u6240\u8981\u6c42\uff0c\u90a3\u4e48\u5efa\u8bae\u5ba1\u8ba1\u65e5\u5fd7\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"\u65e5\u5fd7\u7ec4\u4ef6")," \u5199\u5165\u6570\u636e\u5e93\uff0c\u5982\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"Nlog\u3001Log4Net")," \u8fd9\u4e9b\u7b49\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u63d2\u5165\u5ba1\u8ba1\u65e5\u5fd7\u8868\ndbContext.Set().Add(new Audit\n{\n Table = entityType.Name, // \u8868\u540d\n Column = propName, // \u66f4\u65b0\u7684\u5217\n newValue = newValue, // \u65b0\u503c\n OldValue = oldValue, // \u65e7\u503c\n CreatedTime = DateTime.Now, // \u64cd\u4f5c\u65f6\u95f4\n UserId = userId, // \u64cd\u4f5c\u4eba\n Operate = entity.State.ToString() // \u64cd\u4f5c\u65b9\u5f0f\uff1a\u65b0\u589e\u3001\u66f4\u65b0\u3001\u5220\u9664\n});\n")),(0,o.kt)("p",{parentName:"admonition"},"\u66ff\u6362\u4e3a\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"logger.Information(JsonConvert.SerializeObject(new Audit\n{\n Table = entityType.Name, // \u8868\u540d\n Column = propName, // \u66f4\u65b0\u7684\u5217\n newValue = newValue, // \u65b0\u503c\n OldValue = oldValue, // \u65e7\u503c\n CreatedTime = DateTime.Now, // \u64cd\u4f5c\u65f6\u95f4\n UserId = userId, // \u64cd\u4f5c\u4eba\n Operate = entity.State.ToString() // \u64cd\u4f5c\u65b9\u5f0f\uff1a\u65b0\u589e\u3001\u66f4\u65b0\u3001\u5220\u9664\n}));\n"))),(0,o.kt)("p",null,"\u901a\u8fc7\u4e0a\u9762\u7684\u4f8b\u5b50\uff0c\u6211\u4eec\u5c31\u53ef\u4ee5\u5bf9\u6570\u636e\u5e93\u6240\u6709\u7684\u65b0\u589e\u3001\u66f4\u65b0\u3001\u5220\u9664\u8fdb\u884c\u76d1\u63a7\u4e86\u3002"),(0,o.kt)("h3",{id:"92232-\u6267\u884c-sql-\u5ba1\u8ba1\u65e5\u5fd7"},"9.22.3.2 \u6267\u884c ",(0,o.kt)("inlineCode",{parentName:"h3"},"sql")," \u5ba1\u8ba1\u65e5\u5fd7"),(0,o.kt)("p",null,"\u4e3b\u8981\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"DbCommandInterceptor")," \u62e6\u622a\u5b9e\u73b0\uff0c\u5177\u4f53\u4f7f\u7528\u53ef\u67e5\u770b ",(0,o.kt)("a",{parentName:"p",href:"./dbcontext-Interceptor#92422-dbcommandinterceptor"},"\u6570\u636e\u5e93\u62e6\u622a\u5668 - DbCommandInterceptor"),"\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11}",showLineNumbers:!0,"":!0,"{11}":!0},"using Microsoft.EntityFrameworkCore.Diagnostics;\nusing System.Data.Common;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Furion.Web.Core\n{\n /// \n /// \u6267\u884c sql \u5ba1\u8ba1\n /// \n public sealed class SqlCommandAuditInterceptor : DbCommandInterceptor\n {\n public override InterceptionResult NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)\n {\n // \u83b7\u53d6\u6267\u884c\u7684 sql \u8bed\u53e5\n var sql = command.CommandText;\n\n // \u83b7\u53d6\u6267\u884c\u7684 sql \u7c7b\u578b\uff0c\u662f sql \u8bed\u53e5\uff0c\u8fd8\u662f\u5b58\u50a8\u8fc7\u7a0b\uff0c\u8fd8\u662f\u5176\u4ed6\n var type = command.CommandType;\n\n // \u83b7\u53d6 sql \u4f20\u9012\u7684\u547d\u4ee4\u53c2\u6570\n var parameters = command.Parameters;\n\n // \u5199\u65e5\u5fd7~~~~\n\n return base.NonQueryExecuting(command, eventData, result);\n }\n\n public override ValueTask> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n // \u83b7\u53d6\u6267\u884c\u7684 sql \u8bed\u53e5\n var sql = command.CommandText;\n\n // \u83b7\u53d6\u6267\u884c\u7684 sql \u7c7b\u578b\uff0c\u662f sql \u8bed\u53e5\uff0c\u8fd8\u662f\u5b58\u50a8\u8fc7\u7a0b\uff0c\u8fd8\u662f\u5176\u4ed6\n var type = command.CommandType;\n\n // \u83b7\u53d6 sql \u4f20\u9012\u7684\u547d\u4ee4\u53c2\u6570\n var parameters = command.Parameters;\n\n // \u5199\u65e5\u5fd7~~~~\n\n return base.NonQueryExecutingAsync(command, eventData, result, cancellationToken);\n }\n\n // \u5176\u4ed6 override\n }\n}\n")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"\u6ce8\u518c\u5ba1\u8ba1\u65e5\u5fd7")),(0,o.kt)("p",null,"\u53ea\u9700\u8981\u5728\u6ce8\u518c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u6307\u5b9a ",(0,o.kt)("inlineCode",{parentName:"p"},"interceptors")," \u53c2\u6570\u5373\u53ef"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// services.AddDb \u4e00\u6837\nservices.AddDbPool(interceptors: new IInterceptor[] {\n new SqlCommandAuditInterceptor()\n});\n")),(0,o.kt)("h3",{id:"92233-\u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7"},"9.22.3.3 \u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7"),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u9700\u5b9e\u73b0\u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7\u53ef\u67e5\u9605 \u3010",(0,o.kt)("a",{parentName:"p",href:"/furion/docs/audit"},"5.4 \u8bf7\u6c42\u5ba1\u8ba1\u65e5\u5fd7\u7ae0\u8282"),"\u3011")),(0,o.kt)("h2",{id:"9224-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.22.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return p},kt:function(){return c}});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function i(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var u=a.createContext({}),s=function(e){var n=a.useContext(u),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},p=function(e){var n=s(e.components);return a.createElement(u.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,o=e.originalType,u=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),m=s(t),c=r,v=m["".concat(u,".").concat(c)]||m[c]||d[c]||o;return t?a.createElement(v,i(i({ref:n},p),{},{components:t})):a.createElement(v,i({ref:n},p))}));function c(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var o=t.length,i=new Array(o);i[0]=m;var l={};for(var u in n)hasOwnProperty.call(n,u)&&(l[u]=n[u]);l.originalType=e,l.mdxType="string"==typeof e?e:r,i[1]=l;for(var s=2;s=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=r.createContext({}),m=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},u=function(e){var t=m(e.components);return r.createElement(p.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},s=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,p=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),s=m(n),d=a,k=s["".concat(p,".").concat(d)]||s[d]||c[d]||i;return n?r.createElement(k,o(o({ref:t},u),{},{components:n})):r.createElement(k,o({ref:t},u))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,o=new Array(i);o[0]=s;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var m=2;m=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=r.createContext({}),m=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},u=function(e){var t=m(e.components);return r.createElement(p.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},s=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,p=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),s=m(n),d=a,k=s["".concat(p,".").concat(d)]||s[d]||c[d]||i;return n?r.createElement(k,o(o({ref:t},u),{},{components:n})):r.createElement(k,o({ref:t},u))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,o=new Array(i);o[0]=s;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var m=2;m=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var u=a.createContext({}),c=function(e){var t=a.useContext(u),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},d=function(e){var t=c(e.components);return a.createElement(u.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},p=a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,o=e.originalType,u=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),p=c(r),f=n,m=p["".concat(u,".").concat(f)]||p[f]||s[f]||o;return r?a.createElement(m,l(l({ref:t},d),{},{components:r})):a.createElement(m,l({ref:t},d))}));function f(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=r.length,l=new Array(o);l[0]=p;var i={};for(var u in t)hasOwnProperty.call(t,u)&&(i[u]=t[u]);i.originalType=e,i.mdxType="string"==typeof e?e:n,l[1]=i;for(var c=2;c=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var u=a.createContext({}),c=function(e){var t=a.useContext(u),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},d=function(e){var t=c(e.components);return a.createElement(u.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},p=a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,o=e.originalType,u=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),p=c(r),f=n,m=p["".concat(u,".").concat(f)]||p[f]||s[f]||o;return r?a.createElement(m,l(l({ref:t},d),{},{components:r})):a.createElement(m,l({ref:t},d))}));function f(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=r.length,l=new Array(o);l[0]=p;var i={};for(var u in t)hasOwnProperty.call(t,u)&&(i[u]=t[u]);i.originalType=e,i.mdxType="string"==typeof e?e:n,l[1]=i;for(var c=2;c=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(l=0;l=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var o=l.createContext({}),u=function(e){var t=l.useContext(o),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},m=function(e){var t=u(e.components);return l.createElement(o.Provider,{value:t},e.children)},k={inlineCode:"code",wrapper:function(e){var t=e.children;return l.createElement(l.Fragment,{},t)}},d=l.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,o=e.parentName,m=p(e,["components","mdxType","originalType","parentName"]),d=u(n),s=a,c=d["".concat(o,".").concat(s)]||d[s]||k[s]||i;return n?l.createElement(c,r(r({ref:t},m),{},{components:n})):l.createElement(c,r({ref:t},m))}));function s(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,r=new Array(i);r[0]=d;var p={};for(var o in t)hasOwnProperty.call(t,o)&&(p[o]=t[o]);p.originalType=e,p.mdxType="string"==typeof e?e:a,r[1]=p;for(var u=2;u();\n')),(0,i.kt)("p",null,"\u5982\u9700\u8de8\u5e93\u67e5\u8be2\uff0c\u9700\u7528\u5230\u6570\u636e\u5e93\u6280\u672f\uff0c\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"SqlServer")," \u94fe\u63a5\u670d\u52a1\u5668\u6216\u540c\u4e49\u8bcd\u3002"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93\u8868"))),(0,i.kt)("p",null,"\u7b2c\u4e00\u6b65\u3001\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u7279\u6027",(0,i.kt)("inlineCode",{parentName:"p"},"[AppDbContext( Mode=DbContextMode.Dynamic)]")),(0,i.kt)("p",null,"\u7b2c\u4e8c\u6b65\u3001\u9700\u8981\u52a8\u6001\u4fee\u6539\u8868\u540d\u7684\u5b9e\u4f53\u7ee7\u627f ",(0,i.kt)("inlineCode",{parentName:"p"},"IEntityMutableTable")," \u63a5\u53e3\uff0c\u5e76\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"p"},"GetTableName()")," \u8fd4\u56de\u8868\u540d\u65b9\u6cd5"),(0,i.kt)("p",null,"\u6700\u540e\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"BuildChange")," \u5207\u6362\u5373\u53ef\u3002"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var (rep, scoped) = repository.BuildChange();\n")),(0,i.kt)("p",null,"\u8c03\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"BuildChange")," \u65b9\u6cd5\u4e4b\u540e\u4f1a\u81ea\u52a8\u8c03\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"GetTableName()")," \u65b9\u6cd5\u3002"),(0,i.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"p"},"DynamicModelCacheKeyFactory")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/ef/core/modeling/dynamic-model"},"EF Core - \u591a\u4e2a\u6a21\u578b\u4e4b\u95f4\u4ea4\u66ff")," \u7ae0\u8282\u3002")),(0,i.kt)("h2",{id:"9287-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.28.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/9ce2543b.f74974a7.js b/handbook/build/assets/js/9ce2543b.f74974a7.js deleted file mode 100644 index dd33341489..0000000000 --- a/handbook/build/assets/js/9ce2543b.f74974a7.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[6467],{6729:function(e,t,n){n.r(t),n.d(t,{assets:function(){return k},contentTitle:function(){return u},default:function(){return c},frontMatter:function(){return o},metadata:function(){return m},toc:function(){return d}});var l=n(3117),a=n(102),i=(n(7294),n(3905)),r=n(1402),p=["components"],o={id:"split-db",title:"9.28 \u5206\u8868\u5206\u5e93",sidebar_label:"9.28 \u5206\u8868\u5206\u5e93"},u=void 0,m={unversionedId:"split-db",id:"split-db",title:"9.28 \u5206\u8868\u5206\u5e93",description:"",source:"@site/docs/split-db.mdx",sourceDirName:".",slug:"/split-db",permalink:"/furion/docs/split-db",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/split-db.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"split-db",title:"9.28 \u5206\u8868\u5206\u5e93",sidebar_label:"9.28 \u5206\u8868\u5206\u5e93"},sidebar:"docs",previous:{title:"9.27 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",permalink:"/furion/docs/dbcontext-read-write"},next:{title:"9.29 EFCore \u6700\u4f73\u5b9e\u8df5",permalink:"/furion/docs/efcore-recommend"}},k={},d=[{value:"9.28.1 \u5e94\u7528\u573a\u666f",id:"9281-\u5e94\u7528\u573a\u666f",level:2},{value:"9.28.2 \u5782\u76f4\u5207\u5206",id:"9282-\u5782\u76f4\u5207\u5206",level:2},{value:"9.28.2.1 \u5782\u76f4\u5206\u5e93",id:"92821-\u5782\u76f4\u5206\u5e93",level:3},{value:"9.28.2.2 \u5782\u76f4\u5206\u8868",id:"92822-\u5782\u76f4\u5206\u8868",level:3},{value:"9.28.2.3 \u4f18\u7f3a\u70b9",id:"92823-\u4f18\u7f3a\u70b9",level:3},{value:"9.28.3 \u6c34\u5e73\u5207\u5206",id:"9283-\u6c34\u5e73\u5207\u5206",level:2},{value:"9.28.3.1 \u6c34\u5e73\u5206\u5e93",id:"92831-\u6c34\u5e73\u5206\u5e93",level:3},{value:"9.28.3.2 \u6c34\u5e73\u5206\u8868",id:"92832-\u6c34\u5e73\u5206\u8868",level:3},{value:"9.28.3.3 \u4f18\u7f3a\u70b9",id:"92833-\u4f18\u7f3a\u70b9",level:3},{value:"9.28.4 \u6570\u636e\u5206\u7247\u89c4\u5219",id:"9284-\u6570\u636e\u5206\u7247\u89c4\u5219",level:2},{value:"9.28.4.1 Hash \u53d6\u6a21\u5206\u8868",id:"92841-hash-\u53d6\u6a21\u5206\u8868",level:3},{value:"9.28.4.2 \u6570\u503c Range \u5206\u8868",id:"92842-\u6570\u503c-range-\u5206\u8868",level:3},{value:"9.28.4.3 \u4e00\u81f4\u6027 Hash \u7b97\u6cd5",id:"92843-\u4e00\u81f4\u6027-hash-\u7b97\u6cd5",level:3},{value:"9.28.5 \u5206\u5e93\u5206\u8868\u5e26\u6765\u7684\u95ee\u9898",id:"9285-\u5206\u5e93\u5206\u8868\u5e26\u6765\u7684\u95ee\u9898",level:2},{value:"9.28.5.1 \u5206\u5e03\u5f0f\u4e8b\u52a1\u95ee\u9898",id:"92851-\u5206\u5e03\u5f0f\u4e8b\u52a1\u95ee\u9898",level:3},{value:"9.28.5.2 \u8de8\u8282\u70b9\u5173\u8054\u67e5\u8be2 Join \u95ee\u9898",id:"92852-\u8de8\u8282\u70b9\u5173\u8054\u67e5\u8be2-join-\u95ee\u9898",level:3},{value:"9.28.5.3 \u8de8\u8282\u70b9\u5206\u9875\u3001\u6392\u5e8f\u3001\u51fd\u6570\u95ee\u9898",id:"92853-\u8de8\u8282\u70b9\u5206\u9875\u6392\u5e8f\u51fd\u6570\u95ee\u9898",level:3},{value:"9.28.5.4 \u5168\u5c40\u4e3b\u952e\u907f\u91cd\u95ee\u9898",id:"92854-\u5168\u5c40\u4e3b\u952e\u907f\u91cd\u95ee\u9898",level:3},{value:"9.28.5.5 \u6570\u636e\u8fc1\u79fb\u95ee\u9898",id:"92855-\u6570\u636e\u8fc1\u79fb\u95ee\u9898",level:3},{value:"9.28.6 \u5982\u4f55\u5b9e\u73b0",id:"9286-\u5982\u4f55\u5b9e\u73b0",level:2},{value:"9.28.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9287-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],s={toc:d};function c(e){var t=e.components,n=(0,a.Z)(e,p);return(0,i.kt)("wrapper",(0,l.Z)({},s,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{title:"\u7279\u6b64\u58f0\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u672c\u7ae0 ",(0,i.kt)("inlineCode",{parentName:"p"},"9.28.2")," \u81f3 ",(0,i.kt)("inlineCode",{parentName:"p"},"9.28.5")," \u5c0f\u8282\u632a\u7528\u535a\u4e3b\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://www.cnblogs.com/qdhxhz/"},"\u96e8\u70b9\u7684\u540d\u5b57")," \u7684 ",(0,i.kt)("a",{parentName:"p",href:"https://www.cnblogs.com/qdhxhz/p/11608222.html"},"\u5206\u5e93\u5206\u8868 - \u7406\u8bba")," \u535a\u5ba2\u5185\u5bb9\u3002",(0,i.kt)("strong",{parentName:"p"},"\u7279\u6b64\u58f0\u660e\u3002"))),(0,i.kt)("h2",{id:"9281-\u5e94\u7528\u573a\u666f"},"9.28.1 \u5e94\u7528\u573a\u666f"),(0,i.kt)("p",null,"\u6570\u636e\u5e93\u4e2d\u7684\u6570\u636e\u91cf\u4e0d\u4e00\u5b9a\u662f\u53ef\u63a7\u7684\uff0c\u5728\u672a\u8fdb\u884c\u5206\u5e93\u5206\u8868\u7684\u60c5\u51b5\u4e0b\uff0c\u968f\u7740\u65f6\u95f4\u548c\u4e1a\u52a1\u7684\u53d1\u5c55\uff0c\u5e93\u4e2d\u7684\u8868\u4f1a\u8d8a\u6765\u8d8a\u591a\uff0c\u8868\u4e2d\u7684\u6570\u636e\u91cf\u4e5f\u4f1a\u8d8a\u6765\u8d8a\u5927\uff0c\u76f8\u5e94\u5730\uff0c\u6570\u636e\u64cd\u4f5c\u589e\u5220\u6539\u67e5\u7684\u5f00\u9500\u4e5f\u4f1a\u8d8a\u6765\u8d8a\u5927\u3002"),(0,i.kt)("p",null,"\u53e6\u5916\uff0c\u7531\u4e8e\u65e0\u6cd5\u8fdb\u884c\u5206\u5e03\u5f0f\u90e8\u7f72\uff0c\u800c\u4e00\u53f0\u670d\u52a1\u5668\u7684\u8d44\u6e90\uff08CPU\u3001\u78c1\u76d8\u3001\u5185\u5b58\u3001IO \u7b49\uff09\u662f\u6709\u9650\u7684\uff0c\u6700\u7ec8\u6570\u636e\u5e93\u6240\u80fd\u627f\u8f7d\u7684\u6570\u636e\u91cf\u3001\u6570\u636e\u5904\u7406\u80fd\u529b\u90fd\u5c06\u906d\u9047\u74f6\u9888\u3002"),(0,i.kt)("p",null,"\u8fd9\u4e2a\u65f6\u5019\u5c31\u9700\u8981\u5bf9\u6570\u636e\u5e93\u6216\u6570\u636e\u8868\u8fdb\u884c\u62c6\u5206\u3002"),(0,i.kt)("p",null,"\u6570\u636e\u5207\u5206\u53ef\u4ee5\u5206\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"\u5782\u76f4\u5207\u5206")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"\u6c34\u5e73\u5207\u5206"),"\u3002"),(0,i.kt)("h2",{id:"9282-\u5782\u76f4\u5207\u5206"},"9.28.2 \u5782\u76f4\u5207\u5206"),(0,i.kt)("p",null,"\u5782\u76f4\u5207\u5206\u53c8\u53ef\u4ee5\u5206\u4e3a: \u5782\u76f4\u5206\u5e93\u548c\u5782\u76f4\u5206\u8868\u3002"),(0,i.kt)("h3",{id:"92821-\u5782\u76f4\u5206\u5e93"},"9.28.2.1 \u5782\u76f4\u5206\u5e93"),(0,i.kt)("p",null,'\u6839\u636e\u4e1a\u52a1\u8026\u5408\u6027\uff0c\u5c06\u5173\u8054\u5ea6\u4f4e\u7684\u4e0d\u540c\u8868\u5b58\u50a8\u5728\u4e0d\u540c\u7684\u6570\u636e\u5e93\u3002\u505a\u6cd5\u4e0e\u5927\u7cfb\u7edf\u62c6\u5206\u4e3a\u591a\u4e2a\u5c0f\u7cfb\u7edf\u7c7b\u4f3c\uff0c\u6309\u4e1a\u52a1\u5206\u7c7b\u8fdb\u884c\u72ec\u7acb\u5212\u5206\u3002\u4e0e"\u5fae\u670d\u52a1\u6cbb\u7406"\u7684\u505a\u6cd5\u76f8\u4f3c\uff0c\u6bcf\u4e2a\u5fae\u670d\u52a1\u4f7f\u7528\u5355\u72ec\u7684\u4e00\u4e2a\u6570\u636e\u5e93\u3002'),(0,i.kt)("img",{src:(0,r.Z)("img/dbsplit1.jpg")}),(0,i.kt)("admonition",{title:"\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u4e00\u5f00\u59cb\u6211\u4eec\u662f\u5355\u4f53\u670d\u52a1\uff0c\u6240\u4ee5\u53ea\u6709\u4e00\u4e2a\u6570\u636e\u5e93\uff0c\u6240\u6709\u7684\u8868\u90fd\u5728\u8fd9\u4e2a\u5e93\u91cc\u3002"),(0,i.kt)("p",{parentName:"admonition"},"\u540e\u6765\u56e0\u4e3a\u4e1a\u52a1\u9700\u6c42,\u5355\u4f53\u670d\u52a1\u53d8\u6210\u5fae\u670d\u52a1\u6cbb\u7406\u3002\u6240\u4ee5\u5c06\u4e4b\u524d\u7684\u4e00\u4e2a\u5546\u54c1\u5e93\uff0c\u62c6\u5206\u6210\u591a\u4e2a\u6570\u636e\u5e93\u3002\u6bcf\u4e2a\u5fae\u670d\u52a1\u5bf9\u4e8e\u4e00\u4e2a\u6570\u636e\u5e93\u3002")),(0,i.kt)("h3",{id:"92822-\u5782\u76f4\u5206\u8868"},"9.28.2.2 \u5782\u76f4\u5206\u8868"),(0,i.kt)("p",null,"\u628a\u4e00\u4e2a\u8868\u7684\u591a\u4e2a\u5b57\u6bb5\u5206\u522b\u62c6\u6210\u591a\u4e2a\u8868\uff0c\u4e00\u822c\u6309\u5b57\u6bb5\u7684\u51b7\u70ed\u62c6\u5206\uff0c\u70ed\u5b57\u6bb5\u4e00\u4e2a\u8868\uff0c\u51b7\u5b57\u6bb5\u4e00\u4e2a\u8868\u3002\u4ece\u800c\u63d0\u5347\u4e86\u6570\u636e\u5e93\u6027\u80fd\u3002"),(0,i.kt)("img",{src:(0,r.Z)("img/dbsplit2.jpg")}),(0,i.kt)("admonition",{title:"\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u4e00\u5f00\u59cb\u5546\u54c1\u8868\u4e2d\u5305\u542b\u5546\u54c1\u7684\u6240\u6709\u5b57\u6bb5\uff0c\u4f46\u662f\u6211\u4eec\u53d1\u73b0:"),(0,i.kt)("p",{parentName:"admonition"},"1.\u5546\u54c1\u8be6\u60c5\u548c\u5546\u54c1\u5c5e\u6027\u5b57\u6bb5\u8f83\u957f\u30022.\u5546\u54c1\u5217\u8868\u7684\u65f6\u5019\u6211\u4eec\u662f\u4e0d\u9700\u8981\u663e\u793a\u5546\u54c1\u8be6\u60c5\u548c\u5546\u54c1\u5c5e\u6027\u4fe1\u606f\uff0c\u53ea\u6709\u5728\u70b9\u8fdb\u5546\u54c1\u5546\u54c1\u7684\u65f6\u5019\u624d\u4f1a\u5c55\u793a\u5546\u54c1\u8be6\u60c5\u4fe1\u606f\u3002"),(0,i.kt)("p",{parentName:"admonition"},"\u6240\u4ee5\u53ef\u4ee5\u8003\u8651\u628a\u5546\u54c1\u8be6\u60c5\u548c\u5546\u54c1\u5c5e\u6027\u5355\u72ec\u5207\u5206\u4e00\u5f20\u8868\uff0c\u63d0\u9ad8\u67e5\u8be2\u6548\u7387\u3002")),(0,i.kt)("h3",{id:"92823-\u4f18\u7f3a\u70b9"},"9.28.2.3 \u4f18\u7f3a\u70b9"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"\u4f18\u70b9"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"\u89e3\u51b3\u4e1a\u52a1\u7cfb\u7edf\u5c42\u9762\u7684\u8026\u5408\uff0c\u4e1a\u52a1\u6e05\u6670"),(0,i.kt)("li",{parentName:"ul"},"\u4e0e\u5fae\u670d\u52a1\u7684\u6cbb\u7406\u7c7b\u4f3c\uff0c\u4e5f\u80fd\u5bf9\u4e0d\u540c\u4e1a\u52a1\u7684\u6570\u636e\u8fdb\u884c\u5206\u7ea7\u7ba1\u7406\u3001\u7ef4\u62a4\u3001\u76d1\u63a7\u3001\u6269\u5c55\u7b49"),(0,i.kt)("li",{parentName:"ul"},"\u9ad8\u5e76\u53d1\u573a\u666f\u4e0b\uff0c\u5782\u76f4\u5207\u5206\u4e00\u5b9a\u7a0b\u5ea6\u7684\u63d0\u5347 IO\u3001\u6570\u636e\u5e93\u8fde\u63a5\u6570\u3001\u5355\u673a\u786c\u4ef6\u8d44\u6e90\u7684\u74f6\u9888"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"\u7f3a\u70b9"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"\u5206\u5e93\u540e\u65e0\u6cd5 Join\uff0c\u53ea\u80fd\u901a\u8fc7\u63a5\u53e3\u805a\u5408\u65b9\u5f0f\u89e3\u51b3\uff0c\u63d0\u5347\u4e86\u5f00\u53d1\u7684\u590d\u6742\u5ea6"),(0,i.kt)("li",{parentName:"ul"},"\u5206\u5e93\u540e\u5206\u5e03\u5f0f\u4e8b\u52a1\u5904\u7406\u590d\u6742"),(0,i.kt)("li",{parentName:"ul"},"\u4f9d\u7136\u5b58\u5728\u5355\u8868\u6570\u636e\u91cf\u8fc7\u5927\u7684\u95ee\u9898\uff08\u9700\u8981\u6c34\u5e73\u5207\u5206\uff09")))),(0,i.kt)("h2",{id:"9283-\u6c34\u5e73\u5207\u5206"},"9.28.3 \u6c34\u5e73\u5207\u5206"),(0,i.kt)("p",null,"\u5f53\u4e00\u4e2a\u5e94\u7528\u96be\u4ee5\u518d\u7ec6\u7c92\u5ea6\u7684\u5782\u76f4\u5207\u5206\u6216\u5207\u5206\u540e\u6570\u636e\u91cf\u884c\u6570\u5de8\u5927\uff0c\u5b58\u5728\u5355\u5e93\u8bfb\u5199\u3001\u5b58\u50a8\u6027\u80fd\u74f6\u9888\uff0c\u8fd9\u65f6\u5019\u5c31\u9700\u8981\u8fdb\u884c\u6c34\u5e73\u5207\u5206\u4e86\u3002"),(0,i.kt)("p",null,"\u6c34\u5e73\u5207\u5206\u4e5f\u53ef\u4ee5\u5206\u4e3a\uff1a\u6c34\u5e73\u5206\u5e93\u548c\u6c34\u5e73\u5206\u8868\u3002"),(0,i.kt)("h3",{id:"92831-\u6c34\u5e73\u5206\u5e93"},"9.28.3.1 \u6c34\u5e73\u5206\u5e93"),(0,i.kt)("p",null,"\u4e0a\u9762\u867d\u7136\u5df2\u7ecf\u628a\u5546\u54c1\u5e93\u5206\u6210 3 \u4e2a\u5e93\uff0c\u4f46\u662f\u968f\u7740\u4e1a\u52a1\u7684\u589e\u52a0\u4e00\u4e2a\u8ba2\u5355\u5e93\u4e5f\u51fa\u73b0 QPS \u8fc7\u9ad8\uff0c\u6570\u636e\u5e93\u54cd\u5e94\u901f\u5ea6\u6765\u4e0d\u53ca\uff0c\u4e00\u822c mysql \u5355\u673a\u4e5f\u5c31 1000 \u5de6\u53f3\u7684 QPS\uff0c\u5982\u679c\u8d85\u8fc7 1000 \u5c31\u8981\u8003\u8651\u5206\u5e93\u3002"),(0,i.kt)("img",{src:(0,r.Z)("img/dbsplit3.jpg")}),(0,i.kt)("h3",{id:"92832-\u6c34\u5e73\u5206\u8868"},"9.28.3.2 \u6c34\u5e73\u5206\u8868"),(0,i.kt)("p",null,"\u4e00\u822c\u6211\u4eec\u4e00\u5f20\u8868\u7684\u6570\u636e\u4e0d\u8981\u8d85\u8fc7 1 \u5343\u4e07,\u5982\u679c\u8868\u6570\u636e\u8d85\u8fc7 1 \u5343\u4e07\uff0c\u5e76\u4e14\u8fd8\u5728\u4e0d\u65ad\u589e\u52a0\u6570\u636e\uff0c\u90a3\u5c31\u53ef\u4ee5\u8003\u8651\u5206\u8868\u3002"),(0,i.kt)("img",{src:(0,r.Z)("img/dbsplit4.jpg")}),(0,i.kt)("h3",{id:"92833-\u4f18\u7f3a\u70b9"},"9.28.3.3 \u4f18\u7f3a\u70b9"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"\u4f18\u70b9"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"\u4e0d\u5b58\u5728\u5355\u5e93\u6570\u636e\u91cf\u8fc7\u5927\u3001\u9ad8\u5e76\u53d1\u7684\u6027\u80fd\u74f6\u9888\uff0c\u63d0\u5347\u7cfb\u7edf\u7a33\u5b9a\u6027\u548c\u8d1f\u8f7d\u80fd\u529b"),(0,i.kt)("li",{parentName:"ul"},"\u5e94\u7528\u7aef\u6539\u9020\u8f83\u5c0f\uff0c\u4e0d\u9700\u8981\u62c6\u5206\u4e1a\u52a1\u6a21\u5757"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"\u7f3a\u70b9"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"\u8de8\u5206\u7247\u7684\u4e8b\u52a1\u4e00\u81f4\u6027\u96be\u4ee5\u4fdd\u8bc1"),(0,i.kt)("li",{parentName:"ul"},"\u8de8\u5e93\u7684 Join \u5173\u8054\u67e5\u8be2\u6027\u80fd\u8f83\u5dee"),(0,i.kt)("li",{parentName:"ul"},"\u6570\u636e\u591a\u6b21\u6269\u5c55\u96be\u5ea6\u548c\u7ef4\u62a4\u91cf\u6781\u5927")))),(0,i.kt)("h2",{id:"9284-\u6570\u636e\u5206\u7247\u89c4\u5219"},"9.28.4 \u6570\u636e\u5206\u7247\u89c4\u5219"),(0,i.kt)("p",null,"\u6211\u4eec\u8003\u8651\u53bb\u6c34\u5e73\u5207\u5206\u8868\uff0c\u5c06\u4e00\u5f20\u8868\u6c34\u5e73\u5207\u5206\u6210\u591a\u5f20\u8868\uff0c\u8fd9\u5c31\u6d89\u53ca\u5230\u6570\u636e\u5206\u7247\u7684\u89c4\u5219\uff0c\u6bd4\u8f83\u5e38\u89c1\u7684\u6709\uff1aHash \u53d6\u6a21\u5206\u8868\u3001\u6570\u503c Range \u5206\u8868\u3001\u4e00\u81f4\u6027 Hash \u7b97\u6cd5\u5206\u8868\u3002"),(0,i.kt)("h3",{id:"92841-hash-\u53d6\u6a21\u5206\u8868"},"9.28.4.1 Hash \u53d6\u6a21\u5206\u8868"),(0,i.kt)("p",null,"\u4e00\u822c\u91c7\u7528 Hash \u53d6\u6a21\u7684\u5207\u5206\u65b9\u5f0f\uff0c\u4f8b\u5982\uff1a\u5047\u8bbe\u6309 goods_id \u5206 4 \u5f20\u8868\u3002\uff08goods_id%4 \u53d6\u6574\u786e\u5b9a\u8868\uff09"),(0,i.kt)("img",{src:(0,r.Z)("img/dbsplit5.jpg")}),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u4f18\u7f3a\u70b9")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"\u4f18\u70b9"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"\u6570\u636e\u5206\u7247\u76f8\u5bf9\u6bd4\u8f83\u5747\u5300\uff0c\u4e0d\u5bb9\u6613\u51fa\u73b0\u70ed\u70b9\u548c\u5e76\u53d1\u8bbf\u95ee\u7684\u74f6\u9888\u3002"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"\u7f3a\u70b9"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"\u540e\u671f\u5206\u7247\u96c6\u7fa4\u6269\u5bb9\u65f6\uff0c\u9700\u8981\u8fc1\u79fb\u65e7\u7684\u6570\u636e\u5f88\u96be\u3002"),(0,i.kt)("li",{parentName:"ul"},"\u5bb9\u6613\u9762\u4e34\u8de8\u5206\u7247\u67e5\u8be2\u7684\u590d\u6742\u95ee\u9898\u3002\u6bd4\u5982\u4e0a\u4f8b\u4e2d\uff0c\u5982\u679c\u9891\u7e41\u7528\u5230\u7684\u67e5\u8be2\u6761\u4ef6\u4e2d\u4e0d\u5e26 goods_id \u65f6\uff0c\u5c06\u4f1a\u5bfc\u81f4\u65e0\u6cd5\u5b9a\u4f4d\u6570\u636e\u5e93\uff0c\u4ece\u800c\u9700\u8981\u540c\u65f6\u5411 4 \u4e2a\u5e93\u53d1\u8d77\u67e5\u8be2\uff0c\n\u518d\u5728\u5185\u5b58\u4e2d\u5408\u5e76\u6570\u636e\uff0c\u53d6\u6700\u5c0f\u96c6\u8fd4\u56de\u7ed9\u5e94\u7528\uff0c\u5206\u5e93\u53cd\u800c\u6210\u4e3a\u62d6\u7d2f\u3002")))),(0,i.kt)("h3",{id:"92842-\u6570\u503c-range-\u5206\u8868"},"9.28.4.2 \u6570\u503c Range \u5206\u8868"),(0,i.kt)("p",null,"\u6309\u7167\u65f6\u95f4\u533a\u95f4\u6216 ID \u533a\u95f4\u6765\u5207\u5206\u3002\u4f8b\u5982\uff1a\u5c06 goods_id \u4e3a 1-1000 \u7684\u8bb0\u5f55\u5206\u5230\u7b2c\u4e00\u4e2a\u8868\uff0c1000-2000 \u7684\u5206\u5230\u7b2c\u4e8c\u4e2a\u8868\uff0c\u4ee5\u6b64\u7c7b\u63a8\u3002"),(0,i.kt)("img",{src:(0,r.Z)("img/dbsplit6.jpg")}),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u4f18\u7f3a\u70b9")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"\u4f18\u70b9"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"\u5355\u8868\u5927\u5c0f\u53ef\u63a7"),(0,i.kt)("li",{parentName:"ul"},"\u5929\u7136\u4fbf\u4e8e\u6c34\u5e73\u6269\u5c55\uff0c\u540e\u671f\u5982\u679c\u60f3\u5bf9\u6574\u4e2a\u5206\u7247\u96c6\u7fa4\u6269\u5bb9\u65f6\uff0c\u53ea\u9700\u8981\u6dfb\u52a0\u8282\u70b9\u5373\u53ef\uff0c\u65e0\u9700\u5bf9\u5176\u4ed6\u5206\u7247\u7684\u6570\u636e\u8fdb\u884c\u8fc1\u79fb"),(0,i.kt)("li",{parentName:"ul"},"\u4f7f\u7528\u5206\u7247\u5b57\u6bb5\u8fdb\u884c\u8303\u56f4\u67e5\u627e\u65f6\uff0c\u8fde\u7eed\u5206\u7247\u53ef\u5feb\u901f\u5b9a\u4f4d\u5206\u7247\u8fdb\u884c\u5feb\u901f\u67e5\u8be2\uff0c\u6709\u6548\u907f\u514d\u8de8\u5206\u7247\u67e5\u8be2\u7684\u95ee\u9898\u3002"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"\u7f3a\u70b9"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"\u70ed\u70b9\u6570\u636e\u6210\u4e3a\u6027\u80fd\u74f6\u9888\u3002\n\u4f8b\u5982\u6309\u65f6\u95f4\u5b57\u6bb5\u5206\u7247\uff0c\u6709\u4e9b\u5206\u7247\u5b58\u50a8\u6700\u8fd1\u65f6\u95f4\u6bb5\u5185\u7684\u6570\u636e\uff0c\u53ef\u80fd\u4f1a\u88ab\u9891\u7e41\u7684\u8bfb\u5199\uff0c\u800c\u6709\u4e9b\u5206\u7247\u5b58\u50a8\u7684\u5386\u53f2\u6570\u636e\uff0c\u5219\u5f88\u5c11\u88ab\u67e5\u8be2")))),(0,i.kt)("h3",{id:"92843-\u4e00\u81f4\u6027-hash-\u7b97\u6cd5"},"9.28.4.3 \u4e00\u81f4\u6027 Hash \u7b97\u6cd5"),(0,i.kt)("p",null,"\u4e00\u81f4\u6027 Hash \u7b97\u6cd5\u80fd\u5f88\u597d\u7684\u89e3\u51b3\u56e0\u4e3a Hash \u53d6\u6a21\u800c\u4ea7\u751f\u7684\u5206\u7247\u96c6\u7fa4\u6269\u5bb9\u65f6\uff0c\u9700\u8981\u8fc1\u79fb\u65e7\u7684\u6570\u636e\u7684\u96be\u9898\u3002\u5177\u4f53\u539f\u7406\u53ef\u53c2\u8003 ",(0,i.kt)("a",{parentName:"p",href:"https://www.cnblogs.com/duhuo/p/4996105.html"},"https://www.cnblogs.com/duhuo/p/4996105.html")),(0,i.kt)("h2",{id:"9285-\u5206\u5e93\u5206\u8868\u5e26\u6765\u7684\u95ee\u9898"},"9.28.5 \u5206\u5e93\u5206\u8868\u5e26\u6765\u7684\u95ee\u9898"),(0,i.kt)("p",null,"\u4efb\u4f55\u4e8b\u60c5\u90fd\u6709\u4e24\u9762\u6027\uff0c\u5206\u5e93\u5206\u8868\u4e5f\u4e0d\u4f8b\u5916\uff0c\u5982\u679c\u91c7\u7528\u5206\u5e93\u5206\u8868\uff0c\u4f1a\u5f15\u5165\u65b0\u7684\u7684\u95ee\u9898\uff1a"),(0,i.kt)("h3",{id:"92851-\u5206\u5e03\u5f0f\u4e8b\u52a1\u95ee\u9898"},"9.28.5.1 \u5206\u5e03\u5f0f\u4e8b\u52a1\u95ee\u9898"),(0,i.kt)("p",null,"\u4f7f\u7528\u5206\u5e03\u5f0f\u4e8b\u52a1\u4e2d\u95f4\u4ef6\u89e3\u51b3\uff0c\u5177\u4f53\u662f\u901a\u8fc7\u6700\u7ec8\u4e00\u81f4\u6027\u8fd8\u662f\u5f3a\u4e00\u81f4\u6027\u5206\u5e03\u5f0f\u4e8b\u52a1\uff0c\u770b\u4e1a\u52a1\u9700\u6c42\uff0c\u8fd9\u91cc\u5c31\u4e0d\u591a\u8bf4\u3002"),(0,i.kt)("h3",{id:"92852-\u8de8\u8282\u70b9\u5173\u8054\u67e5\u8be2-join-\u95ee\u9898"},"9.28.5.2 \u8de8\u8282\u70b9\u5173\u8054\u67e5\u8be2 Join \u95ee\u9898"),(0,i.kt)("p",null,"\u5207\u5206\u4e4b\u524d\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7 Join \u6765\u5b8c\u6210\u3002\u800c\u5207\u5206\u4e4b\u540e\uff0c\u6570\u636e\u53ef\u80fd\u5206\u5e03\u5728\u4e0d\u540c\u7684\u8282\u70b9\u4e0a\uff0c\u6b64\u65f6 Join \u5e26\u6765\u7684\u95ee\u9898\u5c31\u6bd4\u8f83\u9ebb\u70e6\u4e86\uff0c\u8003\u8651\u5230\u6027\u80fd\uff0c\u5c3d\u91cf\u907f\u514d\u4f7f\u7528 Join \u67e5\u8be2\u3002"),(0,i.kt)("p",null,"\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\u7684\u4e00\u4e9b\u65b9\u6cd5\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u5168\u5c40\u8868"))),(0,i.kt)("p",null,'\u5168\u5c40\u8868\uff0c\u4e5f\u53ef\u770b\u505a\u662f "\u6570\u636e\u5b57\u5178\u8868"\uff0c\u5c31\u662f\u7cfb\u7edf\u4e2d\u6240\u6709\u6a21\u5757\u90fd\u53ef\u80fd\u4f9d\u8d56\u7684\u4e00\u4e9b\u8868\uff0c\u4e3a\u4e86\u907f\u514d\u8de8\u5e93 Join \u67e5\u8be2\uff0c\u53ef\u4ee5\u5c06 \u8fd9\u7c7b\u8868\u5728\u6bcf\u4e2a\u6570\u636e\u5e93\u4e2d\u90fd\u4fdd\u5b58\u4e00\u4efd\u3002\u8fd9\u4e9b\u6570\u636e\u901a\u5e38\u5f88\u5c11\u4f1a\u8fdb\u884c\u4fee\u6539\uff0c\u6240\u4ee5\u4e5f\u4e0d\u62c5\u5fc3\u4e00\u81f4\u6027\u7684\u95ee\u9898\u3002'),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u5b57\u6bb5\u5197\u4f59"))),(0,i.kt)("p",null,'\u5229\u7528\u7a7a\u95f4\u6362\u65f6\u95f4\uff0c\u4e3a\u4e86\u6027\u80fd\u800c\u907f\u514d join \u67e5\u8be2\u3002\u4f8b\uff1a\u8ba2\u5355\u8868\u4fdd\u5b58 userId \u65f6\u5019,\u4e5f\u5c06 userName \u5197\u4f59\u4fdd\u5b58\u4e00\u4efd\uff0c\u8fd9\u6837\u67e5\u8be2\u8ba2\u5355\u8be6\u60c5\u65f6\u5c31\u4e0d\u9700\u8981\u518d\u53bb\u67e5\u8be2"\u4e70\u5bb6 user \u8868"\u4e86\u3002'),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u6570\u636e\u7ec4\u88c5"))),(0,i.kt)("p",null,"\u5728\u7cfb\u7edf\u5c42\u9762\uff0c\u5206\u4e24\u6b21\u67e5\u8be2\u3002\u7b2c\u4e00\u6b21\u67e5\u8be2\u7684\u7ed3\u679c\u96c6\u4e2d\u627e\u51fa\u5173\u8054\u6570\u636e id\uff0c\u7136\u540e\u6839\u636e id \u53d1\u8d77\u7b2c\u4e8c\u6b21\u8bf7\u6c42\u5f97\u5230\u5173\u8054\u6570\u636e\u3002\u6700\u540e\u5c06\u83b7\u5f97\u5230\u7684\u6570\u636e\u8fdb\u884c\u5b57\u6bb5\u62fc\u88c5\u3002"),(0,i.kt)("h3",{id:"92853-\u8de8\u8282\u70b9\u5206\u9875\u6392\u5e8f\u51fd\u6570\u95ee\u9898"},"9.28.5.3 \u8de8\u8282\u70b9\u5206\u9875\u3001\u6392\u5e8f\u3001\u51fd\u6570\u95ee\u9898"),(0,i.kt)("p",null,"\u8de8\u8282\u70b9\u591a\u5e93\u8fdb\u884c\u67e5\u8be2\u65f6\uff0c\u4f1a\u51fa\u73b0 Limit \u5206\u9875\u3001Order by \u6392\u5e8f\u7b49\u95ee\u9898\u3002\u5206\u9875\u9700\u8981\u6309\u7167\u6307\u5b9a\u5b57\u6bb5\u8fdb\u884c\u6392\u5e8f\uff0c\u5f53\u6392\u5e8f\u5b57\u6bb5\u5c31\u662f\u5206\u7247\u5b57\u6bb5\u65f6\uff0c\u901a\u8fc7\u5206\u7247\u89c4\u5219\u5c31\u6bd4\u8f83\u5bb9\u6613\u5b9a\u4f4d\u5230\u6307\u5b9a\u7684\u5206\u7247\uff1b"),(0,i.kt)("p",null,"\u5f53\u6392\u5e8f\u5b57\u6bb5\u975e\u5206\u7247\u5b57\u6bb5\u65f6\uff0c\u5c31\u53d8\u5f97\u6bd4\u8f83\u590d\u6742\u4e86\u3002\u9700\u8981\u5148\u5728\u4e0d\u540c\u7684\u5206\u7247\u8282\u70b9\u4e2d\u5c06\u6570\u636e\u8fdb\u884c\u6392\u5e8f\u5e76\u8fd4\u56de\uff0c\u7136\u540e\u5c06\u4e0d\u540c\u5206\u7247\u8fd4\u56de\u7684\u7ed3\u679c\u96c6\u8fdb\u884c\u6c47\u603b\u548c\u518d\u6b21\u6392\u5e8f\uff0c\u6700\u7ec8\u8fd4\u56de\u7ed9\u7528\u6237\u3002"),(0,i.kt)("h3",{id:"92854-\u5168\u5c40\u4e3b\u952e\u907f\u91cd\u95ee\u9898"},"9.28.5.4 \u5168\u5c40\u4e3b\u952e\u907f\u91cd\u95ee\u9898"),(0,i.kt)("p",null,"\u5982\u679c\u90fd\u7528\u4e3b\u952e\u81ea\u589e\u80af\u5b9a\u4e0d\u5408\u7406\uff0c\u5982\u679c\u7528 UUID \u90a3\u4e48\u65e0\u6cd5\u505a\u5230\u6839\u636e\u4e3b\u952e\u6392\u5e8f\uff0c\u6240\u4ee5\u6211\u4eec\u53ef\u4ee5\u8003\u8651\u901a\u8fc7",(0,i.kt)("a",{parentName:"p",href:"https://www.cnblogs.com/qdhxhz/p/11372658.html"},"\u96ea\u82b1 ID")," \u6765\u4f5c\u4e3a\u6570\u636e\u5e93\u7684\u4e3b\u952e\uff0c"),(0,i.kt)("h3",{id:"92855-\u6570\u636e\u8fc1\u79fb\u95ee\u9898"},"9.28.5.5 \u6570\u636e\u8fc1\u79fb\u95ee\u9898"),(0,i.kt)("p",null,"\u91c7\u7528\u53cc\u5199\u7684\u65b9\u5f0f\uff0c\u4fee\u6539\u4ee3\u7801\uff0c\u6240\u6709\u6d89\u53ca\u5230\u5206\u5e93\u5206\u8868\u7684\u8868\u7684\u589e\u3001\u5220\u3001\u6539\u7684\u4ee3\u7801\uff0c\u90fd\u8981\u5bf9\u65b0\u5e93\u8fdb\u884c\u589e\u5220\u6539\u3002\u540c\u65f6\uff0c\u518d\u6709\u4e00\u4e2a\u6570\u636e\u62bd\u53d6\u670d\u52a1\uff0c\u4e0d\u65ad\u5730\u4ece\u8001\u5e93\u62bd\u6570\u636e\uff0c\u5f80\u65b0\u5e93\u5199\uff0c"),(0,i.kt)("p",null,"\u8fb9\u5199\u8fb9\u6309\u65f6\u95f4\u6bd4\u8f83\u6570\u636e\u662f\u4e0d\u662f\u6700\u65b0\u7684\u3002"),(0,i.kt)("h2",{id:"9286-\u5982\u4f55\u5b9e\u73b0"},"9.28.6 \u5982\u4f55\u5b9e\u73b0"),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"caution"},(0,i.kt)("p",{parentName:"admonition"},"\u7531\u4e8e\u5206\u8868\u5206\u5e93\u4e0d\u4ec5\u4ec5\u9700\u8981\u5185\u7f6e\u4ee3\u7801\u7684\u652f\u6301\uff0c\u540c\u65f6\u8fd8\u9700\u8981\u96c6\u6210\u6570\u636e\u5e93\u4e2d\u95f4\u4ef6\uff0c\u8fd9\u91cc\u63a8\u8350 ",(0,i.kt)("inlineCode",{parentName:"p"},"MyCat")," \u4e2d\u95f4\u4ef6\u3002",(0,i.kt)("a",{parentName:"p",href:"http://www.mycat.org.cn/"},"MyCat \u5b98\u65b9\u7f51\u7ad9"))),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u63d0\u4f9b\u4e86\u8f7b\u91cf\u7ea7\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5206\u8868\u5206\u5e93")," \u652f\u6301\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93"))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u76f4\u63a5\u6539\u53d8\u6570\u636e\u5e93\nrepository.ChangeDatabase("\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32");\n\n// \u901a\u8fc7\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u5207\u6362\nrepository.Change();\n')),(0,i.kt)("p",null,"\u5982\u9700\u8de8\u5e93\u67e5\u8be2\uff0c\u9700\u7528\u5230\u6570\u636e\u5e93\u6280\u672f\uff0c\u5982 ",(0,i.kt)("inlineCode",{parentName:"p"},"SqlServer")," \u94fe\u63a5\u670d\u52a1\u5668\u6216\u540c\u4e49\u8bcd\u3002"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93\u8868"))),(0,i.kt)("p",null,"\u7b2c\u4e00\u6b65\u3001\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u7279\u6027",(0,i.kt)("inlineCode",{parentName:"p"},"[AppDbContext( Mode=DbContextMode.Dynamic)]")),(0,i.kt)("p",null,"\u7b2c\u4e8c\u6b65\u3001\u9700\u8981\u52a8\u6001\u4fee\u6539\u8868\u540d\u7684\u5b9e\u4f53\u7ee7\u627f ",(0,i.kt)("inlineCode",{parentName:"p"},"IEntityMutableTable")," \u63a5\u53e3\uff0c\u5e76\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"p"},"GetTableName()")," \u8fd4\u56de\u8868\u540d\u65b9\u6cd5"),(0,i.kt)("p",null,"\u6700\u540e\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"BuildChange")," \u5207\u6362\u5373\u53ef\u3002"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var (rep, scoped) = repository.BuildChange();\n")),(0,i.kt)("p",null,"\u8c03\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"BuildChange")," \u65b9\u6cd5\u4e4b\u540e\u4f1a\u81ea\u52a8\u8c03\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"GetTableName()")," \u65b9\u6cd5\u3002"),(0,i.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"p"},"DynamicModelCacheKeyFactory")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/ef/core/modeling/dynamic-model"},"EF Core - \u591a\u4e2a\u6a21\u578b\u4e4b\u95f4\u4ea4\u66ff")," \u7ae0\u8282\u3002")),(0,i.kt)("h2",{id:"9287-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.28.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return m},kt:function(){return s}});var l=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,l)}return n}function r(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(l=0;l=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var o=l.createContext({}),u=function(e){var t=l.useContext(o),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},m=function(e){var t=u(e.components);return l.createElement(o.Provider,{value:t},e.children)},k={inlineCode:"code",wrapper:function(e){var t=e.children;return l.createElement(l.Fragment,{},t)}},d=l.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,o=e.parentName,m=p(e,["components","mdxType","originalType","parentName"]),d=u(n),s=a,c=d["".concat(o,".").concat(s)]||d[s]||k[s]||i;return n?l.createElement(c,r(r({ref:t},m),{},{components:n})):l.createElement(c,r({ref:t},m))}));function s(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,r=new Array(i);r[0]=d;var p={};for(var o in t)hasOwnProperty.call(t,o)&&(p[o]=t[o]);p.originalType=e,p.mdxType="string"==typeof e?e:a,r[1]=p;for(var u=2;u0&&r.createElement(o,{years:u}))))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[3608],{3169:function(e,t,a){a.r(t),a.d(t,{default:function(){return s}});var r=a(7294),n=a(9960),l=a(5999),c=a(833),i=a(7302);function m(e){var t=e.year,a=e.posts;return r.createElement(r.Fragment,null,r.createElement("h3",null,t),r.createElement("ul",null,a.map((function(e){return r.createElement("li",{key:e.metadata.date},r.createElement(n.Z,{to:e.metadata.permalink},e.metadata.formattedDate," - ",e.metadata.title))}))))}function o(e){var t=e.years;return r.createElement("section",{className:"margin-vert--lg"},r.createElement("div",{className:"container"},r.createElement("div",{className:"row"},t.map((function(e,t){return r.createElement("div",{key:t,className:"col col--4 margin-vert--lg"},r.createElement(m,e))})))))}function s(e){var t,a,n=e.archive,m=(0,l.I)({id:"theme.blog.archive.title",message:"Archive",description:"The page & hero title of the blog archive page"}),s=(0,l.I)({id:"theme.blog.archive.description",message:"Archive",description:"The page & hero description of the blog archive page"}),u=(t=n.blogPosts,a=t.reduceRight((function(e,t){var a,r=t.metadata.date.split("-")[0],n=null!=(a=e.get(r))?a:[];return e.set(r,[t].concat(n))}),new Map),Array.from(a,(function(e){return{year:e[0],posts:e[1]}})));return r.createElement(r.Fragment,null,r.createElement(c.d,{title:m,description:s}),r.createElement(i.Z,null,r.createElement("header",{className:"hero hero--primary"},r.createElement("div",{className:"container"},r.createElement("h1",{className:"hero__title"},m),r.createElement("p",{className:"hero__subtitle"},s))),r.createElement("main",null,u.length>0&&r.createElement(o,{years:u}))))}}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/9e7ef9fa.c0b774f3.js b/handbook/build/assets/js/9e7ef9fa.c0b774f3.js new file mode 100644 index 0000000000..8f061229d1 --- /dev/null +++ b/handbook/build/assets/js/9e7ef9fa.c0b774f3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[1866],{3905:function(e,n,t){t.d(n,{Zo:function(){return m},kt:function(){return c}});var i=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function a(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=i.createContext({}),p=function(e){var n=i.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},m=function(e){var n=p(e.components);return i.createElement(s.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},u=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,m=l(e,["components","mdxType","originalType","parentName"]),u=p(t),c=r,k=u["".concat(s,".").concat(c)]||u[c]||d[c]||o;return t?i.createElement(k,a(a({ref:n},m),{},{components:t})):i.createElement(k,a({ref:n},m))}));function c(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var o=t.length,a=new Array(o);a[0]=u;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:r,a[1]=l;for(var p=2;p\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0",id:"91921-\u6253\u5f00-\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0",level:3},{value:"9.19.2.2 \u5207\u6362\u9ed8\u8ba4\u9879\u76ee",id:"91922-\u5207\u6362\u9ed8\u8ba4\u9879\u76ee",level:3},{value:"9.19.2.3 \u8f93\u5165 cli.ps1 \u547d\u4ee4",id:"91923-\u8f93\u5165-clips1-\u547d\u4ee4",level:3},{value:"9.19.3 \u754c\u9762\u64cd\u4f5c\u6a21\u5f0f",id:"9193-\u754c\u9762\u64cd\u4f5c\u6a21\u5f0f",level:2},{value:"9.19.3.1 \u542f\u52a8\u754c\u9762\u64cd\u4f5c",id:"91931-\u542f\u52a8\u754c\u9762\u64cd\u4f5c",level:3},{value:"9.19.3.2 \u52a0\u8f7d\u6570\u636e\u5e93\u8868",id:"91932-\u52a0\u8f7d\u6570\u636e\u5e93\u8868",level:3},{value:"9.19.3.3 \u9009\u62e9\u8868\u6216\u89c6\u56fe\u751f\u6210",id:"91933-\u9009\u62e9\u8868\u6216\u89c6\u56fe\u751f\u6210",level:3},{value:"9.19.3.4 \u9009\u62e9\u4fdd\u5b58\u76ee\u5f55",id:"91934-\u9009\u62e9\u4fdd\u5b58\u76ee\u5f55",level:3},{value:"9.19.3.5 \u751f\u6210\u6700\u7ec8\u5b9e\u4f53\u4ee3\u7801",id:"91935-\u751f\u6210\u6700\u7ec8\u5b9e\u4f53\u4ee3\u7801",level:3},{value:"9.19.4 \u547d\u4ee4\u53c2\u6570\u914d\u7f6e",id:"9194-\u547d\u4ee4\u53c2\u6570\u914d\u7f6e",level:2},{value:"9.19.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9195-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:u};function k(e){var n=e.components,t=(0,r.Z)(e,l);return(0,o.kt)("wrapper",(0,i.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{title:"\u89c6\u9891\u6559\u7a0b",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("a",{parentName:"p",href:"https://www.bilibili.com/video/BV1Rt4y1W7oJ"},"https://www.bilibili.com/video/BV1Rt4y1W7oJ"))),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u811a\u672c",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u5728\u9605\u8bfb\u4e0b\u9762\u6587\u6863\u4e4b\u524d\uff0c\u5fc5\u987b\u628a",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6e90\u7801\u6587\u4ef6\u5939\u4e0b\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"tools/cli.ps1")," \u6587\u4ef6\u62f7\u8d1d\u5230\u672c\u5730\u4e2d\u3002\u800c\u4e14 ",(0,o.kt)("inlineCode",{parentName:"p"},"Fur.Web.Entry")," \u5c42\u9700\u8981\u5b89\u88c5 ",(0,o.kt)("inlineCode",{parentName:"p"},"Microsoft.EntityFrameworkCore.Tools")," \u5305\u3002")),(0,o.kt)("admonition",{title:"\u7cfb\u7edf\u63d0\u793a\u7981\u6b62\u8fd0\u884c\u811a\u672c\u89e3\u51b3",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u51fa\u73b0 ",(0,o.kt)("inlineCode",{parentName:"p"},"cli.ps1")," \u65e0\u6cd5\u8fd0\u884c\u7684\u60c5\u51b5\uff0c\u5982\u63d0\u793a\uff1a",(0,o.kt)("inlineCode",{parentName:"p"},"\u201c\u56e0\u4e3a\u5728\u6b64\u7cfb\u7edf\u4e0a\u7981\u6b62\u8fd0\u884c\u811a\u672c\u201d"),"\uff0c\u53ea\u9700\u8981\u6253\u5f00\u7cfb\u7edf\u7ba1\u7406\u5458 ",(0,o.kt)("inlineCode",{parentName:"p"},"CMD/Powershell")," \u6267\u884c\uff1a",(0,o.kt)("inlineCode",{parentName:"p"},"set-ExecutionPolicy RemoteSigned")," \u547d\u4ee4\u5e76\u6839\u636e\u64cd\u4f5c\u63d0\u793a\u8f93\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"A")," \u5373\u53ef\u3002"),(0,o.kt)("p",{parentName:"admonition"},"\u4e4b\u540e\u91cd\u542f ",(0,o.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u5de5\u5177\u3002")),(0,o.kt)("h2",{id:"9191-\u6570\u636e\u5e93\u5f00\u53d1\u65b9\u5f0f"},"9.19.1 \u6570\u636e\u5e93\u5f00\u53d1\u65b9\u5f0f"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e24\u79cd\u4e3b\u8981\u65b9\u6cd5\u6765 ",(0,o.kt)("strong",{parentName:"p"},"\u4fdd\u6301\u5b9e\u4f53\u6a21\u578b\u548c\u6570\u636e\u5e93\u67b6\u6784\u540c\u6b65"),"\u3002"),(0,o.kt)("p",null,"\u81f3\u4e8e\u6211\u4eec\u5e94\u8be5\u9009\u7528\u54ea\u4e2a\u65b9\u6cd5\uff0c\u8bf7\u786e\u5b9a\u4f60\u662f\u5e0c\u671b\u4ee5\u5b9e\u4f53\u6a21\u578b\u4e3a\u51c6\u8fd8\u662f\u4ee5\u6570\u636e\u5e93\u4e3a\u51c6\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"\u5982\u679c\u5e0c\u671b ",(0,o.kt)("strong",{parentName:"p"},"\u4ee5\u5b9e\u4f53\u6a21\u578b\u4e3a\u51c6"),"\uff0c\u8bf7\u4f7f\u7528\u6b63\u5411\u5de5\u7a0b\uff08Code First\uff09\u3002 \u5bf9\u5b9e\u4f53\u6a21\u578b\u8fdb\u884c\u66f4\u6539\u65f6\uff0c\u6b64\u65b9\u6cd5\u4f1a\u4ee5\u589e\u91cf\u65b9\u5f0f\u5c06\u76f8\u5e94\u67b6\u6784\u66f4\u6539\u5e94\u7528\u5230\u6570\u636e\u5e93\uff0c\u4ee5\u4f7f\u6570\u636e\u5e93\u4fdd\u6301\u4e0e\u5b9e\u4f53\u6a21\u578b\u517c\u5bb9\u3002")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"\u5982\u679c\u5e0c\u671b ",(0,o.kt)("strong",{parentName:"p"},"\u4ee5\u6570\u636e\u5e93\u67b6\u6784\u4e3a\u51c6"),"\uff0c\u8bf7\u4f7f\u7528\u53cd\u5411\u5de5\u7a0b\uff08Database First\uff09\u3002 \u4f7f\u7528\u6b64\u65b9\u6cd5\uff0c\u53ef\u901a\u8fc7\u5c06\u6570\u636e\u5e93\u67b6\u6784\u53cd\u5411\u5de5\u7a0b\u5230\u5b9e\u4f53\u6a21\u578b\u6765\u751f\u6210\u76f8\u5e94\u7684\u5b9e\u4f53\u7c7b\u578b\u3002"))),(0,o.kt)("p",null,"\u672c\u7ae0\u8282\u662f ",(0,o.kt)("strong",{parentName:"p"},"\u53cd\u5411\u5de5\u7a0b\uff08Database First\uff09")," \u7684\u76f8\u5173\u5185\u5bb9\u3002"),(0,o.kt)("h2",{id:"9192-\u64cd\u4f5c\u6307\u5357"},"9.19.2 \u64cd\u4f5c\u6307\u5357"),(0,o.kt)("admonition",{title:"\u64cd\u4f5c\u4e4b\u524d\u6ce8\u610f\u4e8b\u9879",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u76ee\u524d ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion Tools")," \u751f\u6210\u5de5\u5177",(0,o.kt)("strong",{parentName:"p"},"\u9ed8\u8ba4\u4e0d\u652f\u6301\u4efb\u4f55\u6570\u636e\u5e93"),"\u751f\u6210\uff0c\u6240\u4ee5\u5982\u9700\u751f\u6210\u7279\u5b9a\u6570\u636e\u5e93\u7684\u4ee3\u7801\uff0c\u53ea\u9700\u8981\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion.EntityFrameworkCore.Core")," \u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93\u5305\u5373\u53ef\uff1a"),(0,o.kt)("p",{parentName:"admonition"},"\u5404\u4e2a\u6570\u636e\u5e93\u7684\u5305\u53ef\u67e5\u9605\uff1a",(0,o.kt)("a",{parentName:"p",href:"dbcontext-multi-database"},"\u591a\u6570\u636e\u5e93\u64cd\u4f5c-\u6570\u636e\u5e93\u63d0\u4f9b\u5668\u5bf9\u5e94\u5305")),(0,o.kt)("p",{parentName:"admonition"},"\u53e6\u5916\uff0c\u53ea\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"SqlServer")," \u6570\u636e\u5e93\u652f\u6301\u53ef\u89c6\u5316 ",(0,o.kt)("inlineCode",{parentName:"p"},"GUI")," \u64cd\u4f5c\uff0c\u5176\u4ed6\u7684\u53ea\u80fd\u547d\u4ee4\u884c\u64cd\u4f5c\u3002")),(0,o.kt)("h3",{id:"91921-\u6253\u5f00-\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0"},"9.19.2.1 \u6253\u5f00 ",(0,o.kt)("inlineCode",{parentName:"h3"},"\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0")),(0,o.kt)("p",null,"\u6ce8\u610f\uff1a\u5f00\u59cb\u4e4b\u524d\u5148\u628a ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion.Web.Entry")," \u8bbe\u4e3a\u542f\u52a8\u9879\u76ee\u3002"),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst1.png")}),(0,o.kt)("h3",{id:"91922-\u5207\u6362\u9ed8\u8ba4\u9879\u76ee"},"9.19.2.2 \u5207\u6362\u9ed8\u8ba4\u9879\u76ee"),(0,o.kt)("p",null,"\u5c06 ",(0,o.kt)("inlineCode",{parentName:"p"},"\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0")," \u9ed8\u8ba4\u9879\u76ee\u8bbe\u7f6e\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion.Core"),"\uff0c\u5982\u679c\u60a8\u662f\u5176\u4ed6\u540d\u5b57\uff0c\u5219\u5207\u6362\u5bf9\u5e94\u5373\u53ef\u3002"),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst2.png")}),(0,o.kt)("h3",{id:"91923-\u8f93\u5165-clips1-\u547d\u4ee4"},"9.19.2.3 \u8f93\u5165 ",(0,o.kt)("inlineCode",{parentName:"h3"},"cli.ps1")," \u547d\u4ee4"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"PM> Show-Command ../tools/cli.ps1\n")),(0,o.kt)("img",{src:(0,a.Z)("img/df10.png")}),(0,o.kt)("admonition",{title:"\u5168\u547d\u4ee4\u65b9\u5f0f\uff08\u63a8\u8350\uff09\u2764\ufe0f",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u9664\u4e86\u91c7\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"Show-Command")," \u65b9\u5f0f\u4ee5\u5916\uff0c\u8fd8\u53ef\u4ee5\u76f4\u63a5\u6267\u884c\u547d\u4ee4\uff0c\u5982\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},'&"./tools/cli.ps1" -DbProvider "Microsoft.EntityFrameworkCore.SqlServer" -CoreProject "XXX.Core" -EntryProject "XXX.Web.Entry" -ConnectionName "Default"\n'))),(0,o.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528\u7684\u662f ",(0,o.kt)("inlineCode",{parentName:"p"},"SqlServer")," \u6570\u636e\u5e93\uff0c\u5219\u9ed8\u8ba4\u4e0d\u9700\u8981\u6307\u5b9a ",(0,o.kt)("inlineCode",{parentName:"p"},"-DbProvider")," \u53c2\u6570\u3002")),(0,o.kt)("p",null,"\u5982\u679c\u4e0d\u6e05\u695a\u5f53\u524d\u8fd0\u884c\u73af\u5883\u7684\u8def\u5f84\uff0c\u53ef\u4ee5\u8f93\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"pwd")," \u67e5\u770b\u3002"),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u6570\u636e\u5e93\u547d\u540d",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u9700\u8981\u4fdd\u6301\u548c\u6570\u636e\u5e93\u4e00\u6a21\u4e00\u6837\u7684\u547d\u540d\uff0c\u5219\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"-UseDatabaseNames")," \u53c2\u6570\u6307\u5b9a\uff0c\u5982\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},' &"../tools/cli.ps1" -UseDatabaseNames\n'))),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst3.png")}),(0,o.kt)("admonition",{title:"\u7b49\u5f85\u8f93\u5165",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u6267\u884c\u4e0a\u9762\u547d\u4ee4\u540e\uff0c\u6b64\u65f6 ",(0,o.kt)("inlineCode",{parentName:"p"},"Cli")," \u6709\u4e00\u4e2a\u7b49\u5f85\u8f93\u5165\u63d0\u793a\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Furion Tools v1.0.0 \u8bf7\u952e\u5165\u64cd\u4f5c\u7c7b\u578b\uff1a[G] \u754c\u9762\u64cd\u4f5c\uff0c[\u4efb\u610f\u5b57\u7b26] \u547d\u4ee4\u884c\u64cd\u4f5c\nFurion Tools v1.0.0 \u60a8\u7684\u8f93\u5165\u662f:\n")),(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("strong",{parentName:"p"},"\u8f93\u5165\u5927\u5199 ",(0,o.kt)("inlineCode",{parentName:"strong"},"G")," \u8fdb\u5165\u754c\u9762\u64cd\u4f5c\u6a21\u5f0f\uff0c\u5176\u4ed6\u4efb\u610f\u5b57\u7b26\u8fdb\u5165\u547d\u4ee4\u884c\u64cd\u4f5c\u6a21\u5f0f\u3002"))),(0,o.kt)("admonition",{title:"\u6ce8\u610f\u4e8b\u9879",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"\u76ee\u524d\u53ea\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql Server")," \u6570\u636e\u5e93\u624d\u652f\u6301 ",(0,o.kt)("inlineCode",{parentName:"p"},"GUI \u754c\u9762\u64cd\u4f5c\u6a21\u5f0f"),"\uff0c\u5176\u4ed6\u6570\u636e\u5e93\u8bf7\u4f7f\u7528\u547d\u4ee4\u884c\u6a21\u5f0f\u3002")),(0,o.kt)("h2",{id:"9193-\u754c\u9762\u64cd\u4f5c\u6a21\u5f0f"},"9.19.3 \u754c\u9762\u64cd\u4f5c\u6a21\u5f0f"),(0,o.kt)("h3",{id:"91931-\u542f\u52a8\u754c\u9762\u64cd\u4f5c"},"9.19.3.1 \u542f\u52a8\u754c\u9762\u64cd\u4f5c"),(0,o.kt)("p",null,"\u5f53\u6211\u4eec\u8f93\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"G")," \u65f6\uff0c\u5c06\u6253\u5f00 ",(0,o.kt)("inlineCode",{parentName:"p"},"GUI")," \u754c\u9762\u64cd\u4f5c\u6a21\u5f0f\uff0c\u5982\uff1a"),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst4.png")}),(0,o.kt)("p",null,"\u8fd9\u65f6\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Furion Tools")," \u4f1a\u81ea\u52a8\u67e5\u627e\u6240\u6709\u6570\u636e\u5e93\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\uff1a"),(0,o.kt)("admonition",{title:"\u6ce8\u610f\u4e8b\u9879",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u9879\u9700\u5199\u5230 ",(0,o.kt)("inlineCode",{parentName:"p"},"json")," \u914d\u7f6e\u6587\u4ef6\u4e2d\uff0c\u4e14\u6839\u8282\u70b9\u9700\u8981\u5199\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"ConnectionStrings")," \u3002")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {12-13}",showLineNumbers:!0,"":!0,"{12-13}":!0},'{\n "Logging": {\n "LogLevel": {\n "Default": "Information",\n "Microsoft": "Warning",\n "Microsoft.Hosting.Lifetime": "Information",\n "Microsoft.EntityFrameworkCore": "Information"\n }\n },\n "AllowedHosts": "*",\n "ConnectionStrings": {\n "DbConnectionString": "Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;",\n "Sqlite3ConnectionString": "Data Source=./Furion.db"\n }\n}\n')),(0,o.kt)("h3",{id:"91932-\u52a0\u8f7d\u6570\u636e\u5e93\u8868"},"9.19.3.2 \u52a0\u8f7d\u6570\u636e\u5e93\u8868"),(0,o.kt)("p",null,"\u9009\u62e9\u8fde\u63a5\u5b57\u7b26\u4e32\u4e4b\u540e\uff0c\u70b9\u51fb ",(0,o.kt)("inlineCode",{parentName:"p"},"\u52a0\u8f7d\u6570\u636e\u5e93\u8868\u548c\u89c6\u56fe")," \u6309\u94ae\u52a0\u8f7d\u3002"),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst5.png")}),(0,o.kt)("h3",{id:"91933-\u9009\u62e9\u8868\u6216\u89c6\u56fe\u751f\u6210"},"9.19.3.3 \u9009\u62e9\u8868\u6216\u89c6\u56fe\u751f\u6210"),(0,o.kt)("p",null,"\u52a0\u8f7d\u8868\u5b8c\u6210\u540e\uff0c\u53ef\u4ee5\u9009\u62e9\u60a8\u8981\u751f\u6210\u7684\u8868\u6216\u89c6\u56fe\uff0c",(0,o.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u9009")),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst6.png")}),(0,o.kt)("p",null,"\u70b9\u51fb\u5e95\u90e8\u6309\u94ae ",(0,o.kt)("inlineCode",{parentName:"p"},"\u7acb\u5373\u751f\u6210")),(0,o.kt)("h3",{id:"91934-\u9009\u62e9\u4fdd\u5b58\u76ee\u5f55"},"9.19.3.4 \u9009\u62e9\u4fdd\u5b58\u76ee\u5f55"),(0,o.kt)("p",null,"\u70b9\u51fb ",(0,o.kt)("inlineCode",{parentName:"p"},"\u7acb\u5373\u751f\u6210")," \u6309\u94ae\u540e\uff0c\u4f1a\u5f39\u51fa\u5b9e\u4f53\u4fdd\u5b58\u9009\u62e9\u76ee\u5f55\u8d44\u6e90\u7ba1\u7406\u5668\uff0c\u9ed8\u8ba4\u5b9e\u4f53\u53ea\u80fd\u4fdd\u5b58\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion.Core")," \u5c42\uff1a"),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst7.png")}),(0,o.kt)("p",null,"\u70b9\u51fb\u786e\u5b9a\u540e\u5c31\u53ef\u5b8c\u6210\u6240\u6709\u751f\u6210\u64cd\u4f5c\u3002"),(0,o.kt)("h3",{id:"91935-\u751f\u6210\u6700\u7ec8\u5b9e\u4f53\u4ee3\u7801"},"9.19.3.5 \u751f\u6210\u6700\u7ec8\u5b9e\u4f53\u4ee3\u7801"),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst8.png")}),(0,o.kt)("p",null,"\u6700\u7ec8\u811a\u672c\u5982\u4e0b\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},'PM> &"../tools/cli.ps1"\n// -----------------------------------------------------------------------------\n// ______ _______ _\n// | ____| |__ __| | |\n// | |__ _ _ _ __ | | ___ ___ | |___\n// | __| | | | \'__| | |/ _ \\ / _ \\| / __|\n// | | | |_| | | | | (_) | (_) | \\__ \\\n// |_| \\__,_|_| |_|\\___/ \\___/|_|___/\n//\n// -----------------------------------------------------------------------------\nFurion Tools v1.0.0 \u542f\u52a8\u4e2d......\nFurion Tools v1.0.0 \u542f\u52a8\u6210\u529f\uff01\nFurion Tools v1.0.0 \u8bf7\u952e\u5165\u64cd\u4f5c\u7c7b\u578b\uff1a[G] \u754c\u9762\u64cd\u4f5c\uff0c[\u4efb\u610f\u5b57\u7b26] \u547d\u4ee4\u884c\u64cd\u4f5c\nFurion Tools v1.0.0 \u60a8\u7684\u8f93\u5165\u662f: G\nFurion Tools v1.0.0 \u6b63\u5728\u52a0\u8f7d\u6570\u636e\u5e93\u8868\u548c\u89c6\u56fe......\nFurion Tools v1.0.0 \u52a0\u8f7d\u6210\u529f\uff01\nFurion Tools v1.0.0 \u6b63\u5728\u7f16\u8bd1\u89e3\u51b3\u65b9\u6848\u4ee3\u7801......\nBuild started...\nBuild succeeded.\nFor foreign key FK_PersonDetail_Person_PersonId on table dbo.PersonDetail, unable to model the end of the foreign key on principal table dbo.Person. This is usually because the principal table was not included in the selection set.\nFurion Tools v1.0.0 \u7f16\u8bd1\u6210\u529f\uff01\nFurion Tools v1.0.0 \u5f00\u59cb\u751f\u6210\u5b9e\u4f53\u6587\u4ef6......\nFurion Tools v1.0.0 \u6b63\u5728\u751f\u6210 City.cs \u5b9e\u4f53\u4ee3\u7801......\nFurion Tools v1.0.0 \u6210\u529f\u751f\u6210 City.cs \u5b9e\u4f53\u4ee3\u7801\n// -----------------------------------------------------------------------------\n// \u4ee5\u4e0b\u4ee3\u7801\u7531 Furion Tools v1.0.0 \u751f\u6210\n// -----------------------------------------------------------------------------\n\nusing Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Collections.Generic;\n\n#nullable disable\n\nnamespace Furion.Core\n{\n public partial class City : IEntity, IEntityTypeBuilder\n {\n\n public City()\n {\n InverseParent = new HashSet();\n }\n\n public int Id { get; set; }\n public string Name { get; set; }\n public int? ParentId { get; set; }\n public DateTime CreatedTime { get; set; }\n public DateTime? UpdatedTime { get; set; }\n public bool IsDeleted { get; set; }\n\n public virtual City Parent { get; set; }\n public virtual ICollection InverseParent { get; set; }\n\n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasIndex(e => e.ParentId, "IX_City_ParentId");\n\n entityBuilder.HasOne(d => d.Parent)\n .WithMany(p => p.InverseParent)\n .HasForeignKey(d => d.ParentId);\n\n }\n\n }\n}\n\nFurion Tools v1.0.0 \u6b63\u5728\u751f\u6210 PersonDetail.cs \u5b9e\u4f53\u4ee3\u7801......\nFurion Tools v1.0.0 \u6210\u529f\u751f\u6210 PersonDetail.cs \u5b9e\u4f53\u4ee3\u7801\n// -----------------------------------------------------------------------------\n// \u4ee5\u4e0b\u4ee3\u7801\u7531 Furion Tools v1.0.0 \u751f\u6210\n// -----------------------------------------------------------------------------\n\nusing Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Collections.Generic;\n\n#nullable disable\n\nnamespace Furion.Core\n{\n public partial class PersonDetail : IEntity, IEntityTypeBuilder\n {\n\n public int Id { get; set; }\n public string PhoneNumber { get; set; }\n public string Qq { get; set; }\n public int PersonId { get; set; }\n\n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasIndex(e => e.PersonId, "IX_PersonDetail_PersonId")\n .IsUnique();\n\n entityBuilder.Property(e => e.Qq).HasColumnName("QQ");\n\n }\n\n }\n}\n\nFurion Tools v1.0.0 \u6b63\u5728\u751f\u6210 Post.cs \u5b9e\u4f53\u4ee3\u7801......\nFurion Tools v1.0.0 \u6210\u529f\u751f\u6210 Post.cs \u5b9e\u4f53\u4ee3\u7801\n// -----------------------------------------------------------------------------\n// \u4ee5\u4e0b\u4ee3\u7801\u7531 Furion Tools v1.0.0 \u751f\u6210\n// -----------------------------------------------------------------------------\n\nusing Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Collections.Generic;\n\n#nullable disable\n\nnamespace Furion.Core\n{\n public partial class Post : IEntity\n {\n\n public int Id { get; set; }\n public string Name { get; set; }\n public DateTime CreatedTime { get; set; }\n public DateTime? UpdatedTime { get; set; }\n public bool IsDeleted { get; set; }\n\n }\n}\n\nFurion Tools v1.0.0 \u6b63\u5728\u751f\u6210 VPerson.cs \u5b9e\u4f53\u4ee3\u7801......\nFurion Tools v1.0.0 \u6210\u529f\u751f\u6210 VPerson.cs \u5b9e\u4f53\u4ee3\u7801\n// -----------------------------------------------------------------------------\n// \u4ee5\u4e0b\u4ee3\u7801\u7531 Furion Tools v1.0.0 \u751f\u6210\n// -----------------------------------------------------------------------------\n\nusing Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Collections.Generic;\n\n#nullable disable\n\nnamespace Furion.Core\n{\n public partial class VPerson : IEntity, IEntityTypeBuilder\n {\n\n public int Id { get; set; }\n public string Name { get; set; }\n public int Age { get; set; }\n public string Address { get; set; }\n\n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasNoKey();\n\n entityBuilder.ToView("V_Person");\n\n entityBuilder.Property(e => e.Id).ValueGeneratedOnAdd();\n\n entityBuilder.Property(e => e.Name).HasMaxLength(32);\n\n }\n\n }\n}\n\nFurion Tools v1.0.0 \u5168\u90e8\u5b9e\u4f53\u751f\u6210\u6210\u529f\uff01\nPM>\n')),(0,o.kt)("h2",{id:"9194-\u547d\u4ee4\u53c2\u6570\u914d\u7f6e"},"9.19.4 \u547d\u4ee4\u53c2\u6570\u914d\u7f6e"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion Tools Cli")," \u652f\u6301\u591a\u4e2a\u53c2\u6570\u914d\u7f6e\uff0c\u4f7f\u7528\u65b9\u6cd5\u53ea\u9700\u8981\u5728\u547d\u4ee4\u540e\u9762\u6dfb\u52a0\u5373\u53ef\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},' &"../tools/cli.ps1" -Context \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u540d -ConnectionName \u8fde\u63a5\u5b57\u7b26\u4e32Key\n')),(0,o.kt)("p",null,"\u652f\u6301\u53c2\u6570\u5982\u4e0b\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-Tables"),"\uff1a\u914d\u7f6e\u8981\u751f\u6210\u7684\u6570\u636e\u5e93\u8868\uff0c\u6570\u7ec4\u7c7b\u578b\uff0c\u5982\u679c\u4e3a\u7a7a\uff0c\u5219\u751f\u6210\u6570\u636e\u5e93\u6240\u6709\u8868\u548c\u89c6\u56fe\u3002\u5982\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"-Tables Person,PersonDetails")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-Context"),"\uff1a\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"FurionDbContext"),"\uff0c\u5982\u679c\u6709\u591a\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u5219\u6b64\u53c2\u6570\u5fc5\u987b\u914d\u7f6e"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-ConnectionName"),"\uff1a\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u5bf9\u5e94 ",(0,o.kt)("inlineCode",{parentName:"li"},"appsetting.json")," \u4e2d\u7684 ",(0,o.kt)("inlineCode",{parentName:"li"},"ConnectionStrings")," \u5b9a\u4e49\u7684 ",(0,o.kt)("inlineCode",{parentName:"li"},"Key")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-OutputDir"),"\uff1a\u751f\u6210\u5b9e\u4f53\u4ee3\u7801\u8f93\u51fa\u76ee\u5f55\uff0c\u9ed8\u8ba4\u4e3a\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"./Furion.Core/Entities/")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-DbProvider"),"\uff1a\u6570\u636e\u5e93\u63d0\u4f9b\u5668\uff0c\u9ed8\u8ba4\u662f ",(0,o.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.SqlServer"),"\uff0c\u5176\u4ed6\u6570\u636e\u5e93\u8bf7\u6307\u5b9a\u5bf9\u5e94\u7a0b\u5e8f\u96c6",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"SqlServer"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.SqlServer")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Sqlite"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.Sqlite")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Cosmos"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.Cosmos")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"InMemoryDatabase"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.InMemory")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"MySql"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Pomelo.EntityFrameworkCore.MySql")," \u6216 ",(0,o.kt)("inlineCode",{parentName:"li"},"MySql.EntityFrameworkCore")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"PostgreSQL"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Npgsql.EntityFrameworkCore.PostgreSQL")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Oracle"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Oracle.EntityFrameworkCore")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Dm"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.Dm")))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-EntryProject"),"\uff1aWeb \u542f\u7528\u9879\u76ee\u5c42\u540d\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"Furion.Web.Entry")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-CoreProject"),"\uff1a\u5b9e\u4f53\u9879\u76ee\u5c42\u540d\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"Furion.Core")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-DbContextLocators"),"\uff1a\u591a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"MasterDbContextLocator"),"\uff0c\u652f\u6301\u591a\u4e2a\uff0c\u5982\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"MasterDbContextLocator,MySqlDbContextLocator")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-Product"),"\uff1a\u89e3\u51b3\u65b9\u6848\u9ed8\u8ba4\u524d\u7f00\uff0c\u5982 ",(0,o.kt)("inlineCode",{parentName:"li"},"Furion")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-UseDatabaseNames"),"\uff1a\u662f\u5426\u4fdd\u6301\u751f\u6210\u548c\u6570\u636e\u5e93\u3001\u8868\u4e00\u81f4\u7684\u540d\u79f0"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-Namespace"),"\uff1a\u6307\u5b9a\u5b9e\u4f53\u547d\u540d\u7a7a\u95f4")),(0,o.kt)("h2",{id:"9195-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.19.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/9e7ef9fa.d9a3ef03.js b/handbook/build/assets/js/9e7ef9fa.d9a3ef03.js deleted file mode 100644 index 1cdee295bc..0000000000 --- a/handbook/build/assets/js/9e7ef9fa.d9a3ef03.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[1866],{34:function(e,n,t){t.r(n),t.d(n,{assets:function(){return d},contentTitle:function(){return p},default:function(){return k},frontMatter:function(){return s},metadata:function(){return m},toc:function(){return u}});var i=t(3117),r=t(102),o=(t(7294),t(3905)),a=t(1402),l=["components"],s={id:"dbcontext-db-first",title:"9.19 \u6570\u636e\u5e93\u751f\u6210\u6a21\u578b",sidebar_label:"9.19 \u6570\u636e\u5e93\u751f\u6210\u6a21\u578b (Db First)"},p=void 0,m={unversionedId:"dbcontext-db-first",id:"dbcontext-db-first",title:"9.19 \u6570\u636e\u5e93\u751f\u6210\u6a21\u578b",description:"",source:"@site/docs/dbcontext-db-first.mdx",sourceDirName:".",slug:"/dbcontext-db-first",permalink:"/furion/docs/dbcontext-db-first",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-db-first.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1653276586,formattedLastUpdatedAt:"May 23, 2022",frontMatter:{id:"dbcontext-db-first",title:"9.19 \u6570\u636e\u5e93\u751f\u6210\u6a21\u578b",sidebar_label:"9.19 \u6570\u636e\u5e93\u751f\u6210\u6a21\u578b (Db First)"},sidebar:"docs",previous:{title:"9.18 \u591a\u79cd\u6570\u636e\u5e93\u64cd\u4f5c \u2728",permalink:"/furion/docs/dbcontext-multi-database"},next:{title:"9.20 \u6a21\u578b\u751f\u6210\u6570\u636e\u5e93 (Code First)",permalink:"/furion/docs/dbcontext-code-first"}},d={},u=[{value:"9.19.1 \u6570\u636e\u5e93\u5f00\u53d1\u65b9\u5f0f",id:"9191-\u6570\u636e\u5e93\u5f00\u53d1\u65b9\u5f0f",level:2},{value:"9.19.2 \u64cd\u4f5c\u6307\u5357",id:"9192-\u64cd\u4f5c\u6307\u5357",level:2},{value:"9.19.2.1 \u6253\u5f00 \u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0",id:"91921-\u6253\u5f00-\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0",level:3},{value:"9.19.2.2 \u5207\u6362\u9ed8\u8ba4\u9879\u76ee",id:"91922-\u5207\u6362\u9ed8\u8ba4\u9879\u76ee",level:3},{value:"9.19.2.3 \u8f93\u5165 cli.ps1 \u547d\u4ee4",id:"91923-\u8f93\u5165-clips1-\u547d\u4ee4",level:3},{value:"9.19.3 \u754c\u9762\u64cd\u4f5c\u6a21\u5f0f",id:"9193-\u754c\u9762\u64cd\u4f5c\u6a21\u5f0f",level:2},{value:"9.19.3.1 \u542f\u52a8\u754c\u9762\u64cd\u4f5c",id:"91931-\u542f\u52a8\u754c\u9762\u64cd\u4f5c",level:3},{value:"9.19.3.2 \u52a0\u8f7d\u6570\u636e\u5e93\u8868",id:"91932-\u52a0\u8f7d\u6570\u636e\u5e93\u8868",level:3},{value:"9.19.3.3 \u9009\u62e9\u8868\u6216\u89c6\u56fe\u751f\u6210",id:"91933-\u9009\u62e9\u8868\u6216\u89c6\u56fe\u751f\u6210",level:3},{value:"9.19.3.4 \u9009\u62e9\u4fdd\u5b58\u76ee\u5f55",id:"91934-\u9009\u62e9\u4fdd\u5b58\u76ee\u5f55",level:3},{value:"9.19.3.5 \u751f\u6210\u6700\u7ec8\u5b9e\u4f53\u4ee3\u7801",id:"91935-\u751f\u6210\u6700\u7ec8\u5b9e\u4f53\u4ee3\u7801",level:3},{value:"9.19.4 \u547d\u4ee4\u53c2\u6570\u914d\u7f6e",id:"9194-\u547d\u4ee4\u53c2\u6570\u914d\u7f6e",level:2},{value:"9.19.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9195-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],c={toc:u};function k(e){var n=e.components,t=(0,r.Z)(e,l);return(0,o.kt)("wrapper",(0,i.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{title:"\u89c6\u9891\u6559\u7a0b",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("a",{parentName:"p",href:"https://www.bilibili.com/video/BV1Rt4y1W7oJ"},"https://www.bilibili.com/video/BV1Rt4y1W7oJ"))),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u811a\u672c",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u5728\u9605\u8bfb\u4e0b\u9762\u6587\u6863\u4e4b\u524d\uff0c\u5fc5\u987b\u628a",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6e90\u7801\u6587\u4ef6\u5939\u4e0b\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"tools/cli.ps1")," \u6587\u4ef6\u62f7\u8d1d\u5230\u672c\u5730\u4e2d\u3002\u800c\u4e14 ",(0,o.kt)("inlineCode",{parentName:"p"},"Fur.Web.Entry")," \u5c42\u9700\u8981\u5b89\u88c5 ",(0,o.kt)("inlineCode",{parentName:"p"},"Microsoft.EntityFrameworkCore.Tools")," \u5305\u3002")),(0,o.kt)("admonition",{title:"\u7cfb\u7edf\u63d0\u793a\u7981\u6b62\u8fd0\u884c\u811a\u672c\u89e3\u51b3",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u51fa\u73b0 ",(0,o.kt)("inlineCode",{parentName:"p"},"cli.ps1")," \u65e0\u6cd5\u8fd0\u884c\u7684\u60c5\u51b5\uff0c\u5982\u63d0\u793a\uff1a",(0,o.kt)("inlineCode",{parentName:"p"},"\u201c\u56e0\u4e3a\u5728\u6b64\u7cfb\u7edf\u4e0a\u7981\u6b62\u8fd0\u884c\u811a\u672c\u201d"),"\uff0c\u53ea\u9700\u8981\u6253\u5f00\u7cfb\u7edf\u7ba1\u7406\u5458 ",(0,o.kt)("inlineCode",{parentName:"p"},"CMD/Powershell")," \u6267\u884c\uff1a",(0,o.kt)("inlineCode",{parentName:"p"},"set-ExecutionPolicy RemoteSigned")," \u547d\u4ee4\u5e76\u6839\u636e\u64cd\u4f5c\u63d0\u793a\u8f93\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"A")," \u5373\u53ef\u3002"),(0,o.kt)("p",{parentName:"admonition"},"\u4e4b\u540e\u91cd\u542f ",(0,o.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u5de5\u5177\u3002")),(0,o.kt)("h2",{id:"9191-\u6570\u636e\u5e93\u5f00\u53d1\u65b9\u5f0f"},"9.19.1 \u6570\u636e\u5e93\u5f00\u53d1\u65b9\u5f0f"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e24\u79cd\u4e3b\u8981\u65b9\u6cd5\u6765 ",(0,o.kt)("strong",{parentName:"p"},"\u4fdd\u6301\u5b9e\u4f53\u6a21\u578b\u548c\u6570\u636e\u5e93\u67b6\u6784\u540c\u6b65"),"\u3002"),(0,o.kt)("p",null,"\u81f3\u4e8e\u6211\u4eec\u5e94\u8be5\u9009\u7528\u54ea\u4e2a\u65b9\u6cd5\uff0c\u8bf7\u786e\u5b9a\u4f60\u662f\u5e0c\u671b\u4ee5\u5b9e\u4f53\u6a21\u578b\u4e3a\u51c6\u8fd8\u662f\u4ee5\u6570\u636e\u5e93\u4e3a\u51c6\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"\u5982\u679c\u5e0c\u671b ",(0,o.kt)("strong",{parentName:"p"},"\u4ee5\u5b9e\u4f53\u6a21\u578b\u4e3a\u51c6"),"\uff0c\u8bf7\u4f7f\u7528\u6b63\u5411\u5de5\u7a0b\uff08Code First\uff09\u3002 \u5bf9\u5b9e\u4f53\u6a21\u578b\u8fdb\u884c\u66f4\u6539\u65f6\uff0c\u6b64\u65b9\u6cd5\u4f1a\u4ee5\u589e\u91cf\u65b9\u5f0f\u5c06\u76f8\u5e94\u67b6\u6784\u66f4\u6539\u5e94\u7528\u5230\u6570\u636e\u5e93\uff0c\u4ee5\u4f7f\u6570\u636e\u5e93\u4fdd\u6301\u4e0e\u5b9e\u4f53\u6a21\u578b\u517c\u5bb9\u3002")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"\u5982\u679c\u5e0c\u671b ",(0,o.kt)("strong",{parentName:"p"},"\u4ee5\u6570\u636e\u5e93\u67b6\u6784\u4e3a\u51c6"),"\uff0c\u8bf7\u4f7f\u7528\u53cd\u5411\u5de5\u7a0b\uff08Database First\uff09\u3002 \u4f7f\u7528\u6b64\u65b9\u6cd5\uff0c\u53ef\u901a\u8fc7\u5c06\u6570\u636e\u5e93\u67b6\u6784\u53cd\u5411\u5de5\u7a0b\u5230\u5b9e\u4f53\u6a21\u578b\u6765\u751f\u6210\u76f8\u5e94\u7684\u5b9e\u4f53\u7c7b\u578b\u3002"))),(0,o.kt)("p",null,"\u672c\u7ae0\u8282\u662f ",(0,o.kt)("strong",{parentName:"p"},"\u53cd\u5411\u5de5\u7a0b\uff08Database First\uff09")," \u7684\u76f8\u5173\u5185\u5bb9\u3002"),(0,o.kt)("h2",{id:"9192-\u64cd\u4f5c\u6307\u5357"},"9.19.2 \u64cd\u4f5c\u6307\u5357"),(0,o.kt)("admonition",{title:"\u64cd\u4f5c\u4e4b\u524d\u6ce8\u610f\u4e8b\u9879",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u76ee\u524d ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion Tools")," \u751f\u6210\u5de5\u5177",(0,o.kt)("strong",{parentName:"p"},"\u9ed8\u8ba4\u4e0d\u652f\u6301\u4efb\u4f55\u6570\u636e\u5e93"),"\u751f\u6210\uff0c\u6240\u4ee5\u5982\u9700\u751f\u6210\u7279\u5b9a\u6570\u636e\u5e93\u7684\u4ee3\u7801\uff0c\u53ea\u9700\u8981\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion.EntityFrameworkCore.Core")," \u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93\u5305\u5373\u53ef\uff1a"),(0,o.kt)("p",{parentName:"admonition"},"\u5404\u4e2a\u6570\u636e\u5e93\u7684\u5305\u53ef\u67e5\u9605\uff1a",(0,o.kt)("a",{parentName:"p",href:"dbcontext-multi-database"},"\u591a\u6570\u636e\u5e93\u64cd\u4f5c-\u6570\u636e\u5e93\u63d0\u4f9b\u5668\u5bf9\u5e94\u5305")),(0,o.kt)("p",{parentName:"admonition"},"\u53e6\u5916\uff0c\u53ea\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"SqlServer")," \u6570\u636e\u5e93\u652f\u6301\u53ef\u89c6\u5316 ",(0,o.kt)("inlineCode",{parentName:"p"},"GUI")," \u64cd\u4f5c\uff0c\u5176\u4ed6\u7684\u53ea\u80fd\u547d\u4ee4\u884c\u64cd\u4f5c\u3002")),(0,o.kt)("h3",{id:"91921-\u6253\u5f00-\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0"},"9.19.2.1 \u6253\u5f00 ",(0,o.kt)("inlineCode",{parentName:"h3"},"\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0")),(0,o.kt)("p",null,"\u6ce8\u610f\uff1a\u5f00\u59cb\u4e4b\u524d\u5148\u628a ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion.Web.Entry")," \u8bbe\u4e3a\u542f\u52a8\u9879\u76ee\u3002"),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst1.png")}),(0,o.kt)("h3",{id:"91922-\u5207\u6362\u9ed8\u8ba4\u9879\u76ee"},"9.19.2.2 \u5207\u6362\u9ed8\u8ba4\u9879\u76ee"),(0,o.kt)("p",null,"\u5c06 ",(0,o.kt)("inlineCode",{parentName:"p"},"\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0")," \u9ed8\u8ba4\u9879\u76ee\u8bbe\u7f6e\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion.Core"),"\uff0c\u5982\u679c\u60a8\u662f\u5176\u4ed6\u540d\u5b57\uff0c\u5219\u5207\u6362\u5bf9\u5e94\u5373\u53ef\u3002"),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst2.png")}),(0,o.kt)("h3",{id:"91923-\u8f93\u5165-clips1-\u547d\u4ee4"},"9.19.2.3 \u8f93\u5165 ",(0,o.kt)("inlineCode",{parentName:"h3"},"cli.ps1")," \u547d\u4ee4"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"PM> Show-Command ../tools/cli.ps1\n")),(0,o.kt)("img",{src:(0,a.Z)("img/df10.png")}),(0,o.kt)("admonition",{title:"\u5168\u547d\u4ee4\u65b9\u5f0f\uff08\u63a8\u8350\uff09\u2764\ufe0f",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u9664\u4e86\u91c7\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"Show-Command")," \u65b9\u5f0f\u4ee5\u5916\uff0c\u8fd8\u53ef\u4ee5\u76f4\u63a5\u6267\u884c\u547d\u4ee4\uff0c\u5982\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},'&"./tools/cli.ps1" -DbProvider "Microsoft.EntityFrameworkCore.SqlServer" -CoreProject "XXX.Core" -EntryProject "XXX.Web.Entry" -ConnectionName "Default"\n'))),(0,o.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528\u7684\u662f ",(0,o.kt)("inlineCode",{parentName:"p"},"SqlServer")," \u6570\u636e\u5e93\uff0c\u5219\u9ed8\u8ba4\u4e0d\u9700\u8981\u6307\u5b9a ",(0,o.kt)("inlineCode",{parentName:"p"},"-DbProvider")," \u53c2\u6570\u3002")),(0,o.kt)("p",null,"\u5982\u679c\u4e0d\u6e05\u695a\u5f53\u524d\u8fd0\u884c\u73af\u5883\u7684\u8def\u5f84\uff0c\u53ef\u4ee5\u8f93\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"pwd")," \u67e5\u770b\u3002"),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u6570\u636e\u5e93\u547d\u540d",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u9700\u8981\u4fdd\u6301\u548c\u6570\u636e\u5e93\u4e00\u6a21\u4e00\u6837\u7684\u547d\u540d\uff0c\u5219\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"-UseDatabaseNames")," \u53c2\u6570\u6307\u5b9a\uff0c\u5982\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},' &"../tools/cli.ps1" -UseDatabaseNames\n'))),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst3.png")}),(0,o.kt)("admonition",{title:"\u7b49\u5f85\u8f93\u5165",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u6267\u884c\u4e0a\u9762\u547d\u4ee4\u540e\uff0c\u6b64\u65f6 ",(0,o.kt)("inlineCode",{parentName:"p"},"Cli")," \u6709\u4e00\u4e2a\u7b49\u5f85\u8f93\u5165\u63d0\u793a\uff1a"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Furion Tools v1.0.0 \u8bf7\u952e\u5165\u64cd\u4f5c\u7c7b\u578b\uff1a[G] \u754c\u9762\u64cd\u4f5c\uff0c[\u4efb\u610f\u5b57\u7b26] \u547d\u4ee4\u884c\u64cd\u4f5c\nFurion Tools v1.0.0 \u60a8\u7684\u8f93\u5165\u662f:\n")),(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("strong",{parentName:"p"},"\u8f93\u5165\u5927\u5199 ",(0,o.kt)("inlineCode",{parentName:"strong"},"G")," \u8fdb\u5165\u754c\u9762\u64cd\u4f5c\u6a21\u5f0f\uff0c\u5176\u4ed6\u4efb\u610f\u5b57\u7b26\u8fdb\u5165\u547d\u4ee4\u884c\u64cd\u4f5c\u6a21\u5f0f\u3002"))),(0,o.kt)("admonition",{title:"\u6ce8\u610f\u4e8b\u9879",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"\u76ee\u524d\u53ea\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql Server")," \u6570\u636e\u5e93\u624d\u652f\u6301 ",(0,o.kt)("inlineCode",{parentName:"p"},"GUI \u754c\u9762\u64cd\u4f5c\u6a21\u5f0f"),"\uff0c\u5176\u4ed6\u6570\u636e\u5e93\u8bf7\u4f7f\u7528\u547d\u4ee4\u884c\u6a21\u5f0f\u3002")),(0,o.kt)("h2",{id:"9193-\u754c\u9762\u64cd\u4f5c\u6a21\u5f0f"},"9.19.3 \u754c\u9762\u64cd\u4f5c\u6a21\u5f0f"),(0,o.kt)("h3",{id:"91931-\u542f\u52a8\u754c\u9762\u64cd\u4f5c"},"9.19.3.1 \u542f\u52a8\u754c\u9762\u64cd\u4f5c"),(0,o.kt)("p",null,"\u5f53\u6211\u4eec\u8f93\u5165 ",(0,o.kt)("inlineCode",{parentName:"p"},"G")," \u65f6\uff0c\u5c06\u6253\u5f00 ",(0,o.kt)("inlineCode",{parentName:"p"},"GUI")," \u754c\u9762\u64cd\u4f5c\u6a21\u5f0f\uff0c\u5982\uff1a"),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst4.png")}),(0,o.kt)("p",null,"\u8fd9\u65f6\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Furion Tools")," \u4f1a\u81ea\u52a8\u67e5\u627e\u6240\u6709\u6570\u636e\u5e93\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\uff1a"),(0,o.kt)("admonition",{title:"\u6ce8\u610f\u4e8b\u9879",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u9879\u9700\u5199\u5230 ",(0,o.kt)("inlineCode",{parentName:"p"},"json")," \u914d\u7f6e\u6587\u4ef6\u4e2d\uff0c\u4e14\u6839\u8282\u70b9\u9700\u8981\u5199\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"ConnectionStrings")," \u3002")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {12-13}",showLineNumbers:!0,"":!0,"{12-13}":!0},'{\n "Logging": {\n "LogLevel": {\n "Default": "Information",\n "Microsoft": "Warning",\n "Microsoft.Hosting.Lifetime": "Information",\n "Microsoft.EntityFrameworkCore": "Information"\n }\n },\n "AllowedHosts": "*",\n "ConnectionStrings": {\n "DbConnectionString": "Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;",\n "Sqlite3ConnectionString": "Data Source=./Furion.db"\n }\n}\n')),(0,o.kt)("h3",{id:"91932-\u52a0\u8f7d\u6570\u636e\u5e93\u8868"},"9.19.3.2 \u52a0\u8f7d\u6570\u636e\u5e93\u8868"),(0,o.kt)("p",null,"\u9009\u62e9\u8fde\u63a5\u5b57\u7b26\u4e32\u4e4b\u540e\uff0c\u70b9\u51fb ",(0,o.kt)("inlineCode",{parentName:"p"},"\u52a0\u8f7d\u6570\u636e\u5e93\u8868\u548c\u89c6\u56fe")," \u6309\u94ae\u52a0\u8f7d\u3002"),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst5.png")}),(0,o.kt)("h3",{id:"91933-\u9009\u62e9\u8868\u6216\u89c6\u56fe\u751f\u6210"},"9.19.3.3 \u9009\u62e9\u8868\u6216\u89c6\u56fe\u751f\u6210"),(0,o.kt)("p",null,"\u52a0\u8f7d\u8868\u5b8c\u6210\u540e\uff0c\u53ef\u4ee5\u9009\u62e9\u60a8\u8981\u751f\u6210\u7684\u8868\u6216\u89c6\u56fe\uff0c",(0,o.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u9009")),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst6.png")}),(0,o.kt)("p",null,"\u70b9\u51fb\u5e95\u90e8\u6309\u94ae ",(0,o.kt)("inlineCode",{parentName:"p"},"\u7acb\u5373\u751f\u6210")),(0,o.kt)("h3",{id:"91934-\u9009\u62e9\u4fdd\u5b58\u76ee\u5f55"},"9.19.3.4 \u9009\u62e9\u4fdd\u5b58\u76ee\u5f55"),(0,o.kt)("p",null,"\u70b9\u51fb ",(0,o.kt)("inlineCode",{parentName:"p"},"\u7acb\u5373\u751f\u6210")," \u6309\u94ae\u540e\uff0c\u4f1a\u5f39\u51fa\u5b9e\u4f53\u4fdd\u5b58\u9009\u62e9\u76ee\u5f55\u8d44\u6e90\u7ba1\u7406\u5668\uff0c\u9ed8\u8ba4\u5b9e\u4f53\u53ea\u80fd\u4fdd\u5b58\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion.Core")," \u5c42\uff1a"),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst7.png")}),(0,o.kt)("p",null,"\u70b9\u51fb\u786e\u5b9a\u540e\u5c31\u53ef\u5b8c\u6210\u6240\u6709\u751f\u6210\u64cd\u4f5c\u3002"),(0,o.kt)("h3",{id:"91935-\u751f\u6210\u6700\u7ec8\u5b9e\u4f53\u4ee3\u7801"},"9.19.3.5 \u751f\u6210\u6700\u7ec8\u5b9e\u4f53\u4ee3\u7801"),(0,o.kt)("img",{src:(0,a.Z)("img/dbfirst8.png")}),(0,o.kt)("p",null,"\u6700\u7ec8\u811a\u672c\u5982\u4e0b\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},'PM> &"../tools/cli.ps1"\n// -----------------------------------------------------------------------------\n// ______ _______ _\n// | ____| |__ __| | |\n// | |__ _ _ _ __ | | ___ ___ | |___\n// | __| | | | \'__| | |/ _ \\ / _ \\| / __|\n// | | | |_| | | | | (_) | (_) | \\__ \\\n// |_| \\__,_|_| |_|\\___/ \\___/|_|___/\n//\n// -----------------------------------------------------------------------------\nFurion Tools v1.0.0 \u542f\u52a8\u4e2d......\nFurion Tools v1.0.0 \u542f\u52a8\u6210\u529f\uff01\nFurion Tools v1.0.0 \u8bf7\u952e\u5165\u64cd\u4f5c\u7c7b\u578b\uff1a[G] \u754c\u9762\u64cd\u4f5c\uff0c[\u4efb\u610f\u5b57\u7b26] \u547d\u4ee4\u884c\u64cd\u4f5c\nFurion Tools v1.0.0 \u60a8\u7684\u8f93\u5165\u662f: G\nFurion Tools v1.0.0 \u6b63\u5728\u52a0\u8f7d\u6570\u636e\u5e93\u8868\u548c\u89c6\u56fe......\nFurion Tools v1.0.0 \u52a0\u8f7d\u6210\u529f\uff01\nFurion Tools v1.0.0 \u6b63\u5728\u7f16\u8bd1\u89e3\u51b3\u65b9\u6848\u4ee3\u7801......\nBuild started...\nBuild succeeded.\nFor foreign key FK_PersonDetail_Person_PersonId on table dbo.PersonDetail, unable to model the end of the foreign key on principal table dbo.Person. This is usually because the principal table was not included in the selection set.\nFurion Tools v1.0.0 \u7f16\u8bd1\u6210\u529f\uff01\nFurion Tools v1.0.0 \u5f00\u59cb\u751f\u6210\u5b9e\u4f53\u6587\u4ef6......\nFurion Tools v1.0.0 \u6b63\u5728\u751f\u6210 City.cs \u5b9e\u4f53\u4ee3\u7801......\nFurion Tools v1.0.0 \u6210\u529f\u751f\u6210 City.cs \u5b9e\u4f53\u4ee3\u7801\n// -----------------------------------------------------------------------------\n// \u4ee5\u4e0b\u4ee3\u7801\u7531 Furion Tools v1.0.0 \u751f\u6210\n// -----------------------------------------------------------------------------\n\nusing Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Collections.Generic;\n\n#nullable disable\n\nnamespace Furion.Core\n{\n public partial class City : IEntity, IEntityTypeBuilder\n {\n\n public City()\n {\n InverseParent = new HashSet();\n }\n\n public int Id { get; set; }\n public string Name { get; set; }\n public int? ParentId { get; set; }\n public DateTime CreatedTime { get; set; }\n public DateTime? UpdatedTime { get; set; }\n public bool IsDeleted { get; set; }\n\n public virtual City Parent { get; set; }\n public virtual ICollection InverseParent { get; set; }\n\n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasIndex(e => e.ParentId, "IX_City_ParentId");\n\n entityBuilder.HasOne(d => d.Parent)\n .WithMany(p => p.InverseParent)\n .HasForeignKey(d => d.ParentId);\n\n }\n\n }\n}\n\nFurion Tools v1.0.0 \u6b63\u5728\u751f\u6210 PersonDetail.cs \u5b9e\u4f53\u4ee3\u7801......\nFurion Tools v1.0.0 \u6210\u529f\u751f\u6210 PersonDetail.cs \u5b9e\u4f53\u4ee3\u7801\n// -----------------------------------------------------------------------------\n// \u4ee5\u4e0b\u4ee3\u7801\u7531 Furion Tools v1.0.0 \u751f\u6210\n// -----------------------------------------------------------------------------\n\nusing Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Collections.Generic;\n\n#nullable disable\n\nnamespace Furion.Core\n{\n public partial class PersonDetail : IEntity, IEntityTypeBuilder\n {\n\n public int Id { get; set; }\n public string PhoneNumber { get; set; }\n public string Qq { get; set; }\n public int PersonId { get; set; }\n\n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasIndex(e => e.PersonId, "IX_PersonDetail_PersonId")\n .IsUnique();\n\n entityBuilder.Property(e => e.Qq).HasColumnName("QQ");\n\n }\n\n }\n}\n\nFurion Tools v1.0.0 \u6b63\u5728\u751f\u6210 Post.cs \u5b9e\u4f53\u4ee3\u7801......\nFurion Tools v1.0.0 \u6210\u529f\u751f\u6210 Post.cs \u5b9e\u4f53\u4ee3\u7801\n// -----------------------------------------------------------------------------\n// \u4ee5\u4e0b\u4ee3\u7801\u7531 Furion Tools v1.0.0 \u751f\u6210\n// -----------------------------------------------------------------------------\n\nusing Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Collections.Generic;\n\n#nullable disable\n\nnamespace Furion.Core\n{\n public partial class Post : IEntity\n {\n\n public int Id { get; set; }\n public string Name { get; set; }\n public DateTime CreatedTime { get; set; }\n public DateTime? UpdatedTime { get; set; }\n public bool IsDeleted { get; set; }\n\n }\n}\n\nFurion Tools v1.0.0 \u6b63\u5728\u751f\u6210 VPerson.cs \u5b9e\u4f53\u4ee3\u7801......\nFurion Tools v1.0.0 \u6210\u529f\u751f\u6210 VPerson.cs \u5b9e\u4f53\u4ee3\u7801\n// -----------------------------------------------------------------------------\n// \u4ee5\u4e0b\u4ee3\u7801\u7531 Furion Tools v1.0.0 \u751f\u6210\n// -----------------------------------------------------------------------------\n\nusing Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Collections.Generic;\n\n#nullable disable\n\nnamespace Furion.Core\n{\n public partial class VPerson : IEntity, IEntityTypeBuilder\n {\n\n public int Id { get; set; }\n public string Name { get; set; }\n public int Age { get; set; }\n public string Address { get; set; }\n\n public void Configure(EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasNoKey();\n\n entityBuilder.ToView("V_Person");\n\n entityBuilder.Property(e => e.Id).ValueGeneratedOnAdd();\n\n entityBuilder.Property(e => e.Name).HasMaxLength(32);\n\n }\n\n }\n}\n\nFurion Tools v1.0.0 \u5168\u90e8\u5b9e\u4f53\u751f\u6210\u6210\u529f\uff01\nPM>\n')),(0,o.kt)("h2",{id:"9194-\u547d\u4ee4\u53c2\u6570\u914d\u7f6e"},"9.19.4 \u547d\u4ee4\u53c2\u6570\u914d\u7f6e"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion Tools Cli")," \u652f\u6301\u591a\u4e2a\u53c2\u6570\u914d\u7f6e\uff0c\u4f7f\u7528\u65b9\u6cd5\u53ea\u9700\u8981\u5728\u547d\u4ee4\u540e\u9762\u6dfb\u52a0\u5373\u53ef\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},' &"../tools/cli.ps1" -Context \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u540d -ConnectionName \u8fde\u63a5\u5b57\u7b26\u4e32Key\n')),(0,o.kt)("p",null,"\u652f\u6301\u53c2\u6570\u5982\u4e0b\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-Tables"),"\uff1a\u914d\u7f6e\u8981\u751f\u6210\u7684\u6570\u636e\u5e93\u8868\uff0c\u6570\u7ec4\u7c7b\u578b\uff0c\u5982\u679c\u4e3a\u7a7a\uff0c\u5219\u751f\u6210\u6570\u636e\u5e93\u6240\u6709\u8868\u548c\u89c6\u56fe\u3002\u5982\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"-Tables Person,PersonDetails")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-Context"),"\uff1a\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"FurionDbContext"),"\uff0c\u5982\u679c\u6709\u591a\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u5219\u6b64\u53c2\u6570\u5fc5\u987b\u914d\u7f6e"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-ConnectionName"),"\uff1a\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u5bf9\u5e94 ",(0,o.kt)("inlineCode",{parentName:"li"},"appsetting.json")," \u4e2d\u7684 ",(0,o.kt)("inlineCode",{parentName:"li"},"ConnectionStrings")," \u5b9a\u4e49\u7684 ",(0,o.kt)("inlineCode",{parentName:"li"},"Key")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-OutputDir"),"\uff1a\u751f\u6210\u5b9e\u4f53\u4ee3\u7801\u8f93\u51fa\u76ee\u5f55\uff0c\u9ed8\u8ba4\u4e3a\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"./Furion.Core/Entities/")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-DbProvider"),"\uff1a\u6570\u636e\u5e93\u63d0\u4f9b\u5668\uff0c\u9ed8\u8ba4\u662f ",(0,o.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.SqlServer"),"\uff0c\u5176\u4ed6\u6570\u636e\u5e93\u8bf7\u6307\u5b9a\u5bf9\u5e94\u7a0b\u5e8f\u96c6",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"SqlServer"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.SqlServer")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Sqlite"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.Sqlite")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Cosmos"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.Cosmos")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"InMemoryDatabase"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.InMemory")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"MySql"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Pomelo.EntityFrameworkCore.MySql")," \u6216 ",(0,o.kt)("inlineCode",{parentName:"li"},"MySql.EntityFrameworkCore")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"PostgreSQL"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Npgsql.EntityFrameworkCore.PostgreSQL")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Oracle"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Oracle.EntityFrameworkCore")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Dm"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.Dm")))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-EntryProject"),"\uff1aWeb \u542f\u7528\u9879\u76ee\u5c42\u540d\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"Furion.Web.Entry")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-CoreProject"),"\uff1a\u5b9e\u4f53\u9879\u76ee\u5c42\u540d\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"Furion.Core")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-DbContextLocators"),"\uff1a\u591a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"MasterDbContextLocator"),"\uff0c\u652f\u6301\u591a\u4e2a\uff0c\u5982\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"MasterDbContextLocator,MySqlDbContextLocator")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-Product"),"\uff1a\u89e3\u51b3\u65b9\u6848\u9ed8\u8ba4\u524d\u7f00\uff0c\u5982 ",(0,o.kt)("inlineCode",{parentName:"li"},"Furion")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-UseDatabaseNames"),"\uff1a\u662f\u5426\u4fdd\u6301\u751f\u6210\u548c\u6570\u636e\u5e93\u3001\u8868\u4e00\u81f4\u7684\u540d\u79f0"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"-Namespace"),"\uff1a\u6307\u5b9a\u5b9e\u4f53\u547d\u540d\u7a7a\u95f4")),(0,o.kt)("h2",{id:"9195-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.19.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}k.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return m},kt:function(){return c}});var i=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function a(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=i.createContext({}),p=function(e){var n=i.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},m=function(e){var n=p(e.components);return i.createElement(s.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},u=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,m=l(e,["components","mdxType","originalType","parentName"]),u=p(t),c=r,k=u["".concat(s,".").concat(c)]||u[c]||d[c]||o;return t?i.createElement(k,a(a({ref:n},m),{},{components:t})):i.createElement(k,a({ref:n},m))}));function c(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var o=t.length,a=new Array(o);a[0]=u;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:r,a[1]=l;for(var p=2;pILogger<T> \u6cdb\u578b\u65b9\u5f0f",id:"1841-iloggert-\u6cdb\u578b\u65b9\u5f0f",level:3},{value:"18.4.2 ILoggerFactory \u5de5\u5382\u65b9\u5f0f",id:"1842-iloggerfactory-\u5de5\u5382\u65b9\u5f0f",level:3},{value:"18.4.3 Log \u9759\u6001\u7c7b\u65b9\u5f0f",id:"1843-log-\u9759\u6001\u7c7b\u65b9\u5f0f",level:3},{value:"18.4.4 \u61d2\u4eba\u6a21\u5f0f \ud83d\ude01",id:"1844-\u61d2\u4eba\u6a21\u5f0f-",level:3},{value:"18.5 \u914d\u7f6e\u65e5\u5fd7\u8f93\u51fa\u4ecb\u8d28",id:"185-\u914d\u7f6e\u65e5\u5fd7\u8f93\u51fa\u4ecb\u8d28",level:2},{value:"18.5.1 \u8f93\u51fa\u5230\u63a7\u5236\u53f0",id:"1851-\u8f93\u51fa\u5230\u63a7\u5236\u53f0",level:3},{value:"18.5.2 \u8f93\u51fa\u5230\u6587\u4ef6",id:"1852-\u8f93\u51fa\u5230\u6587\u4ef6",level:3},{value:"18.5.3 \u8f93\u51fa\u5230\u6570\u636e\u5e93/\u5176\u4ed6\u5b58\u50a8\u4ecb\u8d28",id:"1853-\u8f93\u51fa\u5230\u6570\u636e\u5e93\u5176\u4ed6\u5b58\u50a8\u4ecb\u8d28",level:3},{value:"18.5.4 ILoggerFactory \u65b9\u5f0f",id:"1854-iloggerfactory-\u65b9\u5f0f",level:3},{value:"18.5.5 ILoggingBuilder \u65b9\u5f0f",id:"1855-iloggingbuilder-\u65b9\u5f0f",level:3},{value:"18.5.6 \u8bb0\u5f55\u8bf7\u6c42\u65e5\u5fd7",id:"1856-\u8bb0\u5f55\u8bf7\u6c42\u65e5\u5fd7",level:3},{value:"18.5.7 Debug \u548c Trace \u9ed8\u8ba4\u4e0d\u8f93\u51fa\u95ee\u9898",id:"1857-debug-\u548c-trace-\u9ed8\u8ba4\u4e0d\u8f93\u51fa\u95ee\u9898",level:3},{value:"18.6 [LoggingMonitor] \u76d1\u542c\u65e5\u5fd7",id:"186-loggingmonitor-\u76d1\u542c\u65e5\u5fd7",level:2},{value:"18.6.1 \u7279\u6027\u914d\u7f6e",id:"1861-\u7279\u6027\u914d\u7f6e",level:3},{value:"18.6.2 \u5168\u5c40\u914d\u7f6e",id:"1862-\u5168\u5c40\u914d\u7f6e",level:3},{value:"18.6.3 \u66f4\u591a\u914d\u7f6e",id:"1863-\u66f4\u591a\u914d\u7f6e",level:3},{value:"18.7 \u6253\u5370\u65e5\u5fd7\u5230 Swagger \u4e2d",id:"187-\u6253\u5370\u65e5\u5fd7\u5230-swagger-\u4e2d",level:2},{value:"18.8 \u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528",id:"188-\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528",level:2},{value:"18.9 \u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df",id:"189-\u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df",level:2},{value:"18.10 \u9759\u6001 Default \u65b9\u5f0f\u6784\u5efa",id:"1810-\u9759\u6001-default-\u65b9\u5f0f\u6784\u5efa",level:2},{value:"18.11 \u89c4\u8303\u65e5\u5fd7\u6a21\u677f",id:"1811-\u89c4\u8303\u65e5\u5fd7\u6a21\u677f",level:2},{value:"18.12 \u65e5\u5fd7\u4e0a\u4e0b\u6587",id:"1812-\u65e5\u5fd7\u4e0a\u4e0b\u6587",level:2},{value:"18.13 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"1813-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],u={toc:m};function d(e){var n=e.components,t=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"181-\u5173\u4e8e\u65e5\u5fd7"},"18.1 \u5173\u4e8e\u65e5\u5fd7"),(0,i.kt)("p",null,"\u901a\u5e38\u65e5\u5fd7\u6307\u7684\u662f",(0,i.kt)("strong",{parentName:"p"},"\u7cfb\u7edf\u65e5\u5fd7"),"\u548c",(0,i.kt)("strong",{parentName:"p"},"\u7a0b\u5e8f\u65e5\u5fd7"),"\u3002"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u7cfb\u7edf\u65e5\u5fd7")," \u662f\u8bb0\u5f55\u7cfb\u7edf\u4e2d\u786c\u4ef6\u3001\u8f6f\u4ef6\u548c\u7cfb\u7edf\u95ee\u9898\u7684\u4fe1\u606f\uff0c\u540c\u65f6\u8fd8\u53ef\u4ee5\u76d1\u89c6\u7cfb\u7edf\u4e2d\u53d1\u751f\u7684\u4e8b\u4ef6\u3002\u7528\u6237\u53ef\u4ee5\u901a\u8fc7\u5b83\u6765\u68c0\u67e5\u9519\u8bef\u53d1\u751f\u7684\u539f\u56e0\uff0c\u6216\u8005\u5bfb\u627e\u53d7\u5230\u653b\u51fb\u65f6\u653b\u51fb\u8005\u7559\u4e0b\u7684\u75d5\u8ff9\u3002\u7cfb\u7edf\u65e5\u5fd7\u5305\u62ec\u7cfb\u7edf\u65e5\u5fd7\u3001\u5e94\u7528\u7a0b\u5e8f\u65e5\u5fd7\u548c\u5b89\u5168\u65e5\u5fd7\u3002"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u7a0b\u5e8f\u65e5\u5fd7")," \u662f\u7a0b\u5e8f\u8fd0\u884c\u4e2d\u4ea7\u751f\u7684\u65e5\u5fd7\uff0c\u901a\u5e38\u7531\u6846\u67b6\u8fd0\u884c\u65f6\u6216\u5f00\u53d1\u8005\u63d0\u4f9b\u7684\u65e5\u5fd7\u3002\u5305\u62ec\u8bf7\u6c42\u65e5\u5fd7\uff0c\u5f02\u5e38\u65e5\u5fd7\u3001\u5ba1\u8ba1\u65e5\u5fd7\u3001\u884c\u4e3a\u65e5\u5fd7\u7b49\u3002"),(0,i.kt)("h2",{id:"182-\u65e5\u5fd7\u4f5c\u7528"},"18.2 \u65e5\u5fd7\u4f5c\u7528"),(0,i.kt)("p",null,"\u5728\u9879\u76ee\u5f00\u53d1\u4e2d\uff0c\u90fd\u4e0d\u53ef\u907f\u514d\u7684\u4f7f\u7528\u5230\u65e5\u5fd7\u3002\u6ca1\u6709\u65e5\u5fd7\u867d\u7136\u4e0d\u4f1a\u5f71\u54cd\u9879\u76ee\u7684\u6b63\u786e\u8fd0\u884c\uff0c\u4f46\u662f\u6ca1\u6709\u65e5\u5fd7\u7684\u9879\u76ee\u53ef\u4ee5\u8bf4\u662f\u4e0d\u5b8c\u6574\u7684\u3002\u65e5\u5fd7\u5728\u8c03\u8bd5\uff0c\u9519\u8bef\u6216\u8005\u5f02\u5e38\u5b9a\u4f4d\uff0c\u6570\u636e\u5206\u6790\u4e2d\u7684\u4f5c\u7528\u662f\u4e0d\u8a00\u800c\u55bb\u7684\u3002"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u8c03\u8bd5")),(0,i.kt)("p",null,"\u5728\u9879\u76ee\u8c03\u8bd5\u65f6\uff0c\u67e5\u770b\u6808\u4fe1\u606f\u53ef\u4ee5\u65b9\u4fbf\u5730\u77e5\u9053\u5f53\u524d\u7a0b\u5e8f\u7684\u8fd0\u884c\u72b6\u6001\uff0c\u8f93\u51fa\u7684\u65e5\u5fd7\u4fbf\u4e8e\u8bb0\u5f55\u7a0b\u5e8f\u5728\u4e4b\u524d\u7684\u8fd0\u884c\u7ed3\u679c\u3002"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u9519\u8bef\u5b9a\u4f4d")),(0,i.kt)("p",null,"\u4e0d\u8981\u4ee5\u4e3a\u9879\u76ee\u80fd\u6b63\u786e\u8dd1\u8d77\u6765\u5c31\u53ef\u4ee5\u9ad8\u6795\u65e0\u5fe7\uff0c\u9879\u76ee\u5728\u8fd0\u884c\u4e00\u6bb5\u65f6\u5019\u540e\uff0c\u53ef\u80fd\u7531\u4e8e\u6570\u636e\u95ee\u9898\uff0c\u7f51\u7edc\u95ee\u9898\uff0c\u5185\u5b58\u95ee\u9898\u7b49\u51fa\u73b0\u5f02\u5e38\u3002\u8fd9\u65f6\u65e5\u5fd7\u53ef\u4ee5\u5e2e\u52a9\u5f00\u53d1\u6216\u8005\u8fd0\u7ef4\u4eba\u5458\u5feb\u901f\u5b9a\u4f4d\u9519\u8bef\u4f4d\u7f6e\uff0c\u63d0\u51fa\u89e3\u51b3\u65b9\u6848\u3002"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u6570\u636e\u5206\u6790")),(0,i.kt)("p",null,"\u5927\u6570\u636e\u7684\u5174\u8d77\uff0c\u4f7f\u5f97\u5927\u91cf\u7684\u65e5\u5fd7\u5206\u6790\u6210\u4e3a\u53ef\u80fd\uff0cELK \u4e5f\u8ba9\u65e5\u5fd7\u5206\u6790\u95e8\u69db\u964d\u4f4e\u4e86\u5f88\u591a\u3002\u65e5\u5fd7\u4e2d\u8574\u542b\u4e86\u5927\u91cf\u7684\u7528\u6237\u6570\u636e\uff0c\u5305\u62ec\u70b9\u51fb\u884c\u4e3a\uff0c\u5174\u8da3\u504f\u597d\u7b49\uff0c\u7528\u6237\u753b\u50cf\u5bf9\u4e8e\u516c\u53f8\u4e0b\u4e00\u6b65\u7684\u6218\u7565\u65b9\u5411\u6709\u4e00\u5b9a\u6307\u5f15\u4f5c\u7528\u3002"),(0,i.kt)("h2",{id:"183-\u65e5\u5fd7\u7ea7\u522b"},"18.3 \u65e5\u5fd7\u7ea7\u522b"),(0,i.kt)("p",null,"\u65e5\u5fd7\u7ea7\u522b\u53ef\u4ee5\u6709\u6548\u7684\u5bf9\u65e5\u5fd7\u4fe1\u606f\u8fdb\u884c\u5f52\u7c7b\uff0c\u65b9\u4fbf\u51c6\u786e\u7684\u67e5\u770b\u7279\u5b9a\u65e5\u5fd7\u5185\u5bb9\u3002\u901a\u5e38\u65e5\u5fd7\u7c7b\u522b\u6709\u4ee5\u4e0b\u7ea7\u522b\uff1a"),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:"center"},"\u7ea7\u522b"),(0,i.kt)("th",{parentName:"tr",align:null},"\u503c"),(0,i.kt)("th",{parentName:"tr",align:"center"},"\u65b9\u6cd5"),(0,i.kt)("th",{parentName:"tr",align:null},"\u63cf\u8ff0"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},"Trace\uff08\u8ddf\u8e2a\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},"0"),(0,i.kt)("td",{parentName:"tr",align:"center"},"LogTrace"),(0,i.kt)("td",{parentName:"tr",align:null},"\u5305\u542b\u6700\u8be6\u7ec6\u7684\u6d88\u606f\u3002 \u8fd9\u4e9b\u6d88\u606f\u53ef\u80fd\u5305\u542b\u654f\u611f\u7684\u5e94\u7528\u6570\u636e\u3002 \u8fd9\u4e9b\u6d88\u606f\u9ed8\u8ba4\u60c5\u51b5\u4e0b\u5904\u4e8e\u7981\u7528\u72b6\u6001\uff0c\u5e76\u4e14\u4e0d\u5e94\u5728\u751f\u4ea7\u4e2d\u542f\u7528\u3002")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},"Debug\uff08\u8c03\u8bd5\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},"1"),(0,i.kt)("td",{parentName:"tr",align:"center"},"LogDebug"),(0,i.kt)("td",{parentName:"tr",align:null},"\u7528\u4e8e\u8c03\u8bd5\u548c\u5f00\u53d1\u3002 \u7531\u4e8e\u91cf\u5927\uff0c\u8bf7\u5728\u751f\u4ea7\u4e2d\u5c0f\u5fc3\u4f7f\u7528\u3002")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},"Information\uff08\u4fe1\u606f\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},"2"),(0,i.kt)("td",{parentName:"tr",align:"center"},"LogInformation"),(0,i.kt)("td",{parentName:"tr",align:null},"\u8ddf\u8e2a\u5e94\u7528\u7684\u5e38\u89c4\u6d41\u3002 \u53ef\u80fd\u5177\u6709\u957f\u671f\u503c\u3002")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},"Warning\uff08\u8b66\u544a\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},"3"),(0,i.kt)("td",{parentName:"tr",align:"center"},"LogWarning"),(0,i.kt)("td",{parentName:"tr",align:null},"\u5bf9\u4e8e\u5f02\u5e38\u4e8b\u4ef6\u6216\u610f\u5916\u4e8b\u4ef6\u3002 \u901a\u5e38\u5305\u62ec\u4e0d\u4f1a\u5bfc\u81f4\u5e94\u7528\u5931\u8d25\u7684\u9519\u8bef\u6216\u60c5\u51b5\u3002")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},"Error\uff08\u9519\u8bef\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},"4"),(0,i.kt)("td",{parentName:"tr",align:"center"},"LogError"),(0,i.kt)("td",{parentName:"tr",align:null},"\u8868\u793a\u65e0\u6cd5\u5904\u7406\u7684\u9519\u8bef\u548c\u5f02\u5e38\u3002 \u8fd9\u4e9b\u6d88\u606f\u8868\u793a\u5f53\u524d\u64cd\u4f5c\u6216\u8bf7\u6c42\u5931\u8d25\uff0c\u800c\u4e0d\u662f\u6574\u4e2a\u5e94\u7528\u5931\u8d25\u3002")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},"Critical\uff08\u4e25\u91cd\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},"5"),(0,i.kt)("td",{parentName:"tr",align:"center"},"LogCritical"),(0,i.kt)("td",{parentName:"tr",align:null},"\u9700\u8981\u7acb\u5373\u5173\u6ce8\u7684\u5931\u8d25\u3002 \u4f8b\u5982\u6570\u636e\u4e22\u5931\u3001\u78c1\u76d8\u7a7a\u95f4\u4e0d\u8db3\u3002")))),(0,i.kt)("h2",{id:"184-\u5982\u4f55\u4f7f\u7528"},"18.4 \u5982\u4f55\u4f7f\u7528"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 5")," \u6846\u67b6\u4e2d\uff0c\u5fae\u8f6f\u5df2\u7ecf\u4e3a\u6211\u4eec\u5185\u7f6e\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u65e5\u5fd7\u7ec4\u4ef6"),"\uff0c\u6b63\u5e38\u60c5\u51b5\u4e0b\uff0c\u65e0\u9700\u6211\u4eec\u5f15\u7528\u7b2c\u4e09\u65b9\u5305\u8fdb\u884c\u65e5\u5fd7\u8bb0\u5f55\u3002",(0,i.kt)("inlineCode",{parentName:"p"},".NET 5")," \u6846\u67b6\u4e3a\u6211\u4eec\u63d0\u4f9b\u4e86\u4e24\u79cd\u65e5\u5fd7\u5bf9\u8c61\u521b\u5efa\u65b9\u5f0f\u3002"),(0,i.kt)("h3",{id:"1841-iloggert-\u6cdb\u578b\u65b9\u5f0f"},"18.4.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ILogger")," \u6cdb\u578b\u65b9\u5f0f"),(0,i.kt)("p",null,"\u4f7f\u7528\u975e\u5e38\u7b80\u5355\uff0c\u53ef\u4ee5\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"ILogger")," \u5bf9\u8c61\u8fdb\u884c\u6ce8\u5165\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},'public class PrivacyModel : PageModel\n{\n private readonly ILogger _logger;\n\n public PrivacyModel(ILogger logger)\n {\n _logger = logger;\n }\n\n public void OnGet()\n {\n _logger.LogInformation("GET Pages.PrivacyModel called.");\n }\n}\n')),(0,i.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u901a\u8fc7\u6cdb\u578b ",(0,i.kt)("inlineCode",{parentName:"p"},"ILogger")," \u65b9\u5f0f\u5199\u5165\u65e5\u5fd7\uff0c\u90a3\u4e48\u9ed8\u8ba4\u5c06 ",(0,i.kt)("inlineCode",{parentName:"p"},"T")," \u7c7b\u578b\u5b8c\u6574\u7c7b\u578b\u540d\u79f0\u4f5c\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"\u65e5\u5fd7\u7c7b\u522b"),"\u3002")),(0,i.kt)("h3",{id:"1842-iloggerfactory-\u5de5\u5382\u65b9\u5f0f"},"18.4.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ILoggerFactory")," \u5de5\u5382\u65b9\u5f0f"),(0,i.kt)("p",null,"\u4f7f\u7528\u5de5\u5382\u65b9\u5f0f\uff0c\u9700\u624b\u52a8\u4f20\u5165 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u65e5\u5fd7\u7c7b\u522b"),"\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,7}",showLineNumbers:!0,"":!0,"{5,7}":!0},'public class ContactModel : PageModel\n{\n private readonly ILogger _logger;\n\n public ContactModel(ILoggerFactory logger)\n {\n _logger = logger.CreateLogger("MyCategory");\n }\n\n public void OnGet()\n {\n _logger.LogInformation("GET Pages.ContactModel called.");\n }\n}\n')),(0,i.kt)("h3",{id:"1843-log-\u9759\u6001\u7c7b\u65b9\u5f0f"},"18.4.3 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Log")," \u9759\u6001\u7c7b\u65b9\u5f0f"),(0,i.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 4.2.1 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,10-15}",showLineNumbers:!0,"{2,5,10-15}":!0},'// \u521b\u5efa\u65e5\u5fd7\u5bf9\u8c61\nvar logger = Log.CreateLogger("\u65e5\u5fd7\u540d\u79f0");\n\n// \u521b\u5efa\u65e5\u5fd7\u5de5\u5382\nusing var loggerFactory = Log.CreateLoggerFactory(builder => {\n // ....\n});\n\n// \u65e5\u5fd7\u8bb0\u5f55\nLog.Information("Information");\nLog.Warning("Warning");\nLog.Error("Error");\nLog.Debug("Debug");\nLog.Trace("Trace");\nLog.Critical("Critical");\n')),(0,i.kt)("h3",{id:"1844-\u61d2\u4eba\u6a21\u5f0f-"},"18.4.4 ",(0,i.kt)("inlineCode",{parentName:"h3"},"\u61d2\u4eba\u6a21\u5f0f")," \ud83d\ude01"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u63d0\u4f9b\u4e86\u66f4\u61d2\u7684\u65b9\u5f0f\u5199\u5165\u65e5\u5fd7\uff0c\u4e5f\u5c31\u662f\u901a\u8fc7\u5b57\u7b26\u4e32\u62d3\u5c55\u7684\u65b9\u5f0f\u5199\u5165\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'"\u7b80\u5355\u65e5\u5fd7".LogInformation();\n\n"\u767e\u5c0f\u50e7 \u65b0\u589e\u4e86\u4e00\u6761\u8bb0\u5f55".LogInformation();\n\n"\u7a0b\u5e8f\u51fa\u73b0\u5f02\u5e38\u5566".LogError();\n\n"\u8fd9\u662f\u81ea\u5b9a\u4e49\u7c7b\u522b\u65e5\u5fd7".SetCategory("\u7c7b\u522b").LogInformation();\n')),(0,i.kt)("p",null,"\u901a\u8fc7\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u5f0f\u53ef\u4ee5\u5728\u4efb\u4f55\u65f6\u5019\u65b9\u4fbf\u8bb0\u5f55\u65e5\u5fd7\uff0c\u4e13\u95e8\u4e3a\u61d2\u4eba\u63d0\u4f9b\u7684\u3002"),(0,i.kt)("h2",{id:"185-\u914d\u7f6e\u65e5\u5fd7\u8f93\u51fa\u4ecb\u8d28"},"18.5 \u914d\u7f6e\u65e5\u5fd7\u8f93\u51fa\u4ecb\u8d28"),(0,i.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5c0f\u8282\u4ec5\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 3.9.0+")," \u7248\u672c\u63d0\u4f9b\u3002")),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u7a0b\u5e8f\u4e2d\uff0c\u4e3b\u673a\u542f\u52a8\u65f6\u9ed8\u8ba4\u6ce8\u518c\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"ConsoleLoggerProvider")," \u63d0\u4f9b\u5668\uff0c\u4e5f\u5c31\u662f\u63a7\u5236\u53f0\u65e5\u5fd7\u8f93\u51fa\u63d0\u4f9b\u5668\uff0c\u6240\u4ee5\u65e0\u9700\u4efb\u4f55\u6ce8\u518c\u670d\u52a1\u5373\u53ef\u5728\u63a7\u5236\u53f0\u8f93\u51fa\u3002"),(0,i.kt)("h3",{id:"1851-\u8f93\u51fa\u5230\u63a7\u5236\u53f0"},"18.5.1 \u8f93\u51fa\u5230\u63a7\u5236\u53f0"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"info: Furion.EventBus.EventBusHostedService[0]\n EventBus Hosted Service is running.\ninfo: Microsoft.Hosting.Lifetime[14]\n Now listening on: https://localhost:5001\ninfo: Microsoft.Hosting.Lifetime[14]\n Now listening on: http://localhost:5000\ninfo: Microsoft.Hosting.Lifetime[0]\n Application started. Press Ctrl+C to shut down.\ninfo: Microsoft.Hosting.Lifetime[0]\n Hosting environment: Development\ninfo: Microsoft.Hosting.Lifetime[0]\n Content root path: C:\\Workplaces\\Furion\\samples\\Furion.Web.Entry\\\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u63a7\u5236\u53f0\u8f93\u51fa\u8fc7\u6ee4"))),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},".NET5")," \u7248\u672c\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,2,4}",showLineNumbers:!0,"{1,2,4}":!0},"Host.CreateDefaultBuilder(args)\n .ConfigureLogging(logging =>\n {\n logging.AddFilter((provider, category, logLevel) =>\n {\n // .....\n });\n })\n")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},".NET6+")," \u7248\u672c\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3}",showLineNumbers:!0,"{1,3}":!0},"var builder = WebApplication.CreateBuilder(args);\n\nbuilder.Logging.AddFilter((provider, category, logLevel) =>\n{\n // .....\n});\n")),(0,i.kt)("p",null,"\u5982\u9700\u5176\u4ed6\u914d\u7f6e\u53ef\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u914d\u7f6e\u5373\u53ef\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-12}",showLineNumbers:!0,"{2-12}":!0},'{\n "Logging": {\n "Console": {\n "IncludeScopes": true,\n "LogLevel": {\n "Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",\n "Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",\n "Microsoft.AspNetCore.Mvc.Razor": "Error",\n "Default": "Information"\n }\n }\n }\n}\n')),(0,i.kt)("p",null,"\u5982\u9700\u81ea\u5b9a\u4e49\u63a7\u5236\u53f0\u65e5\u5fd7\u6a21\u677f\u53ef\u67e5\u770b\u5fae\u8f6f\u5b98\u65b9\u6587\u6863 ",(0,i.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/dotnet/core/extensions/console-log-formatter#implement-a-custom-formatter"},"https://docs.microsoft.com/zh-cn/dotnet/core/extensions/console-log-formatter#implement-a-custom-formatter")),(0,i.kt)("p",null,"\u8fd9\u91cc\u4e5f\u63d0\u4f9b\u76f8\u5173 ",(0,i.kt)("inlineCode",{parentName:"p"},"Issue")," \u53c2\u8003\uff1a",(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I5JJJH"},"#I5JJJH"))),(0,i.kt)("h3",{id:"1852-\u8f93\u51fa\u5230\u6587\u4ef6"},"18.5.2 \u8f93\u51fa\u5230\u6587\u4ef6"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u57fa\u7840\u4f7f\u7528"))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,8}",showLineNumbers:!0,"{2,5,8}":!0},'// \u4f8b\u5b50\u4e00\uff1a\u542f\u52a8\u5c42\u6839\u76ee\u5f55\u8f93\u51fa\nservices.AddFileLogging("application.log");\n\n// \u4f8b\u5b50\u4e8c\uff1a\u652f\u6301\u8def\u5f84\nservices.AddFileLogging("logs/application.log");\n\n// \u4f8b\u5b50\u4e09\uff1a\u652f\u6301\u65e5\u5fd7\u8ffd\u52a0\u8fd8\u662f\u8986\u76d6\uff0c\u8bbe\u7f6e true \u4e3a\u8ffd\u52a0\uff0cfalse \u4e3a\u8986\u76d6\nservices.AddFileLogging("application.log", true);\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u4ece\u914d\u7f6e\u6587\u4ef6\u8bfb\u53d6\u914d\u7f6e"))),(0,i.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("strong",{parentName:"p"},"\u53ea\u6709\u4e0d\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},".AddFile")," \u7b2c\u4e00\u4e2a\u53c2\u6570\u914d\u7f6e\u6587\u4ef6\u540d\u624d\u4f1a\u81ea\u52a8\u52a0\u8f7d\u914d\u7f6e\uff0c\u4e5f\u5c31\u662f\u6587\u4ef6\u540d\u5e94\u8be5\u914d\u7f6e\u5728\u914d\u7f6e\u6587\u4ef6\u4e2d\u3002"))),(0,i.kt)("p",null,"\u6587\u4ef6\u65e5\u5fd7\u914d\u7f6e\u8bf4\u660e\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2,7-13,16-22}",showLineNumbers:!0,"{2,7-13,16-22}":!0},'{\n "Logging": {\n "LogLevel": {\n "Default": "Information"\n // .... appsettings \u9ed8\u8ba4\u914d\u7f6e\n },\n "File": {\n "FileName": "application.log", // \u65e5\u5fd7\u6587\u4ef6\u5b8c\u6574\u8def\u5f84\u6216\u6587\u4ef6\u540d\uff0c\u63a8\u8350 .log \u4f5c\u4e3a\u62d3\u5c55\u540d\n "Append": true, // \u8ffd\u52a0\u5230\u5df2\u5b58\u5728\u65e5\u5fd7\u6587\u4ef6\u6216\u8986\u76d6\u5b83\u4eec\n "MinimumLevel": "Information", // \u6700\u4f4e\u65e5\u5fd7\u8bb0\u5f55\u7ea7\u522b\n "FileSizeLimitBytes": 0, // \u63a7\u5236\u6bcf\u4e00\u4e2a\u65e5\u5fd7\u6587\u4ef6\u6700\u5927\u5b58\u50a8\u5927\u5c0f\uff0c\u9ed8\u8ba4\u65e0\u9650\u5236\uff0c\u5982\u679c\u6307\u5b9a\u4e86\u8be5\u503c\uff0c\u90a3\u4e48\u65e5\u5fd7\u6587\u4ef6\u5927\u5c0f\u8d85\u51fa\u4e86\u8be5\u914d\u7f6e\u5c31\u4f1a\u521b\u5efa\u65b0\u7684\u65e5\u5fd7\u6587\u4ef6\uff0c\u65b0\u521b\u5efa\u7684\u65e5\u5fd7\u6587\u4ef6\u547d\u540d\u89c4\u5219\uff1a\u6587\u4ef6\u540d+[\u9012\u589e\u5e8f\u53f7].log\n "MaxRollingFiles": 0 // \u63a7\u5236\u6700\u5927\u521b\u5efa\u7684\u65e5\u5fd7\u6587\u4ef6\u6570\u91cf\uff0c\u9ed8\u8ba4\u65e0\u9650\u5236\uff0c\u914d\u5408 FileSizeLimitBytes \u4f7f\u7528\uff0c\u5982\u679c\u6307\u5b9a\u4e86\u8be5\u503c\uff0c\u90a3\u4e48\u8d85\u51fa\u8be5\u503c\u5c06\u4ece\u6700\u521d\u65e5\u5fd7\u6587\u4ef6\u4e2d\u4ece\u5934\u5199\u5165\u8986\u76d6\n }\n },\n // \u81ea\u5b9a\u4e49\u914d\u7f6e\u8282\u70b9\n "MyLogger": {\n "FileName": "application.log",\n "Append": true,\n "MinimumLevel": "Information",\n "FileSizeLimitBytes": 0,\n "MaxRollingFiles": 0\n }\n}\n')),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,13,16}",showLineNumbers:!0,"{2,5,13,16}":!0},'// \u4f8b\u5b50\u4e00\uff1a\u9ed8\u8ba4\u8bfb\u53d6 Logging:File \u8282\u70b9\nservices.AddFileLogging();\n\n// \u4f8b\u5b50\u4e8c\uff1a\u9ed8\u8ba4\u8bfb\u53d6 Logging:File \u8282\u70b9\uff0c\u652f\u6301\u66f4\u591a\u914d\u7f6e\nservices.AddFileLogging(options =>\n{\n options.MinimumLevel = LogLevel.Warning;\n\n // \u5176\u4ed6\u914d\u7f6e...\n});\n\n// \u4f8b\u5b50\u4e09\uff1a\u81ea\u5b9a\u4e49\u914d\u7f6e\u8282\u70b9\nservices.AddFileLogging(() => "MyLogger");\n\n// \u4f8b\u5b50\u56db\uff1a\u81ea\u5b9a\u4e49\u914d\u7f6e\u8282\u70b9\uff0c\u652f\u6301\u66f4\u591a\u914d\u7f6e\nservices.AddFileLogging(() => "MyLogger", options =>\n{\n options.MinimumLevel = LogLevel.Warning;\n\n // \u5176\u4ed6\u914d\u7f6e...\n});\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u81ea\u5b9a\u4e49\u65e5\u5fd7\u6587\u4ef6\u540d\u89c4\u5219"))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,14,23}",showLineNumbers:!0,"{2,5,14,23}":!0},'// \u4f8b\u5b50\u4e00\uff1a\u652f\u6301\u7cfb\u7edf\u73af\u5883\u53d8\u91cf\uff0c\u5982%SystemDrive%\uff0c%SystemRoot%\nservices.AddFileLogging("application%SystemDrive%-%SystemRoot%.log");\n\n// \u4f8b\u5b50\u4e8c\uff1a\u6bcf\u5929\u521b\u5efa\u4e00\u4e2a\u65e5\u5fd7\u6587\u4ef6\nservices.AddFileLogging("application-{0:yyyy}-{0:MM}-{0:dd}.log", options =>\n{\n options.FileNameRule = fileName =>\n {\n return string.Format(fileName, DateTime.UtcNow);\n };\n});\n\n// \u4f8b\u5b50\u4e09\uff0c\u4efb\u4f55\u81ea\u5df1\u559c\u6b22\u7684\u547d\u540d\u89c4\u5219\nservices.AddFileLogging("application-{0:yyyy}-{0:MM}-{0:dd}.log", options =>\n{\n options.FileNameRule = fileName =>\n {\n // your rule...\n };\n});\n\n// \u4f8b\u5b50\u56db\uff0c\u6279\u91cf\u8bbe\u7f6e\u591a\u4e2a\nArray.ForEach(new[] { LogLevel.Information, LogLevel.Warning, LogLevel.Error }, logLevel =>\n{\n services.AddFileLogging("application-{1}-{0:yyyy}-{0:MM}-{0:dd}.log", options =>\n {\n options.FileNameRule = fileName => string.Format(fileName, DateTime.UtcNow, logLevel.ToString());\n options.WriteFilter = logMsg => logMsg.LogLevel == logLevel;\n });\n});\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u65e5\u5fd7\u8fc7\u6ee4\u5668/\u7b5b\u9009\u5668"))),(0,i.kt)("p",null,"\u901a\u8fc7\u65e5\u5fd7\u7b5b\u9009\u5668\u53ef\u4ee5\u5bf9\u65e5\u5fd7\u8fdb\u884c\u5f52\u7c7b\u5199\u5165"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,10,19}",showLineNumbers:!0,"{2,10,19}":!0},'// \u4f8b\u5b50\u4e00\uff1a\u6839\u636e\u65e5\u5fd7\u7ea7\u522b\u8f93\u51fa\nservices.AddFileLogging("infomation.log", options =>\n{\n options.WriteFilter = (logMsg) =>\n {\n return logMsg.LogLevel == LogLevel.Information;\n };\n});\n\nservices.AddFileLogging("error.log", options =>\n{\n options.WriteFilter = (logMsg) =>\n {\n return logMsg.LogLevel == LogLevel.Error;\n };\n});\n\n// \u4f8b\u5b50\u4e8c\uff0c\u6839\u636e\u4efb\u4f55\u89c4\u5219\uff0c\u6bd4\u5982\u7279\u5b9a\u7684\u7c7b\u540d\nservices.AddFileLogging("someclass.log", options =>\n{\n options.WriteFilter = (logMsg) =>\n {\n return logMsg.LogName.Contains("SomeClassName");\n };\n});\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u81ea\u5b9a\u4e49\u65e5\u5fd7\u6a21\u677f"))),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u6807\u51c6\u7684\u65e5\u5fd7\u8f93\u51fa\u6a21\u677f\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"2022-07-23T20:16:29.3459053+08:00 [INF] [Furion.EventBus.EventBusHostedService] [0] EventBus Hosted Service is running.\n2022-07-23T20:16:29.5827366+08:00 [INF] [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.\n2022-07-23T20:16:29.5828798+08:00 [INF] [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development\n2022-07-23T20:16:29.5829377+08:00 [INF] [Microsoft.Hosting.Lifetime] [0] Content root path: C:\\Workplaces\\Furion\\samples\\Furion.Web.Entry\\\n")),(0,i.kt)("p",null,"\u5982\u9700\u81ea\u5b9a\u4e49\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,16,34}",showLineNumbers:!0,"{2,16,34}":!0},'// \u4f8b\u5b50\u4e00\uff0c\u81ea\u5b9a\u4e49\u65e5\u5fd7\u6a21\u677f\uff08\u5e38\u7528\uff09\nservices.AddFileLogging("mytemplate.log", options =>\n{\n options.MessageFormat = (logMsg) =>\n {\n var stringBuilder = new StringBuilder();\n\n stringBuilder.Append(DateTime.Now.ToString("o"));\n // \u5176\u4ed6\u7684\u3002\u3002\u3002\u81ea\u5df1\u7ec4\u88c5\n\n return stringBuilder.ToString();\n };\n});\n\n// \u4f8b\u5b50\u4e8c\uff0c\u9700\u8981\u8f93\u51fa json \u683c\u5f0f\uff0c\u6bd4\u5982\u5bf9\u63a5\u963f\u91cc\u4e91\u65e5\u5fd7\uff0ckibana\u7b2c\u4e09\u65b9\u65e5\u5fd7\u4f7f\u7528\u8fd9\u4e2a\nservices.AddFileLogging("mytemplate.log", options =>\n{\n options.MessageFormat = (logMsg) =>\n {\n // \u9ad8\u6027\u80fd\u5199\u5165\n return logMsg.WriteArray(writer =>\n {\n writer.WriteStringValue(DateTime.Now.ToString("o"));\n writer.WriteStringValue(logMsg.LogLevel.ToString());\n writer.WriteStringValue(logMsg.LogName);\n writer.WriteNumberValue(logMsg.EventId.Id);\n writer.WriteStringValue(logMsg.Message);\n writer.WriteStringValue(logMsg.Exception?.ToString());\n });\n };\n});\n\n// \u4f8b\u5b50\u4e8c\uff0c\u9700\u8981\u8f93\u51fa json \uff08\u81ea\u5b9a\u4e49\uff09\u683c\u5f0f\uff0c\u6bd4\u5982\u5bf9\u63a5\u963f\u91cc\u4e91\u65e5\u5fd7\uff0ckibana\u7b2c\u4e09\u65b9\u65e5\u5fd7\u4f7f\u7528\u8fd9\u4e2a\nservices.AddFileLogging("mytemplate.log", options =>\n{\n options.MessageFormat = (logMsg) =>\n {\n // \u9ad8\u6027\u80fd\u5199\u5165\n return logMsg.Write(writer =>\n {\n // write \u5bf9\u8c61\u4e3a Utf8JsonWriter\uff0c\u53ef\u901a\u8fc7\u6d41\u5199\u5165\uff0c\u6027\u80fd\u6781\u9ad8\n });\n };\n});\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u65e5\u5fd7\u5199\u5165\u5931\u8d25\u5904\u7406"))),(0,i.kt)("p",null,"\u6709\u65f6\u5019\u53ef\u80fd\u56e0\u4e3a\u65e5\u5fd7\u6587\u4ef6\u88ab\u6253\u5f00\u6216\u8005\u5176\u4ed6\u5e94\u7528\u7a0b\u5e8f\u5360\u7528\u4e86\uff0c\u90a3\u4e48\u5c31\u4f1a\u5bfc\u81f4\u65e5\u5fd7\u5199\u5165\u5931\u8d25\uff0c\u8fd9\u65f6\u5019\u53ef\u4ee5\u8fdb\u884c\u5176\u4ed6\u76f8\u5173\u5904\u7406\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,11,15}",showLineNumbers:!0,"{2,11,15}":!0},'// \u4f8b\u5b50\u4e00\uff1a\u5176\u4ed6\u5904\u7406\nservices.AddFileLogging("template-obj.log", options =>\n{\n options.HandleWriteError = (writeError) =>\n {\n // ~~\n };\n});\n\n// \u4f8b\u5b50\u4e8c\uff0c\u542f\u7528\u5907\u7528\u65e5\u5fd7\u6587\u4ef6\u529f\u80fd\uff0c\u4e5f\u5c31\u662f\u5982\u679c\u6587\u4ef6\u88ab\u5360\u7528\u4e86\uff0c\u53ef\u4ee5\u521b\u5efa\u65b0\u7684\u5907\u7528\u65e5\u5fd7\u7ee7\u7eed\u5199\u5165\uff0c\u63a8\u8350\uff01\uff01\uff01\nservices.AddFileLogging("template-obj.log", options =>\n{\n options.HandleWriteError = (writeError) =>\n {\n writeError.UseRollbackFileName(Path.GetFileNameWithoutExtension(writeError.CurrentFileName) + "-oops" + Path.GetExtension(writeError.CurrentFileName));\n };\n});\n')),(0,i.kt)("h3",{id:"1853-\u8f93\u51fa\u5230\u6570\u636e\u5e93\u5176\u4ed6\u5b58\u50a8\u4ecb\u8d28"},"18.5.3 \u8f93\u51fa\u5230\u6570\u636e\u5e93/\u5176\u4ed6\u5b58\u50a8\u4ecb\u8d28"),(0,i.kt)("p",null,"\u5c06\u65e5\u5fd7\u8f93\u51fa\u5230\u6570\u636e\u5e93\u4e2d\u4e5f\u662f\u975e\u5e38\u5e38\u89c1\u7684\u9700\u6c42\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u628a\u8be5\u529f\u80fd\u505a\u5230\u4e86\u975e\u5e38\u7b80\u5355\uff0c\u652f\u6301\u4efb\u4f55\u5b58\u50a8\u4ecb\u8d28\u3002"),(0,i.kt)("p",null,"\u5728\u5199\u5165\u6570\u636e\u5e93/\u5176\u4ed6\u5b58\u50a8\u4ecb\u8d28\u4e4b\u524d\u9700\u521b\u5efa\u6570\u636e\u5e93\u65e5\u5fd7\u5199\u5165\u5668\u5e76\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"p"},"IDatabaseLoggingWriter")," \u63a5\u53e3\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u4e2a"),"\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,8,12}",showLineNumbers:!0,"{1,5,8,12}":!0},"using Furion.Logging;\n\nnamespace Your.Core;\n\npublic class DatabaseLoggingWriter : IDatabaseLoggingWriter\n{\n // \u652f\u6301\u6784\u9020\u51fd\u6570\u6ce8\u5165\u4efb\u4f55\u5b9e\u4f8b\uff0c\u4f1a\u81ea\u52a8\u91ca\u653e\u4efb\u4f55\u670d\u52a1\uff0c\u6bd4\u5982\u6ce8\u5165 IRepository\uff0c\u6216\u8005 SqlSugarClient\n public DatabaseLoggingWriter()\n {\n }\n\n public void Write(LogMessage logMsg, bool flush)\n {\n // \u8fd9\u91cc\u5199\u4f60\u4efb\u4f55\u63d2\u5165\u6570\u636e\u5e93\u7684\u64cd\u4f5c\uff0c\u65e0\u9700 try catch\n }\n}\n")),(0,i.kt)("p",null,"\u4f60\u6ca1\u770b\u9519\uff0c\u5c31\u8fd9\u4e48\u7b80\u5355\uff01\uff01"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u57fa\u7840\u4f7f\u7528"))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5}",showLineNumbers:!0,"{2,5}":!0},"// \u4f8b\u5b50\u4e00\uff0c\u9ed8\u8ba4\u914d\u7f6e\nservices.AddDatabaseLogging(options => {});\n\n// \u4f8b\u5b50\u4e8c\uff1a\u81ea\u5b9a\u4e49\u914d\u7f6e\nservices.AddDatabaseLogging(options =>\n{\n options.MinimumLevel = LogLevel.Warning;\n\n // \u5176\u4ed6\u914d\u7f6e...\n});\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u4ece\u914d\u7f6e\u6587\u4ef6\u4e2d\u8bfb\u53d6"))),(0,i.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("strong",{parentName:"p"},"\u53ea\u6709\u4e0d\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},".AddDatabase")," \u7b2c\u4e00\u4e2a\u53c2\u6570\u4e3a\u7a7a\u624d\u4f1a\u81ea\u52a8\u52a0\u8f7d\u914d\u7f6e\u3002"))),(0,i.kt)("p",null,"\u6570\u636e\u5e93\u65e5\u5fd7\u914d\u7f6e\u8bf4\u660e\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2,7-9,12-14}",showLineNumbers:!0,"{2,7-9,12-14}":!0},'{\n "Logging": {\n "LogLevel": {\n "Default": "Information"\n // .... appsettings \u9ed8\u8ba4\u914d\u7f6e\n },\n "Database": {\n "MinimumLevel": "Information" // \u6700\u4f4e\u65e5\u5fd7\u8bb0\u5f55\u7ea7\u522b\n }\n },\n // \u81ea\u5b9a\u4e49\u914d\u7f6e\u8282\u70b9\n "MyLogger": {\n "MinimumLevel": "Information"\n }\n}\n')),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,5,18,25}",showLineNumbers:!0,"{2,5,5,18,25}":!0},'// \u4f8b\u5b50\u4e00\uff1a\u9ed8\u8ba4\u8bfb\u53d6 Logging:Database \u8282\u70b9\nservices.AddDatabaseLogging();\n\n// \u4f8b\u5b50\u4e8c\uff1a\u9ed8\u8ba4\u8bfb\u53d6 Logging:Database \u8282\u70b9\uff0c\u652f\u6301\u66f4\u591a\u914d\u7f6e\nservices.AddDatabaseLogging(default(string), options =>\n{\n options.MinimumLevel = LogLevel.Warning;\n\n // \u5176\u4ed6\u914d\u7f6e...\n});\n\n// \u4f8b\u5b50\u4e09\uff1a\u81ea\u5b9a\u4e49\u914d\u7f6e\u8282\u70b9\nservices.AddDatabaseLogging("MyLogger");\n// \u6216\nservices.AddDatabaseLogging(() => "MyLogger");\n\n// \u4f8b\u5b50\u56db\uff1a\u81ea\u5b9a\u4e49\u914d\u7f6e\u8282\u70b9\uff0c\u652f\u6301\u66f4\u591a\u914d\u7f6e\nservices.AddDatabaseLogging("MyLogger", options =>\n{\n options.MinimumLevel = LogLevel.Warning;\n\n // \u5176\u4ed6\u914d\u7f6e...\n});\n// \u6216\nservices.AddDatabaseLogging(() => "MyLogger", options =>\n{\n options.MinimumLevel = LogLevel.Warning;\n\n // \u5176\u4ed6\u914d\u7f6e...\n});\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u65e5\u5fd7\u8fc7\u6ee4\u5668/\u7b5b\u9009\u5668"))),(0,i.kt)("p",null,"\u901a\u8fc7\u65e5\u5fd7\u7b5b\u9009\u5668\u53ef\u4ee5\u5bf9\u65e5\u5fd7\u8fdb\u884c\u5f52\u7c7b\u5199\u5165"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,10,19}",showLineNumbers:!0,"{2,10,19}":!0},'// \u4f8b\u5b50\u4e00\uff1a\u6839\u636e\u65e5\u5fd7\u7ea7\u522b\u8f93\u51fa\uff0c\u53ef\u4ee5\u5206\u522b\u5b9a\u4e49 IDatabaseLoggingWriter\uff0c\u4e5f\u53ef\u4ee5\u7528\u540c\u4e00\u4e2a\u5e95\u5c42\u8fdb\u884c\u5224\u65ad\nservices.AddDatabaseLogging(options =>\n{\n options.WriteFilter = (logMsg) =>\n {\n return logMsg.LogLevel == LogLevel.Information;\n };\n});\n// \u53ef\u4ee5\u5206\u522b\u5b9a\u4e49 IDatabaseLoggingWriter\uff0c\u4e5f\u53ef\u4ee5\u7528\u540c\u4e00\u4e2a\u5e95\u5c42\u8fdb\u884c\u5224\u65ad\nservices.AddDatabaseLogging(options =>\n{\n options.WriteFilter = (logMsg) =>\n {\n return logMsg.LogLevel == LogLevel.Error;\n };\n});\n\n// \u4f8b\u5b50\u4e8c\uff0c\u6839\u636e\u4efb\u4f55\u89c4\u5219\uff0c\u6bd4\u5982\u7279\u5b9a\u7684\u7c7b\u540d\nservices.AddDatabaseLogging(options =>\n{\n options.WriteFilter = (logMsg) =>\n {\n return logMsg.LogName.Contains("SomeClassName");\n };\n});\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u65e5\u5fd7\u5199\u5165\u5931\u8d25\u5904\u7406"))),(0,i.kt)("p",null,"\u6709\u65f6\u5019\u53ef\u80fd\u56e0\u4e3a\u6570\u636e\u5e93\u8fde\u63a5\u5f02\u5e38\u6216\u5176\u4ed6\u539f\u56e0\u8fde\u63a5\u6c60\u6ee1\uff0c\u90a3\u4e48\u5c31\u4f1a\u5bfc\u81f4\u65e5\u5fd7\u5199\u5165\u5931\u8d25\uff0c\u8fd9\u65f6\u5019\u53ef\u4ee5\u8fdb\u884c\u5176\u4ed6\u76f8\u5173\u5904\u7406\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},"// \u4f8b\u5b50\u4e00\uff1a\u5176\u4ed6\u5904\u7406\nservices.AddDatabaseLogging(options =>\n{\n options.HandleWriteError = (writeError) =>\n {\n // ~~\n };\n});\n")),(0,i.kt)("h3",{id:"1854-iloggerfactory-\u65b9\u5f0f"},"18.5.4 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ILoggerFactory")," \u65b9\u5f0f"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e5f\u63d0\u4f9b\u4e86\u8fd0\u884c\u65f6\u52a8\u6001\u521b\u5efa\u65e5\u5fd7\u63d0\u4f9b\u5668\u5e76\u5199\u5165\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,7-8}",showLineNumbers:!0,"":!0,"{5,7-8}":!0},'public class ContactModel : PageModel\n{\n private readonly ILogger _logger;\n\n public ContactModel(ILoggerFactory logger)\n {\n // \u652f\u6301\u6240\u6709 AddLoggingFile \u548c AddDatabaseFile \u914d\u7f6e\n _logger = logger.AddFile(....).CreateLogger("MyCategory");\n }\n\n public void OnGet()\n {\n _logger.LogInformation("GET Pages.ContactModel called.");\n }\n}\n')),(0,i.kt)("h3",{id:"1855-iloggingbuilder-\u65b9\u5f0f"},"18.5.5 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ILoggingBuilder")," \u65b9\u5f0f"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e5f\u63d0\u4f9b\u4e86\u539f\u751f ",(0,i.kt)("inlineCode",{parentName:"p"},"services.AddLogging(builder => {})")," \u65b9\u5f0f\u914d\u7f6e\uff0c\u5982"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,5}",showLineNumbers:!0,"{1,3,5}":!0},'services.AddLogging(builder =>\n{\n builder.AddFile("applicaion.log");\n\n builder.AddDatabase();\n\n //....\n});\n')),(0,i.kt)("h3",{id:"1856-\u8bb0\u5f55\u8bf7\u6c42\u65e5\u5fd7"},"18.5.6 \u8bb0\u5f55\u8bf7\u6c42\u65e5\u5fd7"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"ASP.NET 6")," \u4e2d\uff0c\u6846\u67b6\u9ed8\u8ba4\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"app.UseHttpLogging()")," \u8bb0\u5f55 ",(0,i.kt)("inlineCode",{parentName:"p"},"HTTP")," \u8bf7\u6c42\u65e5\u5fd7\u529f\u80fd\uff0c\u8be6\u7ec6\u4e86\u89e3\u53ef\u67e5\u770b\u5b98\u65b9\u6587\u6863 ",(0,i.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/http-logging/?view=aspnetcore-6.0"},"ASP.NET Core - HTTP \u65e5\u5fd7\u8bb0\u5f55")),(0,i.kt)("p",null,"\u5f53\u7136\u4e5f\u53ef\u4ee5\u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6\u7684\u65b9\u5f0f\u5199\uff0c\u53ea\u9700\u8981\u6ce8\u5165 ",(0,i.kt)("inlineCode",{parentName:"p"},"ILogger<>")," \u63a5\u53e3\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"1857-debug-\u548c-trace-\u9ed8\u8ba4\u4e0d\u8f93\u51fa\u95ee\u9898"},"18.5.7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Debug")," \u548c ",(0,i.kt)("inlineCode",{parentName:"h3"},"Trace")," \u9ed8\u8ba4\u4e0d\u8f93\u51fa\u95ee\u9898"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u5fae\u8f6f\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"appsettings.Development.json")," \u4e2d\u914d\u7f6e\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Default")," \u65e5\u5fd7\u7ea7\u522b\uff0c\u5982\u9700\u81ea\u5b9a\u4e49\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {4}",showLineNumbers:!0,"{4}":!0},'{\n "Logging": {\n "LogLevel": {\n "Default": "Information"\n }\n }\n}\n')),(0,i.kt)("p",null,"\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u4fee\u6539 ",(0,i.kt)("inlineCode",{parentName:"p"},"Default")," \u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"Debug")," \u6216 ",(0,i.kt)("inlineCode",{parentName:"p"},"Trace")," \u5373\u53ef\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u4e0d\u540c\u73af\u5883\u52a0\u8f7d\u4e0d\u540c\u7684\u914d\u7f6e\u6587\u4ef6\u3002\u5f00\u53d1\u73af\u5883\u5e94\u4fee\u6539 ",(0,i.kt)("inlineCode",{parentName:"strong"},"appsettings.Development.json")," \u4e0b\u7684\u914d\u7f6e\u3002")),(0,i.kt)("h2",{id:"186-loggingmonitor-\u76d1\u542c\u65e5\u5fd7"},"18.6 ",(0,i.kt)("inlineCode",{parentName:"h2"},"[LoggingMonitor]")," \u76d1\u542c\u65e5\u5fd7"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 3.9.1")," \u7248\u672c\u65b0\u589e\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"[LoggingMonitor]")," \u7279\u6027\uff0c\u652f\u6301\u5728\u63a7\u5236\u5668\u6216\u64cd\u4f5c\u4e2d\u8d34\u8be5\u7279\u6027\uff0c\u53ef\u4ee5\u5b9e\u73b0\u5f3a\u5927\u7684\u8bf7\u6c42\u65e5\u5fd7\u76d1\u542c\uff0c\u65b9\u4fbf\u6d4b\u8bd5\uff0c\u5982\uff1a"),(0,i.kt)("h3",{id:"1861-\u7279\u6027\u914d\u7f6e"},"18.6.1 \u7279\u6027\u914d\u7f6e"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,7}",showLineNumbers:!0,"{1,7}":!0},"using Furion.Logging;\n\nnamespace Furion.Application;\n\npublic class TestLoggerServices : IDynamicApiController\n{\n [LoggingMonitor]\n public PersonDto GetPerson(int id)\n {\n return new PersonDto\n {\n Id = id\n };\n }\n}\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u652f\u6301\u4ee5\u4e0b\u914d\u7f6e\uff1a",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Title"),"\uff1a\u914d\u7f6e\u6807\u9898\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,i.kt)("inlineCode",{parentName:"li"},"Logging Monitor")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"WithReturnValue"),"\uff1a\u662f\u5426\u5305\u542b\u8fd4\u56de\u503c\u6253\u5370\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,i.kt)("inlineCode",{parentName:"li"},"true"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Furion 4.3.9+ \u6709\u6548")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ReturnValueThreshold"),"\uff1a\u914d\u7f6e\u8fd4\u56de\u503c\u5b57\u7b26\u4e32\u9608\u503c\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"int")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,i.kt)("inlineCode",{parentName:"li"},"0")," \u5168\u91cf\u8f93\u51fa\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Furion 4.3.9+ \u6709\u6548"))))),(0,i.kt)("p",null,"\u8f93\u51fa\u65e5\u5fd7\u4e3a\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},'\u250f\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Logging Monitor \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 Furion.Application.TestLoggerServices.GetPerson (Furion.Application)\n\u2523\n\u2523 \u63a7\u5236\u5668\u540d\u79f0\uff1a TestLoggerServices\n\u2523 \u64cd\u4f5c\u540d\u79f0\uff1a GetPerson\n\u2523 \u8def\u7531\u4fe1\u606f\uff1a [area]: ; [controller]: test-logger; [action]: person\n\u2523 \u8bf7\u6c42\u65b9\u5f0f\uff1a POST\n\u2523 \u8bf7\u6c42\u5730\u5740\uff1a https://localhost:44316/api/test-logger/person/11\n\u2523 \u6765\u6e90\u5730\u5740\uff1a https://localhost:44316/api/index.html\n\u2523 \u6d4f\u89c8\u5668\u6807\u8bc6\uff1a Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62\n\u2523 \u5ba2\u6237\u7aef IP \u5730\u5740\uff1a 0.0.0.1\n\u2523 \u670d\u52a1\u7aef IP \u5730\u5740\uff1a 0.0.0.1\n\u2523 \u670d\u52a1\u7aef\u8fd0\u884c\u73af\u5883\uff1a Development\n\u2523 \u6267\u884c\u8017\u65f6\uff1a 31ms\n\u2523 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 \u6388\u6743\u4fe1\u606f \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 JWT Token\uff1a Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjEsIkFjY291bnQiOiJhZG1pbiIsImlhdCI6MTY1ODcxNjc5NywibmJmIjoxNjU4NzE2Nzk3LCJleHAiOjE2NTg3MTc5OTcsImlzcyI6ImRvdG5ldGNoaW5hIiwiYXVkIjoicG93ZXJieSBGdXJpb24ifQ.VYZkwwqCwlUy3aJjuL-og62I0rkxNQ96kSjEm3VgXtg\n\u2523\n\u2523 UserId (integer)\uff1a 1\n\u2523 Account (string)\uff1a admin\n\u2523 iat (integer)\uff1a 1658716797\n\u2523 nbf (integer)\uff1a 1658716797\n\u2523 exp (integer)\uff1a 1658717997\n\u2523 iss (string)\uff1a dotnetchina\n\u2523 aud (string)\uff1a powerby Furion\n\u2523 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 \u53c2\u6570\u5217\u8868 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 Content-Type\uff1a\n\u2523\n\u2523 id (Int32)\uff1a 11\n\u2523 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 \u8fd4\u56de\u4fe1\u606f \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 \u7c7b\u578b\uff1a Furion.Application.Persons.PersonDto\n\u2523 \u8fd4\u56de\u503c\uff1a {"Id":11,"Name":null,"Age":0,"Address":null,"PhoneNumber":null,"QQ":null,"CreatedTime":"0001-01-01T00:00:00+00:00","Childrens":null,"Posts":null}\n\u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Logging Monitor \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n')),(0,i.kt)("h3",{id:"1862-\u5168\u5c40\u914d\u7f6e"},"18.6.2 \u5168\u5c40\u914d\u7f6e"),(0,i.kt)("p",null,"\u5982\u9700\u5168\u5c40\u542f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"LoggingMonitor")," \u529f\u80fd\uff0c\u65e0\u9700\u5728\u6bcf\u4e2a\u63a7\u5236\u5668\u6216\u8005\u65b9\u6cd5\u4e2d\u8d34\uff0c\u5168\u5c40\u6ce8\u518c\u5982\u4e0b\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddMvcFilter();\n")),(0,i.kt)("admonition",{type:"tip"},(0,i.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Furion 4.0.2")," \u65b0\u63a8\u8350\u914d\u7f6e"),(0,i.kt)("p",{parentName:"admonition"},"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 4.0.2")," \u7248\u672c\u4e2d\u65b0\u589e\u4e86\u975e\u5e38\u7075\u6d3b\u65b9\u4fbf\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"services.AddMonitorLogging()")," \u670d\u52a1\u914d\u7f6e\uff0c\u53ef\u5728\u914d\u7f6e\u4e2d\u968f\u610f\u63a7\u5236\u54ea\u4e2a\u7c7b\u54ea\u4e2a\u65b9\u6cd5\u542f\u7528\u6216\u4e0d\u542f\u7528\u3002"),(0,i.kt)("ul",{parentName:"admonition"},(0,i.kt)("li",{parentName:"ul"},"\u6ce8\u518c\u670d\u52a1")),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddMonitorLogging(); // \u9ed8\u8ba4\u8bfb\u53d6 Logging:Monitor \u4e0b\u914d\u7f6e\uff0c\u652f\u6301\u4f20\u5165\u53c2\u6570\u81ea\u5b9a\u4e49\n")),(0,i.kt)("ul",{parentName:"admonition"},(0,i.kt)("li",{parentName:"ul"},"\u6dfb\u52a0\u914d\u7f6e")),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2,3,4-6}",showLineNumbers:!0,"{2,3,4-6}":!0},'{\n "Logging": {\n "Monitor": {\n "GlobalEnabled": false, // \u662f\u5426\u542f\u7528\u5168\u5c40\u62e6\u622a\uff0c\u9ed8\u8ba4 `false`\n "IncludeOfMethods": [], // \u662f\u5426\u6307\u5b9a\u62e6\u622a\u7279\u5b9a\u65b9\u6cd5\uff0c\u5f53 GlobalEnabled: false \u6709\u6548\n "ExcludeOfMethods": [], // \u662f\u5426\u6307\u5b9a\u6392\u9664\u7279\u5b9a\u65b9\u6cd5\uff0c\u5f53 GlobalEnabled: true \u6709\u6548\n "BahLogLevel": "Information", // \u914d\u7f6e Oops.Oh \u548c Oops.Bah \u4e1a\u52a1\u65e5\u5fd7\u8f93\u51fa\u7ea7\u522b\uff0c\u9ed8\u8ba4 Information\n "WithReturnValue": true, // \u914d\u7f6e\u662f\u5426\u5305\u542b\u8fd4\u56de\u503c\uff0c\u9ed8\u8ba4 `true`\uff0cFurion 4.3.9+ \u6709\u6548\n "ReturnValueThreshold": 0, // \u914d\u7f6e\u8fd4\u56de\u503c\u5b57\u7b26\u4e32\u9608\u503c\uff0c\u9ed8\u8ba4 0\uff0c\u5168\u91cf\u8f93\u51fa\uff0cFurion 4.3.9+ \u6709\u6548\n "MethodsSettings": [\n // \u914d\u7f6e\u88ab\u76d1\u89c6\u65b9\u6cd5\u66f4\u591a\u4fe1\u606f\uff0cFurion 4.3.9+ \u6709\u6548\n {\n "FullName": "Furion.Application.TestLoggerServices.MethodName", // \u65b9\u6cd5\u5b8c\u5168\u9650\u5b9a\u540d\n "WithReturnValue": true, // \u914d\u7f6e\u662f\u5426\u5305\u542b\u8fd4\u56de\u503c\uff0c\u9ed8\u8ba4 `true`\uff0cFurion 4.3.9+ \u6709\u6548\n "ReturnValueThreshold": 0 // \u914d\u7f6e\u8fd4\u56de\u503c\u5b57\u7b26\u4e32\u9608\u503c\uff0c\u9ed8\u8ba4 0\uff0c\u5168\u91cf\u8f93\u51fa\uff0cFurion 4.3.9+ \u6709\u6548\n }\n ]\n }\n }\n}\n')),(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"IncludeOfMethods")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"ExcludeOfMethods")," \u65b9\u6cd5\u7b7e\u540d\u683c\u5f0f\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"\u7c7b\u5b8c\u5168\u9650\u5b9a\u540d.\u65b9\u6cd5\u540d"),"\uff0c\u5982\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"Furion.Application.TestNamedServices.GetName"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion.Application.TestNamedServices")," \u662f\u7c7b\u540d\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"GetName")," \u662f\u65b9\u6cd5\u540d\u3002")),(0,i.kt)("p",null,"\u5982\u679c\u914d\u7f6e\u4e86\u5168\u5c40\u8bf7\u6c42\u76d1\u89c6\u65e5\u5fd7\uff0c\u5bf9\u4e2a\u522b\u4e0d\u9700\u8981\u76d1\u89c6\u7684\u63a5\u53e3\u65b9\u6cd5\u53ea\u9700\u8981\u8d34 ",(0,i.kt)("inlineCode",{parentName:"p"},"[SuppressMonitor]")," \u7279\u6027\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"1863-\u66f4\u591a\u914d\u7f6e"},"18.6.3 \u66f4\u591a\u914d\u7f6e"),(0,i.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 4.3.9 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,i.kt)("p",null,"\u652f\u6301 ",(0,i.kt)("inlineCode",{parentName:"p"},"LoggingMonitor")," \u5199\u5165\u65e5\u5fd7\u62e6\u622a\uff0c\u5982\u6dfb\u52a0\u989d\u5916\u6570\u636e\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,6}",showLineNumbers:!0,"{1,3,6}":!0},'services.AddMonitorLogging(options =>\n{\n options.ConfigureLogger((logger, logContext, context) =>\n {\n var httpContext = context.HttpContext;\n logContext.Set("extra", "\u5176\u4ed6\u6570\u636e");\n });\n});\n')),(0,i.kt)("p",null,"\u9664\u6b64\u4e4b\u5916\uff0c\u8fd8\u652f\u6301\u914d\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"json")," \u8def\u5f84\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'services.AddMonitorLogging(jsonKey: "YourKey:Monitor");\n')),(0,i.kt)("h2",{id:"187-\u6253\u5370\u65e5\u5fd7\u5230-swagger-\u4e2d"},"18.7 \u6253\u5370\u65e5\u5fd7\u5230 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Swagger")," \u4e2d"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u9ed8\u8ba4\u96c6\u6210\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"MiniProfiler")," \u7ec4\u4ef6\u5e76\u4e0e ",(0,i.kt)("inlineCode",{parentName:"p"},"Swagger")," \u8fdb\u884c\u4e86\u7ed3\u5408\uff0c\u5982\u9700\u6253\u5370\u65e5\u5fd7\u6216\u8c03\u8bd5\u4ee3\u7801\uff0c\u53ea\u9700\u8c03\u7528\u4ee5\u4e0b\u65b9\u6cd5\u5373\u53ef\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'App.PrintToMiniProfiler("\u5206\u7c7b", "\u72b6\u6001", "\u8981\u6253\u5370\u7684\u6d88\u606f");\n')),(0,i.kt)("h2",{id:"188-\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528"},"18.8 \u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528"),(0,i.kt)("p",null,"\u7531\u4e8e ",(0,i.kt)("inlineCode",{parentName:"p"},"DbContext")," \u9ed8\u8ba4\u6ce8\u518c\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"Scoped")," \u751f\u5b58\u5468\u671f\uff0c\u6240\u4ee5\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"IServiceScopeFactory")," \u83b7\u53d6\u6240\u6709\u670d\u52a1\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public class JobService : BackgroundService\n{\n // \u65e5\u5fd7\u5bf9\u8c61\n private readonly ILogger _logger;\n\n // \u670d\u52a1\u5de5\u5382\n private readonly IServiceScopeFactory _scopeFactory;\n public JobService(ILogger logger\n , IServiceScopeFactory scopeFactory)\n {\n _logger = logger;\n _scopeFactory = scopeFactory;\n }\n\n protected override Task ExecuteAsync(CancellationToken stoppingToken)\n {\n _logger.LogInformation("\u5199\u65e5\u5fd7~~");\n\n using (var scope = _scopeFactory.CreateScope())\n {\n var services = scope.ServiceProvider;\n\n // \u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n var dbContext = Db.GetDbContext(services);\n\n // \u83b7\u53d6\u4ed3\u50a8\n var respository = Db.GetRepository(services);\n\n // \u89e3\u6790\u5176\u4ed6\u670d\u52a1\n var otherService = services.GetService();\n }\n\n return Task.CompletedTask;\n }\n}\n')),(0,i.kt)("h2",{id:"189-\u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df"},"18.9 \u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u6240\u6709\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5b57\u7b26\u4e32")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5b9e\u4f53")," \u62d3\u5c55\u90fd\u6709\u81ea\u5df1\u72ec\u7acb\u7ef4\u62a4\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"ServiceProvider")," \u4f5c\u7528\u57df\u3002"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Web")," \u8bf7\u6c42\u4e2d\uff0c\u9ed8\u8ba4\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"HttpContext.RequestServices"),"\uff0c\u4f46\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u975e Web"),"\uff0c\u5982\u591a\u7ebf\u7a0b\u64cd\u4f5c\uff0c\u540e\u53f0\u4efb\u52a1\uff0c\u4e8b\u4ef6\u603b\u7ebf\u7b49\u573a\u666f\u4e0b\u4f1a\u81ea\u52a8\u521b\u5efa\u65b0\u7684\u4f5c\u7528\u57df\uff0c\u5b9e\u9645\u4e0a\u8fd9\u662f\u975e\u5e38\u4e0d\u5fc5\u8981\u7684\u5185\u5b58\u5f00\u9500\u3002"),(0,i.kt)("p",null,"\u8fd9\u65f6\uff0c\u6211\u4eec\u53ea\u9700\u8981\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},".SetXXXScoped(service)")," \u5171\u4eab\u5f53\u524d\u670d\u52a1\u63d0\u4f9b\u5668\u4f5c\u7528\u57df\u5373\u53ef\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'Scoped.Create(async (fac, scope) => {\n "\u5199\u65e5\u5fd7".SetLoggerScoped(scope.ServiceProvider).LogInformation();\n});\n')),(0,i.kt)("h2",{id:"1810-\u9759\u6001-default-\u65b9\u5f0f\u6784\u5efa"},"18.10 \u9759\u6001 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Default")," \u65b9\u5f0f\u6784\u5efa"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'StringLoggingPart.Default.SetMessage("\u8fd9\u662f\u4e00\u4e2a\u65e5\u5fd7").LogInformation();\n')),(0,i.kt)("h2",{id:"1811-\u89c4\u8303\u65e5\u5fd7\u6a21\u677f"},"18.11 \u89c4\u8303\u65e5\u5fd7\u6a21\u677f"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion v3.5.3+")," \u65b0\u589e\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"TP.Wrapper(...)")," \u89c4\u8303\u6a21\u677f\uff0c\u4f7f\u7528\u5982\u4e0b\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},'// \u751f\u6210\u6a21\u677f\u5b57\u7b26\u4e32\nvar template = TP.Wrapper("Furion \u6846\u67b6", "\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",\n "##\u4f5c\u8005## \u767e\u5c0f\u50e7",\n "##\u5f53\u524d\u7248\u672c## v3.5.3",\n "##\u6587\u6863\u5730\u5740## https://furion.icu",\n "##Copyright## \u767e\u5c0f\u50e7, Baiqian Co.,Ltd.");\n\nConsole.WriteLine(template);\n')),(0,i.kt)("p",null,"\u65e5\u5fd7\u6253\u5370\u6a21\u677f\u5982\u4e0b\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"\u250f\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Furion \u6846\u67b6 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 \u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002\n\u2523\n\u2523 \u4f5c\u8005\uff1a \u767e\u5c0f\u50e7\n\u2523 \u5f53\u524d\u7248\u672c\uff1a v3.5.3\n\u2523 \u6587\u6863\u5730\u5740\uff1a https://furion.icu\n\u2523 Copyright\uff1a \u767e\u5c0f\u50e7, Baiqian Co.,Ltd.\n\u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Furion \u6846\u67b6 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n")),(0,i.kt)("admonition",{title:"\u5173\u4e8e\u5c5e\u6027\u751f\u6210",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u5217\u8868\u9879\u4ee5 ",(0,i.kt)("inlineCode",{parentName:"p"},"##\u5c5e\u6027\u540d##")," \u5f00\u5934\uff0c\u81ea\u52a8\u751f\u6210 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5c5e\u6027\u540d\uff1a")," \u4f5c\u4e3a\u884c\u9996\u4e14\u81ea\u52a8\u7b49\u5bbd\u5bf9\u9f50\u3002"),(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"Furion 3.9.1")," \u4e4b\u524d\u7248\u672c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"[\u5c5e\u6027\u540d]")," \u5f00\u5934\u3002")),(0,i.kt)("h2",{id:"1812-\u65e5\u5fd7\u4e0a\u4e0b\u6587"},"18.12 \u65e5\u5fd7\u4e0a\u4e0b\u6587"),(0,i.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 4.1.3 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,i.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u5e0c\u671b\u4e3a\u65e5\u5fd7\u63d0\u4f9b\u989d\u5916\u6570\u636e\uff0c\u8fd9\u65f6\u5019\u53ef\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},".ScopeContext()")," \u914d\u7f6e\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6,12}",showLineNumbers:!0,"{2,6,12}":!0},'// \u5199\u6cd5\u4e00\n_logger.ScopeContext(ctx => ctx.Set("Name", "Furion").Set("UserId", 10))\n .LogInformation("\u6211\u662f\u4e00\u4e2a\u65e5\u5fd7 {id}", 20);\n\n// \u5199\u6cd5\u4e8c\n_logger.ScopeContext(new Dictionary {\n { "Name", "Furion" },\n { "UserId", 10 }\n}).LogInformation("\u6211\u662f\u4e00\u4e2a\u65e5\u5fd7 {id}", 20);\n\n// \u5199\u6cd5\u4e09\n_logger.ScopeContext(new LogContext {\n // ....\n}).LogInformation("\u6211\u662f\u4e00\u4e2a\u65e5\u5fd7 {id}", 20)\n')),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"LogMessage")," \u5bf9\u8c61\u4e2d\u4f7f\u7528\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,9,14,16}",showLineNumbers:!0,"{1,9,14,16}":!0},'var value = logMsg.Context.Get("Key");\n\n// \u6bd4\u5982\u5728\u8fc7\u6ee4\u4e2d\u4f7f\u7528\nservices.AddFileLogging("infomation.log", options =>\n{\n options.WriteFilter = (logMsg) =>\n {\n // \u8fd8\u53ef\u4ee5\u8bbe\u7f6e\u7ed9\u8fd0\u884c\u65f6\u4f7f\u7528\uff1alogMsg.Context.Set(...);\n return logMsg.Context.Get("Name") == "Furion";\n };\n});\n\n// \u5728 IDatabaseLoggingWriter \u4e2d\u4f7f\u7528\npublic void Write(LogMessage logMsg, bool flush)\n{\n var name = logMsg.Context.Get("Name");\n}\n')),(0,i.kt)("p",null,"\u8fd8\u53ef\u4ee5\u5b9e\u73b0\u5171\u4eab\u65e5\u5fd7\u4e0a\u4e0b\u6587\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,13,21}",showLineNumbers:!0,"{7,13,21}":!0},'private readonly ILogger _logger;\npublic TestAppService(ILogger logger)\n{\n _logger = logger;\n\n // \u6dfb\u52a0\u5168\u5c40\u7528\u6237\u4fe1\u606f\u4e0a\u4e0b\u6587\u6570\u636e\n _logger.ScopeContext(ctx => ctx.Set("uid", "100").Set("uname", "\u767e\u5c0f\u50e7"));\n}\n\npublic string GetName(int id)\n{\n // \u5171\u4eab\u5168\u5c40\u4e0a\u4e0b\u6587\u6570\u636e\n _logger.LogInformation("\u5199\u5165\u65b0\u7684\u65e5\u5fd7");\n\n return "Furion";\n}\n\npublic string GetTags(int id)\n{\n // \u989d\u5916\u65b0\u589e\u4e0a\u4e0b\u6587\u6570\u636e\n _logger.ScopeContext(ctx => ctx.Set("key", "value")).LogInformation("\u8bbe\u7f6e\u989d\u5916\u7684\u4e0a\u4e0a\u4e0b\u6587\u65e5\u5fd7");\n\n return "\u767e\u5c0f\u50e7";\n}\n')),(0,i.kt)("h2",{id:"1813-\u53cd\u9988\u4e0e\u5efa\u8bae"},"18.13 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,i.kt)("hr",null),(0,i.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"p"},"\u65e5\u5fd7")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/logging/?view=aspnetcore-5.0"},"ASP.NET Core - \u65e5\u5fd7")," \u7ae0\u8282 \u548c ",(0,i.kt)("a",{parentName:"p",href:"https://serilog.net/"},"Serilog")," \u6587\u6863\u3002")))}d.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return p},kt:function(){return d}});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function a(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var g=r.createContext({}),s=function(e){var n=r.useContext(g),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},p=function(e){var n=s(e.components);return r.createElement(g.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},u=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,g=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=s(t),d=o,c=u["".concat(g,".").concat(d)]||u[d]||m[d]||i;return t?r.createElement(c,a(a({ref:n},p),{},{components:t})):r.createElement(c,a({ref:n},p))}));function d(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=u;var l={};for(var g in n)hasOwnProperty.call(n,g)&&(l[g]=n[g]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var s=2;s=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var g=r.createContext({}),s=function(e){var n=r.useContext(g),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},p=function(e){var n=s(e.components);return r.createElement(g.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},u=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,g=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=s(t),d=o,c=u["".concat(g,".").concat(d)]||u[d]||m[d]||i;return t?r.createElement(c,a(a({ref:n},p),{},{components:t})):r.createElement(c,a({ref:n},p))}));function d(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=u;var l={};for(var g in n)hasOwnProperty.call(n,g)&&(l[g]=n[g]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var s=2;sILogger<T> \u6cdb\u578b\u65b9\u5f0f",id:"1841-iloggert-\u6cdb\u578b\u65b9\u5f0f",level:3},{value:"18.4.2 ILoggerFactory \u5de5\u5382\u65b9\u5f0f",id:"1842-iloggerfactory-\u5de5\u5382\u65b9\u5f0f",level:3},{value:"18.4.3 Log \u9759\u6001\u7c7b\u65b9\u5f0f",id:"1843-log-\u9759\u6001\u7c7b\u65b9\u5f0f",level:3},{value:"18.4.4 \u61d2\u4eba\u6a21\u5f0f \ud83d\ude01",id:"1844-\u61d2\u4eba\u6a21\u5f0f-",level:3},{value:"18.5 \u914d\u7f6e\u65e5\u5fd7\u8f93\u51fa\u4ecb\u8d28",id:"185-\u914d\u7f6e\u65e5\u5fd7\u8f93\u51fa\u4ecb\u8d28",level:2},{value:"18.5.1 \u8f93\u51fa\u5230\u63a7\u5236\u53f0",id:"1851-\u8f93\u51fa\u5230\u63a7\u5236\u53f0",level:3},{value:"18.5.2 \u8f93\u51fa\u5230\u6587\u4ef6",id:"1852-\u8f93\u51fa\u5230\u6587\u4ef6",level:3},{value:"18.5.3 \u8f93\u51fa\u5230\u6570\u636e\u5e93/\u5176\u4ed6\u5b58\u50a8\u4ecb\u8d28",id:"1853-\u8f93\u51fa\u5230\u6570\u636e\u5e93\u5176\u4ed6\u5b58\u50a8\u4ecb\u8d28",level:3},{value:"18.5.4 ILoggerFactory \u65b9\u5f0f",id:"1854-iloggerfactory-\u65b9\u5f0f",level:3},{value:"18.5.5 ILoggingBuilder \u65b9\u5f0f",id:"1855-iloggingbuilder-\u65b9\u5f0f",level:3},{value:"18.5.6 \u8bb0\u5f55\u8bf7\u6c42\u65e5\u5fd7",id:"1856-\u8bb0\u5f55\u8bf7\u6c42\u65e5\u5fd7",level:3},{value:"18.5.7 Debug \u548c Trace \u9ed8\u8ba4\u4e0d\u8f93\u51fa\u95ee\u9898",id:"1857-debug-\u548c-trace-\u9ed8\u8ba4\u4e0d\u8f93\u51fa\u95ee\u9898",level:3},{value:"18.6 [LoggingMonitor] \u76d1\u542c\u65e5\u5fd7",id:"186-loggingmonitor-\u76d1\u542c\u65e5\u5fd7",level:2},{value:"18.6.1 \u7279\u6027\u914d\u7f6e",id:"1861-\u7279\u6027\u914d\u7f6e",level:3},{value:"18.6.2 \u5168\u5c40\u914d\u7f6e",id:"1862-\u5168\u5c40\u914d\u7f6e",level:3},{value:"18.6.3 \u66f4\u591a\u914d\u7f6e",id:"1863-\u66f4\u591a\u914d\u7f6e",level:3},{value:"18.7 \u6253\u5370\u65e5\u5fd7\u5230 Swagger \u4e2d",id:"187-\u6253\u5370\u65e5\u5fd7\u5230-swagger-\u4e2d",level:2},{value:"18.8 \u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528",id:"188-\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528",level:2},{value:"18.9 \u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df",id:"189-\u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df",level:2},{value:"18.10 \u9759\u6001 Default \u65b9\u5f0f\u6784\u5efa",id:"1810-\u9759\u6001-default-\u65b9\u5f0f\u6784\u5efa",level:2},{value:"18.11 \u89c4\u8303\u65e5\u5fd7\u6a21\u677f",id:"1811-\u89c4\u8303\u65e5\u5fd7\u6a21\u677f",level:2},{value:"18.12 \u65e5\u5fd7\u4e0a\u4e0b\u6587",id:"1812-\u65e5\u5fd7\u4e0a\u4e0b\u6587",level:2},{value:"18.13 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"1813-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],u={toc:m};function d(e){var n=e.components,t=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"181-\u5173\u4e8e\u65e5\u5fd7"},"18.1 \u5173\u4e8e\u65e5\u5fd7"),(0,i.kt)("p",null,"\u901a\u5e38\u65e5\u5fd7\u6307\u7684\u662f",(0,i.kt)("strong",{parentName:"p"},"\u7cfb\u7edf\u65e5\u5fd7"),"\u548c",(0,i.kt)("strong",{parentName:"p"},"\u7a0b\u5e8f\u65e5\u5fd7"),"\u3002"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u7cfb\u7edf\u65e5\u5fd7")," \u662f\u8bb0\u5f55\u7cfb\u7edf\u4e2d\u786c\u4ef6\u3001\u8f6f\u4ef6\u548c\u7cfb\u7edf\u95ee\u9898\u7684\u4fe1\u606f\uff0c\u540c\u65f6\u8fd8\u53ef\u4ee5\u76d1\u89c6\u7cfb\u7edf\u4e2d\u53d1\u751f\u7684\u4e8b\u4ef6\u3002\u7528\u6237\u53ef\u4ee5\u901a\u8fc7\u5b83\u6765\u68c0\u67e5\u9519\u8bef\u53d1\u751f\u7684\u539f\u56e0\uff0c\u6216\u8005\u5bfb\u627e\u53d7\u5230\u653b\u51fb\u65f6\u653b\u51fb\u8005\u7559\u4e0b\u7684\u75d5\u8ff9\u3002\u7cfb\u7edf\u65e5\u5fd7\u5305\u62ec\u7cfb\u7edf\u65e5\u5fd7\u3001\u5e94\u7528\u7a0b\u5e8f\u65e5\u5fd7\u548c\u5b89\u5168\u65e5\u5fd7\u3002"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"\u7a0b\u5e8f\u65e5\u5fd7")," \u662f\u7a0b\u5e8f\u8fd0\u884c\u4e2d\u4ea7\u751f\u7684\u65e5\u5fd7\uff0c\u901a\u5e38\u7531\u6846\u67b6\u8fd0\u884c\u65f6\u6216\u5f00\u53d1\u8005\u63d0\u4f9b\u7684\u65e5\u5fd7\u3002\u5305\u62ec\u8bf7\u6c42\u65e5\u5fd7\uff0c\u5f02\u5e38\u65e5\u5fd7\u3001\u5ba1\u8ba1\u65e5\u5fd7\u3001\u884c\u4e3a\u65e5\u5fd7\u7b49\u3002"),(0,i.kt)("h2",{id:"182-\u65e5\u5fd7\u4f5c\u7528"},"18.2 \u65e5\u5fd7\u4f5c\u7528"),(0,i.kt)("p",null,"\u5728\u9879\u76ee\u5f00\u53d1\u4e2d\uff0c\u90fd\u4e0d\u53ef\u907f\u514d\u7684\u4f7f\u7528\u5230\u65e5\u5fd7\u3002\u6ca1\u6709\u65e5\u5fd7\u867d\u7136\u4e0d\u4f1a\u5f71\u54cd\u9879\u76ee\u7684\u6b63\u786e\u8fd0\u884c\uff0c\u4f46\u662f\u6ca1\u6709\u65e5\u5fd7\u7684\u9879\u76ee\u53ef\u4ee5\u8bf4\u662f\u4e0d\u5b8c\u6574\u7684\u3002\u65e5\u5fd7\u5728\u8c03\u8bd5\uff0c\u9519\u8bef\u6216\u8005\u5f02\u5e38\u5b9a\u4f4d\uff0c\u6570\u636e\u5206\u6790\u4e2d\u7684\u4f5c\u7528\u662f\u4e0d\u8a00\u800c\u55bb\u7684\u3002"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u8c03\u8bd5")),(0,i.kt)("p",null,"\u5728\u9879\u76ee\u8c03\u8bd5\u65f6\uff0c\u67e5\u770b\u6808\u4fe1\u606f\u53ef\u4ee5\u65b9\u4fbf\u5730\u77e5\u9053\u5f53\u524d\u7a0b\u5e8f\u7684\u8fd0\u884c\u72b6\u6001\uff0c\u8f93\u51fa\u7684\u65e5\u5fd7\u4fbf\u4e8e\u8bb0\u5f55\u7a0b\u5e8f\u5728\u4e4b\u524d\u7684\u8fd0\u884c\u7ed3\u679c\u3002"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u9519\u8bef\u5b9a\u4f4d")),(0,i.kt)("p",null,"\u4e0d\u8981\u4ee5\u4e3a\u9879\u76ee\u80fd\u6b63\u786e\u8dd1\u8d77\u6765\u5c31\u53ef\u4ee5\u9ad8\u6795\u65e0\u5fe7\uff0c\u9879\u76ee\u5728\u8fd0\u884c\u4e00\u6bb5\u65f6\u5019\u540e\uff0c\u53ef\u80fd\u7531\u4e8e\u6570\u636e\u95ee\u9898\uff0c\u7f51\u7edc\u95ee\u9898\uff0c\u5185\u5b58\u95ee\u9898\u7b49\u51fa\u73b0\u5f02\u5e38\u3002\u8fd9\u65f6\u65e5\u5fd7\u53ef\u4ee5\u5e2e\u52a9\u5f00\u53d1\u6216\u8005\u8fd0\u7ef4\u4eba\u5458\u5feb\u901f\u5b9a\u4f4d\u9519\u8bef\u4f4d\u7f6e\uff0c\u63d0\u51fa\u89e3\u51b3\u65b9\u6848\u3002"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u6570\u636e\u5206\u6790")),(0,i.kt)("p",null,"\u5927\u6570\u636e\u7684\u5174\u8d77\uff0c\u4f7f\u5f97\u5927\u91cf\u7684\u65e5\u5fd7\u5206\u6790\u6210\u4e3a\u53ef\u80fd\uff0cELK \u4e5f\u8ba9\u65e5\u5fd7\u5206\u6790\u95e8\u69db\u964d\u4f4e\u4e86\u5f88\u591a\u3002\u65e5\u5fd7\u4e2d\u8574\u542b\u4e86\u5927\u91cf\u7684\u7528\u6237\u6570\u636e\uff0c\u5305\u62ec\u70b9\u51fb\u884c\u4e3a\uff0c\u5174\u8da3\u504f\u597d\u7b49\uff0c\u7528\u6237\u753b\u50cf\u5bf9\u4e8e\u516c\u53f8\u4e0b\u4e00\u6b65\u7684\u6218\u7565\u65b9\u5411\u6709\u4e00\u5b9a\u6307\u5f15\u4f5c\u7528\u3002"),(0,i.kt)("h2",{id:"183-\u65e5\u5fd7\u7ea7\u522b"},"18.3 \u65e5\u5fd7\u7ea7\u522b"),(0,i.kt)("p",null,"\u65e5\u5fd7\u7ea7\u522b\u53ef\u4ee5\u6709\u6548\u7684\u5bf9\u65e5\u5fd7\u4fe1\u606f\u8fdb\u884c\u5f52\u7c7b\uff0c\u65b9\u4fbf\u51c6\u786e\u7684\u67e5\u770b\u7279\u5b9a\u65e5\u5fd7\u5185\u5bb9\u3002\u901a\u5e38\u65e5\u5fd7\u7c7b\u522b\u6709\u4ee5\u4e0b\u7ea7\u522b\uff1a"),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:"center"},"\u7ea7\u522b"),(0,i.kt)("th",{parentName:"tr",align:null},"\u503c"),(0,i.kt)("th",{parentName:"tr",align:"center"},"\u65b9\u6cd5"),(0,i.kt)("th",{parentName:"tr",align:null},"\u63cf\u8ff0"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},"Trace\uff08\u8ddf\u8e2a\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},"0"),(0,i.kt)("td",{parentName:"tr",align:"center"},"LogTrace"),(0,i.kt)("td",{parentName:"tr",align:null},"\u5305\u542b\u6700\u8be6\u7ec6\u7684\u6d88\u606f\u3002 \u8fd9\u4e9b\u6d88\u606f\u53ef\u80fd\u5305\u542b\u654f\u611f\u7684\u5e94\u7528\u6570\u636e\u3002 \u8fd9\u4e9b\u6d88\u606f\u9ed8\u8ba4\u60c5\u51b5\u4e0b\u5904\u4e8e\u7981\u7528\u72b6\u6001\uff0c\u5e76\u4e14\u4e0d\u5e94\u5728\u751f\u4ea7\u4e2d\u542f\u7528\u3002")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},"Debug\uff08\u8c03\u8bd5\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},"1"),(0,i.kt)("td",{parentName:"tr",align:"center"},"LogDebug"),(0,i.kt)("td",{parentName:"tr",align:null},"\u7528\u4e8e\u8c03\u8bd5\u548c\u5f00\u53d1\u3002 \u7531\u4e8e\u91cf\u5927\uff0c\u8bf7\u5728\u751f\u4ea7\u4e2d\u5c0f\u5fc3\u4f7f\u7528\u3002")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},"Information\uff08\u4fe1\u606f\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},"2"),(0,i.kt)("td",{parentName:"tr",align:"center"},"LogInformation"),(0,i.kt)("td",{parentName:"tr",align:null},"\u8ddf\u8e2a\u5e94\u7528\u7684\u5e38\u89c4\u6d41\u3002 \u53ef\u80fd\u5177\u6709\u957f\u671f\u503c\u3002")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},"Warning\uff08\u8b66\u544a\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},"3"),(0,i.kt)("td",{parentName:"tr",align:"center"},"LogWarning"),(0,i.kt)("td",{parentName:"tr",align:null},"\u5bf9\u4e8e\u5f02\u5e38\u4e8b\u4ef6\u6216\u610f\u5916\u4e8b\u4ef6\u3002 \u901a\u5e38\u5305\u62ec\u4e0d\u4f1a\u5bfc\u81f4\u5e94\u7528\u5931\u8d25\u7684\u9519\u8bef\u6216\u60c5\u51b5\u3002")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},"Error\uff08\u9519\u8bef\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},"4"),(0,i.kt)("td",{parentName:"tr",align:"center"},"LogError"),(0,i.kt)("td",{parentName:"tr",align:null},"\u8868\u793a\u65e0\u6cd5\u5904\u7406\u7684\u9519\u8bef\u548c\u5f02\u5e38\u3002 \u8fd9\u4e9b\u6d88\u606f\u8868\u793a\u5f53\u524d\u64cd\u4f5c\u6216\u8bf7\u6c42\u5931\u8d25\uff0c\u800c\u4e0d\u662f\u6574\u4e2a\u5e94\u7528\u5931\u8d25\u3002")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:"center"},"Critical\uff08\u4e25\u91cd\uff09"),(0,i.kt)("td",{parentName:"tr",align:null},"5"),(0,i.kt)("td",{parentName:"tr",align:"center"},"LogCritical"),(0,i.kt)("td",{parentName:"tr",align:null},"\u9700\u8981\u7acb\u5373\u5173\u6ce8\u7684\u5931\u8d25\u3002 \u4f8b\u5982\u6570\u636e\u4e22\u5931\u3001\u78c1\u76d8\u7a7a\u95f4\u4e0d\u8db3\u3002")))),(0,i.kt)("h2",{id:"184-\u5982\u4f55\u4f7f\u7528"},"18.4 \u5982\u4f55\u4f7f\u7528"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 5")," \u6846\u67b6\u4e2d\uff0c\u5fae\u8f6f\u5df2\u7ecf\u4e3a\u6211\u4eec\u5185\u7f6e\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u65e5\u5fd7\u7ec4\u4ef6"),"\uff0c\u6b63\u5e38\u60c5\u51b5\u4e0b\uff0c\u65e0\u9700\u6211\u4eec\u5f15\u7528\u7b2c\u4e09\u65b9\u5305\u8fdb\u884c\u65e5\u5fd7\u8bb0\u5f55\u3002",(0,i.kt)("inlineCode",{parentName:"p"},".NET 5")," \u6846\u67b6\u4e3a\u6211\u4eec\u63d0\u4f9b\u4e86\u4e24\u79cd\u65e5\u5fd7\u5bf9\u8c61\u521b\u5efa\u65b9\u5f0f\u3002"),(0,i.kt)("h3",{id:"1841-iloggert-\u6cdb\u578b\u65b9\u5f0f"},"18.4.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ILogger")," \u6cdb\u578b\u65b9\u5f0f"),(0,i.kt)("p",null,"\u4f7f\u7528\u975e\u5e38\u7b80\u5355\uff0c\u53ef\u4ee5\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"ILogger")," \u5bf9\u8c61\u8fdb\u884c\u6ce8\u5165\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},'public class PrivacyModel : PageModel\n{\n private readonly ILogger _logger;\n\n public PrivacyModel(ILogger logger)\n {\n _logger = logger;\n }\n\n public void OnGet()\n {\n _logger.LogInformation("GET Pages.PrivacyModel called.");\n }\n}\n')),(0,i.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u901a\u8fc7\u6cdb\u578b ",(0,i.kt)("inlineCode",{parentName:"p"},"ILogger")," \u65b9\u5f0f\u5199\u5165\u65e5\u5fd7\uff0c\u90a3\u4e48\u9ed8\u8ba4\u5c06 ",(0,i.kt)("inlineCode",{parentName:"p"},"T")," \u7c7b\u578b\u5b8c\u6574\u7c7b\u578b\u540d\u79f0\u4f5c\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"\u65e5\u5fd7\u7c7b\u522b"),"\u3002")),(0,i.kt)("h3",{id:"1842-iloggerfactory-\u5de5\u5382\u65b9\u5f0f"},"18.4.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ILoggerFactory")," \u5de5\u5382\u65b9\u5f0f"),(0,i.kt)("p",null,"\u4f7f\u7528\u5de5\u5382\u65b9\u5f0f\uff0c\u9700\u624b\u52a8\u4f20\u5165 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u65e5\u5fd7\u7c7b\u522b"),"\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,7}",showLineNumbers:!0,"":!0,"{5,7}":!0},'public class ContactModel : PageModel\n{\n private readonly ILogger _logger;\n\n public ContactModel(ILoggerFactory logger)\n {\n _logger = logger.CreateLogger("MyCategory");\n }\n\n public void OnGet()\n {\n _logger.LogInformation("GET Pages.ContactModel called.");\n }\n}\n')),(0,i.kt)("h3",{id:"1843-log-\u9759\u6001\u7c7b\u65b9\u5f0f"},"18.4.3 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Log")," \u9759\u6001\u7c7b\u65b9\u5f0f"),(0,i.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 4.2.1 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,10-15}",showLineNumbers:!0,"{2,5,10-15}":!0},'// \u521b\u5efa\u65e5\u5fd7\u5bf9\u8c61\nvar logger = Log.CreateLogger("\u65e5\u5fd7\u540d\u79f0");\n\n// \u521b\u5efa\u65e5\u5fd7\u5de5\u5382\nusing var loggerFactory = Log.CreateLoggerFactory(builder => {\n // ....\n});\n\n// \u65e5\u5fd7\u8bb0\u5f55\nLog.Information("Information");\nLog.Warning("Warning");\nLog.Error("Error");\nLog.Debug("Debug");\nLog.Trace("Trace");\nLog.Critical("Critical");\n')),(0,i.kt)("h3",{id:"1844-\u61d2\u4eba\u6a21\u5f0f-"},"18.4.4 ",(0,i.kt)("inlineCode",{parentName:"h3"},"\u61d2\u4eba\u6a21\u5f0f")," \ud83d\ude01"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u63d0\u4f9b\u4e86\u66f4\u61d2\u7684\u65b9\u5f0f\u5199\u5165\u65e5\u5fd7\uff0c\u4e5f\u5c31\u662f\u901a\u8fc7\u5b57\u7b26\u4e32\u62d3\u5c55\u7684\u65b9\u5f0f\u5199\u5165\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'"\u7b80\u5355\u65e5\u5fd7".LogInformation();\n\n"\u767e\u5c0f\u50e7 \u65b0\u589e\u4e86\u4e00\u6761\u8bb0\u5f55".LogInformation();\n\n"\u7a0b\u5e8f\u51fa\u73b0\u5f02\u5e38\u5566".LogError();\n\n"\u8fd9\u662f\u81ea\u5b9a\u4e49\u7c7b\u522b\u65e5\u5fd7".SetCategory("\u7c7b\u522b").LogInformation();\n')),(0,i.kt)("p",null,"\u901a\u8fc7\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u5f0f\u53ef\u4ee5\u5728\u4efb\u4f55\u65f6\u5019\u65b9\u4fbf\u8bb0\u5f55\u65e5\u5fd7\uff0c\u4e13\u95e8\u4e3a\u61d2\u4eba\u63d0\u4f9b\u7684\u3002"),(0,i.kt)("h2",{id:"185-\u914d\u7f6e\u65e5\u5fd7\u8f93\u51fa\u4ecb\u8d28"},"18.5 \u914d\u7f6e\u65e5\u5fd7\u8f93\u51fa\u4ecb\u8d28"),(0,i.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5c0f\u8282\u4ec5\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 3.9.0+")," \u7248\u672c\u63d0\u4f9b\u3002")),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u7a0b\u5e8f\u4e2d\uff0c\u4e3b\u673a\u542f\u52a8\u65f6\u9ed8\u8ba4\u6ce8\u518c\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"ConsoleLoggerProvider")," \u63d0\u4f9b\u5668\uff0c\u4e5f\u5c31\u662f\u63a7\u5236\u53f0\u65e5\u5fd7\u8f93\u51fa\u63d0\u4f9b\u5668\uff0c\u6240\u4ee5\u65e0\u9700\u4efb\u4f55\u6ce8\u518c\u670d\u52a1\u5373\u53ef\u5728\u63a7\u5236\u53f0\u8f93\u51fa\u3002"),(0,i.kt)("h3",{id:"1851-\u8f93\u51fa\u5230\u63a7\u5236\u53f0"},"18.5.1 \u8f93\u51fa\u5230\u63a7\u5236\u53f0"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"info: Furion.EventBus.EventBusHostedService[0]\n EventBus Hosted Service is running.\ninfo: Microsoft.Hosting.Lifetime[14]\n Now listening on: https://localhost:5001\ninfo: Microsoft.Hosting.Lifetime[14]\n Now listening on: http://localhost:5000\ninfo: Microsoft.Hosting.Lifetime[0]\n Application started. Press Ctrl+C to shut down.\ninfo: Microsoft.Hosting.Lifetime[0]\n Hosting environment: Development\ninfo: Microsoft.Hosting.Lifetime[0]\n Content root path: C:\\Workplaces\\Furion\\samples\\Furion.Web.Entry\\\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u63a7\u5236\u53f0\u8f93\u51fa\u8fc7\u6ee4"))),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},".NET5")," \u7248\u672c\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,2,4}",showLineNumbers:!0,"{1,2,4}":!0},"Host.CreateDefaultBuilder(args)\n .ConfigureLogging(logging =>\n {\n logging.AddFilter((provider, category, logLevel) =>\n {\n // .....\n });\n })\n")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},".NET6+")," \u7248\u672c\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3}",showLineNumbers:!0,"{1,3}":!0},"var builder = WebApplication.CreateBuilder(args);\n\nbuilder.Logging.AddFilter((provider, category, logLevel) =>\n{\n // .....\n});\n")),(0,i.kt)("p",null,"\u5982\u9700\u5176\u4ed6\u914d\u7f6e\u53ef\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u914d\u7f6e\u5373\u53ef\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-12}",showLineNumbers:!0,"{2-12}":!0},'{\n "Logging": {\n "Console": {\n "IncludeScopes": true,\n "LogLevel": {\n "Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",\n "Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",\n "Microsoft.AspNetCore.Mvc.Razor": "Error",\n "Default": "Information"\n }\n }\n }\n}\n')),(0,i.kt)("p",null,"\u5982\u9700\u81ea\u5b9a\u4e49\u63a7\u5236\u53f0\u65e5\u5fd7\u6a21\u677f\u53ef\u67e5\u770b\u5fae\u8f6f\u5b98\u65b9\u6587\u6863 ",(0,i.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/dotnet/core/extensions/console-log-formatter#implement-a-custom-formatter"},"https://docs.microsoft.com/zh-cn/dotnet/core/extensions/console-log-formatter#implement-a-custom-formatter")),(0,i.kt)("p",null,"\u8fd9\u91cc\u4e5f\u63d0\u4f9b\u76f8\u5173 ",(0,i.kt)("inlineCode",{parentName:"p"},"Issue")," \u53c2\u8003\uff1a",(0,i.kt)("strong",{parentName:"p"},(0,i.kt)("a",{parentName:"strong",href:"https://gitee.com/dotnetchina/Furion/issues/I5JJJH"},"#I5JJJH"))),(0,i.kt)("h3",{id:"1852-\u8f93\u51fa\u5230\u6587\u4ef6"},"18.5.2 \u8f93\u51fa\u5230\u6587\u4ef6"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u57fa\u7840\u4f7f\u7528"))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,8}",showLineNumbers:!0,"{2,5,8}":!0},'// \u4f8b\u5b50\u4e00\uff1a\u542f\u52a8\u5c42\u6839\u76ee\u5f55\u8f93\u51fa\nservices.AddFileLogging("application.log");\n\n// \u4f8b\u5b50\u4e8c\uff1a\u652f\u6301\u8def\u5f84\nservices.AddFileLogging("logs/application.log");\n\n// \u4f8b\u5b50\u4e09\uff1a\u652f\u6301\u65e5\u5fd7\u8ffd\u52a0\u8fd8\u662f\u8986\u76d6\uff0c\u8bbe\u7f6e true \u4e3a\u8ffd\u52a0\uff0cfalse \u4e3a\u8986\u76d6\nservices.AddFileLogging("application.log", true);\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u4ece\u914d\u7f6e\u6587\u4ef6\u8bfb\u53d6\u914d\u7f6e"))),(0,i.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("strong",{parentName:"p"},"\u53ea\u6709\u4e0d\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},".AddFile")," \u7b2c\u4e00\u4e2a\u53c2\u6570\u914d\u7f6e\u6587\u4ef6\u540d\u624d\u4f1a\u81ea\u52a8\u52a0\u8f7d\u914d\u7f6e\uff0c\u4e5f\u5c31\u662f\u6587\u4ef6\u540d\u5e94\u8be5\u914d\u7f6e\u5728\u914d\u7f6e\u6587\u4ef6\u4e2d\u3002"))),(0,i.kt)("p",null,"\u6587\u4ef6\u65e5\u5fd7\u914d\u7f6e\u8bf4\u660e\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2,7-13,16-22}",showLineNumbers:!0,"{2,7-13,16-22}":!0},'{\n "Logging": {\n "LogLevel": {\n "Default": "Information"\n // .... appsettings \u9ed8\u8ba4\u914d\u7f6e\n },\n "File": {\n "FileName": "application.log", // \u65e5\u5fd7\u6587\u4ef6\u5b8c\u6574\u8def\u5f84\u6216\u6587\u4ef6\u540d\uff0c\u63a8\u8350 .log \u4f5c\u4e3a\u62d3\u5c55\u540d\n "Append": true, // \u8ffd\u52a0\u5230\u5df2\u5b58\u5728\u65e5\u5fd7\u6587\u4ef6\u6216\u8986\u76d6\u5b83\u4eec\n "MinimumLevel": "Information", // \u6700\u4f4e\u65e5\u5fd7\u8bb0\u5f55\u7ea7\u522b\n "FileSizeLimitBytes": 0, // \u63a7\u5236\u6bcf\u4e00\u4e2a\u65e5\u5fd7\u6587\u4ef6\u6700\u5927\u5b58\u50a8\u5927\u5c0f\uff0c\u9ed8\u8ba4\u65e0\u9650\u5236\uff0c\u5982\u679c\u6307\u5b9a\u4e86\u8be5\u503c\uff0c\u90a3\u4e48\u65e5\u5fd7\u6587\u4ef6\u5927\u5c0f\u8d85\u51fa\u4e86\u8be5\u914d\u7f6e\u5c31\u4f1a\u521b\u5efa\u65b0\u7684\u65e5\u5fd7\u6587\u4ef6\uff0c\u65b0\u521b\u5efa\u7684\u65e5\u5fd7\u6587\u4ef6\u547d\u540d\u89c4\u5219\uff1a\u6587\u4ef6\u540d+[\u9012\u589e\u5e8f\u53f7].log\n "MaxRollingFiles": 0 // \u63a7\u5236\u6700\u5927\u521b\u5efa\u7684\u65e5\u5fd7\u6587\u4ef6\u6570\u91cf\uff0c\u9ed8\u8ba4\u65e0\u9650\u5236\uff0c\u914d\u5408 FileSizeLimitBytes \u4f7f\u7528\uff0c\u5982\u679c\u6307\u5b9a\u4e86\u8be5\u503c\uff0c\u90a3\u4e48\u8d85\u51fa\u8be5\u503c\u5c06\u4ece\u6700\u521d\u65e5\u5fd7\u6587\u4ef6\u4e2d\u4ece\u5934\u5199\u5165\u8986\u76d6\n }\n },\n // \u81ea\u5b9a\u4e49\u914d\u7f6e\u8282\u70b9\n "MyLogger": {\n "FileName": "application.log",\n "Append": true,\n "MinimumLevel": "Information",\n "FileSizeLimitBytes": 0,\n "MaxRollingFiles": 0\n }\n}\n')),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,13,16}",showLineNumbers:!0,"{2,5,13,16}":!0},'// \u4f8b\u5b50\u4e00\uff1a\u9ed8\u8ba4\u8bfb\u53d6 Logging:File \u8282\u70b9\nservices.AddFileLogging();\n\n// \u4f8b\u5b50\u4e8c\uff1a\u9ed8\u8ba4\u8bfb\u53d6 Logging:File \u8282\u70b9\uff0c\u652f\u6301\u66f4\u591a\u914d\u7f6e\nservices.AddFileLogging(options =>\n{\n options.MinimumLevel = LogLevel.Warning;\n\n // \u5176\u4ed6\u914d\u7f6e...\n});\n\n// \u4f8b\u5b50\u4e09\uff1a\u81ea\u5b9a\u4e49\u914d\u7f6e\u8282\u70b9\nservices.AddFileLogging(() => "MyLogger");\n\n// \u4f8b\u5b50\u56db\uff1a\u81ea\u5b9a\u4e49\u914d\u7f6e\u8282\u70b9\uff0c\u652f\u6301\u66f4\u591a\u914d\u7f6e\nservices.AddFileLogging(() => "MyLogger", options =>\n{\n options.MinimumLevel = LogLevel.Warning;\n\n // \u5176\u4ed6\u914d\u7f6e...\n});\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u81ea\u5b9a\u4e49\u65e5\u5fd7\u6587\u4ef6\u540d\u89c4\u5219"))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,14,23}",showLineNumbers:!0,"{2,5,14,23}":!0},'// \u4f8b\u5b50\u4e00\uff1a\u652f\u6301\u7cfb\u7edf\u73af\u5883\u53d8\u91cf\uff0c\u5982%SystemDrive%\uff0c%SystemRoot%\nservices.AddFileLogging("application%SystemDrive%-%SystemRoot%.log");\n\n// \u4f8b\u5b50\u4e8c\uff1a\u6bcf\u5929\u521b\u5efa\u4e00\u4e2a\u65e5\u5fd7\u6587\u4ef6\nservices.AddFileLogging("application-{0:yyyy}-{0:MM}-{0:dd}.log", options =>\n{\n options.FileNameRule = fileName =>\n {\n return string.Format(fileName, DateTime.UtcNow);\n };\n});\n\n// \u4f8b\u5b50\u4e09\uff0c\u4efb\u4f55\u81ea\u5df1\u559c\u6b22\u7684\u547d\u540d\u89c4\u5219\nservices.AddFileLogging("application-{0:yyyy}-{0:MM}-{0:dd}.log", options =>\n{\n options.FileNameRule = fileName =>\n {\n // your rule...\n };\n});\n\n// \u4f8b\u5b50\u56db\uff0c\u6279\u91cf\u8bbe\u7f6e\u591a\u4e2a\nArray.ForEach(new[] { LogLevel.Information, LogLevel.Warning, LogLevel.Error }, logLevel =>\n{\n services.AddFileLogging("application-{1}-{0:yyyy}-{0:MM}-{0:dd}.log", options =>\n {\n options.FileNameRule = fileName => string.Format(fileName, DateTime.UtcNow, logLevel.ToString());\n options.WriteFilter = logMsg => logMsg.LogLevel == logLevel;\n });\n});\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u65e5\u5fd7\u8fc7\u6ee4\u5668/\u7b5b\u9009\u5668"))),(0,i.kt)("p",null,"\u901a\u8fc7\u65e5\u5fd7\u7b5b\u9009\u5668\u53ef\u4ee5\u5bf9\u65e5\u5fd7\u8fdb\u884c\u5f52\u7c7b\u5199\u5165"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,10,19}",showLineNumbers:!0,"{2,10,19}":!0},'// \u4f8b\u5b50\u4e00\uff1a\u6839\u636e\u65e5\u5fd7\u7ea7\u522b\u8f93\u51fa\nservices.AddFileLogging("infomation.log", options =>\n{\n options.WriteFilter = (logMsg) =>\n {\n return logMsg.LogLevel == LogLevel.Information;\n };\n});\n\nservices.AddFileLogging("error.log", options =>\n{\n options.WriteFilter = (logMsg) =>\n {\n return logMsg.LogLevel == LogLevel.Error;\n };\n});\n\n// \u4f8b\u5b50\u4e8c\uff0c\u6839\u636e\u4efb\u4f55\u89c4\u5219\uff0c\u6bd4\u5982\u7279\u5b9a\u7684\u7c7b\u540d\nservices.AddFileLogging("someclass.log", options =>\n{\n options.WriteFilter = (logMsg) =>\n {\n return logMsg.LogName.Contains("SomeClassName");\n };\n});\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u81ea\u5b9a\u4e49\u65e5\u5fd7\u6a21\u677f"))),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u6807\u51c6\u7684\u65e5\u5fd7\u8f93\u51fa\u6a21\u677f\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"2022-07-23T20:16:29.3459053+08:00 [INF] [Furion.EventBus.EventBusHostedService] [0] EventBus Hosted Service is running.\n2022-07-23T20:16:29.5827366+08:00 [INF] [Microsoft.Hosting.Lifetime] [0] Application started. Press Ctrl+C to shut down.\n2022-07-23T20:16:29.5828798+08:00 [INF] [Microsoft.Hosting.Lifetime] [0] Hosting environment: Development\n2022-07-23T20:16:29.5829377+08:00 [INF] [Microsoft.Hosting.Lifetime] [0] Content root path: C:\\Workplaces\\Furion\\samples\\Furion.Web.Entry\\\n")),(0,i.kt)("p",null,"\u5982\u9700\u81ea\u5b9a\u4e49\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,16,34}",showLineNumbers:!0,"{2,16,34}":!0},'// \u4f8b\u5b50\u4e00\uff0c\u81ea\u5b9a\u4e49\u65e5\u5fd7\u6a21\u677f\uff08\u5e38\u7528\uff09\nservices.AddFileLogging("mytemplate.log", options =>\n{\n options.MessageFormat = (logMsg) =>\n {\n var stringBuilder = new StringBuilder();\n\n stringBuilder.Append(DateTime.Now.ToString("o"));\n // \u5176\u4ed6\u7684\u3002\u3002\u3002\u81ea\u5df1\u7ec4\u88c5\n\n return stringBuilder.ToString();\n };\n});\n\n// \u4f8b\u5b50\u4e8c\uff0c\u9700\u8981\u8f93\u51fa json \u683c\u5f0f\uff0c\u6bd4\u5982\u5bf9\u63a5\u963f\u91cc\u4e91\u65e5\u5fd7\uff0ckibana\u7b2c\u4e09\u65b9\u65e5\u5fd7\u4f7f\u7528\u8fd9\u4e2a\nservices.AddFileLogging("mytemplate.log", options =>\n{\n options.MessageFormat = (logMsg) =>\n {\n // \u9ad8\u6027\u80fd\u5199\u5165\n return logMsg.WriteArray(writer =>\n {\n writer.WriteStringValue(DateTime.Now.ToString("o"));\n writer.WriteStringValue(logMsg.LogLevel.ToString());\n writer.WriteStringValue(logMsg.LogName);\n writer.WriteNumberValue(logMsg.EventId.Id);\n writer.WriteStringValue(logMsg.Message);\n writer.WriteStringValue(logMsg.Exception?.ToString());\n });\n };\n});\n\n// \u4f8b\u5b50\u4e8c\uff0c\u9700\u8981\u8f93\u51fa json \uff08\u81ea\u5b9a\u4e49\uff09\u683c\u5f0f\uff0c\u6bd4\u5982\u5bf9\u63a5\u963f\u91cc\u4e91\u65e5\u5fd7\uff0ckibana\u7b2c\u4e09\u65b9\u65e5\u5fd7\u4f7f\u7528\u8fd9\u4e2a\nservices.AddFileLogging("mytemplate.log", options =>\n{\n options.MessageFormat = (logMsg) =>\n {\n // \u9ad8\u6027\u80fd\u5199\u5165\n return logMsg.Write(writer =>\n {\n // write \u5bf9\u8c61\u4e3a Utf8JsonWriter\uff0c\u53ef\u901a\u8fc7\u6d41\u5199\u5165\uff0c\u6027\u80fd\u6781\u9ad8\n });\n };\n});\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u65e5\u5fd7\u5199\u5165\u5931\u8d25\u5904\u7406"))),(0,i.kt)("p",null,"\u6709\u65f6\u5019\u53ef\u80fd\u56e0\u4e3a\u65e5\u5fd7\u6587\u4ef6\u88ab\u6253\u5f00\u6216\u8005\u5176\u4ed6\u5e94\u7528\u7a0b\u5e8f\u5360\u7528\u4e86\uff0c\u90a3\u4e48\u5c31\u4f1a\u5bfc\u81f4\u65e5\u5fd7\u5199\u5165\u5931\u8d25\uff0c\u8fd9\u65f6\u5019\u53ef\u4ee5\u8fdb\u884c\u5176\u4ed6\u76f8\u5173\u5904\u7406\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,11,15}",showLineNumbers:!0,"{2,11,15}":!0},'// \u4f8b\u5b50\u4e00\uff1a\u5176\u4ed6\u5904\u7406\nservices.AddFileLogging("template-obj.log", options =>\n{\n options.HandleWriteError = (writeError) =>\n {\n // ~~\n };\n});\n\n// \u4f8b\u5b50\u4e8c\uff0c\u542f\u7528\u5907\u7528\u65e5\u5fd7\u6587\u4ef6\u529f\u80fd\uff0c\u4e5f\u5c31\u662f\u5982\u679c\u6587\u4ef6\u88ab\u5360\u7528\u4e86\uff0c\u53ef\u4ee5\u521b\u5efa\u65b0\u7684\u5907\u7528\u65e5\u5fd7\u7ee7\u7eed\u5199\u5165\uff0c\u63a8\u8350\uff01\uff01\uff01\nservices.AddFileLogging("template-obj.log", options =>\n{\n options.HandleWriteError = (writeError) =>\n {\n writeError.UseRollbackFileName(Path.GetFileNameWithoutExtension(writeError.CurrentFileName) + "-oops" + Path.GetExtension(writeError.CurrentFileName));\n };\n});\n')),(0,i.kt)("h3",{id:"1853-\u8f93\u51fa\u5230\u6570\u636e\u5e93\u5176\u4ed6\u5b58\u50a8\u4ecb\u8d28"},"18.5.3 \u8f93\u51fa\u5230\u6570\u636e\u5e93/\u5176\u4ed6\u5b58\u50a8\u4ecb\u8d28"),(0,i.kt)("p",null,"\u5c06\u65e5\u5fd7\u8f93\u51fa\u5230\u6570\u636e\u5e93\u4e2d\u4e5f\u662f\u975e\u5e38\u5e38\u89c1\u7684\u9700\u6c42\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u628a\u8be5\u529f\u80fd\u505a\u5230\u4e86\u975e\u5e38\u7b80\u5355\uff0c\u652f\u6301\u4efb\u4f55\u5b58\u50a8\u4ecb\u8d28\u3002"),(0,i.kt)("p",null,"\u5728\u5199\u5165\u6570\u636e\u5e93/\u5176\u4ed6\u5b58\u50a8\u4ecb\u8d28\u4e4b\u524d\u9700\u521b\u5efa\u6570\u636e\u5e93\u65e5\u5fd7\u5199\u5165\u5668\u5e76\u5b9e\u73b0 ",(0,i.kt)("inlineCode",{parentName:"p"},"IDatabaseLoggingWriter")," \u63a5\u53e3\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u4e2a"),"\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5,8,12}",showLineNumbers:!0,"{1,5,8,12}":!0},"using Furion.Logging;\n\nnamespace Your.Core;\n\npublic class DatabaseLoggingWriter : IDatabaseLoggingWriter\n{\n // \u652f\u6301\u6784\u9020\u51fd\u6570\u6ce8\u5165\u4efb\u4f55\u5b9e\u4f8b\uff0c\u4f1a\u81ea\u52a8\u91ca\u653e\u4efb\u4f55\u670d\u52a1\uff0c\u6bd4\u5982\u6ce8\u5165 IRepository\uff0c\u6216\u8005 SqlSugarClient\n public DatabaseLoggingWriter()\n {\n }\n\n public void Write(LogMessage logMsg, bool flush)\n {\n // \u8fd9\u91cc\u5199\u4f60\u4efb\u4f55\u63d2\u5165\u6570\u636e\u5e93\u7684\u64cd\u4f5c\uff0c\u65e0\u9700 try catch\n }\n}\n")),(0,i.kt)("p",null,"\u4f60\u6ca1\u770b\u9519\uff0c\u5c31\u8fd9\u4e48\u7b80\u5355\uff01\uff01"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u57fa\u7840\u4f7f\u7528"))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5}",showLineNumbers:!0,"{2,5}":!0},"// \u4f8b\u5b50\u4e00\uff0c\u9ed8\u8ba4\u914d\u7f6e\nservices.AddDatabaseLogging(options => {});\n\n// \u4f8b\u5b50\u4e8c\uff1a\u81ea\u5b9a\u4e49\u914d\u7f6e\nservices.AddDatabaseLogging(options =>\n{\n options.MinimumLevel = LogLevel.Warning;\n\n // \u5176\u4ed6\u914d\u7f6e...\n});\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u4ece\u914d\u7f6e\u6587\u4ef6\u4e2d\u8bfb\u53d6"))),(0,i.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("strong",{parentName:"p"},"\u53ea\u6709\u4e0d\u5728 ",(0,i.kt)("inlineCode",{parentName:"strong"},".AddDatabase")," \u7b2c\u4e00\u4e2a\u53c2\u6570\u4e3a\u7a7a\u624d\u4f1a\u81ea\u52a8\u52a0\u8f7d\u914d\u7f6e\u3002"))),(0,i.kt)("p",null,"\u6570\u636e\u5e93\u65e5\u5fd7\u914d\u7f6e\u8bf4\u660e\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2,7-9,12-14}",showLineNumbers:!0,"{2,7-9,12-14}":!0},'{\n "Logging": {\n "LogLevel": {\n "Default": "Information"\n // .... appsettings \u9ed8\u8ba4\u914d\u7f6e\n },\n "Database": {\n "MinimumLevel": "Information" // \u6700\u4f4e\u65e5\u5fd7\u8bb0\u5f55\u7ea7\u522b\n }\n },\n // \u81ea\u5b9a\u4e49\u914d\u7f6e\u8282\u70b9\n "MyLogger": {\n "MinimumLevel": "Information"\n }\n}\n')),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,5,5,18,25}",showLineNumbers:!0,"{2,5,5,18,25}":!0},'// \u4f8b\u5b50\u4e00\uff1a\u9ed8\u8ba4\u8bfb\u53d6 Logging:Database \u8282\u70b9\nservices.AddDatabaseLogging();\n\n// \u4f8b\u5b50\u4e8c\uff1a\u9ed8\u8ba4\u8bfb\u53d6 Logging:Database \u8282\u70b9\uff0c\u652f\u6301\u66f4\u591a\u914d\u7f6e\nservices.AddDatabaseLogging(default(string), options =>\n{\n options.MinimumLevel = LogLevel.Warning;\n\n // \u5176\u4ed6\u914d\u7f6e...\n});\n\n// \u4f8b\u5b50\u4e09\uff1a\u81ea\u5b9a\u4e49\u914d\u7f6e\u8282\u70b9\nservices.AddDatabaseLogging("MyLogger");\n// \u6216\nservices.AddDatabaseLogging(() => "MyLogger");\n\n// \u4f8b\u5b50\u56db\uff1a\u81ea\u5b9a\u4e49\u914d\u7f6e\u8282\u70b9\uff0c\u652f\u6301\u66f4\u591a\u914d\u7f6e\nservices.AddDatabaseLogging("MyLogger", options =>\n{\n options.MinimumLevel = LogLevel.Warning;\n\n // \u5176\u4ed6\u914d\u7f6e...\n});\n// \u6216\nservices.AddDatabaseLogging(() => "MyLogger", options =>\n{\n options.MinimumLevel = LogLevel.Warning;\n\n // \u5176\u4ed6\u914d\u7f6e...\n});\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u65e5\u5fd7\u8fc7\u6ee4\u5668/\u7b5b\u9009\u5668"))),(0,i.kt)("p",null,"\u901a\u8fc7\u65e5\u5fd7\u7b5b\u9009\u5668\u53ef\u4ee5\u5bf9\u65e5\u5fd7\u8fdb\u884c\u5f52\u7c7b\u5199\u5165"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,10,19}",showLineNumbers:!0,"{2,10,19}":!0},'// \u4f8b\u5b50\u4e00\uff1a\u6839\u636e\u65e5\u5fd7\u7ea7\u522b\u8f93\u51fa\uff0c\u53ef\u4ee5\u5206\u522b\u5b9a\u4e49 IDatabaseLoggingWriter\uff0c\u4e5f\u53ef\u4ee5\u7528\u540c\u4e00\u4e2a\u5e95\u5c42\u8fdb\u884c\u5224\u65ad\nservices.AddDatabaseLogging(options =>\n{\n options.WriteFilter = (logMsg) =>\n {\n return logMsg.LogLevel == LogLevel.Information;\n };\n});\n// \u53ef\u4ee5\u5206\u522b\u5b9a\u4e49 IDatabaseLoggingWriter\uff0c\u4e5f\u53ef\u4ee5\u7528\u540c\u4e00\u4e2a\u5e95\u5c42\u8fdb\u884c\u5224\u65ad\nservices.AddDatabaseLogging(options =>\n{\n options.WriteFilter = (logMsg) =>\n {\n return logMsg.LogLevel == LogLevel.Error;\n };\n});\n\n// \u4f8b\u5b50\u4e8c\uff0c\u6839\u636e\u4efb\u4f55\u89c4\u5219\uff0c\u6bd4\u5982\u7279\u5b9a\u7684\u7c7b\u540d\nservices.AddDatabaseLogging(options =>\n{\n options.WriteFilter = (logMsg) =>\n {\n return logMsg.LogName.Contains("SomeClassName");\n };\n});\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("strong",{parentName:"li"},"\u65e5\u5fd7\u5199\u5165\u5931\u8d25\u5904\u7406"))),(0,i.kt)("p",null,"\u6709\u65f6\u5019\u53ef\u80fd\u56e0\u4e3a\u6570\u636e\u5e93\u8fde\u63a5\u5f02\u5e38\u6216\u5176\u4ed6\u539f\u56e0\u8fde\u63a5\u6c60\u6ee1\uff0c\u90a3\u4e48\u5c31\u4f1a\u5bfc\u81f4\u65e5\u5fd7\u5199\u5165\u5931\u8d25\uff0c\u8fd9\u65f6\u5019\u53ef\u4ee5\u8fdb\u884c\u5176\u4ed6\u76f8\u5173\u5904\u7406\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},"// \u4f8b\u5b50\u4e00\uff1a\u5176\u4ed6\u5904\u7406\nservices.AddDatabaseLogging(options =>\n{\n options.HandleWriteError = (writeError) =>\n {\n // ~~\n };\n});\n")),(0,i.kt)("h3",{id:"1854-iloggerfactory-\u65b9\u5f0f"},"18.5.4 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ILoggerFactory")," \u65b9\u5f0f"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e5f\u63d0\u4f9b\u4e86\u8fd0\u884c\u65f6\u52a8\u6001\u521b\u5efa\u65e5\u5fd7\u63d0\u4f9b\u5668\u5e76\u5199\u5165\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,7-8}",showLineNumbers:!0,"":!0,"{5,7-8}":!0},'public class ContactModel : PageModel\n{\n private readonly ILogger _logger;\n\n public ContactModel(ILoggerFactory logger)\n {\n // \u652f\u6301\u6240\u6709 AddLoggingFile \u548c AddDatabaseFile \u914d\u7f6e\n _logger = logger.AddFile(....).CreateLogger("MyCategory");\n }\n\n public void OnGet()\n {\n _logger.LogInformation("GET Pages.ContactModel called.");\n }\n}\n')),(0,i.kt)("h3",{id:"1855-iloggingbuilder-\u65b9\u5f0f"},"18.5.5 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ILoggingBuilder")," \u65b9\u5f0f"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e5f\u63d0\u4f9b\u4e86\u539f\u751f ",(0,i.kt)("inlineCode",{parentName:"p"},"services.AddLogging(builder => {})")," \u65b9\u5f0f\u914d\u7f6e\uff0c\u5982"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,5}",showLineNumbers:!0,"{1,3,5}":!0},'services.AddLogging(builder =>\n{\n builder.AddFile("applicaion.log");\n\n builder.AddDatabase();\n\n //....\n});\n')),(0,i.kt)("h3",{id:"1856-\u8bb0\u5f55\u8bf7\u6c42\u65e5\u5fd7"},"18.5.6 \u8bb0\u5f55\u8bf7\u6c42\u65e5\u5fd7"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"ASP.NET 6")," \u4e2d\uff0c\u6846\u67b6\u9ed8\u8ba4\u63d0\u4f9b\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"app.UseHttpLogging()")," \u8bb0\u5f55 ",(0,i.kt)("inlineCode",{parentName:"p"},"HTTP")," \u8bf7\u6c42\u65e5\u5fd7\u529f\u80fd\uff0c\u8be6\u7ec6\u4e86\u89e3\u53ef\u67e5\u770b\u5b98\u65b9\u6587\u6863 ",(0,i.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/http-logging/?view=aspnetcore-6.0"},"ASP.NET Core - HTTP \u65e5\u5fd7\u8bb0\u5f55")),(0,i.kt)("p",null,"\u5f53\u7136\u4e5f\u53ef\u4ee5\u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6\u7684\u65b9\u5f0f\u5199\uff0c\u53ea\u9700\u8981\u6ce8\u5165 ",(0,i.kt)("inlineCode",{parentName:"p"},"ILogger<>")," \u63a5\u53e3\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"1857-debug-\u548c-trace-\u9ed8\u8ba4\u4e0d\u8f93\u51fa\u95ee\u9898"},"18.5.7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Debug")," \u548c ",(0,i.kt)("inlineCode",{parentName:"h3"},"Trace")," \u9ed8\u8ba4\u4e0d\u8f93\u51fa\u95ee\u9898"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u5fae\u8f6f\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"appsettings.Development.json")," \u4e2d\u914d\u7f6e\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Default")," \u65e5\u5fd7\u7ea7\u522b\uff0c\u5982\u9700\u81ea\u5b9a\u4e49\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {4}",showLineNumbers:!0,"{4}":!0},'{\n "Logging": {\n "LogLevel": {\n "Default": "Information"\n }\n }\n}\n')),(0,i.kt)("p",null,"\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u4fee\u6539 ",(0,i.kt)("inlineCode",{parentName:"p"},"Default")," \u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"Debug")," \u6216 ",(0,i.kt)("inlineCode",{parentName:"p"},"Trace")," \u5373\u53ef\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u4e0d\u540c\u73af\u5883\u52a0\u8f7d\u4e0d\u540c\u7684\u914d\u7f6e\u6587\u4ef6\u3002\u5f00\u53d1\u73af\u5883\u5e94\u4fee\u6539 ",(0,i.kt)("inlineCode",{parentName:"strong"},"appsettings.Development.json")," \u4e0b\u7684\u914d\u7f6e\u3002")),(0,i.kt)("h2",{id:"186-loggingmonitor-\u76d1\u542c\u65e5\u5fd7"},"18.6 ",(0,i.kt)("inlineCode",{parentName:"h2"},"[LoggingMonitor]")," \u76d1\u542c\u65e5\u5fd7"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 3.9.1")," \u7248\u672c\u65b0\u589e\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"[LoggingMonitor]")," \u7279\u6027\uff0c\u652f\u6301\u5728\u63a7\u5236\u5668\u6216\u64cd\u4f5c\u4e2d\u8d34\u8be5\u7279\u6027\uff0c\u53ef\u4ee5\u5b9e\u73b0\u5f3a\u5927\u7684\u8bf7\u6c42\u65e5\u5fd7\u76d1\u542c\uff0c\u65b9\u4fbf\u6d4b\u8bd5\uff0c\u5982\uff1a"),(0,i.kt)("h3",{id:"1861-\u7279\u6027\u914d\u7f6e"},"18.6.1 \u7279\u6027\u914d\u7f6e"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,7}",showLineNumbers:!0,"{1,7}":!0},"using Furion.Logging;\n\nnamespace Furion.Application;\n\npublic class TestLoggerServices : IDynamicApiController\n{\n [LoggingMonitor]\n public PersonDto GetPerson(int id)\n {\n return new PersonDto\n {\n Id = id\n };\n }\n}\n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"[LoggingMonitor]")," \u652f\u6301\u4ee5\u4e0b\u914d\u7f6e\uff1a",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Title"),"\uff1a\u914d\u7f6e\u6807\u9898\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,i.kt)("inlineCode",{parentName:"li"},"Logging Monitor")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"WithReturnValue"),"\uff1a\u662f\u5426\u5305\u542b\u8fd4\u56de\u503c\u6253\u5370\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,i.kt)("inlineCode",{parentName:"li"},"true"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Furion 4.3.9+ \u6709\u6548")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"ReturnValueThreshold"),"\uff1a\u914d\u7f6e\u8fd4\u56de\u503c\u5b57\u7b26\u4e32\u9608\u503c\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"int")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,i.kt)("inlineCode",{parentName:"li"},"0")," \u5168\u91cf\u8f93\u51fa\uff0c",(0,i.kt)("inlineCode",{parentName:"li"},"Furion 4.3.9+ \u6709\u6548"))))),(0,i.kt)("p",null,"\u8f93\u51fa\u65e5\u5fd7\u4e3a\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},'\u250f\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Logging Monitor \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 Furion.Application.TestLoggerServices.GetPerson (Furion.Application)\n\u2523\n\u2523 \u63a7\u5236\u5668\u540d\u79f0\uff1a TestLoggerServices\n\u2523 \u64cd\u4f5c\u540d\u79f0\uff1a GetPerson\n\u2523 \u8def\u7531\u4fe1\u606f\uff1a [area]: ; [controller]: test-logger; [action]: person\n\u2523 \u8bf7\u6c42\u65b9\u5f0f\uff1a POST\n\u2523 \u8bf7\u6c42\u5730\u5740\uff1a https://localhost:44316/api/test-logger/person/11\n\u2523 \u6765\u6e90\u5730\u5740\uff1a https://localhost:44316/api/index.html\n\u2523 \u6d4f\u89c8\u5668\u6807\u8bc6\uff1a Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62\n\u2523 \u5ba2\u6237\u7aef IP \u5730\u5740\uff1a 0.0.0.1\n\u2523 \u670d\u52a1\u7aef IP \u5730\u5740\uff1a 0.0.0.1\n\u2523 \u670d\u52a1\u7aef\u8fd0\u884c\u73af\u5883\uff1a Development\n\u2523 \u6267\u884c\u8017\u65f6\uff1a 31ms\n\u2523 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 \u6388\u6743\u4fe1\u606f \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 JWT Token\uff1a Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjEsIkFjY291bnQiOiJhZG1pbiIsImlhdCI6MTY1ODcxNjc5NywibmJmIjoxNjU4NzE2Nzk3LCJleHAiOjE2NTg3MTc5OTcsImlzcyI6ImRvdG5ldGNoaW5hIiwiYXVkIjoicG93ZXJieSBGdXJpb24ifQ.VYZkwwqCwlUy3aJjuL-og62I0rkxNQ96kSjEm3VgXtg\n\u2523\n\u2523 UserId (integer)\uff1a 1\n\u2523 Account (string)\uff1a admin\n\u2523 iat (integer)\uff1a 1658716797\n\u2523 nbf (integer)\uff1a 1658716797\n\u2523 exp (integer)\uff1a 1658717997\n\u2523 iss (string)\uff1a dotnetchina\n\u2523 aud (string)\uff1a powerby Furion\n\u2523 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 \u53c2\u6570\u5217\u8868 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 Content-Type\uff1a\n\u2523\n\u2523 id (Int32)\uff1a 11\n\u2523 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 \u8fd4\u56de\u4fe1\u606f \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 \u7c7b\u578b\uff1a Furion.Application.Persons.PersonDto\n\u2523 \u8fd4\u56de\u503c\uff1a {"Id":11,"Name":null,"Age":0,"Address":null,"PhoneNumber":null,"QQ":null,"CreatedTime":"0001-01-01T00:00:00+00:00","Childrens":null,"Posts":null}\n\u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Logging Monitor \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n')),(0,i.kt)("h3",{id:"1862-\u5168\u5c40\u914d\u7f6e"},"18.6.2 \u5168\u5c40\u914d\u7f6e"),(0,i.kt)("p",null,"\u5982\u9700\u5168\u5c40\u542f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"LoggingMonitor")," \u529f\u80fd\uff0c\u65e0\u9700\u5728\u6bcf\u4e2a\u63a7\u5236\u5668\u6216\u8005\u65b9\u6cd5\u4e2d\u8d34\uff0c\u5168\u5c40\u6ce8\u518c\u5982\u4e0b\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddMvcFilter();\n")),(0,i.kt)("admonition",{type:"tip"},(0,i.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Furion 4.0.2")," \u65b0\u63a8\u8350\u914d\u7f6e"),(0,i.kt)("p",{parentName:"admonition"},"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 4.0.2")," \u7248\u672c\u4e2d\u65b0\u589e\u4e86\u975e\u5e38\u7075\u6d3b\u65b9\u4fbf\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"services.AddMonitorLogging()")," \u670d\u52a1\u914d\u7f6e\uff0c\u53ef\u5728\u914d\u7f6e\u4e2d\u968f\u610f\u63a7\u5236\u54ea\u4e2a\u7c7b\u54ea\u4e2a\u65b9\u6cd5\u542f\u7528\u6216\u4e0d\u542f\u7528\u3002"),(0,i.kt)("ul",{parentName:"admonition"},(0,i.kt)("li",{parentName:"ul"},"\u6ce8\u518c\u670d\u52a1")),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddMonitorLogging(); // \u9ed8\u8ba4\u8bfb\u53d6 Logging:Monitor \u4e0b\u914d\u7f6e\uff0c\u652f\u6301\u4f20\u5165\u53c2\u6570\u81ea\u5b9a\u4e49\n")),(0,i.kt)("ul",{parentName:"admonition"},(0,i.kt)("li",{parentName:"ul"},"\u6dfb\u52a0\u914d\u7f6e")),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2,3,4-6}",showLineNumbers:!0,"{2,3,4-6}":!0},'{\n "Logging": {\n "Monitor": {\n "GlobalEnabled": false, // \u662f\u5426\u542f\u7528\u5168\u5c40\u62e6\u622a\uff0c\u9ed8\u8ba4 `false`\n "IncludeOfMethods": [], // \u662f\u5426\u6307\u5b9a\u62e6\u622a\u7279\u5b9a\u65b9\u6cd5\uff0c\u5f53 GlobalEnabled: false \u6709\u6548\n "ExcludeOfMethods": [], // \u662f\u5426\u6307\u5b9a\u6392\u9664\u7279\u5b9a\u65b9\u6cd5\uff0c\u5f53 GlobalEnabled: true \u6709\u6548\n "BahLogLevel": "Information", // \u914d\u7f6e Oops.Oh \u548c Oops.Bah \u4e1a\u52a1\u65e5\u5fd7\u8f93\u51fa\u7ea7\u522b\uff0c\u9ed8\u8ba4 Information\n "WithReturnValue": true, // \u914d\u7f6e\u662f\u5426\u5305\u542b\u8fd4\u56de\u503c\uff0c\u9ed8\u8ba4 `true`\uff0cFurion 4.3.9+ \u6709\u6548\n "ReturnValueThreshold": 0, // \u914d\u7f6e\u8fd4\u56de\u503c\u5b57\u7b26\u4e32\u9608\u503c\uff0c\u9ed8\u8ba4 0\uff0c\u5168\u91cf\u8f93\u51fa\uff0cFurion 4.3.9+ \u6709\u6548\n "MethodsSettings": [\n // \u914d\u7f6e\u88ab\u76d1\u89c6\u65b9\u6cd5\u66f4\u591a\u4fe1\u606f\uff0cFurion 4.3.9+ \u6709\u6548\n {\n "FullName": "Furion.Application.TestLoggerServices.MethodName", // \u65b9\u6cd5\u5b8c\u5168\u9650\u5b9a\u540d\n "WithReturnValue": true, // \u914d\u7f6e\u662f\u5426\u5305\u542b\u8fd4\u56de\u503c\uff0c\u9ed8\u8ba4 `true`\uff0cFurion 4.3.9+ \u6709\u6548\n "ReturnValueThreshold": 0 // \u914d\u7f6e\u8fd4\u56de\u503c\u5b57\u7b26\u4e32\u9608\u503c\uff0c\u9ed8\u8ba4 0\uff0c\u5168\u91cf\u8f93\u51fa\uff0cFurion 4.3.9+ \u6709\u6548\n }\n ]\n }\n }\n}\n')),(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"IncludeOfMethods")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"ExcludeOfMethods")," \u65b9\u6cd5\u7b7e\u540d\u683c\u5f0f\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"\u7c7b\u5b8c\u5168\u9650\u5b9a\u540d.\u65b9\u6cd5\u540d"),"\uff0c\u5982\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"Furion.Application.TestNamedServices.GetName"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion.Application.TestNamedServices")," \u662f\u7c7b\u540d\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"GetName")," \u662f\u65b9\u6cd5\u540d\u3002")),(0,i.kt)("p",null,"\u5982\u679c\u914d\u7f6e\u4e86\u5168\u5c40\u8bf7\u6c42\u76d1\u89c6\u65e5\u5fd7\uff0c\u5bf9\u4e2a\u522b\u4e0d\u9700\u8981\u76d1\u89c6\u7684\u63a5\u53e3\u65b9\u6cd5\u53ea\u9700\u8981\u8d34 ",(0,i.kt)("inlineCode",{parentName:"p"},"[SuppressMonitor]")," \u7279\u6027\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"1863-\u66f4\u591a\u914d\u7f6e"},"18.6.3 \u66f4\u591a\u914d\u7f6e"),(0,i.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 4.3.9 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,i.kt)("p",null,"\u652f\u6301 ",(0,i.kt)("inlineCode",{parentName:"p"},"LoggingMonitor")," \u5199\u5165\u65e5\u5fd7\u62e6\u622a\uff0c\u5982\u6dfb\u52a0\u989d\u5916\u6570\u636e\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,6}",showLineNumbers:!0,"{1,3,6}":!0},'services.AddMonitorLogging(options =>\n{\n options.ConfigureLogger((logger, logContext, context) =>\n {\n var httpContext = context.HttpContext;\n logContext.Set("extra", "\u5176\u4ed6\u6570\u636e");\n });\n});\n')),(0,i.kt)("p",null,"\u9664\u6b64\u4e4b\u5916\uff0c\u8fd8\u652f\u6301\u914d\u7f6e ",(0,i.kt)("inlineCode",{parentName:"p"},"json")," \u8def\u5f84\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'services.AddMonitorLogging(jsonKey: "YourKey:Monitor");\n')),(0,i.kt)("h2",{id:"187-\u6253\u5370\u65e5\u5fd7\u5230-swagger-\u4e2d"},"18.7 \u6253\u5370\u65e5\u5fd7\u5230 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Swagger")," \u4e2d"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u9ed8\u8ba4\u96c6\u6210\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"MiniProfiler")," \u7ec4\u4ef6\u5e76\u4e0e ",(0,i.kt)("inlineCode",{parentName:"p"},"Swagger")," \u8fdb\u884c\u4e86\u7ed3\u5408\uff0c\u5982\u9700\u6253\u5370\u65e5\u5fd7\u6216\u8c03\u8bd5\u4ee3\u7801\uff0c\u53ea\u9700\u8c03\u7528\u4ee5\u4e0b\u65b9\u6cd5\u5373\u53ef\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'App.PrintToMiniProfiler("\u5206\u7c7b", "\u72b6\u6001", "\u8981\u6253\u5370\u7684\u6d88\u606f");\n')),(0,i.kt)("h2",{id:"188-\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528"},"18.8 \u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528"),(0,i.kt)("p",null,"\u7531\u4e8e ",(0,i.kt)("inlineCode",{parentName:"p"},"DbContext")," \u9ed8\u8ba4\u6ce8\u518c\u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"Scoped")," \u751f\u5b58\u5468\u671f\uff0c\u6240\u4ee5\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"IServiceScopeFactory")," \u83b7\u53d6\u6240\u6709\u670d\u52a1\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public class JobService : BackgroundService\n{\n // \u65e5\u5fd7\u5bf9\u8c61\n private readonly ILogger _logger;\n\n // \u670d\u52a1\u5de5\u5382\n private readonly IServiceScopeFactory _scopeFactory;\n public JobService(ILogger logger\n , IServiceScopeFactory scopeFactory)\n {\n _logger = logger;\n _scopeFactory = scopeFactory;\n }\n\n protected override Task ExecuteAsync(CancellationToken stoppingToken)\n {\n _logger.LogInformation("\u5199\u65e5\u5fd7~~");\n\n using (var scope = _scopeFactory.CreateScope())\n {\n var services = scope.ServiceProvider;\n\n // \u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n var dbContext = Db.GetDbContext(services);\n\n // \u83b7\u53d6\u4ed3\u50a8\n var respository = Db.GetRepository(services);\n\n // \u89e3\u6790\u5176\u4ed6\u670d\u52a1\n var otherService = services.GetService();\n }\n\n return Task.CompletedTask;\n }\n}\n')),(0,i.kt)("h2",{id:"189-\u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df"},"18.9 \u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u6240\u6709\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5b57\u7b26\u4e32")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5b9e\u4f53")," \u62d3\u5c55\u90fd\u6709\u81ea\u5df1\u72ec\u7acb\u7ef4\u62a4\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"ServiceProvider")," \u4f5c\u7528\u57df\u3002"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Web")," \u8bf7\u6c42\u4e2d\uff0c\u9ed8\u8ba4\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"HttpContext.RequestServices"),"\uff0c\u4f46\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u975e Web"),"\uff0c\u5982\u591a\u7ebf\u7a0b\u64cd\u4f5c\uff0c\u540e\u53f0\u4efb\u52a1\uff0c\u4e8b\u4ef6\u603b\u7ebf\u7b49\u573a\u666f\u4e0b\u4f1a\u81ea\u52a8\u521b\u5efa\u65b0\u7684\u4f5c\u7528\u57df\uff0c\u5b9e\u9645\u4e0a\u8fd9\u662f\u975e\u5e38\u4e0d\u5fc5\u8981\u7684\u5185\u5b58\u5f00\u9500\u3002"),(0,i.kt)("p",null,"\u8fd9\u65f6\uff0c\u6211\u4eec\u53ea\u9700\u8981\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},".SetXXXScoped(service)")," \u5171\u4eab\u5f53\u524d\u670d\u52a1\u63d0\u4f9b\u5668\u4f5c\u7528\u57df\u5373\u53ef\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'Scoped.Create(async (fac, scope) => {\n "\u5199\u65e5\u5fd7".SetLoggerScoped(scope.ServiceProvider).LogInformation();\n});\n')),(0,i.kt)("h2",{id:"1810-\u9759\u6001-default-\u65b9\u5f0f\u6784\u5efa"},"18.10 \u9759\u6001 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Default")," \u65b9\u5f0f\u6784\u5efa"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'StringLoggingPart.Default.SetMessage("\u8fd9\u662f\u4e00\u4e2a\u65e5\u5fd7").LogInformation();\n')),(0,i.kt)("h2",{id:"1811-\u89c4\u8303\u65e5\u5fd7\u6a21\u677f"},"18.11 \u89c4\u8303\u65e5\u5fd7\u6a21\u677f"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion v3.5.3+")," \u65b0\u589e\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"TP.Wrapper(...)")," \u89c4\u8303\u6a21\u677f\uff0c\u4f7f\u7528\u5982\u4e0b\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},'// \u751f\u6210\u6a21\u677f\u5b57\u7b26\u4e32\nvar template = TP.Wrapper("Furion \u6846\u67b6", "\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",\n "##\u4f5c\u8005## \u767e\u5c0f\u50e7",\n "##\u5f53\u524d\u7248\u672c## v3.5.3",\n "##\u6587\u6863\u5730\u5740## https://furion.icu",\n "##Copyright## \u767e\u5c0f\u50e7, Baiqian Co.,Ltd.");\n\nConsole.WriteLine(template);\n')),(0,i.kt)("p",null,"\u65e5\u5fd7\u6253\u5370\u6a21\u677f\u5982\u4e0b\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"\u250f\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Furion \u6846\u67b6 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 \u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002\n\u2523\n\u2523 \u4f5c\u8005\uff1a \u767e\u5c0f\u50e7\n\u2523 \u5f53\u524d\u7248\u672c\uff1a v3.5.3\n\u2523 \u6587\u6863\u5730\u5740\uff1a https://furion.icu\n\u2523 Copyright\uff1a \u767e\u5c0f\u50e7, Baiqian Co.,Ltd.\n\u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Furion \u6846\u67b6 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n")),(0,i.kt)("admonition",{title:"\u5173\u4e8e\u5c5e\u6027\u751f\u6210",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u5217\u8868\u9879\u4ee5 ",(0,i.kt)("inlineCode",{parentName:"p"},"##\u5c5e\u6027\u540d##")," \u5f00\u5934\uff0c\u81ea\u52a8\u751f\u6210 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5c5e\u6027\u540d\uff1a")," \u4f5c\u4e3a\u884c\u9996\u4e14\u81ea\u52a8\u7b49\u5bbd\u5bf9\u9f50\u3002"),(0,i.kt)("p",{parentName:"admonition"},(0,i.kt)("inlineCode",{parentName:"p"},"Furion 3.9.1")," \u4e4b\u524d\u7248\u672c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"[\u5c5e\u6027\u540d]")," \u5f00\u5934\u3002")),(0,i.kt)("h2",{id:"1812-\u65e5\u5fd7\u4e0a\u4e0b\u6587"},"18.12 \u65e5\u5fd7\u4e0a\u4e0b\u6587"),(0,i.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion 4.1.3 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,i.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u5e0c\u671b\u4e3a\u65e5\u5fd7\u63d0\u4f9b\u989d\u5916\u6570\u636e\uff0c\u8fd9\u65f6\u5019\u53ef\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},".ScopeContext()")," \u914d\u7f6e\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,6,12}",showLineNumbers:!0,"{2,6,12}":!0},'// \u5199\u6cd5\u4e00\n_logger.ScopeContext(ctx => ctx.Set("Name", "Furion").Set("UserId", 10))\n .LogInformation("\u6211\u662f\u4e00\u4e2a\u65e5\u5fd7 {id}", 20);\n\n// \u5199\u6cd5\u4e8c\n_logger.ScopeContext(new Dictionary {\n { "Name", "Furion" },\n { "UserId", 10 }\n}).LogInformation("\u6211\u662f\u4e00\u4e2a\u65e5\u5fd7 {id}", 20);\n\n// \u5199\u6cd5\u4e09\n_logger.ScopeContext(new LogContext {\n // ....\n}).LogInformation("\u6211\u662f\u4e00\u4e2a\u65e5\u5fd7 {id}", 20)\n')),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"LogMessage")," \u5bf9\u8c61\u4e2d\u4f7f\u7528\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,9,14,16}",showLineNumbers:!0,"{1,9,14,16}":!0},'var value = logMsg.Context.Get("Key");\n\n// \u6bd4\u5982\u5728\u8fc7\u6ee4\u4e2d\u4f7f\u7528\nservices.AddFileLogging("infomation.log", options =>\n{\n options.WriteFilter = (logMsg) =>\n {\n // \u8fd8\u53ef\u4ee5\u8bbe\u7f6e\u7ed9\u8fd0\u884c\u65f6\u4f7f\u7528\uff1alogMsg.Context.Set(...);\n return logMsg.Context.Get("Name") == "Furion";\n };\n});\n\n// \u5728 IDatabaseLoggingWriter \u4e2d\u4f7f\u7528\npublic void Write(LogMessage logMsg, bool flush)\n{\n var name = logMsg.Context.Get("Name");\n}\n')),(0,i.kt)("p",null,"\u8fd8\u53ef\u4ee5\u5b9e\u73b0\u5171\u4eab\u65e5\u5fd7\u4e0a\u4e0b\u6587\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,13,21}",showLineNumbers:!0,"{7,13,21}":!0},'private readonly ILogger _logger;\npublic TestAppService(ILogger logger)\n{\n _logger = logger;\n\n // \u6dfb\u52a0\u5168\u5c40\u7528\u6237\u4fe1\u606f\u4e0a\u4e0b\u6587\u6570\u636e\n _logger.ScopeContext(ctx => ctx.Set("uid", "100").Set("uname", "\u767e\u5c0f\u50e7"));\n}\n\npublic string GetName(int id)\n{\n // \u5171\u4eab\u5168\u5c40\u4e0a\u4e0b\u6587\u6570\u636e\n _logger.LogInformation("\u5199\u5165\u65b0\u7684\u65e5\u5fd7");\n\n return "Furion";\n}\n\npublic string GetTags(int id)\n{\n // \u989d\u5916\u65b0\u589e\u4e0a\u4e0b\u6587\u6570\u636e\n _logger.ScopeContext(ctx => ctx.Set("key", "value")).LogInformation("\u8bbe\u7f6e\u989d\u5916\u7684\u4e0a\u4e0a\u4e0b\u6587\u65e5\u5fd7");\n\n return "\u767e\u5c0f\u50e7";\n}\n')),(0,i.kt)("h2",{id:"1813-\u53cd\u9988\u4e0e\u5efa\u8bae"},"18.13 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,i.kt)("hr",null),(0,i.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"p"},"\u65e5\u5fd7")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/logging/?view=aspnetcore-5.0"},"ASP.NET Core - \u65e5\u5fd7")," \u7ae0\u8282 \u548c ",(0,i.kt)("a",{parentName:"p",href:"https://serilog.net/"},"Serilog")," \u6587\u6863\u3002")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/a125e20e.21aa56b6.js b/handbook/build/assets/js/a125e20e.21aa56b6.js new file mode 100644 index 0000000000..44365d617f --- /dev/null +++ b/handbook/build/assets/js/a125e20e.21aa56b6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[6828],{3905:function(e,n,t){t.d(n,{Zo:function(){return u},kt:function(){return m}});var o=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function i(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=o.createContext({}),p=function(e){var n=o.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u=function(e){var n=p(e.components);return o.createElement(s.Provider,{value:n},e.children)},g={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},c=o.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),c=p(t),m=r,d=c["".concat(s,".").concat(m)]||c[m]||g[m]||a;return t?o.createElement(d,i(i({ref:n},u),{},{components:t})):o.createElement(d,i({ref:n},u))}));function m(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,i=new Array(a);i[0]=c;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:r,i[1]=l;for(var p=2;pusing",id:"\u9ed8\u8ba4\u5168\u5c40-using",level:3}],m={toc:c};function d(e){var n=e.components,t=(0,r.Z)(e,l);return(0,a.kt)("wrapper",(0,o.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\u7b80\u4ecb"},"\u7b80\u4ecb"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET6/C#10")," \u4e4b\u540e\uff0c\u5fae\u8f6f\u65b0\u589e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings")," \u673a\u5236\uff0c\u53ef\u4ee5\u5728\u9879\u76ee\u7684\u6839\u76ee\u5f55\u4e0b\u521b\u5efa\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u6587\u4ef6\uff0c\u628a\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u653e\u7f6e\u5176\u4e2d\u3002"),(0,a.kt)("p",null,"\u8fd9\u6837 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u6240\u5728\u7684\u9879\u76ee ",(0,a.kt)("inlineCode",{parentName:"p"},".cs")," \u6587\u4ef6\u5c31\u65e0\u9700\u91cd\u590d ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u4e86\uff0c\u5927\u5927\u7684\u63d0\u9ad8\u5f00\u53d1\u6548\u7387\uff0c\u4e5f\u8ba9\u4ee3\u7801\u53d8\u7684\u66f4\u52a0\u7b80\u6d01\u3002"),(0,a.kt)("h3",{id:"\u5fc5\u8981\u914d\u7f6e"},"\u5fc5\u8981\u914d\u7f6e"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u542f\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"GlobalUsings")," \u673a\u5236\u9700\u8981\u4ee5\u4e0b\u4e24\u4e2a\u6b65\u9aa4\uff1a")),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"\u5728\u4f60\u9700\u8981\u5168\u5c40 ",(0,a.kt)("inlineCode",{parentName:"li"},"using")," \u7684\u9879\u76ee\u5c42\u6839\u76ee\u5f55\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"li"},"GlobalUsings.cs")," \u6587\u4ef6\uff0c\u5982\u679c\u591a\u4e2a\u9879\u76ee\u5c42\u9700\u8981\uff0c\u5219\u6bcf\u4e2a\u5c42\u90fd\u5e94\u8be5\u6709\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"li"},"GlobalUsings.cs")),(0,a.kt)("li",{parentName:"ol"},"\u7f16\u8f91\u9879\u76ee\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},".csproj")," \u6587\u4ef6\uff0c\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"li"},"enable"),"\uff0c\u6ce8\u610f\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"")," \u4e2d\u6dfb\u52a0\uff0c\u901a\u5e38\u548c ",(0,a.kt)("inlineCode",{parentName:"li"},"")," \u540c\u7236\u540c\u7ea7")),(0,a.kt)("h3",{id:"\u57fa\u672c\u4f7f\u7528"},"\u57fa\u672c\u4f7f\u7528"),(0,a.kt)("p",null,"\u914d\u7f6e\u4e4b\u540e\uff0c\u73b0\u5728\u5c31\u53ef\u4ee5\u628a\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u653e\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u4e2d\u4e86\uff0c\u5199\u6cd5\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="Furion \u63a8\u8350\u7684\u5168\u5c40\u547d\u540d\u7a7a\u95f4"',showLineNumbers:!0,title:'"Furion','\u63a8\u8350\u7684\u5168\u5c40\u547d\u540d\u7a7a\u95f4"':!0},"global using Furion;\nglobal using Furion.DatabaseAccessor;\nglobal using Furion.DataEncryption;\nglobal using Furion.DataValidation;\nglobal using Furion.DependencyInjection;\nglobal using Furion.DynamicApiController;\nglobal using Furion.Extensions;\nglobal using Furion.FriendlyException;\nglobal using Mapster;\nglobal using Microsoft.AspNetCore.Authorization;\nglobal using Microsoft.AspNetCore.Http;\nglobal using Microsoft.AspNetCore.Mvc;\nglobal using Microsoft.CodeAnalysis;\nglobal using Microsoft.EntityFrameworkCore;\nglobal using System.ComponentModel.DataAnnotations;\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u5fc5\u987b\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"strong"},"global")," \u5f00\u5934\uff01")),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u4e00\u822c\u63a8\u8350\u628a\u5b9e\u4f53\u7c7b\u7684\u547d\u540d\u7a7a\u95f4\u4e5f\u653e\u8fdb\u53bb\uff0c\u56e0\u4e3a\u4ed3\u50a8 ",(0,a.kt)("inlineCode",{parentName:"p"},"IRepository")," \u4f7f\u7528\u7684\u9891\u7387\u975e\u5e38\u9ad8\u3002"),(0,a.kt)("p",{parentName:"admonition"},"\u53e6\u5916\u63a8\u8350\u5927\u5bb6\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u4e2d\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"CodeMaid")," \u63d2\u4ef6\u54e6\uff0c\u81ea\u52a8\u6e05\u7406\u89e3\u51b3\u65b9\u6848\u6240\u6709\u65e0\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using"),"\uff0c\u7ed3\u5408 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u975e\u5e38\u68d2\uff01")),(0,a.kt)("admonition",{title:"\u4e2a\u522b\u60c5\u51b5",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u53ef\u80fd\u7531\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u7248\u672c\u7684\u95ee\u9898\uff0c\u5bfc\u81f4 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u5b9a\u4e49\u51fa\u9519\uff0c\u8fd9\u65f6\u5019\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u540e\u9762\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"global::"),"\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"global using global::Furion;\n"))),(0,a.kt)("p",null,"\u63a5\u4e0b\u6765\u5728\u4ee3\u7801\u4e2d\u4f7f\u7528\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},"// \u65e0\u9700 using Furion \u7684\u547d\u540d\u7a7a\u95f4\u4e86\u54e6\uff0c\u6e05\u723d\u4e86\u4e0d\u5c11\n\nnamespace Your.Application;\n\npublic class DefaultAppService : IDynamicApiController\n{\n private readonly IRepository _boardCardRepository;\n private readonly IRepository _boardGroupRepository;\n private readonly IRepository _boardCardAttachmentRepository;\n private readonly IRepository _boardCardUserRepository;\n}\n\n// ....\n")),(0,a.kt)("img",{src:(0,i.Z)("img/cd2223.png")}),(0,a.kt)("h3",{id:"\u9ed8\u8ba4\u5168\u5c40-using"},"\u9ed8\u8ba4\u5168\u5c40 ",(0,a.kt)("inlineCode",{parentName:"h3"},"using")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u5b9e\u9645\u4e0a\u5fae\u8f6f\u5df2\u7ecf\u81ea\u52a8\u628a\u4e00\u4e9b\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"using")," \u5728\u7f16\u8bd1\u540e\u7684\u4ee3\u7801\u4e2d\u81ea\u52a8\u8865\u4e0a\u4e86"),"\uff0c\u8def\u5f84\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u9879\u76ee/obj/Debug/net6.0/\u9879\u76ee.GlobalUsings.cs")," \u6587\u4ef6\u4e2d\uff0c\u6587\u4ef6\u5185\u5bb9\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \nglobal using global::System;\nglobal using global::System.Collections.Generic;\nglobal using global::System.IO;\nglobal using global::System.Linq;\nglobal using global::System.Net.Http;\nglobal using global::System.Threading;\nglobal using global::System.Threading.Tasks;\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u4e5f\u5c31\u662f\u4ee5\u4e0a\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"using")," \u65e0\u9700\u5199\u5728\u4f60\u521b\u5efa\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"GlobalUsings.cs")," \u4e2d\u4e86\uff0c\u5fae\u8f6f\u4f1a\u5728\u7f16\u8bd1\u65f6\u81ea\u52a8\u5408\u5e76\u3002")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/a125e20e.6c234aa6.js b/handbook/build/assets/js/a125e20e.6c234aa6.js deleted file mode 100644 index 6a009543bb..0000000000 --- a/handbook/build/assets/js/a125e20e.6c234aa6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[6828],{6117:function(e,n,t){t.r(n),t.d(n,{assets:function(){return g},contentTitle:function(){return p},default:function(){return d},frontMatter:function(){return s},metadata:function(){return u},toc:function(){return c}});var o=t(3117),r=t(102),a=(t(7294),t(3905)),i=t(1402),l=["components"],s={slug:"global-usings",title:"7. GlobalUsings \u7684\u4f7f\u7528",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5",".net6"]},p=void 0,u={permalink:"/furion/blog/global-usings",editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/blog/2022-05-31-global-usings.mdx",source:"@site/blog/2022-05-31-global-usings.mdx",title:"7. GlobalUsings \u7684\u4f7f\u7528",description:"",date:"2022-05-31T00:00:00.000Z",formattedDate:"May 31, 2022",tags:[{label:"furion",permalink:"/furion/blog/tags/furion"},{label:"furos",permalink:"/furion/blog/tags/furos"},{label:".net",permalink:"/furion/blog/tags/net"},{label:".netcore",permalink:"/furion/blog/tags/netcore"},{label:".net5",permalink:"/furion/blog/tags/net-5"},{label:".net6",permalink:"/furion/blog/tags/net-6"}],readingTime:2.715,hasTruncateMarker:!1,authors:[{name:"dotNET China",title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",url:"https://www.chinadot.net",imageURL:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png"}],frontMatter:{slug:"global-usings",title:"7. GlobalUsings \u7684\u4f7f\u7528",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5",".net6"]},nextItem:{title:"6. .NET 6 Preview 7 \u5c1d\u9c9c",permalink:"/furion/blog/net6-preview7"}},g={authorsImageUrls:[void 0]},c=[{value:"\u7b80\u4ecb",id:"\u7b80\u4ecb",level:3},{value:"\u5fc5\u8981\u914d\u7f6e",id:"\u5fc5\u8981\u914d\u7f6e",level:3},{value:"\u57fa\u672c\u4f7f\u7528",id:"\u57fa\u672c\u4f7f\u7528",level:3},{value:"\u9ed8\u8ba4\u5168\u5c40 using",id:"\u9ed8\u8ba4\u5168\u5c40-using",level:3}],m={toc:c};function d(e){var n=e.components,t=(0,r.Z)(e,l);return(0,a.kt)("wrapper",(0,o.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\u7b80\u4ecb"},"\u7b80\u4ecb"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET6/C#10")," \u4e4b\u540e\uff0c\u5fae\u8f6f\u65b0\u589e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings")," \u673a\u5236\uff0c\u53ef\u4ee5\u5728\u9879\u76ee\u7684\u6839\u76ee\u5f55\u4e0b\u521b\u5efa\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u6587\u4ef6\uff0c\u628a\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u653e\u7f6e\u5176\u4e2d\u3002"),(0,a.kt)("p",null,"\u8fd9\u6837 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u6240\u5728\u7684\u9879\u76ee ",(0,a.kt)("inlineCode",{parentName:"p"},".cs")," \u6587\u4ef6\u5c31\u65e0\u9700\u91cd\u590d ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u4e86\uff0c\u5927\u5927\u7684\u63d0\u9ad8\u5f00\u53d1\u6548\u7387\uff0c\u4e5f\u8ba9\u4ee3\u7801\u53d8\u7684\u66f4\u52a0\u7b80\u6d01\u3002"),(0,a.kt)("h3",{id:"\u5fc5\u8981\u914d\u7f6e"},"\u5fc5\u8981\u914d\u7f6e"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u542f\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"GlobalUsings")," \u673a\u5236\u9700\u8981\u4ee5\u4e0b\u4e24\u4e2a\u6b65\u9aa4\uff1a")),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"\u5728\u4f60\u9700\u8981\u5168\u5c40 ",(0,a.kt)("inlineCode",{parentName:"li"},"using")," \u7684\u9879\u76ee\u5c42\u6839\u76ee\u5f55\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"li"},"GlobalUsings.cs")," \u6587\u4ef6\uff0c\u5982\u679c\u591a\u4e2a\u9879\u76ee\u5c42\u9700\u8981\uff0c\u5219\u6bcf\u4e2a\u5c42\u90fd\u5e94\u8be5\u6709\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"li"},"GlobalUsings.cs")),(0,a.kt)("li",{parentName:"ol"},"\u7f16\u8f91\u9879\u76ee\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},".csproj")," \u6587\u4ef6\uff0c\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"li"},"enable"),"\uff0c\u6ce8\u610f\u662f\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"")," \u4e2d\u6dfb\u52a0\uff0c\u901a\u5e38\u548c ",(0,a.kt)("inlineCode",{parentName:"li"},"")," \u540c\u7236\u540c\u7ea7")),(0,a.kt)("h3",{id:"\u57fa\u672c\u4f7f\u7528"},"\u57fa\u672c\u4f7f\u7528"),(0,a.kt)("p",null,"\u914d\u7f6e\u4e4b\u540e\uff0c\u73b0\u5728\u5c31\u53ef\u4ee5\u628a\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u653e\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u4e2d\u4e86\uff0c\u5199\u6cd5\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers title="Furion \u63a8\u8350\u7684\u5168\u5c40\u547d\u540d\u7a7a\u95f4"',showLineNumbers:!0,title:'"Furion','\u63a8\u8350\u7684\u5168\u5c40\u547d\u540d\u7a7a\u95f4"':!0},"global using Furion;\nglobal using Furion.DatabaseAccessor;\nglobal using Furion.DataEncryption;\nglobal using Furion.DataValidation;\nglobal using Furion.DependencyInjection;\nglobal using Furion.DynamicApiController;\nglobal using Furion.Extensions;\nglobal using Furion.FriendlyException;\nglobal using Mapster;\nglobal using Microsoft.AspNetCore.Authorization;\nglobal using Microsoft.AspNetCore.Http;\nglobal using Microsoft.AspNetCore.Mvc;\nglobal using Microsoft.CodeAnalysis;\nglobal using Microsoft.EntityFrameworkCore;\nglobal using System.ComponentModel.DataAnnotations;\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u5fc5\u987b\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"strong"},"global")," \u5f00\u5934\uff01")),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u4e00\u822c\u63a8\u8350\u628a\u5b9e\u4f53\u7c7b\u7684\u547d\u540d\u7a7a\u95f4\u4e5f\u653e\u8fdb\u53bb\uff0c\u56e0\u4e3a\u4ed3\u50a8 ",(0,a.kt)("inlineCode",{parentName:"p"},"IRepository")," \u4f7f\u7528\u7684\u9891\u7387\u975e\u5e38\u9ad8\u3002"),(0,a.kt)("p",{parentName:"admonition"},"\u53e6\u5916\u63a8\u8350\u5927\u5bb6\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u4e2d\u5b89\u88c5 ",(0,a.kt)("inlineCode",{parentName:"p"},"CodeMaid")," \u63d2\u4ef6\u54e6\uff0c\u81ea\u52a8\u6e05\u7406\u89e3\u51b3\u65b9\u6848\u6240\u6709\u65e0\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using"),"\uff0c\u7ed3\u5408 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u975e\u5e38\u68d2\uff01")),(0,a.kt)("admonition",{title:"\u4e2a\u522b\u60c5\u51b5",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u53ef\u80fd\u7531\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u7248\u672c\u7684\u95ee\u9898\uff0c\u5bfc\u81f4 ",(0,a.kt)("inlineCode",{parentName:"p"},"GlobalUsings.cs")," \u5b9a\u4e49\u51fa\u9519\uff0c\u8fd9\u65f6\u5019\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"using")," \u540e\u9762\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"global::"),"\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"global using global::Furion;\n"))),(0,a.kt)("p",null,"\u63a5\u4e0b\u6765\u5728\u4ee3\u7801\u4e2d\u4f7f\u7528\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},"// \u65e0\u9700 using Furion \u7684\u547d\u540d\u7a7a\u95f4\u4e86\u54e6\uff0c\u6e05\u723d\u4e86\u4e0d\u5c11\n\nnamespace Your.Application;\n\npublic class DefaultAppService : IDynamicApiController\n{\n private readonly IRepository _boardCardRepository;\n private readonly IRepository _boardGroupRepository;\n private readonly IRepository _boardCardAttachmentRepository;\n private readonly IRepository _boardCardUserRepository;\n}\n\n// ....\n")),(0,a.kt)("img",{src:(0,i.Z)("img/cd2223.png")}),(0,a.kt)("h3",{id:"\u9ed8\u8ba4\u5168\u5c40-using"},"\u9ed8\u8ba4\u5168\u5c40 ",(0,a.kt)("inlineCode",{parentName:"h3"},"using")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u5b9e\u9645\u4e0a\u5fae\u8f6f\u5df2\u7ecf\u81ea\u52a8\u628a\u4e00\u4e9b\u5e38\u7528\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"using")," \u5728\u7f16\u8bd1\u540e\u7684\u4ee3\u7801\u4e2d\u81ea\u52a8\u8865\u4e0a\u4e86"),"\uff0c\u8def\u5f84\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u9879\u76ee/obj/Debug/net6.0/\u9879\u76ee.GlobalUsings.cs")," \u6587\u4ef6\u4e2d\uff0c\u6587\u4ef6\u5185\u5bb9\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \nglobal using global::System;\nglobal using global::System.Collections.Generic;\nglobal using global::System.IO;\nglobal using global::System.Linq;\nglobal using global::System.Net.Http;\nglobal using global::System.Threading;\nglobal using global::System.Threading.Tasks;\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u4e5f\u5c31\u662f\u4ee5\u4e0a\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"using")," \u65e0\u9700\u5199\u5728\u4f60\u521b\u5efa\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"GlobalUsings.cs")," \u4e2d\u4e86\uff0c\u5fae\u8f6f\u4f1a\u5728\u7f16\u8bd1\u65f6\u81ea\u52a8\u5408\u5e76\u3002")))}d.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return u},kt:function(){return m}});var o=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function i(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=o.createContext({}),p=function(e){var n=o.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u=function(e){var n=p(e.components);return o.createElement(s.Provider,{value:n},e.children)},g={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},c=o.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),c=p(t),m=r,d=c["".concat(s,".").concat(m)]||c[m]||g[m]||a;return t?o.createElement(d,i(i({ref:n},u),{},{components:t})):o.createElement(d,i({ref:n},u))}));function m(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,i=new Array(a);i[0]=c;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:r,i[1]=l;for(var p=2;p UploadFileAsync(List files)\n{\n // \u4fdd\u5b58\u5230\u7f51\u7ad9\u6839\u76ee\u5f55\u4e0b\u7684 uploads \u76ee\u5f55\n var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");\n if(!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);\n\n long size = files.Sum(f => f.Length);\n\n foreach (var formFile in files)\n {\n if (formFile.Length > 0)\n {\n // \u907f\u514d\u6587\u4ef6\u540d\u91cd\u590d\uff0c\u91c7\u7528 GUID \u751f\u6210\n var filePath = Path.Combine(savePath, Guid.NewGuid().ToString("N") + Path.GetExtension(formFile.FileName)); // \u53ef\u4ee5\u66ff\u4ee3\u4e3a\u4f60\u9700\u8981\u5b58\u50a8\u7684\u771f\u5b9e\u8def\u5f84\n\n using (var stream = System.IO.File.Create(filePath))\n {\n await formFile.CopyToAsync(stream);\n }\n }\n }\n\n // \u5728\u52a8\u6001 API \u76f4\u63a5\u8fd4\u56de\u5bf9\u8c61\u5373\u53ef\uff0c\u65e0\u9700 OK \u548c IActionResult\n return Ok(new { count = files.Count, size });\n}\n')),(0,a.kt)("admonition",{title:"\u5173\u4e8e\u4f7f\u7528axios\u4e0a\u4f20\u6587\u4ef6,\u65b9\u6cd5\u83b7\u53d6\u5230\u53c2\u6570files.Count=0",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"axios\u8bf7\u6c42\u914d\u7f6e"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},' let formData = new FormData();\n formData.append("files", this.file); //files\u9700\u4e0e\u65b9\u6cd5\u91cc\u7684\u53c2\u6570files\u540d\u79f0\u4e00\u6837\n let config = {\n headers: {\n "Content-Type": "multipart/form-data",\n },\n };\n axios.post(this.uploadURL, formData, config).then((res) => {//\u9700\u5f15\u5165axios\n console.log(res);\n });\n'))))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return p},kt:function(){return m}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=r.createContext({}),u=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=u(e.components);return r.createElement(s.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},f=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),f=u(n),m=o,d=f["".concat(s,".").concat(m)]||f[m]||c[m]||a;return n?r.createElement(d,i(i({ref:t},p),{},{components:n})):r.createElement(d,i({ref:t},p))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var u=2;u=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=r.createContext({}),u=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=u(e.components);return r.createElement(s.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},f=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),f=u(n),m=o,d=f["".concat(s,".").concat(m)]||f[m]||c[m]||a;return n?r.createElement(d,i(i({ref:t},p),{},{components:n})):r.createElement(d,i({ref:t},p))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var u=2;u UploadFileAsync(List files)\n{\n // \u4fdd\u5b58\u5230\u7f51\u7ad9\u6839\u76ee\u5f55\u4e0b\u7684 uploads \u76ee\u5f55\n var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");\n if(!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);\n\n long size = files.Sum(f => f.Length);\n\n foreach (var formFile in files)\n {\n if (formFile.Length > 0)\n {\n // \u907f\u514d\u6587\u4ef6\u540d\u91cd\u590d\uff0c\u91c7\u7528 GUID \u751f\u6210\n var filePath = Path.Combine(savePath, Guid.NewGuid().ToString("N") + Path.GetExtension(formFile.FileName)); // \u53ef\u4ee5\u66ff\u4ee3\u4e3a\u4f60\u9700\u8981\u5b58\u50a8\u7684\u771f\u5b9e\u8def\u5f84\n\n using (var stream = System.IO.File.Create(filePath))\n {\n await formFile.CopyToAsync(stream);\n }\n }\n }\n\n // \u5728\u52a8\u6001 API \u76f4\u63a5\u8fd4\u56de\u5bf9\u8c61\u5373\u53ef\uff0c\u65e0\u9700 OK \u548c IActionResult\n return Ok(new { count = files.Count, size });\n}\n')),(0,a.kt)("admonition",{title:"\u5173\u4e8e\u4f7f\u7528axios\u4e0a\u4f20\u6587\u4ef6,\u65b9\u6cd5\u83b7\u53d6\u5230\u53c2\u6570files.Count=0",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"axios\u8bf7\u6c42\u914d\u7f6e"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},' let formData = new FormData();\n formData.append("files", this.file); //files\u9700\u4e0e\u65b9\u6cd5\u91cc\u7684\u53c2\u6570files\u540d\u79f0\u4e00\u6837\n let config = {\n headers: {\n "Content-Type": "multipart/form-data",\n },\n };\n axios.post(this.uploadURL, formData, config).then((res) => {//\u9700\u5f15\u5165axios\n console.log(res);\n });\n'))))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/a2d62645.f029c5ed.js b/handbook/build/assets/js/a2d62645.f029c5ed.js new file mode 100644 index 0000000000..d8608a5817 --- /dev/null +++ b/handbook/build/assets/js/a2d62645.f029c5ed.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[2232],{3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return m}});var i=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function l(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=i.createContext({}),d=function(e){var t=i.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},s=function(e){var t=d(e.components);return i.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},c=i.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,p=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),c=d(n),m=r,k=c["".concat(p,".").concat(m)]||c[m]||u[m]||a;return n?i.createElement(k,l(l({ref:t},s),{},{components:n})):i.createElement(k,l({ref:t},s))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,l=new Array(a);l[0]=c;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,l[1]=o;for(var d=2;d\u975e\u6258\u7ba1",id:"34134-\u8bbe\u7f6e\u4e3a-\u975e\u6258\u7ba1",level:3},{value:"34.1.3.5 \u91cd\u542f\u7f51\u7ad9",id:"34135-\u91cd\u542f\u7f51\u7ad9",level:3},{value:"34.1.4 \u5e38\u89c1\u95ee\u9898",id:"3414-\u5e38\u89c1\u95ee\u9898",level:2},{value:"34.1.4.1 405 \u72b6\u6001\u7801\uff0c\u4e0d\u652f\u6301 PUT\uff0cDELETE \u8bf7\u6c42",id:"34141-405-\u72b6\u6001\u7801\u4e0d\u652f\u6301-putdelete-\u8bf7\u6c42",level:3},{value:"34.1.4.2 WebSocket/ SignalR \u8fde\u63a5\u62a5\u9519",id:"34142-websocket-signalr-\u8fde\u63a5\u62a5\u9519",level:3},{value:"34.1.4.3 \u90e8\u7f72\u4e4b\u540e\u7f3a\u5931 api-ms-win.xxxx.dll \u95ee\u9898",id:"34143-\u90e8\u7f72\u4e4b\u540e\u7f3a\u5931-api-ms-winxxxxdll-\u95ee\u9898",level:3},{value:"34.1.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"3415-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:c};function k(e){var t=e.components,n=(0,r.Z)(e,o);return(0,a.kt)("wrapper",(0,i.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{title:"\u7cbe\u7b80\u53d1\u5e03\u6587\u4ef6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u9700\u8981\u7cbe\u7b80\u53d1\u5e03\u540e\u7684\u6587\u4ef6\uff0c\u4e5f\u5c31\u662f\u5220\u9664\u4e0d\u5fc5\u8981\u7684\u6587\u4ef6\u5939\uff0c\u53ef\u4ee5\u7f16\u8f91 Web \u9879\u76ee\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},".csproj")," \u5e76\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"en-US"),"\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"\n net6.0\n en-US\n\n"))),(0,a.kt)("h2",{id:"3411-\u53d1\u5e03\u7f51\u7ad9"},"34.1.1 \u53d1\u5e03\u7f51\u7ad9"),(0,a.kt)("h3",{id:"34111-\u9009\u62e9\u542f\u52a8\u9879\u53d1\u5e03"},"34.1.1.1 \u9009\u62e9\u542f\u52a8\u9879\u53d1\u5e03"),(0,a.kt)("img",{src:(0,l.Z)("img/dp1.png")}),(0,a.kt)("h3",{id:"34112-\u9009\u62e9\u53d1\u5e03\u5230\u6587\u4ef6\u5939"},"34.1.1.2 \u9009\u62e9\u53d1\u5e03\u5230\u6587\u4ef6\u5939"),(0,a.kt)("img",{src:(0,l.Z)("img/dy2.png")}),(0,a.kt)("h3",{id:"34113-\u914d\u7f6e\u53d1\u5e03\u540e\u8def\u5f84"},"34.1.1.3 \u914d\u7f6e\u53d1\u5e03\u540e\u8def\u5f84"),(0,a.kt)("img",{src:(0,l.Z)("img/dp3.png")}),(0,a.kt)("h3",{id:"34114-\u70b9\u51fb\u53d1\u5e03"},"34.1.1.4 \u70b9\u51fb\u53d1\u5e03"),(0,a.kt)("img",{src:(0,l.Z)("img/dp4.png")}),(0,a.kt)("h2",{id:"3412-\u670d\u52a1\u5668\u73af\u5883\u914d\u7f6e"},"34.1.2 \u670d\u52a1\u5668\u73af\u5883\u914d\u7f6e"),(0,a.kt)("h3",{id:"34121-\u7b2c\u4e00\u6b65"},"34.1.2.1 \u7b2c\u4e00\u6b65"),(0,a.kt)("p",null,"\u5b89\u88c5.NET Core \u8fd0\u884c\u65f6\u6346\u7ed1\u5305\uff1a",(0,a.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/permalink/dotnetcore-current-windows-runtime-bundle-installer"},"\u70b9\u51fb\u4e0b\u8f7d")),(0,a.kt)("h3",{id:"34122-\u7b2c\u4e8c\u6b65\u547d\u4ee4"},"34.1.2.2 \u7b2c\u4e8c\u6b65\uff08\u547d\u4ee4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"net stop was /y\n")),(0,a.kt)("h3",{id:"34123-\u7b2c\u4e09\u6b65\u547d\u4ee4"},"34.1.2.3 \u7b2c\u4e09\u6b65\uff08\u547d\u4ee4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"net start w3svc\n")),(0,a.kt)("h3",{id:"34124-\u7b2c\u56db\u6b65\u547d\u4ee4"},"34.1.2.4 \u7b2c\u56db\u6b65\uff08\u547d\u4ee4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"set ASPNETCORE_ENVIRONMENT=Production\n")),(0,a.kt)("h2",{id:"3413-\u90e8\u7f72\u5230-iis"},"34.1.3 \u90e8\u7f72\u5230 IIS"),(0,a.kt)("h3",{id:"34131-\u6dfb\u52a0\u65b0\u7f51\u7ad9"},"34.1.3.1 \u6dfb\u52a0\u65b0\u7f51\u7ad9"),(0,a.kt)("img",{src:(0,l.Z)("img/ds1.png")}),(0,a.kt)("h3",{id:"34132-\u914d\u7f6e\u7f51\u7ad9\u4fe1\u606f"},"34.1.3.2 \u914d\u7f6e\u7f51\u7ad9\u4fe1\u606f"),(0,a.kt)("img",{src:(0,l.Z)("img/ds2.png")}),(0,a.kt)("h3",{id:"34133-\u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u6c60"},"34.1.3.3 \u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u6c60"),(0,a.kt)("img",{src:(0,l.Z)("img/ds3.png")}),(0,a.kt)("h3",{id:"34134-\u8bbe\u7f6e\u4e3a-\u975e\u6258\u7ba1"},"34.1.3.4 \u8bbe\u7f6e\u4e3a ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u975e\u6258\u7ba1")),(0,a.kt)("img",{src:(0,l.Z)("img/ds4.png")}),(0,a.kt)("h3",{id:"34135-\u91cd\u542f\u7f51\u7ad9"},"34.1.3.5 \u91cd\u542f\u7f51\u7ad9"),(0,a.kt)("p",null,"\u53ea\u9700\u91cd\u542f\u7f51\u7ad9\u6216\u5e94\u7528\u7a0b\u5e8f\u6c60\u5373\u53ef\u3002"),(0,a.kt)("h2",{id:"3414-\u5e38\u89c1\u95ee\u9898"},"34.1.4 \u5e38\u89c1\u95ee\u9898"),(0,a.kt)("h3",{id:"34141-405-\u72b6\u6001\u7801\u4e0d\u652f\u6301-putdelete-\u8bf7\u6c42"},"34.1.4.1 405 \u72b6\u6001\u7801\uff0c\u4e0d\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"h3"},"PUT\uff0cDELETE")," \u8bf7\u6c42"),(0,a.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"IIS"),"\u62d2\u7edd ",(0,a.kt)("inlineCode",{parentName:"p"},"PUT"),"\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"DELETE")," \u8bf7\u6c42\uff0c\u539f\u56e0\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"IIS")," \u9ed8\u8ba4\u6ce8\u518c\u4e86\u4e00\u4e2a\u540d\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"WebDAVModule")," \u7684\u81ea\u5b9a\u4e49 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpModule")," \u5bfc\u81f4\u7684\u3002"),(0,a.kt)("p",null,"\u89e3\u51b3\u8be5\u95ee\u9898\uff0c\u53ea\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"web.config")," \u79fb\u9664\u5373\u53ef\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-xml",metastring:"{2-6}","{2-6}":!0},'\n \n \n \n \n \n\n')),(0,a.kt)("h3",{id:"34142-websocket-signalr-\u8fde\u63a5\u62a5\u9519"},"34.1.4.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"WebSocket"),"/ ",(0,a.kt)("inlineCode",{parentName:"h3"},"SignalR")," \u8fde\u63a5\u62a5\u9519"),(0,a.kt)("p",null,"\u5982\u679c\u9879\u76ee\u90e8\u7f72\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"IIS")," \u4e2d\u51fa\u73b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"WebSoket"),"/",(0,a.kt)("inlineCode",{parentName:"p"},"SignalR")," \u4e0d\u80fd\u8fde\u63a5\u6216\u8fde\u63a5\u5931\u8d25\u7b49\u95ee\u9898\uff0c\u8bf7\u786e\u4fdd ",(0,a.kt)("inlineCode",{parentName:"p"},"IIS")," \u670d\u52a1\u4e2d\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"WebSocket \u534f\u8bae")," \u662f\u52fe\u9009\u72b6\u6001"),(0,a.kt)("img",{src:(0,l.Z)("img/iis2.png")}),(0,a.kt)("h3",{id:"34143-\u90e8\u7f72\u4e4b\u540e\u7f3a\u5931-api-ms-winxxxxdll-\u95ee\u9898"},"34.1.4.3 \u90e8\u7f72\u4e4b\u540e\u7f3a\u5931 ",(0,a.kt)("inlineCode",{parentName:"h3"},"api-ms-win.xxxx.dll")," \u95ee\u9898"),(0,a.kt)("p",null,"\u6709\u65f6\u5019\u5c06\u53d1\u5e03\u6587\u4ef6\u53d1\u5e03\u5230\u670d\u52a1\u5668\u540e\uff0c\u51fa\u73b0\u4e22\u5931 ",(0,a.kt)("inlineCode",{parentName:"p"},"api.ms-win.xxxx.dll")," \u6587\u4ef6\uff0c\u8fd9\u65f6\u53ea\u9700\u8981\u91cd\u65b0\u53d1\u5e03\u5e76\u9009\u62e9\u670d\u52a1\u5668\u7279\u5b9a\u7684\u67b6\u6784\u5373\u53ef\u3002"),(0,a.kt)("img",{src:(0,l.Z)("img/iis4.jpg")}),(0,a.kt)("img",{src:(0,l.Z)("img/iis3.png")}),(0,a.kt)("h2",{id:"3415-\u53cd\u9988\u4e0e\u5efa\u8bae"},"34.1.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/a2d62645.fcb746f2.js b/handbook/build/assets/js/a2d62645.fcb746f2.js deleted file mode 100644 index cb3fc98bc6..0000000000 --- a/handbook/build/assets/js/a2d62645.fcb746f2.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[2232],{3893:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return d},default:function(){return k},frontMatter:function(){return p},metadata:function(){return s},toc:function(){return c}});var i=n(3117),r=n(102),a=(n(7294),n(3905)),l=n(1402),o=["components"],p={id:"deploy-iis",title:"34.1 \u5728 IIS \u90e8\u7f72",sidebar_label:"34.1 \u5728 IIS \u90e8\u7f72"},d=void 0,s={unversionedId:"deploy-iis",id:"deploy-iis",title:"34.1 \u5728 IIS \u90e8\u7f72",description:"",source:"@site/docs/deploy-iis.mdx",sourceDirName:".",slug:"/deploy-iis",permalink:"/furion/docs/deploy-iis",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/deploy-iis.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1662003907,formattedLastUpdatedAt:"Sep 1, 2022",frontMatter:{id:"deploy-iis",title:"34.1 \u5728 IIS \u90e8\u7f72",sidebar_label:"34.1 \u5728 IIS \u90e8\u7f72"},sidebar:"docs",previous:{title:"33. IPC \u8fdb\u7a0b\u901a\u4fe1",permalink:"/furion/docs/ipc"},next:{title:"34.2 \u5728 Docker \u90e8\u7f72",permalink:"/furion/docs/deploy-docker"}},u={},c=[{value:"34.1.1 \u53d1\u5e03\u7f51\u7ad9",id:"3411-\u53d1\u5e03\u7f51\u7ad9",level:2},{value:"34.1.1.1 \u9009\u62e9\u542f\u52a8\u9879\u53d1\u5e03",id:"34111-\u9009\u62e9\u542f\u52a8\u9879\u53d1\u5e03",level:3},{value:"34.1.1.2 \u9009\u62e9\u53d1\u5e03\u5230\u6587\u4ef6\u5939",id:"34112-\u9009\u62e9\u53d1\u5e03\u5230\u6587\u4ef6\u5939",level:3},{value:"34.1.1.3 \u914d\u7f6e\u53d1\u5e03\u540e\u8def\u5f84",id:"34113-\u914d\u7f6e\u53d1\u5e03\u540e\u8def\u5f84",level:3},{value:"34.1.1.4 \u70b9\u51fb\u53d1\u5e03",id:"34114-\u70b9\u51fb\u53d1\u5e03",level:3},{value:"34.1.2 \u670d\u52a1\u5668\u73af\u5883\u914d\u7f6e",id:"3412-\u670d\u52a1\u5668\u73af\u5883\u914d\u7f6e",level:2},{value:"34.1.2.1 \u7b2c\u4e00\u6b65",id:"34121-\u7b2c\u4e00\u6b65",level:3},{value:"34.1.2.2 \u7b2c\u4e8c\u6b65\uff08\u547d\u4ee4\uff09",id:"34122-\u7b2c\u4e8c\u6b65\u547d\u4ee4",level:3},{value:"34.1.2.3 \u7b2c\u4e09\u6b65\uff08\u547d\u4ee4\uff09",id:"34123-\u7b2c\u4e09\u6b65\u547d\u4ee4",level:3},{value:"34.1.2.4 \u7b2c\u56db\u6b65\uff08\u547d\u4ee4\uff09",id:"34124-\u7b2c\u56db\u6b65\u547d\u4ee4",level:3},{value:"34.1.3 \u90e8\u7f72\u5230 IIS",id:"3413-\u90e8\u7f72\u5230-iis",level:2},{value:"34.1.3.1 \u6dfb\u52a0\u65b0\u7f51\u7ad9",id:"34131-\u6dfb\u52a0\u65b0\u7f51\u7ad9",level:3},{value:"34.1.3.2 \u914d\u7f6e\u7f51\u7ad9\u4fe1\u606f",id:"34132-\u914d\u7f6e\u7f51\u7ad9\u4fe1\u606f",level:3},{value:"34.1.3.3 \u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u6c60",id:"34133-\u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u6c60",level:3},{value:"34.1.3.4 \u8bbe\u7f6e\u4e3a \u975e\u6258\u7ba1",id:"34134-\u8bbe\u7f6e\u4e3a-\u975e\u6258\u7ba1",level:3},{value:"34.1.3.5 \u91cd\u542f\u7f51\u7ad9",id:"34135-\u91cd\u542f\u7f51\u7ad9",level:3},{value:"34.1.4 \u5e38\u89c1\u95ee\u9898",id:"3414-\u5e38\u89c1\u95ee\u9898",level:2},{value:"34.1.4.1 405 \u72b6\u6001\u7801\uff0c\u4e0d\u652f\u6301 PUT\uff0cDELETE \u8bf7\u6c42",id:"34141-405-\u72b6\u6001\u7801\u4e0d\u652f\u6301-putdelete-\u8bf7\u6c42",level:3},{value:"34.1.4.2 WebSocket/ SignalR \u8fde\u63a5\u62a5\u9519",id:"34142-websocket-signalr-\u8fde\u63a5\u62a5\u9519",level:3},{value:"34.1.4.3 \u90e8\u7f72\u4e4b\u540e\u7f3a\u5931 api-ms-win.xxxx.dll \u95ee\u9898",id:"34143-\u90e8\u7f72\u4e4b\u540e\u7f3a\u5931-api-ms-winxxxxdll-\u95ee\u9898",level:3},{value:"34.1.5 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"3415-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:c};function k(e){var t=e.components,n=(0,r.Z)(e,o);return(0,a.kt)("wrapper",(0,i.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{title:"\u7cbe\u7b80\u53d1\u5e03\u6587\u4ef6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u9700\u8981\u7cbe\u7b80\u53d1\u5e03\u540e\u7684\u6587\u4ef6\uff0c\u4e5f\u5c31\u662f\u5220\u9664\u4e0d\u5fc5\u8981\u7684\u6587\u4ef6\u5939\uff0c\u53ef\u4ee5\u7f16\u8f91 Web \u9879\u76ee\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},".csproj")," \u5e76\u6dfb\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"en-US"),"\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"\n net6.0\n en-US\n\n"))),(0,a.kt)("h2",{id:"3411-\u53d1\u5e03\u7f51\u7ad9"},"34.1.1 \u53d1\u5e03\u7f51\u7ad9"),(0,a.kt)("h3",{id:"34111-\u9009\u62e9\u542f\u52a8\u9879\u53d1\u5e03"},"34.1.1.1 \u9009\u62e9\u542f\u52a8\u9879\u53d1\u5e03"),(0,a.kt)("img",{src:(0,l.Z)("img/dp1.png")}),(0,a.kt)("h3",{id:"34112-\u9009\u62e9\u53d1\u5e03\u5230\u6587\u4ef6\u5939"},"34.1.1.2 \u9009\u62e9\u53d1\u5e03\u5230\u6587\u4ef6\u5939"),(0,a.kt)("img",{src:(0,l.Z)("img/dy2.png")}),(0,a.kt)("h3",{id:"34113-\u914d\u7f6e\u53d1\u5e03\u540e\u8def\u5f84"},"34.1.1.3 \u914d\u7f6e\u53d1\u5e03\u540e\u8def\u5f84"),(0,a.kt)("img",{src:(0,l.Z)("img/dp3.png")}),(0,a.kt)("h3",{id:"34114-\u70b9\u51fb\u53d1\u5e03"},"34.1.1.4 \u70b9\u51fb\u53d1\u5e03"),(0,a.kt)("img",{src:(0,l.Z)("img/dp4.png")}),(0,a.kt)("h2",{id:"3412-\u670d\u52a1\u5668\u73af\u5883\u914d\u7f6e"},"34.1.2 \u670d\u52a1\u5668\u73af\u5883\u914d\u7f6e"),(0,a.kt)("h3",{id:"34121-\u7b2c\u4e00\u6b65"},"34.1.2.1 \u7b2c\u4e00\u6b65"),(0,a.kt)("p",null,"\u5b89\u88c5.NET Core \u8fd0\u884c\u65f6\u6346\u7ed1\u5305\uff1a",(0,a.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/permalink/dotnetcore-current-windows-runtime-bundle-installer"},"\u70b9\u51fb\u4e0b\u8f7d")),(0,a.kt)("h3",{id:"34122-\u7b2c\u4e8c\u6b65\u547d\u4ee4"},"34.1.2.2 \u7b2c\u4e8c\u6b65\uff08\u547d\u4ee4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"net stop was /y\n")),(0,a.kt)("h3",{id:"34123-\u7b2c\u4e09\u6b65\u547d\u4ee4"},"34.1.2.3 \u7b2c\u4e09\u6b65\uff08\u547d\u4ee4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"net start w3svc\n")),(0,a.kt)("h3",{id:"34124-\u7b2c\u56db\u6b65\u547d\u4ee4"},"34.1.2.4 \u7b2c\u56db\u6b65\uff08\u547d\u4ee4\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"set ASPNETCORE_ENVIRONMENT=Production\n")),(0,a.kt)("h2",{id:"3413-\u90e8\u7f72\u5230-iis"},"34.1.3 \u90e8\u7f72\u5230 IIS"),(0,a.kt)("h3",{id:"34131-\u6dfb\u52a0\u65b0\u7f51\u7ad9"},"34.1.3.1 \u6dfb\u52a0\u65b0\u7f51\u7ad9"),(0,a.kt)("img",{src:(0,l.Z)("img/ds1.png")}),(0,a.kt)("h3",{id:"34132-\u914d\u7f6e\u7f51\u7ad9\u4fe1\u606f"},"34.1.3.2 \u914d\u7f6e\u7f51\u7ad9\u4fe1\u606f"),(0,a.kt)("img",{src:(0,l.Z)("img/ds2.png")}),(0,a.kt)("h3",{id:"34133-\u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u6c60"},"34.1.3.3 \u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u6c60"),(0,a.kt)("img",{src:(0,l.Z)("img/ds3.png")}),(0,a.kt)("h3",{id:"34134-\u8bbe\u7f6e\u4e3a-\u975e\u6258\u7ba1"},"34.1.3.4 \u8bbe\u7f6e\u4e3a ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u975e\u6258\u7ba1")),(0,a.kt)("img",{src:(0,l.Z)("img/ds4.png")}),(0,a.kt)("h3",{id:"34135-\u91cd\u542f\u7f51\u7ad9"},"34.1.3.5 \u91cd\u542f\u7f51\u7ad9"),(0,a.kt)("p",null,"\u53ea\u9700\u91cd\u542f\u7f51\u7ad9\u6216\u5e94\u7528\u7a0b\u5e8f\u6c60\u5373\u53ef\u3002"),(0,a.kt)("h2",{id:"3414-\u5e38\u89c1\u95ee\u9898"},"34.1.4 \u5e38\u89c1\u95ee\u9898"),(0,a.kt)("h3",{id:"34141-405-\u72b6\u6001\u7801\u4e0d\u652f\u6301-putdelete-\u8bf7\u6c42"},"34.1.4.1 405 \u72b6\u6001\u7801\uff0c\u4e0d\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"h3"},"PUT\uff0cDELETE")," \u8bf7\u6c42"),(0,a.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"IIS"),"\u62d2\u7edd ",(0,a.kt)("inlineCode",{parentName:"p"},"PUT"),"\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"DELETE")," \u8bf7\u6c42\uff0c\u539f\u56e0\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"IIS")," \u9ed8\u8ba4\u6ce8\u518c\u4e86\u4e00\u4e2a\u540d\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"WebDAVModule")," \u7684\u81ea\u5b9a\u4e49 ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpModule")," \u5bfc\u81f4\u7684\u3002"),(0,a.kt)("p",null,"\u89e3\u51b3\u8be5\u95ee\u9898\uff0c\u53ea\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"web.config")," \u79fb\u9664\u5373\u53ef\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-xml",metastring:"{2-6}","{2-6}":!0},'\n \n \n \n \n \n\n')),(0,a.kt)("h3",{id:"34142-websocket-signalr-\u8fde\u63a5\u62a5\u9519"},"34.1.4.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"WebSocket"),"/ ",(0,a.kt)("inlineCode",{parentName:"h3"},"SignalR")," \u8fde\u63a5\u62a5\u9519"),(0,a.kt)("p",null,"\u5982\u679c\u9879\u76ee\u90e8\u7f72\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"IIS")," \u4e2d\u51fa\u73b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"WebSoket"),"/",(0,a.kt)("inlineCode",{parentName:"p"},"SignalR")," \u4e0d\u80fd\u8fde\u63a5\u6216\u8fde\u63a5\u5931\u8d25\u7b49\u95ee\u9898\uff0c\u8bf7\u786e\u4fdd ",(0,a.kt)("inlineCode",{parentName:"p"},"IIS")," \u670d\u52a1\u4e2d\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"WebSocket \u534f\u8bae")," \u662f\u52fe\u9009\u72b6\u6001"),(0,a.kt)("img",{src:(0,l.Z)("img/iis2.png")}),(0,a.kt)("h3",{id:"34143-\u90e8\u7f72\u4e4b\u540e\u7f3a\u5931-api-ms-winxxxxdll-\u95ee\u9898"},"34.1.4.3 \u90e8\u7f72\u4e4b\u540e\u7f3a\u5931 ",(0,a.kt)("inlineCode",{parentName:"h3"},"api-ms-win.xxxx.dll")," \u95ee\u9898"),(0,a.kt)("p",null,"\u6709\u65f6\u5019\u5c06\u53d1\u5e03\u6587\u4ef6\u53d1\u5e03\u5230\u670d\u52a1\u5668\u540e\uff0c\u51fa\u73b0\u4e22\u5931 ",(0,a.kt)("inlineCode",{parentName:"p"},"api.ms-win.xxxx.dll")," \u6587\u4ef6\uff0c\u8fd9\u65f6\u53ea\u9700\u8981\u91cd\u65b0\u53d1\u5e03\u5e76\u9009\u62e9\u670d\u52a1\u5668\u7279\u5b9a\u7684\u67b6\u6784\u5373\u53ef\u3002"),(0,a.kt)("img",{src:(0,l.Z)("img/iis4.jpg")}),(0,a.kt)("img",{src:(0,l.Z)("img/iis3.png")}),(0,a.kt)("h2",{id:"3415-\u53cd\u9988\u4e0e\u5efa\u8bae"},"34.1.5 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}k.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return m}});var i=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function l(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=i.createContext({}),d=function(e){var t=i.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},s=function(e){var t=d(e.components);return i.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},c=i.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,p=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),c=d(n),m=r,k=c["".concat(p,".").concat(m)]||c[m]||u[m]||a;return n?i.createElement(k,l(l({ref:t},s),{},{components:n})):i.createElement(k,l({ref:t},s))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,l=new Array(a);l[0]=c;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,l[1]=o;for(var d=2;d=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=o.createContext({}),s=function(e){var n=o.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},m=function(e){var n=s(e.components);return o.createElement(l.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},d=o.forwardRef((function(e,n){var t=e.components,i=e.mdxType,r=e.originalType,l=e.parentName,m=p(e,["components","mdxType","originalType","parentName"]),d=s(t),c=i,k=d["".concat(l,".").concat(c)]||d[c]||u[c]||r;return t?o.createElement(k,a(a({ref:n},m),{},{components:t})):o.createElement(k,a({ref:n},m))}));function c(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var r=t.length,a=new Array(r);a[0]=d;var p={};for(var l in n)hasOwnProperty.call(n,l)&&(p[l]=n[l]);p.originalType=e,p.mdxType="string"==typeof e?e:i,a[1]=p;for(var s=2;sAppDbContext",id:"912-appdbcontext",level:2},{value:"9.1.3 AppDbContext \u548c DbContext \u533a\u522b",id:"913-appdbcontext-\u548c-dbcontext-\u533a\u522b",level:2},{value:"9.1.4 \u5982\u4f55\u5b9a\u4e49\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"914-\u5982\u4f55\u5b9a\u4e49\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:2},{value:"9.1.4.1 \u521b\u5efa\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"9141-\u521b\u5efa\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:3},{value:"9.1.4.2 \u521b\u5efa\u5176\u4ed6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"9142-\u521b\u5efa\u5176\u4ed6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:3},{value:"9.1.5 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32",id:"915-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32",level:2},{value:"9.1.5.1 \u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e",id:"9151-\u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e",level:3},{value:"9.1.5.2 [AppDbContext] \u65b9\u5f0f\u914d\u7f6e",id:"9152-appdbcontext-\u65b9\u5f0f\u914d\u7f6e",level:3},{value:"9.1.5.3 OnConfiguring \u65b9\u5f0f\u914d\u7f6e",id:"9153-onconfiguring-\u65b9\u5f0f\u914d\u7f6e",level:3},{value:"9.1.5.4 \u5404\u7c7b\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u793a\u4f8b",id:"9154-\u5404\u7c7b\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u793a\u4f8b",level:3},{value:"9.1.6 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4e49\u4f4d\u7f6e",id:"916-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4e49\u4f4d\u7f6e",level:2},{value:"9.1.7 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c",id:"917-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c",level:2},{value:"9.1.8 \u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c",id:"918-\u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c",level:2},{value:"9.1.9 \u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61",id:"919-\u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61",level:2},{value:"9.1.10 \u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528",id:"9110-\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528",level:2},{value:"9.1.11 AppDbContext \u5168\u5c40\u914d\u7f6e\u5c5e\u6027",id:"9111-appdbcontext-\u5168\u5c40\u914d\u7f6e\u5c5e\u6027",level:2},{value:"9.1.12 \u914d\u7f6e\u5b9e\u4f53 \u61d2\u52a0\u8f7d",id:"9112-\u914d\u7f6e\u5b9e\u4f53-\u61d2\u52a0\u8f7d",level:2},{value:"9.1.13 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9113-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:u};function c(e){var n=e.components,t=(0,i.Z)(e,a);return(0,r.kt)("wrapper",(0,o.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("admonition",{title:"\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u6ce8\u610f\u4e8b\u9879",type:"warning"},(0,r.kt)("p",{parentName:"admonition"},"\u5982\u679c\u8fde\u63a5\u5b57\u7b26\u4e32\u662f\u914d\u7f6e\u5728\u81ea\u5b9a\u4e49\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u4e2d\uff0c\u90a3\u4e48\u5fc5\u987b\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u4e2d\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},".json")," \u53f3\u952e\u5c5e\u6027\uff0c\u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"\u590d\u5236")," \u8f93\u51fa\u76ee\u5f55\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"\u5982\u679c\u8f83\u65b0\u5219\u590d\u5236"),"\uff0c\u751f\u6210\u64cd\u4f5c\u4e3a\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"\u5185\u5bb9"),"\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u5426\u5219\u5c31\u4f1a\u63d0\u793a\u627e\u4e0d\u5230\u914d\u7f6e\u6216\u8fde\u63a5\u5b57\u7b26\u4e32\u7684\u9519\u8bef\u3002")),(0,r.kt)("h2",{id:"911-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.1.1 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,r.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u662f\u8d1f\u8d23\u548c\u6570\u636e\u5e93\u4ea4\u4e92\u7684\u5bf9\u8c61\uff0c\u63d0\u4f9b\u7a0b\u5e8f\u5bf9\u6570\u636e\u5e93\u5b58\u53d6\u63d0\u4f9b\u4e86\u5927\u91cf\u7684\u65b9\u6cd5\u3002"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u96c6\u6210\u4e86\u5fae\u8f6f\u4eb2\u513f\u5b50\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"EntityFramework Core")," \uff0c\u4e5f\u5c31\u662f\u901a\u5e38\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6307\u7684\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u7c7b\u6216\u5b83\u7684\u5b9e\u73b0\u7c7b\u3002"),(0,r.kt)("h2",{id:"912-appdbcontext"},"9.1.2 ",(0,r.kt)("inlineCode",{parentName:"h2"},"AppDbContext")),(0,r.kt)("p",null,"\u5728\u6211\u4eec\u5b9e\u9645\u9879\u76ee\u5f00\u53d1\u8fc7\u7a0b\u4e2d\uff0c\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"EFCore")," \u63d0\u4f9b\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u64cd\u4f5c\u5bf9\u8c61\u64cd\u4f5c\u6570\u636e\u5e93\u6709\u4e9b\u7e41\u7410\u548c\u590d\u6742\uff0c\u4e14\u9ed8\u8ba4\u4e0d\u5177\u5907\u8bfb\u5199\u5206\u79bb\u3001\u591a\u5e93\u7b49\u64cd\u4f5c\u529f\u80fd\u3002"),(0,r.kt)("p",null,"\u6240\u4ee5\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u8be5\u4e0a\u4e0b\u6587\u7ee7\u627f\u81ea ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext"),"\u3002"),(0,r.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u540e\u7eed\u7ae0\u8282\uff0c\u7686\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"EFCore")," \u4ee3\u66ff ",(0,r.kt)("inlineCode",{parentName:"p"},"EntityFramework Core"),"\u3002")),(0,r.kt)("h2",{id:"913-appdbcontext-\u548c-dbcontext-\u533a\u522b"},"9.1.3 ",(0,r.kt)("inlineCode",{parentName:"h2"},"AppDbContext")," \u548c ",(0,r.kt)("inlineCode",{parentName:"h2"},"DbContext")," \u533a\u522b"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u7ee7\u627f\u81ea ",(0,r.kt)("inlineCode",{parentName:"li"},"DbContext"),"\uff0c\u5177\u5907 ",(0,r.kt)("inlineCode",{parentName:"li"},"DbContext")," \u6240\u6709\u529f\u80fd\u3002"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u6cdb\u578b\u7248\u672c\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u81ea\u52a8\u914d\u7f6e\u5b9e\u4f53\u4fe1\u606f\uff0c\u65e0\u9700\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnModelCreating")," \u4e2d\u914d\u7f6e"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u5185\u7f6e\u591a\u79df\u6237\u652f\u6301"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u5168\u5c40\u6a21\u578b\u914d\u7f6e\u62e6\u622a\u5668"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u6570\u636e\u63d0\u4ea4\u66f4\u6539\u591a\u4e2a\u4e8b\u4ef6"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u63d0\u4f9b\u66f4\u52a0\u5f3a\u5927\u7684\u6a21\u578b\u64cd\u4f5c\u80fd\u529b\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\uff0c\u8bfb\u5199\u5206\u79bb\u7b49"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u80fd\u591f\u5f97\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6846\u67b6\u66f4\u591a\u7684\u529f\u80fd\u652f\u6301")),(0,r.kt)("h2",{id:"914-\u5982\u4f55\u5b9a\u4e49\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.1.4 \u5982\u4f55\u5b9a\u4e49\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u4e86\uff0c\u63d0\u4f9b\u4e86\u4e24\u79cd ",(0,r.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u5b9a\u4e49\u65b9\u5f0f\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u64cd\u4f5c\u9ed8\u8ba4\u6570\u636e\u5e93"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u64cd\u4f5c N \u4e2a\u6570\u636e\u5e93")),(0,r.kt)("p",null,"\u5176\u4e2d ",(0,r.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u9ed8\u8ba4\u7ee7\u627f\u81ea ",(0,r.kt)("inlineCode",{parentName:"p"},"AppDbContext"),"\u3002"),(0,r.kt)("p",null,"\u4e0b\u9762\u662f\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u521b\u5efa\u7684\u591a\u4e2a\u4f8b\u5b50\uff1a"),(0,r.kt)("h3",{id:"9141-\u521b\u5efa\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.1.4.1 \u521b\u5efa\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,6,12}",showLineNumbers:!0,"":!0,"{1,6,12}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("\u8fde\u63a5\u5b57\u7b26\u4e32\u6216appsetting.json \u952e")]\n public class FurionDbContext : AppDbContext // \u7ee7\u627f AppDbContext<> \u7c7b\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurionDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,r.kt)("h3",{id:"9142-\u521b\u5efa\u5176\u4ed6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.1.4.2 \u521b\u5efa\u5176\u4ed6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,6,12}",showLineNumbers:!0,"":!0,"{1,6,12}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("\u8fde\u63a5\u5b57\u7b26\u4e32\u6216appsetting.json \u952e")]\n public class FurOtherDbContext : AppDbContext // \u7ee7\u627f AppDbContext<> \u7c7b\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurOtherDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u6240\u6709\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u90fd\u5e94\u8be5\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.EntityFramework.Core")," \u9879\u76ee\u4e2d\u521b\u5efa\u3002\u53e6\u5916\u5982\u679c\u7cfb\u7edf\u7528\u5230\u4e86\u591a\u4e2a\u6570\u636e\u5e93\uff0c\u90a3\u4e48\u4ece\u7b2c\u4e8c\u4e2a\u5f00\u59cb\u5fc5\u987b\u6307\u5b9a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002\u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"p"},"TDbContextLocator")," \u5c06\u5728\u4e0b\u4e00\u7ae0\u8282 \u300a",(0,r.kt)("a",{parentName:"p",href:"dbcontext-locator"},"9.2 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668"),"\u300b\u9610\u8ff0\u3002")),(0,r.kt)("h2",{id:"915-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"},"9.1.5 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u591a\u79cd\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u65b9\u5f0f\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},'AddDbPool("\u8fde\u63a5\u5b57\u7b26\u4e32")')," \u65b9\u5f0f"),(0,r.kt)("li",{parentName:"ul"},"\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},'[AppDbContext("\u8fde\u63a5\u5b57\u7b26\u4e32/Key")]')," \u7279\u6027\u65b9\u5f0f\uff08\u53ea\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext \u5b9e\u73b0\u7c7b\u6709\u6548"),"\uff09",(0,r.kt)("strong",{parentName:"li"},"\u63a8\u8350")),(0,r.kt)("li",{parentName:"ul"},"\u901a\u8fc7\u91cd\u5199 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnConfiguring(DbContextOptionsBuilder optionsBuilder)")," \u914d\u7f6e")),(0,r.kt)("h3",{id:"9151-\u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e"},"9.1.5.1 \u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {12-19} title="Furion.EntityFramework.Core\\Startup.cs"',showLineNumbers:!0,"":!0,"{12-19}":!0,title:'"Furion.EntityFramework.Core\\Startup.cs"'},'using Furion.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppStartup(600)]\n public sealed class FurEntityFrameworkCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n // \u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u652f\u6301N\u4e2a\u6570\u636e\u5e93\n services.AddDatabaseAccessor(options =>\n {\n // \u914d\u7f6e\u9ed8\u8ba4\u6570\u636e\u5e93\n options.AddDbPool(DbProvider.SqlServer, connectionMetadata:"\u8fde\u63a5\u5b57\u7b26\u4e32");\n\n // \u914d\u7f6e\u591a\u4e2a\u6570\u636e\u5e93\uff0c\u591a\u4e2a\u6570\u636e\u5e93\u5fc5\u987b\u6307\u5b9a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\n options.AddDbPool(DbProvider.Sqlite, connectionMetadata:"\u8fde\u63a5\u5b57\u7b26\u4e32");\n });\n }\n }\n}\n')),(0,r.kt)("admonition",{title:"\u65b0\u7248 MySQL \u6ce8\u610f",type:"caution"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"MySQL")," \u5728\u65b0\u7248\u672c\u5305\u4e2d\u6ce8\u518c\u6709\u6240\u4fee\u6539\uff0c\u6240\u4ee5\u6ce8\u518c\u65b9\u5f0f\u4e3a\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'services.AddDatabaseAccessor(options =>\n{\n options.AddDbPool($"{DbProvider.MySql}@8.0.22");\n});\n'))),(0,r.kt)("h3",{id:"9152-appdbcontext-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.2 ",(0,r.kt)("inlineCode",{parentName:"h3"},"[AppDbContext]")," \u65b9\u5f0f\u914d\u7f6e"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,6}",showLineNumbers:!0,"":!0,"{1,6}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("DbConnectionString")] // \u652f\u6301 `appsetting.json` \u540d\u6216 \u8fde\u63a5\u5b57\u7b26\u4e32\n public class FurionDbContext : AppDbContext\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurionDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,r.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u63a8\u8350\u4f7f\u7528\u6b64\u65b9\u5f0f\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u3002")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"[AppDbContext]"))," \u5185\u7f6e\u5c5e\u6027\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ConnectionMetadata"),"\uff1a\u652f\u6301\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u914d\u7f6e\u6587\u4ef6\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ConnectionStrings")," \u4e2d\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Key")," \u6216\u914d\u7f6e\u6587\u4ef6\u7684\u5b8c\u6574\u7684\u914d\u7f6e\u8def\u5f84\uff0c\u5982\u679c\u662f\u5185\u5b58\u6570\u636e\u5e93\uff0c\u5219\u4e3a\u6570\u636e\u5e93\u540d\u79f0\u3002"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"TablePrefix"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u8868\u7edf\u4e00\u524d\u7f00"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"TableSuffix"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u8868\u7edf\u4e00\u540e\u7f00"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ProviderName"),"\uff1a\u914d\u7f6e\u6570\u636e\u5e93\u63d0\u4f9b\u5668\u7c7b\u578b\uff0c\u4f20\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"DbProvider.Xxx")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Mode"),"\uff1a\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6a21\u5f0f\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"DbContextMode")," \u679a\u4e3e\u7c7b\u578b\uff0c\u53d6\u503c\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Cached"),"\uff1a\u7f13\u5b58\u6a21\u578b\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u9ed8\u8ba4\u503c"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Dynamic"),"\uff1a\u52a8\u6001\u6a21\u578b\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SlaveDbContextLocators"),"\uff1a\u4e3b\u4ece\u5e93\u914d\u7f6e\uff0c\u8bbe\u7f6e\u591a\u4e2a\u4ece\u5e93\u5b9a\u4f4d\u5668\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"Type[]")," \u7c7b\u578b")),(0,r.kt)("h3",{id:"9153-onconfiguring-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.3 ",(0,r.kt)("inlineCode",{parentName:"h3"},"OnConfiguring")," \u65b9\u5f0f\u914d\u7f6e"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {16-20}",showLineNumbers:!0,"":!0,"{16-20}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n public class FurionDbContext : AppDbContext\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurionDbContext(DbContextOptions options) : base(options)\n {\n }\n\n protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n {\n base.OnConfiguring(optionsBuilder);\n\n optionsBuilder.UseSqlServer("\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32");\n }\n }\n}\n')),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u8fd9\u4e09\u79cd\u65b9\u5f0f\u53ef\u4ee5\u540c\u65f6\u4f7f\u7528\uff0c\u4f46\u662f\u6709\u4f18\u5148\u7ea7\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"[AppDbContext]")," -> ",(0,r.kt)("inlineCode",{parentName:"p"},"\u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e")," -> ",(0,r.kt)("inlineCode",{parentName:"p"},"OnConfiguring"),"\uff08\u4f4e\u5230\u9ad8\uff09"),(0,r.kt)("p",{parentName:"admonition"},"\u4e5f\u5c31\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"OnConfiguring")," \u914d\u7f6e\u4f1a\u8986\u76d6 ",(0,r.kt)("inlineCode",{parentName:"p"},"\u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e")," \u914d\u7f6e\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"\u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e")," \u914d\u7f6e\u4f1a\u8986\u76d6 ",(0,r.kt)("inlineCode",{parentName:"p"},"[AppDbContext]")," \u914d\u7f6e\u6240\u914d\u7f6e\u7684\u8fde\u63a5\u5b57\u7b26\u4e32\u3002")),(0,r.kt)("h3",{id:"9154-\u5404\u7c7b\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u793a\u4f8b"},"9.1.5.4 \u5404\u7c7b\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u793a\u4f8b"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Sqlite"),"\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Data Source=./Furion.db")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"MySql"),"\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Data Source=localhost;Database=Furion;User ID=root;Password=000000;pooling=true;port=3306;sslmode=none;CharSet=utf8;")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SqlServer"),"\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Oracle"),"\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"User Id=orcl;Password=orcl;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl)))")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"PostgreSQL"),"\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"PORT=5432;DATABASE=postgres;HOST=127.0.0.1;PASSWORD=postgres;USER ID=postgres;"))),(0,r.kt)("h2",{id:"916-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4e49\u4f4d\u7f6e"},"9.1.6 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4e49\u4f4d\u7f6e"),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u9700\u5b9a\u4e49\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.EntityFramework.Core")," \u4e2d\uff0c\u4e14\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u90fd\u5fc5\u987b\u62e5\u6709\u552f\u4e00\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContextLocator")," \u5b9a\u4f4d\u5668")),(0,r.kt)("h2",{id:"917-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c"},"9.1.7 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c"),(0,r.kt)("p",null,"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u914d\u7f6e\u597d\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u540e\uff0c\u9700\u8981\u6ce8\u518c\u8be5\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u5e76\u6307\u5b9a\u6570\u636e\u5e93\u7c7b\u578b\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {11-13} title="Furion\\framework\\Furion.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"',showLineNumbers:!0,"":!0,"{11-13}":!0,title:'"Furion\\framework\\Furion.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"'},"using Furion.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppStartup(600)]\n public sealed class FurEntityFrameworkCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddDatabaseAccessor(options =>\n {\n options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),(0,r.kt)("p",null,"\u5982\u679c\u6709\u591a\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u90a3\u4e48\u4ece\u7b2c\u4e8c\u4e2a\u8d77\uff0c\u5c31\u9700\u8981\u7ed1\u5b9a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668"),"\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"options.AddDbPool(DbProvider.Sqlite); // \u7b2c\u4e00\u4e2a\u6570\u636e\u5e93\n\noptions.AddDbPool(DbProvider.SqlServer); // \u7b2c\u4e8c\u4e2a\u6570\u636e\u5e93\n\noptions.AddDbPool(DbProvider.SqlServer); // \u7b2c\u4e09\u4e2a\u6570\u636e\u5e93\n")),(0,r.kt)("h2",{id:"918-\u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c"},"9.1.8 \u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u4e3a\u4e86\u80fd\u591f\u5b9e\u73b0\u6570\u636e\u5e93\u7684\u7b80\u5355\u4f7f\u7528\u8fdb\u884c\u4e86\u6ce8\u518c\u5c01\u88c5\uff0c\u4f46\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u53ef\u80fd\u9700\u8981\u6dfb\u52a0\u66f4\u591a\u914d\u7f6e\uff0c\u8fd9\u65f6\u5c31\u9700\u8981\u4f7f\u7528\u539f\u751f\u81ea\u5b9a\u4e49\u914d\u7f6e\u65b9\u5f0f\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddDatabaseAccessor(options =>\n{\n // \u81ea\u5b9a\u4e49\u539f\u751f\u914d\u7f6e\n options.AddDb((services, builder) =>\n {\n builder.UseSqlite(...);\n }\n});\n")),(0,r.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u5feb\u901f\u89e3\u6790\u8fde\u63a5\u5b57\u7b26\u4e32\u7684\u9759\u6001\u65b9\u6cd5\uff0c\u81ea\u52a8\u6839\u636e\u540d\u79f0\u8bfb\u53d6\u914d\u7f6e\uff0c\u81ea\u52a8\u89e3\u6790 ",(0,r.kt)("inlineCode",{parentName:"p"},'[AppContext("...")]')," \u4fe1\u606f\uff0c\u5982\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u83b7\u53d6\u8fde\u63a5\u5b57\u7b26\u4e32\nvar connStr = DbProvider.GetConnectionString(/*\u8fd9\u91cc\u53ef\u5199\u53ef\u4e0d\u5199*/);\n\noptions.AddDb((services, builder) =>\n{\n builder.UseSqlite(connStr, ...);\n}\n"))),(0,r.kt)("h2",{id:"919-\u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61"},"9.1.9 \u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u662f\u5b9a\u4e49\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.EntityFramework.Core")," \u9879\u76ee\u5c42\uff0c\u5e76\u4e14\u8be5\u5c42\u4e0d\u88ab ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Application")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Core")," \u7b49\u5c42\u5f15\u7528\u3002"),(0,r.kt)("p",null,"\u6240\u4ee5\u5c31\u4e0d\u80fd\u76f4\u63a5\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Application")," \u9879\u76ee\u5c42\u76f4\u63a5\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.EntityFramework.Core")," \u5b9a\u4e49\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3002"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u63d0\u4f9b\u4e86\u4e24\u79cd\u65b9\u5f0f\u5904\u7406\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"repository.Context")," \uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61\uff0c\u8fd4\u56de\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"DbContext")," \u62bd\u8c61\u7c7b\u578b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"repository.DynamicContext"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61\uff0c\u8fd4\u56de\u7684\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"dynamic")," \u7c7b\u578b")),(0,r.kt)("p",null,"\u5982\u679c\u4f60\u53ea\u662f\u60f3\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u7684\u529f\u80fd\uff0c\u76f4\u63a5\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"repository.Context")," \u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"repository.Context.SaveChanges();\n")),(0,r.kt)("p",null,"\u5982\u679c\u4f60\u60f3\u80fd\u591f\u83b7\u53d6\u5177\u4f53\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u7c7b\u578b\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"p"},"MyDbContext"),"\uff0c\u90a3\u4e48\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"repository.DynamicContext")," \u5c31\u53ef\u4ee5\u83b7\u53d6\u5230\u5177\u4f53\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"MyDbContext")," \u7c7b\u578b\u3002\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var persons = repository.DynamicContext.Persons.Find(1);\nvar users = repository.DynamicContext.Users;\n")),(0,r.kt)("p",null,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u76f4\u63a5\u64cd\u4f5c ",(0,r.kt)("inlineCode",{parentName:"p"},"MyDbContext")," \u5b9a\u4e49\u7684\u5c5e\u6027\u548c\u65b9\u6cd5\u4e86\u3002"),(0,r.kt)("h2",{id:"9110-\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528"},"9.1.10 \u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528"),(0,r.kt)("p",null,"\u7531\u4e8e ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u9ed8\u8ba4\u6ce8\u518c\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"Scoped")," \u751f\u5b58\u5468\u671f\uff0c\u6240\u4ee5\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"IServiceScopeFactory")," \u83b7\u53d6\u6240\u6709\u670d\u52a1\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public class JobService : BackgroundService\n{\n // \u65e5\u5fd7\u5bf9\u8c61\n private readonly ILogger _logger;\n\n // \u670d\u52a1\u5de5\u5382\n private readonly IServiceScopeFactory _scopeFactory;\n public JobService(ILogger logger\n , IServiceScopeFactory scopeFactory)\n {\n _logger = logger;\n _scopeFactory = scopeFactory;\n }\n\n protected override Task ExecuteAsync(CancellationToken stoppingToken)\n {\n _logger.LogInformation("\u5199\u65e5\u5fd7~~");\n\n using (var scope = _scopeFactory.CreateScope())\n {\n var services = scope.ServiceProvider;\n\n // \u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n var dbContext = Db.GetDbContext(services);\n\n // \u83b7\u53d6\u4ed3\u50a8\n var repository = Db.GetRepository(services);\n\n // \u89e3\u6790\u5176\u4ed6\u670d\u52a1\n var otherService = services.GetService();\n }\n\n return Task.CompletedTask;\n }\n}\n')),(0,r.kt)("admonition",{title:"\u6570\u636e\u5e93\u64cd\u4f5c\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f5c\u7528\u57df\u4e2d\u5bf9",(0,r.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u6709\u4efb\u4f55\u53d8\u66f4\u64cd\u4f5c"),"\uff0c\u9700\u624b\u52a8\u8c03\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216\u5e26 ",(0,r.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u65b9\u6cd5\u3002\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"Scoped.CreateUow(handler)")," \u4ee3\u66ff\u3002")),(0,r.kt)("h2",{id:"9111-appdbcontext-\u5168\u5c40\u914d\u7f6e\u5c5e\u6027"},"9.1.11 ",(0,r.kt)("inlineCode",{parentName:"h2"},"AppDbContext")," \u5168\u5c40\u914d\u7f6e\u5c5e\u6027"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"InsertOrUpdateIgnoreNullValues"),"\uff1a\u65b0\u589e\u6216\u66f4\u65b0\u5ffd\u7565\u7a7a\u503c\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false"),"\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u5728\u6784\u9020\u51fd\u6570\u4e2d\u914d\u7f6e")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EnabledEntityStateTracked"),"\uff1a\u542f\u7528\u5b9e\u4f53\u8ddf\u8e2a\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true"),"\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u5728\u6784\u9020\u51fd\u6570\u4e2d\u914d\u7f6e")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EnabledEntityChangedListener"),"\uff1a\u542f\u7528\u5b9e\u4f53\u6570\u636e\u66f4\u6539\u76d1\u542c\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false"),"\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u5728\u6784\u9020\u51fd\u6570\u4e2d\u914d\u7f6e")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Tenant"),"\uff1a\u9ed8\u8ba4\u5185\u7f6e\u591a\u79df\u6237"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"FailedAutoRollback"),"\uff1a\u662f\u5426\u542f\u7528\u4fdd\u5b58\u5931\u8d25\u540e\u4e8b\u52a1\u81ea\u52a8\u56de\u6eda\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true"),"\uff0c\u53ef\u4ee5\u5728\u4efb\u4f55\u5730\u65b9\u914d\u7f6e")),(0,r.kt)("h2",{id:"9112-\u914d\u7f6e\u5b9e\u4f53-\u61d2\u52a0\u8f7d"},"9.1.12 \u914d\u7f6e\u5b9e\u4f53 ",(0,r.kt)("inlineCode",{parentName:"h2"},"\u61d2\u52a0\u8f7d")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u7b2c\u4e00\u6b65\uff1a\u5b89\u88c5 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u62d3\u5c55\u5305")),(0,r.kt)("p",null,"\u5728\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4e49\u6240\u5728\u7684\u5c42\u5b89\u88c5 ",(0,r.kt)("inlineCode",{parentName:"p"},"Microsoft.EntityFrameworkCore.Proxies")," \u62d3\u5c55\u5305"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u7b2c\u4e8c\u6b65\uff1a\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"AddDb")," \u65b9\u5f0f\u6ce8\u518c")),(0,r.kt)("p",null,"\u786e\u4fdd\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"AddDb")," \u6ce8\u518c\u800c\u975e ",(0,r.kt)("inlineCode",{parentName:"p"},"AddDbPool"),"\u3002"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u7b2c\u4e09\u6b65\uff1a\u91cd\u5199 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnConfiguring")," \u65b9\u6cd5")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,15}",showLineNumbers:!0,"":!0,"{13,15}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]\n public class DefaultDbContext : AppDbContext\n {\n public DefaultDbContext(DbContextOptions options) : base(options)\n {\n }\n\n protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n {\n optionsBuilder.UseLazyLoadingProxies()\n .UseSqlite(DbProvider.GetConnectionString());\n\n base.OnConfiguring(optionsBuilder);\n }\n }\n}\n')),(0,r.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"p"},"EFCore")," \u61d2\u52a0\u8f7d\u53ef\u67e5\u770b ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"https://docs.microsoft.com/zh-cn/ef/core/querying/related-data/lazy"},"\u3010EFCore - \u5ef6\u8fdf\u52a0\u8f7d\u3011"))," \u6587\u6863\u3002")),(0,r.kt)("h2",{id:"9113-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.1.13 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,r.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,r.kt)("hr",null),(0,r.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"p"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/ef/core/miscellaneous/configuring-dbcontext"},"EF Core - \u914d\u7f6e DbContext")," \u7ae0\u8282\u3002")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/a4688235.2d20d46b.js b/handbook/build/assets/js/a4688235.2d20d46b.js deleted file mode 100644 index 2d613aed56..0000000000 --- a/handbook/build/assets/js/a4688235.2d20d46b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[969],{7519:function(e,n,t){t.r(n),t.d(n,{assets:function(){return m},contentTitle:function(){return l},default:function(){return c},frontMatter:function(){return p},metadata:function(){return s},toc:function(){return u}});var o=t(3117),i=t(102),r=(t(7294),t(3905)),a=["components"],p={id:"dbcontext",title:"9.1 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",sidebar_label:"9.1 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},l=void 0,s={unversionedId:"dbcontext",id:"dbcontext",title:"9.1 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",description:"\u5982\u679c\u8fde\u63a5\u5b57\u7b26\u4e32\u662f\u914d\u7f6e\u5728\u81ea\u5b9a\u4e49\u7684 .json \u6587\u4ef6\u4e2d\uff0c\u90a3\u4e48\u5fc5\u987b\u5728 Visual Studio \u4e2d\u914d\u7f6e .json \u53f3\u952e\u5c5e\u6027\uff0c\u8bbe\u7f6e \u590d\u5236 \u8f93\u51fa\u76ee\u5f55\u4e3a \u5982\u679c\u8f83\u65b0\u5219\u590d\u5236\uff0c\u751f\u6210\u64cd\u4f5c\u4e3a\uff1a\u5185\u5bb9\u3002",source:"@site/docs/dbcontext.mdx",sourceDirName:".",slug:"/dbcontext",permalink:"/furion/docs/dbcontext",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1657169317,formattedLastUpdatedAt:"Jul 7, 2022",frontMatter:{id:"dbcontext",title:"9.1 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",sidebar_label:"9.1 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},sidebar:"docs",previous:{title:"9.0 \u5165\u95e8\u7b80\u8981 \u2728",permalink:"/furion/docs/dbcontext-start"},next:{title:"9.2 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668",permalink:"/furion/docs/dbcontext-locator"}},m={},u=[{value:"9.1.1 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"911-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:2},{value:"9.1.2 AppDbContext",id:"912-appdbcontext",level:2},{value:"9.1.3 AppDbContext \u548c DbContext \u533a\u522b",id:"913-appdbcontext-\u548c-dbcontext-\u533a\u522b",level:2},{value:"9.1.4 \u5982\u4f55\u5b9a\u4e49\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"914-\u5982\u4f55\u5b9a\u4e49\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:2},{value:"9.1.4.1 \u521b\u5efa\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"9141-\u521b\u5efa\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:3},{value:"9.1.4.2 \u521b\u5efa\u5176\u4ed6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"9142-\u521b\u5efa\u5176\u4ed6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:3},{value:"9.1.5 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32",id:"915-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32",level:2},{value:"9.1.5.1 \u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e",id:"9151-\u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e",level:3},{value:"9.1.5.2 [AppDbContext] \u65b9\u5f0f\u914d\u7f6e",id:"9152-appdbcontext-\u65b9\u5f0f\u914d\u7f6e",level:3},{value:"9.1.5.3 OnConfiguring \u65b9\u5f0f\u914d\u7f6e",id:"9153-onconfiguring-\u65b9\u5f0f\u914d\u7f6e",level:3},{value:"9.1.5.4 \u5404\u7c7b\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u793a\u4f8b",id:"9154-\u5404\u7c7b\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u793a\u4f8b",level:3},{value:"9.1.6 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4e49\u4f4d\u7f6e",id:"916-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4e49\u4f4d\u7f6e",level:2},{value:"9.1.7 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c",id:"917-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c",level:2},{value:"9.1.8 \u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c",id:"918-\u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c",level:2},{value:"9.1.9 \u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61",id:"919-\u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61",level:2},{value:"9.1.10 \u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528",id:"9110-\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528",level:2},{value:"9.1.11 AppDbContext \u5168\u5c40\u914d\u7f6e\u5c5e\u6027",id:"9111-appdbcontext-\u5168\u5c40\u914d\u7f6e\u5c5e\u6027",level:2},{value:"9.1.12 \u914d\u7f6e\u5b9e\u4f53 \u61d2\u52a0\u8f7d",id:"9112-\u914d\u7f6e\u5b9e\u4f53-\u61d2\u52a0\u8f7d",level:2},{value:"9.1.13 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9113-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:u};function c(e){var n=e.components,t=(0,i.Z)(e,a);return(0,r.kt)("wrapper",(0,o.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("admonition",{title:"\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u6ce8\u610f\u4e8b\u9879",type:"warning"},(0,r.kt)("p",{parentName:"admonition"},"\u5982\u679c\u8fde\u63a5\u5b57\u7b26\u4e32\u662f\u914d\u7f6e\u5728\u81ea\u5b9a\u4e49\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u4e2d\uff0c\u90a3\u4e48\u5fc5\u987b\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u4e2d\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},".json")," \u53f3\u952e\u5c5e\u6027\uff0c\u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"\u590d\u5236")," \u8f93\u51fa\u76ee\u5f55\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"\u5982\u679c\u8f83\u65b0\u5219\u590d\u5236"),"\uff0c\u751f\u6210\u64cd\u4f5c\u4e3a\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"\u5185\u5bb9"),"\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u5426\u5219\u5c31\u4f1a\u63d0\u793a\u627e\u4e0d\u5230\u914d\u7f6e\u6216\u8fde\u63a5\u5b57\u7b26\u4e32\u7684\u9519\u8bef\u3002")),(0,r.kt)("h2",{id:"911-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.1.1 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,r.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u662f\u8d1f\u8d23\u548c\u6570\u636e\u5e93\u4ea4\u4e92\u7684\u5bf9\u8c61\uff0c\u63d0\u4f9b\u7a0b\u5e8f\u5bf9\u6570\u636e\u5e93\u5b58\u53d6\u63d0\u4f9b\u4e86\u5927\u91cf\u7684\u65b9\u6cd5\u3002"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u96c6\u6210\u4e86\u5fae\u8f6f\u4eb2\u513f\u5b50\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"EntityFramework Core")," \uff0c\u4e5f\u5c31\u662f\u901a\u5e38\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6307\u7684\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u7c7b\u6216\u5b83\u7684\u5b9e\u73b0\u7c7b\u3002"),(0,r.kt)("h2",{id:"912-appdbcontext"},"9.1.2 ",(0,r.kt)("inlineCode",{parentName:"h2"},"AppDbContext")),(0,r.kt)("p",null,"\u5728\u6211\u4eec\u5b9e\u9645\u9879\u76ee\u5f00\u53d1\u8fc7\u7a0b\u4e2d\uff0c\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"EFCore")," \u63d0\u4f9b\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u64cd\u4f5c\u5bf9\u8c61\u64cd\u4f5c\u6570\u636e\u5e93\u6709\u4e9b\u7e41\u7410\u548c\u590d\u6742\uff0c\u4e14\u9ed8\u8ba4\u4e0d\u5177\u5907\u8bfb\u5199\u5206\u79bb\u3001\u591a\u5e93\u7b49\u64cd\u4f5c\u529f\u80fd\u3002"),(0,r.kt)("p",null,"\u6240\u4ee5\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u8be5\u4e0a\u4e0b\u6587\u7ee7\u627f\u81ea ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext"),"\u3002"),(0,r.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u540e\u7eed\u7ae0\u8282\uff0c\u7686\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"EFCore")," \u4ee3\u66ff ",(0,r.kt)("inlineCode",{parentName:"p"},"EntityFramework Core"),"\u3002")),(0,r.kt)("h2",{id:"913-appdbcontext-\u548c-dbcontext-\u533a\u522b"},"9.1.3 ",(0,r.kt)("inlineCode",{parentName:"h2"},"AppDbContext")," \u548c ",(0,r.kt)("inlineCode",{parentName:"h2"},"DbContext")," \u533a\u522b"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u7ee7\u627f\u81ea ",(0,r.kt)("inlineCode",{parentName:"li"},"DbContext"),"\uff0c\u5177\u5907 ",(0,r.kt)("inlineCode",{parentName:"li"},"DbContext")," \u6240\u6709\u529f\u80fd\u3002"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u6cdb\u578b\u7248\u672c\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u81ea\u52a8\u914d\u7f6e\u5b9e\u4f53\u4fe1\u606f\uff0c\u65e0\u9700\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnModelCreating")," \u4e2d\u914d\u7f6e"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u5185\u7f6e\u591a\u79df\u6237\u652f\u6301"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u5168\u5c40\u6a21\u578b\u914d\u7f6e\u62e6\u622a\u5668"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u6570\u636e\u63d0\u4ea4\u66f4\u6539\u591a\u4e2a\u4e8b\u4ef6"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u63d0\u4f9b\u66f4\u52a0\u5f3a\u5927\u7684\u6a21\u578b\u64cd\u4f5c\u80fd\u529b\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\uff0c\u8bfb\u5199\u5206\u79bb\u7b49"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u80fd\u591f\u5f97\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u6846\u67b6\u66f4\u591a\u7684\u529f\u80fd\u652f\u6301")),(0,r.kt)("h2",{id:"914-\u5982\u4f55\u5b9a\u4e49\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.1.4 \u5982\u4f55\u5b9a\u4e49\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u4e86\uff0c\u63d0\u4f9b\u4e86\u4e24\u79cd ",(0,r.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u5b9a\u4e49\u65b9\u5f0f\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u64cd\u4f5c\u9ed8\u8ba4\u6570\u636e\u5e93"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext")," \u64cd\u4f5c N \u4e2a\u6570\u636e\u5e93")),(0,r.kt)("p",null,"\u5176\u4e2d ",(0,r.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u9ed8\u8ba4\u7ee7\u627f\u81ea ",(0,r.kt)("inlineCode",{parentName:"p"},"AppDbContext"),"\u3002"),(0,r.kt)("p",null,"\u4e0b\u9762\u662f\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u521b\u5efa\u7684\u591a\u4e2a\u4f8b\u5b50\uff1a"),(0,r.kt)("h3",{id:"9141-\u521b\u5efa\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.1.4.1 \u521b\u5efa\u9ed8\u8ba4\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,6,12}",showLineNumbers:!0,"":!0,"{1,6,12}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("\u8fde\u63a5\u5b57\u7b26\u4e32\u6216appsetting.json \u952e")]\n public class FurionDbContext : AppDbContext // \u7ee7\u627f AppDbContext<> \u7c7b\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurionDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,r.kt)("h3",{id:"9142-\u521b\u5efa\u5176\u4ed6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.1.4.2 \u521b\u5efa\u5176\u4ed6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,6,12}",showLineNumbers:!0,"":!0,"{1,6,12}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("\u8fde\u63a5\u5b57\u7b26\u4e32\u6216appsetting.json \u952e")]\n public class FurOtherDbContext : AppDbContext // \u7ee7\u627f AppDbContext<> \u7c7b\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurOtherDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u6240\u6709\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u90fd\u5e94\u8be5\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.EntityFramework.Core")," \u9879\u76ee\u4e2d\u521b\u5efa\u3002\u53e6\u5916\u5982\u679c\u7cfb\u7edf\u7528\u5230\u4e86\u591a\u4e2a\u6570\u636e\u5e93\uff0c\u90a3\u4e48\u4ece\u7b2c\u4e8c\u4e2a\u5f00\u59cb\u5fc5\u987b\u6307\u5b9a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002\u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"p"},"TDbContextLocator")," \u5c06\u5728\u4e0b\u4e00\u7ae0\u8282 \u300a",(0,r.kt)("a",{parentName:"p",href:"dbcontext-locator"},"9.2 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668"),"\u300b\u9610\u8ff0\u3002")),(0,r.kt)("h2",{id:"915-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"},"9.1.5 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u591a\u79cd\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u65b9\u5f0f\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},'AddDbPool("\u8fde\u63a5\u5b57\u7b26\u4e32")')," \u65b9\u5f0f"),(0,r.kt)("li",{parentName:"ul"},"\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},'[AppDbContext("\u8fde\u63a5\u5b57\u7b26\u4e32/Key")]')," \u7279\u6027\u65b9\u5f0f\uff08\u53ea\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"AppDbContext \u5b9e\u73b0\u7c7b\u6709\u6548"),"\uff09",(0,r.kt)("strong",{parentName:"li"},"\u63a8\u8350")),(0,r.kt)("li",{parentName:"ul"},"\u901a\u8fc7\u91cd\u5199 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnConfiguring(DbContextOptionsBuilder optionsBuilder)")," \u914d\u7f6e")),(0,r.kt)("h3",{id:"9151-\u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e"},"9.1.5.1 \u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {12-19} title="Furion.EntityFramework.Core\\Startup.cs"',showLineNumbers:!0,"":!0,"{12-19}":!0,title:'"Furion.EntityFramework.Core\\Startup.cs"'},'using Furion.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppStartup(600)]\n public sealed class FurEntityFrameworkCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n // \u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u652f\u6301N\u4e2a\u6570\u636e\u5e93\n services.AddDatabaseAccessor(options =>\n {\n // \u914d\u7f6e\u9ed8\u8ba4\u6570\u636e\u5e93\n options.AddDbPool(DbProvider.SqlServer, connectionMetadata:"\u8fde\u63a5\u5b57\u7b26\u4e32");\n\n // \u914d\u7f6e\u591a\u4e2a\u6570\u636e\u5e93\uff0c\u591a\u4e2a\u6570\u636e\u5e93\u5fc5\u987b\u6307\u5b9a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\n options.AddDbPool(DbProvider.Sqlite, connectionMetadata:"\u8fde\u63a5\u5b57\u7b26\u4e32");\n });\n }\n }\n}\n')),(0,r.kt)("admonition",{title:"\u65b0\u7248 MySQL \u6ce8\u610f",type:"caution"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"MySQL")," \u5728\u65b0\u7248\u672c\u5305\u4e2d\u6ce8\u518c\u6709\u6240\u4fee\u6539\uff0c\u6240\u4ee5\u6ce8\u518c\u65b9\u5f0f\u4e3a\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'services.AddDatabaseAccessor(options =>\n{\n options.AddDbPool($"{DbProvider.MySql}@8.0.22");\n});\n'))),(0,r.kt)("h3",{id:"9152-appdbcontext-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.2 ",(0,r.kt)("inlineCode",{parentName:"h3"},"[AppDbContext]")," \u65b9\u5f0f\u914d\u7f6e"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,6}",showLineNumbers:!0,"":!0,"{1,6}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("DbConnectionString")] // \u652f\u6301 `appsetting.json` \u540d\u6216 \u8fde\u63a5\u5b57\u7b26\u4e32\n public class FurionDbContext : AppDbContext\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurionDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,r.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u63a8\u8350\u4f7f\u7528\u6b64\u65b9\u5f0f\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u3002")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"[AppDbContext]"))," \u5185\u7f6e\u5c5e\u6027\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ConnectionMetadata"),"\uff1a\u652f\u6301\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u914d\u7f6e\u6587\u4ef6\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"ConnectionStrings")," \u4e2d\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Key")," \u6216\u914d\u7f6e\u6587\u4ef6\u7684\u5b8c\u6574\u7684\u914d\u7f6e\u8def\u5f84\uff0c\u5982\u679c\u662f\u5185\u5b58\u6570\u636e\u5e93\uff0c\u5219\u4e3a\u6570\u636e\u5e93\u540d\u79f0\u3002"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"TablePrefix"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u8868\u7edf\u4e00\u524d\u7f00"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"TableSuffix"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u8868\u7edf\u4e00\u540e\u7f00"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ProviderName"),"\uff1a\u914d\u7f6e\u6570\u636e\u5e93\u63d0\u4f9b\u5668\u7c7b\u578b\uff0c\u4f20\u5165 ",(0,r.kt)("inlineCode",{parentName:"li"},"DbProvider.Xxx")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Mode"),"\uff1a\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6a21\u5f0f\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"DbContextMode")," \u679a\u4e3e\u7c7b\u578b\uff0c\u53d6\u503c\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Cached"),"\uff1a\u7f13\u5b58\u6a21\u578b\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u9ed8\u8ba4\u503c"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Dynamic"),"\uff1a\u52a8\u6001\u6a21\u578b\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SlaveDbContextLocators"),"\uff1a\u4e3b\u4ece\u5e93\u914d\u7f6e\uff0c\u8bbe\u7f6e\u591a\u4e2a\u4ece\u5e93\u5b9a\u4f4d\u5668\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"Type[]")," \u7c7b\u578b")),(0,r.kt)("h3",{id:"9153-onconfiguring-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.3 ",(0,r.kt)("inlineCode",{parentName:"h3"},"OnConfiguring")," \u65b9\u5f0f\u914d\u7f6e"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {16-20}",showLineNumbers:!0,"":!0,"{16-20}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n public class FurionDbContext : AppDbContext\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurionDbContext(DbContextOptions options) : base(options)\n {\n }\n\n protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n {\n base.OnConfiguring(optionsBuilder);\n\n optionsBuilder.UseSqlServer("\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32");\n }\n }\n}\n')),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u8fd9\u4e09\u79cd\u65b9\u5f0f\u53ef\u4ee5\u540c\u65f6\u4f7f\u7528\uff0c\u4f46\u662f\u6709\u4f18\u5148\u7ea7\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"[AppDbContext]")," -> ",(0,r.kt)("inlineCode",{parentName:"p"},"\u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e")," -> ",(0,r.kt)("inlineCode",{parentName:"p"},"OnConfiguring"),"\uff08\u4f4e\u5230\u9ad8\uff09"),(0,r.kt)("p",{parentName:"admonition"},"\u4e5f\u5c31\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"OnConfiguring")," \u914d\u7f6e\u4f1a\u8986\u76d6 ",(0,r.kt)("inlineCode",{parentName:"p"},"\u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e")," \u914d\u7f6e\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"\u5728\u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\u65f6\u914d\u7f6e")," \u914d\u7f6e\u4f1a\u8986\u76d6 ",(0,r.kt)("inlineCode",{parentName:"p"},"[AppDbContext]")," \u914d\u7f6e\u6240\u914d\u7f6e\u7684\u8fde\u63a5\u5b57\u7b26\u4e32\u3002")),(0,r.kt)("h3",{id:"9154-\u5404\u7c7b\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u793a\u4f8b"},"9.1.5.4 \u5404\u7c7b\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u793a\u4f8b"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Sqlite"),"\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Data Source=./Furion.db")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"MySql"),"\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Data Source=localhost;Database=Furion;User ID=root;Password=000000;pooling=true;port=3306;sslmode=none;CharSet=utf8;")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SqlServer"),"\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Oracle"),"\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"User Id=orcl;Password=orcl;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl)))")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"PostgreSQL"),"\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"PORT=5432;DATABASE=postgres;HOST=127.0.0.1;PASSWORD=postgres;USER ID=postgres;"))),(0,r.kt)("h2",{id:"916-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4e49\u4f4d\u7f6e"},"9.1.6 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4e49\u4f4d\u7f6e"),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u9700\u5b9a\u4e49\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.EntityFramework.Core")," \u4e2d\uff0c\u4e14\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u90fd\u5fc5\u987b\u62e5\u6709\u552f\u4e00\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContextLocator")," \u5b9a\u4f4d\u5668")),(0,r.kt)("h2",{id:"917-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c"},"9.1.7 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c"),(0,r.kt)("p",null,"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u914d\u7f6e\u597d\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u540e\uff0c\u9700\u8981\u6ce8\u518c\u8be5\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u5e76\u6307\u5b9a\u6570\u636e\u5e93\u7c7b\u578b\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {11-13} title="Furion\\framework\\Furion.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"',showLineNumbers:!0,"":!0,"{11-13}":!0,title:'"Furion\\framework\\Furion.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"'},"using Furion.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppStartup(600)]\n public sealed class FurEntityFrameworkCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddDatabaseAccessor(options =>\n {\n options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),(0,r.kt)("p",null,"\u5982\u679c\u6709\u591a\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u90a3\u4e48\u4ece\u7b2c\u4e8c\u4e2a\u8d77\uff0c\u5c31\u9700\u8981\u7ed1\u5b9a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668"),"\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"options.AddDbPool(DbProvider.Sqlite); // \u7b2c\u4e00\u4e2a\u6570\u636e\u5e93\n\noptions.AddDbPool(DbProvider.SqlServer); // \u7b2c\u4e8c\u4e2a\u6570\u636e\u5e93\n\noptions.AddDbPool(DbProvider.SqlServer); // \u7b2c\u4e09\u4e2a\u6570\u636e\u5e93\n")),(0,r.kt)("h2",{id:"918-\u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c"},"9.1.8 \u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u4e3a\u4e86\u80fd\u591f\u5b9e\u73b0\u6570\u636e\u5e93\u7684\u7b80\u5355\u4f7f\u7528\u8fdb\u884c\u4e86\u6ce8\u518c\u5c01\u88c5\uff0c\u4f46\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u53ef\u80fd\u9700\u8981\u6dfb\u52a0\u66f4\u591a\u914d\u7f6e\uff0c\u8fd9\u65f6\u5c31\u9700\u8981\u4f7f\u7528\u539f\u751f\u81ea\u5b9a\u4e49\u914d\u7f6e\u65b9\u5f0f\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddDatabaseAccessor(options =>\n{\n // \u81ea\u5b9a\u4e49\u539f\u751f\u914d\u7f6e\n options.AddDb((services, builder) =>\n {\n builder.UseSqlite(...);\n }\n});\n")),(0,r.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u5feb\u901f\u89e3\u6790\u8fde\u63a5\u5b57\u7b26\u4e32\u7684\u9759\u6001\u65b9\u6cd5\uff0c\u81ea\u52a8\u6839\u636e\u540d\u79f0\u8bfb\u53d6\u914d\u7f6e\uff0c\u81ea\u52a8\u89e3\u6790 ",(0,r.kt)("inlineCode",{parentName:"p"},'[AppContext("...")]')," \u4fe1\u606f\uff0c\u5982\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u83b7\u53d6\u8fde\u63a5\u5b57\u7b26\u4e32\nvar connStr = DbProvider.GetConnectionString(/*\u8fd9\u91cc\u53ef\u5199\u53ef\u4e0d\u5199*/);\n\noptions.AddDb((services, builder) =>\n{\n builder.UseSqlite(connStr, ...);\n}\n"))),(0,r.kt)("h2",{id:"919-\u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61"},"9.1.9 \u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u662f\u5b9a\u4e49\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.EntityFramework.Core")," \u9879\u76ee\u5c42\uff0c\u5e76\u4e14\u8be5\u5c42\u4e0d\u88ab ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Application")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Core")," \u7b49\u5c42\u5f15\u7528\u3002"),(0,r.kt)("p",null,"\u6240\u4ee5\u5c31\u4e0d\u80fd\u76f4\u63a5\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Application")," \u9879\u76ee\u5c42\u76f4\u63a5\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.EntityFramework.Core")," \u5b9a\u4e49\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3002"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u63d0\u4f9b\u4e86\u4e24\u79cd\u65b9\u5f0f\u5904\u7406\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"repository.Context")," \uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61\uff0c\u8fd4\u56de\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"DbContext")," \u62bd\u8c61\u7c7b\u578b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"repository.DynamicContext"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61\uff0c\u8fd4\u56de\u7684\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"dynamic")," \u7c7b\u578b")),(0,r.kt)("p",null,"\u5982\u679c\u4f60\u53ea\u662f\u60f3\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u7684\u529f\u80fd\uff0c\u76f4\u63a5\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"repository.Context")," \u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"repository.Context.SaveChanges();\n")),(0,r.kt)("p",null,"\u5982\u679c\u4f60\u60f3\u80fd\u591f\u83b7\u53d6\u5177\u4f53\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u7c7b\u578b\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"p"},"MyDbContext"),"\uff0c\u90a3\u4e48\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"repository.DynamicContext")," \u5c31\u53ef\u4ee5\u83b7\u53d6\u5230\u5177\u4f53\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"MyDbContext")," \u7c7b\u578b\u3002\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var persons = repository.DynamicContext.Persons.Find(1);\nvar users = repository.DynamicContext.Users;\n")),(0,r.kt)("p",null,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u76f4\u63a5\u64cd\u4f5c ",(0,r.kt)("inlineCode",{parentName:"p"},"MyDbContext")," \u5b9a\u4e49\u7684\u5c5e\u6027\u548c\u65b9\u6cd5\u4e86\u3002"),(0,r.kt)("h2",{id:"9110-\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528"},"9.1.10 \u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528"),(0,r.kt)("p",null,"\u7531\u4e8e ",(0,r.kt)("inlineCode",{parentName:"p"},"DbContext")," \u9ed8\u8ba4\u6ce8\u518c\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"Scoped")," \u751f\u5b58\u5468\u671f\uff0c\u6240\u4ee5\u5728\u540e\u53f0\u4efb\u52a1\u4e2d\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"IServiceScopeFactory")," \u83b7\u53d6\u6240\u6709\u670d\u52a1\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public class JobService : BackgroundService\n{\n // \u65e5\u5fd7\u5bf9\u8c61\n private readonly ILogger _logger;\n\n // \u670d\u52a1\u5de5\u5382\n private readonly IServiceScopeFactory _scopeFactory;\n public JobService(ILogger logger\n , IServiceScopeFactory scopeFactory)\n {\n _logger = logger;\n _scopeFactory = scopeFactory;\n }\n\n protected override Task ExecuteAsync(CancellationToken stoppingToken)\n {\n _logger.LogInformation("\u5199\u65e5\u5fd7~~");\n\n using (var scope = _scopeFactory.CreateScope())\n {\n var services = scope.ServiceProvider;\n\n // \u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n var dbContext = Db.GetDbContext(services);\n\n // \u83b7\u53d6\u4ed3\u50a8\n var repository = Db.GetRepository(services);\n\n // \u89e3\u6790\u5176\u4ed6\u670d\u52a1\n var otherService = services.GetService();\n }\n\n return Task.CompletedTask;\n }\n}\n')),(0,r.kt)("admonition",{title:"\u6570\u636e\u5e93\u64cd\u4f5c\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f5c\u7528\u57df\u4e2d\u5bf9",(0,r.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u6709\u4efb\u4f55\u53d8\u66f4\u64cd\u4f5c"),"\uff0c\u9700\u624b\u52a8\u8c03\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"SaveChanges")," \u6216\u5e26 ",(0,r.kt)("inlineCode",{parentName:"p"},"Now")," \u7ed3\u5c3e\u7684\u65b9\u6cd5\u3002\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"Scoped.CreateUow(handler)")," \u4ee3\u66ff\u3002")),(0,r.kt)("h2",{id:"9111-appdbcontext-\u5168\u5c40\u914d\u7f6e\u5c5e\u6027"},"9.1.11 ",(0,r.kt)("inlineCode",{parentName:"h2"},"AppDbContext")," \u5168\u5c40\u914d\u7f6e\u5c5e\u6027"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"InsertOrUpdateIgnoreNullValues"),"\uff1a\u65b0\u589e\u6216\u66f4\u65b0\u5ffd\u7565\u7a7a\u503c\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false"),"\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u5728\u6784\u9020\u51fd\u6570\u4e2d\u914d\u7f6e")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EnabledEntityStateTracked"),"\uff1a\u542f\u7528\u5b9e\u4f53\u8ddf\u8e2a\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true"),"\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u5728\u6784\u9020\u51fd\u6570\u4e2d\u914d\u7f6e")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EnabledEntityChangedListener"),"\uff1a\u542f\u7528\u5b9e\u4f53\u6570\u636e\u66f4\u6539\u76d1\u542c\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false"),"\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u5728\u6784\u9020\u51fd\u6570\u4e2d\u914d\u7f6e")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Tenant"),"\uff1a\u9ed8\u8ba4\u5185\u7f6e\u591a\u79df\u6237"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"FailedAutoRollback"),"\uff1a\u662f\u5426\u542f\u7528\u4fdd\u5b58\u5931\u8d25\u540e\u4e8b\u52a1\u81ea\u52a8\u56de\u6eda\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true"),"\uff0c\u53ef\u4ee5\u5728\u4efb\u4f55\u5730\u65b9\u914d\u7f6e")),(0,r.kt)("h2",{id:"9112-\u914d\u7f6e\u5b9e\u4f53-\u61d2\u52a0\u8f7d"},"9.1.12 \u914d\u7f6e\u5b9e\u4f53 ",(0,r.kt)("inlineCode",{parentName:"h2"},"\u61d2\u52a0\u8f7d")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u7b2c\u4e00\u6b65\uff1a\u5b89\u88c5 ",(0,r.kt)("inlineCode",{parentName:"li"},"EFCore")," \u62d3\u5c55\u5305")),(0,r.kt)("p",null,"\u5728\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4e49\u6240\u5728\u7684\u5c42\u5b89\u88c5 ",(0,r.kt)("inlineCode",{parentName:"p"},"Microsoft.EntityFrameworkCore.Proxies")," \u62d3\u5c55\u5305"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u7b2c\u4e8c\u6b65\uff1a\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"AddDb")," \u65b9\u5f0f\u6ce8\u518c")),(0,r.kt)("p",null,"\u786e\u4fdd\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"AddDb")," \u6ce8\u518c\u800c\u975e ",(0,r.kt)("inlineCode",{parentName:"p"},"AddDbPool"),"\u3002"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u7b2c\u4e09\u6b65\uff1a\u91cd\u5199 ",(0,r.kt)("inlineCode",{parentName:"li"},"OnConfiguring")," \u65b9\u6cd5")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,15}",showLineNumbers:!0,"":!0,"{13,15}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]\n public class DefaultDbContext : AppDbContext\n {\n public DefaultDbContext(DbContextOptions options) : base(options)\n {\n }\n\n protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n {\n optionsBuilder.UseLazyLoadingProxies()\n .UseSqlite(DbProvider.GetConnectionString());\n\n base.OnConfiguring(optionsBuilder);\n }\n }\n}\n')),(0,r.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"p"},"EFCore")," \u61d2\u52a0\u8f7d\u53ef\u67e5\u770b ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("a",{parentName:"strong",href:"https://docs.microsoft.com/zh-cn/ef/core/querying/related-data/lazy"},"\u3010EFCore - \u5ef6\u8fdf\u52a0\u8f7d\u3011"))," \u6587\u6863\u3002")),(0,r.kt)("h2",{id:"9113-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.1.13 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,r.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,r.kt)("hr",null),(0,r.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"p"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/ef/core/miscellaneous/configuring-dbcontext"},"EF Core - \u914d\u7f6e DbContext")," \u7ae0\u8282\u3002")))}c.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return m},kt:function(){return c}});var o=t(7294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function a(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=o.createContext({}),s=function(e){var n=o.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},m=function(e){var n=s(e.components);return o.createElement(l.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},d=o.forwardRef((function(e,n){var t=e.components,i=e.mdxType,r=e.originalType,l=e.parentName,m=p(e,["components","mdxType","originalType","parentName"]),d=s(t),c=i,k=d["".concat(l,".").concat(c)]||d[c]||u[c]||r;return t?o.createElement(k,a(a({ref:n},m),{},{components:t})):o.createElement(k,a({ref:n},m))}));function c(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var r=t.length,a=new Array(r);a[0]=d;var p={};for(var l in n)hasOwnProperty.call(n,l)&&(p[l]=n[l]);p.originalType=e,p.mdxType="string"==typeof e?e:i,a[1]=p;for(var s=2;s")," \u5373\u53ef\u3002"),(0,a.kt)("p",null,"\u5982\uff1a\u53ea\u6709\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4e49\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]\n public class DefaultDbContext : AppDbContext // \u65e0\u9700\u6307\u5b9a\u5b9a\u4f4d\u5668\n {\n public DefaultDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u5173\u4e8e\u591a\u6570\u636e\u5e93\u5b9a\u4f4d\u5668",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u6570\u636e\u5e93\u7684\u5b9a\u4f4d\u5668\u9ed8\u8ba4\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"MasterDbContextLocator"),"\uff0c\u6240\u4ee5\u65e0\u9700\u663e\u793a\u6307\u5b9a\u5b9a\u4f4d\u5668\uff0c",(0,a.kt)("strong",{parentName:"p"},"\u4f46\u4ece\u7b2c\u4e8c\u4e2a\u6570\u636e\u5e93\u5f00\u59cb\uff0c\u90fd\u5fc5\u987b\u6307\u5b9a\u6570\u636e\u5e93\u5b9a\u4f4d\u5668"),"\u3002\u5982\uff1a"),(0,a.kt)("ul",{parentName:"admonition"},(0,a.kt)("li",{parentName:"ul"},"\u6ce8\u518c\u4e0a\u4e0b\u6587\uff1a")),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"options.AddDbPool();\n")),(0,a.kt)("ul",{parentName:"admonition"},(0,a.kt)("li",{parentName:"ul"},"\u5b9a\u4e49\u4e0a\u4e0b\u6587")),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]\n public class OtherDbContext : AppDbContext // \u9700\u6307\u5b9a\u5b9a\u4f4d\u5668\n {\n public OtherDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,a.kt)("p",{parentName:"admonition"},"\u53e6\u5916\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Entity/IEntity")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"IRepository")," \u7b49\u90fd\u9700\u8981\u6307\u5b9a\u5b9a\u4f4d\u5668\uff0c\u5982\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"IEntity"),"\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"IRepository")," \u64cd\u4f5c\u3002")),(0,a.kt)("h2",{id:"925-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u652f\u6301\u5bf9\u8c61"},"9.2.5 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u652f\u6301\u5bf9\u8c61"),(0,a.kt)("p",null,"\u76ee\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u652f\u6301\u4ee5\u4e0b\u591a\u4e2a\u5bf9\u8c61\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"AppDbContext"),"\uff1a\u6570\u636e\u4e0a\u4e0b\u6587"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IRepository"),"\uff1a\u5b9e\u4f53\u4ed3\u50a8"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ISqlRepository"),": Sql \u64cd\u4f5c\u4ed3\u50a8"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IDbRepository"),": \u7279\u5b9a\u6570\u636e\u5e93\u64cd\u4f5c\u4ed3\u50a8"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IMSRepository"),": \u8bfb\u5199\u5206\u79bb\u4ed3\u50a8"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Func"),"\uff1a\u4f9d\u8d56\u6ce8\u5165\u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Entity")," \uff1a\u5b9e\u4f53\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"EntityBase"),"\uff1a\u5b9e\u4f53\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"EntityNotKey"),"\uff1a\u65e0\u952e\u5b9e\u4f53\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IEntity"),"\uff1a\u9ed8\u8ba4\u5b9e\u4f53\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IEntitySeedData"),"\uff1a\u79cd\u5b50\u6570\u636e\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IEntityTypeBuilder"),"\uff1a\u5b9e\u4f53\u7c7b\u578b\u6784\u5efa\u5668"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IModelBuilderFilter"),"\uff1a\u6a21\u578b\u6784\u5efa\u7b5b\u9009\u5668"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"[QueryableFunction(DbContextLocators=Type[])]"),"\uff1a\u67e5\u8be2\u51fd\u6570")),(0,a.kt)("h2",{id:"926-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.2.6 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}d.isMDXComponent=!0},3905:function(t,e,n){n.d(e,{Zo:function(){return u},kt:function(){return d}});var o=n(7294);function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function a(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);e&&(o=o.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,o)}return n}function i(t){for(var e=1;e=0||(r[n]=t[n]);return r}(t,e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(r[n]=t[n])}return r}var p=o.createContext({}),c=function(t){var e=o.useContext(p),n=e;return t&&(n="function"==typeof t?t(e):i(i({},e),t)),n},u=function(t){var e=c(t.components);return o.createElement(p.Provider,{value:e},t.children)},m={inlineCode:"code",wrapper:function(t){var e=t.children;return o.createElement(o.Fragment,{},e)}},s=o.forwardRef((function(t,e){var n=t.components,r=t.mdxType,a=t.originalType,p=t.parentName,u=l(t,["components","mdxType","originalType","parentName"]),s=c(n),d=r,k=s["".concat(p,".").concat(d)]||s[d]||m[d]||a;return n?o.createElement(k,i(i({ref:e},u),{},{components:n})):o.createElement(k,i({ref:e},u))}));function d(t,e){var n=arguments,r=e&&e.mdxType;if("string"==typeof t||r){var a=n.length,i=new Array(a);i[0]=s;var l={};for(var p in e)hasOwnProperty.call(e,p)&&(l[p]=e[p]);l.originalType=t,l.mdxType="string"==typeof t?t:r,i[1]=l;for(var c=2;c=0||(r[n]=t[n]);return r}(t,e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(r[n]=t[n])}return r}var p=o.createContext({}),c=function(t){var e=o.useContext(p),n=e;return t&&(n="function"==typeof t?t(e):i(i({},e),t)),n},u=function(t){var e=c(t.components);return o.createElement(p.Provider,{value:e},t.children)},m={inlineCode:"code",wrapper:function(t){var e=t.children;return o.createElement(o.Fragment,{},e)}},s=o.forwardRef((function(t,e){var n=t.components,r=t.mdxType,a=t.originalType,p=t.parentName,u=l(t,["components","mdxType","originalType","parentName"]),s=c(n),d=r,k=s["".concat(p,".").concat(d)]||s[d]||m[d]||a;return n?o.createElement(k,i(i({ref:e},u),{},{components:n})):o.createElement(k,i({ref:e},u))}));function d(t,e){var n=arguments,r=e&&e.mdxType;if("string"==typeof t||r){var a=n.length,i=new Array(a);i[0]=s;var l={};for(var p in e)hasOwnProperty.call(e,p)&&(l[p]=e[p]);l.originalType=t,l.mdxType="string"==typeof t?t:r,i[1]=l;for(var c=2;c")," \u5373\u53ef\u3002"),(0,a.kt)("p",null,"\u5982\uff1a\u53ea\u6709\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4e49\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]\n public class DefaultDbContext : AppDbContext // \u65e0\u9700\u6307\u5b9a\u5b9a\u4f4d\u5668\n {\n public DefaultDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u5173\u4e8e\u591a\u6570\u636e\u5e93\u5b9a\u4f4d\u5668",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u6570\u636e\u5e93\u7684\u5b9a\u4f4d\u5668\u9ed8\u8ba4\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"MasterDbContextLocator"),"\uff0c\u6240\u4ee5\u65e0\u9700\u663e\u793a\u6307\u5b9a\u5b9a\u4f4d\u5668\uff0c",(0,a.kt)("strong",{parentName:"p"},"\u4f46\u4ece\u7b2c\u4e8c\u4e2a\u6570\u636e\u5e93\u5f00\u59cb\uff0c\u90fd\u5fc5\u987b\u6307\u5b9a\u6570\u636e\u5e93\u5b9a\u4f4d\u5668"),"\u3002\u5982\uff1a"),(0,a.kt)("ul",{parentName:"admonition"},(0,a.kt)("li",{parentName:"ul"},"\u6ce8\u518c\u4e0a\u4e0b\u6587\uff1a")),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"options.AddDbPool();\n")),(0,a.kt)("ul",{parentName:"admonition"},(0,a.kt)("li",{parentName:"ul"},"\u5b9a\u4e49\u4e0a\u4e0b\u6587")),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]\n public class OtherDbContext : AppDbContext // \u9700\u6307\u5b9a\u5b9a\u4f4d\u5668\n {\n public OtherDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,a.kt)("p",{parentName:"admonition"},"\u53e6\u5916\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Entity/IEntity")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"IRepository")," \u7b49\u90fd\u9700\u8981\u6307\u5b9a\u5b9a\u4f4d\u5668\uff0c\u5982\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"IEntity"),"\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"IRepository")," \u64cd\u4f5c\u3002")),(0,a.kt)("h2",{id:"925-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u652f\u6301\u5bf9\u8c61"},"9.2.5 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u652f\u6301\u5bf9\u8c61"),(0,a.kt)("p",null,"\u76ee\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u652f\u6301\u4ee5\u4e0b\u591a\u4e2a\u5bf9\u8c61\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"AppDbContext"),"\uff1a\u6570\u636e\u4e0a\u4e0b\u6587"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IRepository"),"\uff1a\u5b9e\u4f53\u4ed3\u50a8"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ISqlRepository"),": Sql \u64cd\u4f5c\u4ed3\u50a8"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IDbRepository"),": \u7279\u5b9a\u6570\u636e\u5e93\u64cd\u4f5c\u4ed3\u50a8"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IMSRepository"),": \u8bfb\u5199\u5206\u79bb\u4ed3\u50a8"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Func"),"\uff1a\u4f9d\u8d56\u6ce8\u5165\u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Entity")," \uff1a\u5b9e\u4f53\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"EntityBase"),"\uff1a\u5b9e\u4f53\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"EntityNotKey"),"\uff1a\u65e0\u952e\u5b9e\u4f53\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IEntity"),"\uff1a\u9ed8\u8ba4\u5b9e\u4f53\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IEntitySeedData"),"\uff1a\u79cd\u5b50\u6570\u636e\u914d\u7f6e"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IEntityTypeBuilder"),"\uff1a\u5b9e\u4f53\u7c7b\u578b\u6784\u5efa\u5668"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IModelBuilderFilter"),"\uff1a\u6a21\u578b\u6784\u5efa\u7b5b\u9009\u5668"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"[QueryableFunction(DbContextLocators=Type[])]"),"\uff1a\u67e5\u8be2\u51fd\u6570")),(0,a.kt)("h2",{id:"926-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.2.6 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/a6aa9e1f.4482c8b9.js b/handbook/build/assets/js/a6aa9e1f.4482c8b9.js new file mode 100644 index 0000000000..15630475a7 --- /dev/null +++ b/handbook/build/assets/js/a6aa9e1f.4482c8b9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[3089],{46:function(e,t,n){n.r(t),n.d(t,{default:function(){return d}});var a=n(7294),r=n(4334),i=n(2263),l=n(833),o=n(5281),c=n(9058),s=n(9703),m=n(197),u=n(9985);function g(e){var t=e.metadata,n=(0,i.Z)().siteConfig.title,r=t.blogDescription,o=t.blogTitle,c="/"===t.permalink?n:o;return a.createElement(a.Fragment,null,a.createElement(l.d,{title:c,description:r}),a.createElement(m.Z,{tag:"blog_posts_list"}))}function p(e){var t=e.metadata,n=e.items,r=e.sidebar;return a.createElement(c.Z,{sidebar:r},a.createElement(u.Z,{items:n}),a.createElement(s.Z,{metadata:t}))}function d(e){return a.createElement(l.FG,{className:(0,r.Z)(o.k.wrapper.blogPages,o.k.page.blogListPage)},a.createElement(g,e),a.createElement(p,e))}},9703:function(e,t,n){n.d(t,{Z:function(){return l}});var a=n(7294),r=n(5999),i=n(2244);function l(e){var t=e.metadata,n=t.previousPage,l=t.nextPage;return a.createElement("nav",{className:"pagination-nav","aria-label":(0,r.I)({id:"theme.blog.paginator.navAriaLabel",message:"Blog list page navigation",description:"The ARIA label for the blog pagination"})},n&&a.createElement(i.Z,{permalink:n,title:a.createElement(r.Z,{id:"theme.blog.paginator.newerEntries",description:"The label used to navigate to the newer blog posts page (previous page)"},"Newer Entries")}),l&&a.createElement(i.Z,{permalink:l,title:a.createElement(r.Z,{id:"theme.blog.paginator.olderEntries",description:"The label used to navigate to the older blog posts page (next page)"},"Older Entries"),isNext:!0}))}},9985:function(e,t,n){n.d(t,{Z:function(){return l}});var a=n(7294),r=n(9460),i=n(390);function l(e){var t=e.items,n=e.component,l=void 0===n?i.Z:n;return a.createElement(a.Fragment,null,t.map((function(e){var t=e.content;return a.createElement(r.n,{key:t.metadata.permalink,content:t},a.createElement(l,null,a.createElement(t,null)))})))}}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/a6aa9e1f.e5d8d377.js b/handbook/build/assets/js/a6aa9e1f.e5d8d377.js deleted file mode 100644 index 11fdfbccb0..0000000000 --- a/handbook/build/assets/js/a6aa9e1f.e5d8d377.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[3089],{1895:function(e,t,n){n.r(t),n.d(t,{default:function(){return d}});var a=n(7294),r=n(4334),i=n(6832),l=n(4873),o=n(8015),c=n(1485),s=n(1052),m=n(6145),u=n(6903);function g(e){var t=e.metadata,n=(0,i.Z)().siteConfig.title,r=t.blogDescription,o=t.blogTitle,c="/"===t.permalink?n:o;return a.createElement(a.Fragment,null,a.createElement(l.d,{title:c,description:r}),a.createElement(m.Z,{tag:"blog_posts_list"}))}function p(e){var t=e.metadata,n=e.items,r=e.sidebar;return a.createElement(c.Z,{sidebar:r},a.createElement(u.Z,{items:n}),a.createElement(s.Z,{metadata:t}))}function d(e){return a.createElement(l.FG,{className:(0,r.Z)(o.k.wrapper.blogPages,o.k.page.blogListPage)},a.createElement(g,e),a.createElement(p,e))}},1052:function(e,t,n){n.d(t,{Z:function(){return l}});var a=n(7294),r=n(1614),i=n(3500);function l(e){var t=e.metadata,n=t.previousPage,l=t.nextPage;return a.createElement("nav",{className:"pagination-nav","aria-label":(0,r.I)({id:"theme.blog.paginator.navAriaLabel",message:"Blog list page navigation",description:"The ARIA label for the blog pagination"})},n&&a.createElement(i.Z,{permalink:n,title:a.createElement(r.Z,{id:"theme.blog.paginator.newerEntries",description:"The label used to navigate to the newer blog posts page (previous page)"},"Newer Entries")}),l&&a.createElement(i.Z,{permalink:l,title:a.createElement(r.Z,{id:"theme.blog.paginator.olderEntries",description:"The label used to navigate to the older blog posts page (next page)"},"Older Entries"),isNext:!0}))}},6903:function(e,t,n){n.d(t,{Z:function(){return l}});var a=n(7294),r=n(7762),i=n(1827);function l(e){var t=e.items,n=e.component,l=void 0===n?i.Z:n;return a.createElement(a.Fragment,null,t.map((function(e){var t=e.content;return a.createElement(r.n,{key:t.metadata.permalink,content:t},a.createElement(l,null,a.createElement(t,null)))})))}}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/a71f9f93.20230c19.js b/handbook/build/assets/js/a71f9f93.20230c19.js new file mode 100644 index 0000000000..3309e3556d --- /dev/null +++ b/handbook/build/assets/js/a71f9f93.20230c19.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[74],{3905:function(e,t,n){n.d(t,{Zo:function(){return u},kt:function(){return c}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=r.createContext({}),s=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=s(e.components);return r.createElement(p.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,p=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=s(n),c=o,k=d["".concat(p,".").concat(c)]||d[c]||m[c]||a;return n?r.createElement(k,i(i({ref:t},u),{},{components:n})):r.createElement(k,i({ref:t},u))}));function c(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=d;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var s=2;sCode First \u8bf4\u660e",id:"9016-code-first-\u8bf4\u660e",level:3},{value:"9.0.2 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"902-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:m};function c(e){var t=e.components,n=(0,o.Z)(e,i);return(0,a.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"901-\u5165\u95e8\u51c6\u5907"},"9.0.1 \u5165\u95e8\u51c6\u5907"),(0,a.kt)("admonition",{title:"\u5165\u95e8\u6761\u4ef6",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u5bf9 ",(0,a.kt)("inlineCode",{parentName:"p"},"EF/EFCore")," \u6709\u4e00\u5b9a\u57fa\u7840\u4e86\u89e3\uff0c\u8fd8\u672a\u63a5\u89e6\u7684\u53ef\u5148\u770b ",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/ef/core/"},"\u3010EFCore \u57fa\u7840\u3011"))),(0,a.kt)("h3",{id:"9011-\u5b89\u88c5\u5bf9\u5e94\u6570\u636e\u5e93\u5305"},"9.0.1.1 \u5b89\u88c5\u5bf9\u5e94\u6570\u636e\u5e93\u5305"),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5728\u672c\u7ae0\u8282\u6240\u5728\u7684\u7c7b\u522b\u4e2d\uff0c\u6240\u6709\u6570\u636e\u5e93\u64cd\u4f5c\u529f\u80fd\u5747\u9700\u8981\u4f9d\u8d56 ",(0,a.kt)("inlineCode",{parentName:"p"},"EntityFramework Core")," \u6846\u67b6\uff0c\u4f46 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u5e95\u5c42\u5e76\u672a\u96c6\u6210 ",(0,a.kt)("inlineCode",{parentName:"p"},"EntityFramework Core")," \u5305\uff0c\u800c\u662f\u91c7\u7528\u52a8\u6001\u52a0\u8f7d\u7a0b\u5e8f\u96c6\u65b9\u5f0f\u81ea\u52a8\u8f7d\u5165\u3002")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u6240\u4ee5\uff0c\u5982\u9700\u4f7f\u7528\u672c\u5927\u7c7b\u6570\u636e\u5e93\u529f\u80fd\uff0c\u9700\u5b89\u88c5\u5bf9\u5e94\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"EntityFramework Core")," \u6570\u636e\u5e93\u5305\uff1a")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"SqlServer"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.SqlServer")," (\u652f\u6301 SqlServer 2005 +)"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Sqlite"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.Sqlite")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Cosmos"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.Cosmos")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"InMemoryDatabase"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.InMemory")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"MySql"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Pomelo.EntityFrameworkCore.MySql"),"\uff1a(\u652f\u6301 MySql 5.x +)"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"MySql.EntityFrameworkCore"),"\uff1a\u652f\u6301 (MySql 8.x +)"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"PostgreSQL"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Npgsql.EntityFrameworkCore.PostgreSQL")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Oracle"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Oracle.EntityFrameworkCore")," \uff08\u652f\u6301 Oracle 10 +\uff09"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Firebird"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"FirebirdSql.EntityFrameworkCore.Firebird")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Dm"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.Dm"))),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u8fd9\u4e9b\u6570\u636e\u5e93\u5305\u5e94\u8be5\u5b89\u88c5\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.EntityFramework.Core")," \u5c42\u3002\u7279\u6b8a\u60c5\u51b5\u9700\u5b89\u88c5\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Core")," \u5c42\u4e2d\uff0c\u5982 ",(0,a.kt)("inlineCode",{parentName:"p"},"Mysql")," ",(0,a.kt)("inlineCode",{parentName:"p"},"HasCharset()")," \u914d\u7f6e\u3002")),(0,a.kt)("h3",{id:"9012-\u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.0.1.2 \u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7}",showLineNumbers:!0,"":!0,"{7}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]\n public class DefaultDbContext : AppDbContext\n {\n public DefaultDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u90fd\u9700\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u57fa\u7c7b\uff0c\u9ed8\u8ba4\u6570\u636e\u5e93\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"TDbContextLocator")," \u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"MasterDbContextLocator"),"\uff0c\u65e0\u9700\u663e\u5f0f\u7f16\u5199\u3002"),(0,a.kt)("p",{parentName:"admonition"},"\u975e\u9ed8\u8ba4\u6570\u636e\u5e93\u5219\u9700\u663e\u5f0f\u7ee7\u627f\u5e76\u7533\u660e\uff0c\u5982\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"AppDbContext"),"\u3002")),(0,a.kt)("p",null,"\u60f3\u4e86\u89e3\u66f4\u591a\u53ef\u67e5\u9605 \u3010",(0,a.kt)("a",{parentName:"p",href:"./dbcontext-locator"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668"),"\u3011 \u7ae0\u8282\u3002"),(0,a.kt)("h3",{id:"9013-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"},"9.0.1.3 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u591a\u79cd\u65b9\u5f0f\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"appsettings.json")," \u4e2d\u914d\u7f6e")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-3}",showLineNumbers:!0,"":!0,"{2-3}":!0},'{\n "ConnectionStrings": {\n "Sqlite3ConnectionString": "Data Source=./Furion.db"\n }\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u81ea\u5b9a\u4e49 ",(0,a.kt)("inlineCode",{parentName:"li"},".json")," \u6587\u4ef6\u914d\u7f6e")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-3}",showLineNumbers:!0,"":!0,"{2-3}":!0},'{\n "ConnectionStrings": {\n "Sqlite3ConnectionString": "Data Source=./Furion.db"\n }\n}\n')),(0,a.kt)("p",null,"\u8be5\u65b9\u5f0f\u548c\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u7684\u533a\u522b\u662f\u81ea\u5b9a\u4e49\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u4e0d\u4f1a\u81ea\u52a8\u6dfb\u52a0\u5230\u9879\u76ee\u4e2d\uff0c",(0,a.kt)("strong",{parentName:"p"},"\u987b\u5728 ",(0,a.kt)("inlineCode",{parentName:"strong"},"Visual Studio")," \u4e2d\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"strong"},".json")," \u53f3\u952e\u5c5e\u6027\uff0c\u8bbe\u7f6e ",(0,a.kt)("inlineCode",{parentName:"strong"},"\u590d\u5236")," \u8f93\u51fa\u76ee\u5f55\u4e3a ",(0,a.kt)("inlineCode",{parentName:"strong"},"\u5982\u679c\u8f83\u65b0\u5219\u590d\u5236"),"\uff0c\u751f\u6210\u64cd\u4f5c\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"strong"},"\u5185\u5bb9"),"\u3002")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"[AppDbContext]")," \u7279\u6027\u914d\u7f6e")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'[AppDbContext("Data Source=./Furion.db", DbProvider.Sqlite)]\npublic class DefaultDbContext : AppDbContext\n{\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5728\u6ce8\u518c\u4e0a\u4e0b\u6587\u65f6\u914d\u7f6e")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-4}",showLineNumbers:!0,"":!0,"{3-4}":!0},'services.AddDatabaseAccessor(options =>\n{\n // options.AddDb(connectionMetadata: "\u914d\u7f6eKey\u6216\u8fde\u63a5\u5b57\u7b26\u4e32");\n options.AddDbPool(connectionMetadata: "\u914d\u7f6eKey\u6216\u8fde\u63a5\u5b57\u7b26\u4e32");\n});\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"DbContext")," \u4e2d\u914d\u7f6e")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {12-14}",showLineNumbers:!0,"":!0,"{12-14}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n public class DefaultDbContext : AppDbContext\n {\n public DefaultDbContext(DbContextOptions options) : base(options)\n {\n }\n\n protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n {\n optionsBuilder.UseSqlite("\u8fde\u63a5\u5b57\u7b26\u4e32");\n base.OnConfiguring(optionsBuilder);\n }\n }\n}\n')),(0,a.kt)("h3",{id:"9014-\u5404\u7c7b\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u793a\u4f8b"},"9.0.1.4 \u5404\u7c7b\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u793a\u4f8b"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Sqlite"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Data Source=./Furion.db")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"MySql"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Data Source=localhost;Database=Furion;User ID=root;Password=000000;pooling=true;port=3306;sslmode=none;CharSet=utf8;")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"SqlServer"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Oracle"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"User Id=orcl;Password=orcl;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl)))")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"PostgreSQL"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"PORT=5432;DATABASE=postgres;HOST=127.0.0.1;PASSWORD=postgres;USER ID=postgres;"))),(0,a.kt)("h3",{id:"9015-\u6ce8\u518c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.0.1.5 \u6ce8\u518c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {12-19} title="Furion.EntityFramework.Core\\Startup.cs"',showLineNumbers:!0,"":!0,"{12-19}":!0,title:'"Furion.EntityFramework.Core\\Startup.cs"'},"using Furion.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppStartup(600)]\n public sealed class FurEntityFrameworkCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n // \u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u652f\u6301N\u4e2a\u6570\u636e\u5e93\n services.AddDatabaseAccessor(options =>\n {\n // \u914d\u7f6e\u9ed8\u8ba4\u6570\u636e\u5e93\n options.AddDbPool();\n\n // \u914d\u7f6e\u591a\u4e2a\u6570\u636e\u5e93\uff0c\u591a\u4e2a\u6570\u636e\u5e93\u5fc5\u987b\u6307\u5b9a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\n // options.AddDbPool();\n });\n }\n }\n}\n")),(0,a.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a\u6570\u636e\u5e93\u6570\u636e\u5e93\u6ce8\u518c\u65b9\u5f0f",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u9700\u4e86\u89e3\u5404\u79cd\u6570\u636e\u5e93\u53ca\u7248\u672c\u6ce8\u518c\u65b9\u5f0f\u53ef\u67e5\u9605 \u3010",(0,a.kt)("a",{parentName:"p",href:"/furion/docs/dbcontext-multi-database"},"\u591a\u6570\u636e\u5e93\u6ce8\u518c\u7ae0\u8282"),"\u3011")),(0,a.kt)("h3",{id:"9016-code-first-\u8bf4\u660e"},"9.0.1.6 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Code First")," \u8bf4\u660e"),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u9ed8\u8ba4\u6570\u636e\u8fc1\u79fb\u7684\u7a0b\u5e8f\u96c6\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Database.Migrations"),"\uff0c\u6240\u4ee5\u5982\u679c\u60a8\u6539\u4e86\u7a0b\u5e8f\u96c6\u540d\u79f0\u6216\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"Nuget")," \u65b9\u5f0f\u5b89\u88c5\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\uff0c\u5219\u9700\u8981\u914d\u7f6e\u8fc1\u79fb\u7a0b\u5e8f\u96c6\u540d\u79f0\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},'services.AddDatabaseAccessor(options =>\n{\n options.AddDbPool(DbProvider.Sqlite);\n}, "\u5b58\u653e\u8fc1\u79fb\u6587\u4ef6\u7684\u9879\u76ee\u540d\u79f0");\n')),(0,a.kt)("p",{parentName:"admonition"},"\u53e6\u5916\uff0c\u5982\u679c\u5e94\u7528\u4e2d\u914d\u7f6e\u4e86\u591a\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u90a3\u4e48\u6240\u6709\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u8fc1\u79fb\u547d\u4ee4")," \u90fd\u9700\u8981\u6307\u5b9a ",(0,a.kt)("inlineCode",{parentName:"p"},"-Context \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u540d\u79f0")," \u53c2\u6570\u3002\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Add-Migration v1.0.0 -Context DefaultDbContext\n"))),(0,a.kt)("h2",{id:"902-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.0.2 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/a71f9f93.2db4ebc2.js b/handbook/build/assets/js/a71f9f93.2db4ebc2.js deleted file mode 100644 index f76483d284..0000000000 --- a/handbook/build/assets/js/a71f9f93.2db4ebc2.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[74],{104:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return p},default:function(){return c},frontMatter:function(){return l},metadata:function(){return s},toc:function(){return m}});var r=n(3117),o=n(102),a=(n(7294),n(3905)),i=["components"],l={id:"dbcontext-start",title:"9.0 \u5165\u95e8\u7b80\u8981",sidebar_label:"9.0 \u5165\u95e8\u7b80\u8981 \u2728"},p=void 0,s={unversionedId:"dbcontext-start",id:"dbcontext-start",title:"9.0 \u5165\u95e8\u7b80\u8981",description:"9.0.1 \u5165\u95e8\u51c6\u5907",source:"@site/docs/dbcontext-start.mdx",sourceDirName:".",slug:"/dbcontext-start",permalink:"/furion/docs/dbcontext-start",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-start.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1652326202,formattedLastUpdatedAt:"May 12, 2022",frontMatter:{id:"dbcontext-start",title:"9.0 \u5165\u95e8\u7b80\u8981",sidebar_label:"9.0 \u5165\u95e8\u7b80\u8981 \u2728"},sidebar:"docs",previous:{title:"8. \u6570\u636e\u6821\u9a8c",permalink:"/furion/docs/data-validation"},next:{title:"9.1 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",permalink:"/furion/docs/dbcontext"}},u={},m=[{value:"9.0.1 \u5165\u95e8\u51c6\u5907",id:"901-\u5165\u95e8\u51c6\u5907",level:2},{value:"9.0.1.1 \u5b89\u88c5\u5bf9\u5e94\u6570\u636e\u5e93\u5305",id:"9011-\u5b89\u88c5\u5bf9\u5e94\u6570\u636e\u5e93\u5305",level:3},{value:"9.0.1.2 \u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"9012-\u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:3},{value:"9.0.1.3 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32",id:"9013-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32",level:3},{value:"9.0.1.4 \u5404\u7c7b\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u793a\u4f8b",id:"9014-\u5404\u7c7b\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u793a\u4f8b",level:3},{value:"9.0.1.5 \u6ce8\u518c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"9015-\u6ce8\u518c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",level:3},{value:"9.0.1.6 Code First \u8bf4\u660e",id:"9016-code-first-\u8bf4\u660e",level:3},{value:"9.0.2 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"902-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:m};function c(e){var t=e.components,n=(0,o.Z)(e,i);return(0,a.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"901-\u5165\u95e8\u51c6\u5907"},"9.0.1 \u5165\u95e8\u51c6\u5907"),(0,a.kt)("admonition",{title:"\u5165\u95e8\u6761\u4ef6",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u5bf9 ",(0,a.kt)("inlineCode",{parentName:"p"},"EF/EFCore")," \u6709\u4e00\u5b9a\u57fa\u7840\u4e86\u89e3\uff0c\u8fd8\u672a\u63a5\u89e6\u7684\u53ef\u5148\u770b ",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/ef/core/"},"\u3010EFCore \u57fa\u7840\u3011"))),(0,a.kt)("h3",{id:"9011-\u5b89\u88c5\u5bf9\u5e94\u6570\u636e\u5e93\u5305"},"9.0.1.1 \u5b89\u88c5\u5bf9\u5e94\u6570\u636e\u5e93\u5305"),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5728\u672c\u7ae0\u8282\u6240\u5728\u7684\u7c7b\u522b\u4e2d\uff0c\u6240\u6709\u6570\u636e\u5e93\u64cd\u4f5c\u529f\u80fd\u5747\u9700\u8981\u4f9d\u8d56 ",(0,a.kt)("inlineCode",{parentName:"p"},"EntityFramework Core")," \u6846\u67b6\uff0c\u4f46 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u5e95\u5c42\u5e76\u672a\u96c6\u6210 ",(0,a.kt)("inlineCode",{parentName:"p"},"EntityFramework Core")," \u5305\uff0c\u800c\u662f\u91c7\u7528\u52a8\u6001\u52a0\u8f7d\u7a0b\u5e8f\u96c6\u65b9\u5f0f\u81ea\u52a8\u8f7d\u5165\u3002")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u6240\u4ee5\uff0c\u5982\u9700\u4f7f\u7528\u672c\u5927\u7c7b\u6570\u636e\u5e93\u529f\u80fd\uff0c\u9700\u5b89\u88c5\u5bf9\u5e94\u7684 ",(0,a.kt)("inlineCode",{parentName:"strong"},"EntityFramework Core")," \u6570\u636e\u5e93\u5305\uff1a")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"SqlServer"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.SqlServer")," (\u652f\u6301 SqlServer 2005 +)"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Sqlite"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.Sqlite")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Cosmos"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.Cosmos")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"InMemoryDatabase"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.InMemory")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"MySql"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Pomelo.EntityFrameworkCore.MySql"),"\uff1a(\u652f\u6301 MySql 5.x +)"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"MySql.EntityFrameworkCore"),"\uff1a\u652f\u6301 (MySql 8.x +)"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"PostgreSQL"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Npgsql.EntityFrameworkCore.PostgreSQL")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Oracle"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Oracle.EntityFrameworkCore")," \uff08\u652f\u6301 Oracle 10 +\uff09"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Firebird"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"FirebirdSql.EntityFrameworkCore.Firebird")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Dm"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Microsoft.EntityFrameworkCore.Dm"))),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u8fd9\u4e9b\u6570\u636e\u5e93\u5305\u5e94\u8be5\u5b89\u88c5\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.EntityFramework.Core")," \u5c42\u3002\u7279\u6b8a\u60c5\u51b5\u9700\u5b89\u88c5\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Core")," \u5c42\u4e2d\uff0c\u5982 ",(0,a.kt)("inlineCode",{parentName:"p"},"Mysql")," ",(0,a.kt)("inlineCode",{parentName:"p"},"HasCharset()")," \u914d\u7f6e\u3002")),(0,a.kt)("h3",{id:"9012-\u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.0.1.2 \u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7}",showLineNumbers:!0,"":!0,"{7}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]\n public class DefaultDbContext : AppDbContext\n {\n public DefaultDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u90fd\u9700\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u57fa\u7c7b\uff0c\u9ed8\u8ba4\u6570\u636e\u5e93\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"TDbContextLocator")," \u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"MasterDbContextLocator"),"\uff0c\u65e0\u9700\u663e\u5f0f\u7f16\u5199\u3002"),(0,a.kt)("p",{parentName:"admonition"},"\u975e\u9ed8\u8ba4\u6570\u636e\u5e93\u5219\u9700\u663e\u5f0f\u7ee7\u627f\u5e76\u7533\u660e\uff0c\u5982\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"AppDbContext"),"\u3002")),(0,a.kt)("p",null,"\u60f3\u4e86\u89e3\u66f4\u591a\u53ef\u67e5\u9605 \u3010",(0,a.kt)("a",{parentName:"p",href:"./dbcontext-locator"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668"),"\u3011 \u7ae0\u8282\u3002"),(0,a.kt)("h3",{id:"9013-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"},"9.0.1.3 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u591a\u79cd\u65b9\u5f0f\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"appsettings.json")," \u4e2d\u914d\u7f6e")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-3}",showLineNumbers:!0,"":!0,"{2-3}":!0},'{\n "ConnectionStrings": {\n "Sqlite3ConnectionString": "Data Source=./Furion.db"\n }\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u81ea\u5b9a\u4e49 ",(0,a.kt)("inlineCode",{parentName:"li"},".json")," \u6587\u4ef6\u914d\u7f6e")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-3}",showLineNumbers:!0,"":!0,"{2-3}":!0},'{\n "ConnectionStrings": {\n "Sqlite3ConnectionString": "Data Source=./Furion.db"\n }\n}\n')),(0,a.kt)("p",null,"\u8be5\u65b9\u5f0f\u548c\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u7684\u533a\u522b\u662f\u81ea\u5b9a\u4e49\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u4e0d\u4f1a\u81ea\u52a8\u6dfb\u52a0\u5230\u9879\u76ee\u4e2d\uff0c",(0,a.kt)("strong",{parentName:"p"},"\u987b\u5728 ",(0,a.kt)("inlineCode",{parentName:"strong"},"Visual Studio")," \u4e2d\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"strong"},".json")," \u53f3\u952e\u5c5e\u6027\uff0c\u8bbe\u7f6e ",(0,a.kt)("inlineCode",{parentName:"strong"},"\u590d\u5236")," \u8f93\u51fa\u76ee\u5f55\u4e3a ",(0,a.kt)("inlineCode",{parentName:"strong"},"\u5982\u679c\u8f83\u65b0\u5219\u590d\u5236"),"\uff0c\u751f\u6210\u64cd\u4f5c\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"strong"},"\u5185\u5bb9"),"\u3002")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"[AppDbContext]")," \u7279\u6027\u914d\u7f6e")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'[AppDbContext("Data Source=./Furion.db", DbProvider.Sqlite)]\npublic class DefaultDbContext : AppDbContext\n{\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5728\u6ce8\u518c\u4e0a\u4e0b\u6587\u65f6\u914d\u7f6e")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-4}",showLineNumbers:!0,"":!0,"{3-4}":!0},'services.AddDatabaseAccessor(options =>\n{\n // options.AddDb(connectionMetadata: "\u914d\u7f6eKey\u6216\u8fde\u63a5\u5b57\u7b26\u4e32");\n options.AddDbPool(connectionMetadata: "\u914d\u7f6eKey\u6216\u8fde\u63a5\u5b57\u7b26\u4e32");\n});\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"li"},"DbContext")," \u4e2d\u914d\u7f6e")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {12-14}",showLineNumbers:!0,"":!0,"{12-14}":!0},'using Furion.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Furion.EntityFramework.Core\n{\n public class DefaultDbContext : AppDbContext\n {\n public DefaultDbContext(DbContextOptions options) : base(options)\n {\n }\n\n protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n {\n optionsBuilder.UseSqlite("\u8fde\u63a5\u5b57\u7b26\u4e32");\n base.OnConfiguring(optionsBuilder);\n }\n }\n}\n')),(0,a.kt)("h3",{id:"9014-\u5404\u7c7b\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u793a\u4f8b"},"9.0.1.4 \u5404\u7c7b\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u793a\u4f8b"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Sqlite"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Data Source=./Furion.db")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"MySql"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Data Source=localhost;Database=Furion;User ID=root;Password=000000;pooling=true;port=3306;sslmode=none;CharSet=utf8;")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"SqlServer"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Oracle"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"User Id=orcl;Password=orcl;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl)))")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"PostgreSQL"),"\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"PORT=5432;DATABASE=postgres;HOST=127.0.0.1;PASSWORD=postgres;USER ID=postgres;"))),(0,a.kt)("h3",{id:"9015-\u6ce8\u518c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.0.1.5 \u6ce8\u518c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {12-19} title="Furion.EntityFramework.Core\\Startup.cs"',showLineNumbers:!0,"":!0,"{12-19}":!0,title:'"Furion.EntityFramework.Core\\Startup.cs"'},"using Furion.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Furion.EntityFramework.Core\n{\n [AppStartup(600)]\n public sealed class FurEntityFrameworkCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n // \u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u652f\u6301N\u4e2a\u6570\u636e\u5e93\n services.AddDatabaseAccessor(options =>\n {\n // \u914d\u7f6e\u9ed8\u8ba4\u6570\u636e\u5e93\n options.AddDbPool();\n\n // \u914d\u7f6e\u591a\u4e2a\u6570\u636e\u5e93\uff0c\u591a\u4e2a\u6570\u636e\u5e93\u5fc5\u987b\u6307\u5b9a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\n // options.AddDbPool();\n });\n }\n }\n}\n")),(0,a.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a\u6570\u636e\u5e93\u6570\u636e\u5e93\u6ce8\u518c\u65b9\u5f0f",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u9700\u4e86\u89e3\u5404\u79cd\u6570\u636e\u5e93\u53ca\u7248\u672c\u6ce8\u518c\u65b9\u5f0f\u53ef\u67e5\u9605 \u3010",(0,a.kt)("a",{parentName:"p",href:"/furion/docs/dbcontext-multi-database"},"\u591a\u6570\u636e\u5e93\u6ce8\u518c\u7ae0\u8282"),"\u3011")),(0,a.kt)("h3",{id:"9016-code-first-\u8bf4\u660e"},"9.0.1.6 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Code First")," \u8bf4\u660e"),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u9ed8\u8ba4\u6570\u636e\u8fc1\u79fb\u7684\u7a0b\u5e8f\u96c6\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"Furion.Database.Migrations"),"\uff0c\u6240\u4ee5\u5982\u679c\u60a8\u6539\u4e86\u7a0b\u5e8f\u96c6\u540d\u79f0\u6216\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"Nuget")," \u65b9\u5f0f\u5b89\u88c5\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\uff0c\u5219\u9700\u8981\u914d\u7f6e\u8fc1\u79fb\u7a0b\u5e8f\u96c6\u540d\u79f0\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},'services.AddDatabaseAccessor(options =>\n{\n options.AddDbPool(DbProvider.Sqlite);\n}, "\u5b58\u653e\u8fc1\u79fb\u6587\u4ef6\u7684\u9879\u76ee\u540d\u79f0");\n')),(0,a.kt)("p",{parentName:"admonition"},"\u53e6\u5916\uff0c\u5982\u679c\u5e94\u7528\u4e2d\u914d\u7f6e\u4e86\u591a\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u90a3\u4e48\u6240\u6709\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u8fc1\u79fb\u547d\u4ee4")," \u90fd\u9700\u8981\u6307\u5b9a ",(0,a.kt)("inlineCode",{parentName:"p"},"-Context \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u540d\u79f0")," \u53c2\u6570\u3002\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Add-Migration v1.0.0 -Context DefaultDbContext\n"))),(0,a.kt)("h2",{id:"902-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.0.2 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return u},kt:function(){return c}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=r.createContext({}),s=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=s(e.components);return r.createElement(p.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,p=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=s(n),c=o,k=d["".concat(p,".").concat(c)]||d[c]||m[c]||a;return n?r.createElement(k,i(i({ref:t},u),{},{components:n})):r.createElement(k,i({ref:t},u))}));function c(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=d;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var s=2;s=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=i.createContext({}),p=function(e){var n=i.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},c=function(e){var n=p(e.components);return i.createElement(s.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},m=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,s=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),m=p(t),d=r,k=m["".concat(s,".").concat(d)]||m[d]||u[d]||a;return t?i.createElement(k,l(l({ref:n},c),{},{components:t})):i.createElement(k,l({ref:n},c))}));function d(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,l=new Array(a);l[0]=m;var o={};for(var s in n)hasOwnProperty.call(n,s)&&(o[s]=n[s]);o.originalType=e,o.mdxType="string"==typeof e?e:r,l[1]=o;for(var p=2;pIOC/DI \u4f18\u7f3a\u70b9",id:"123-iocdi-\u4f18\u7f3a\u70b9",level:2},{value:"12.4 \u4f9d\u8d56\u6ce8\u5165\u7684\u4e09\u79cd\u65b9\u5f0f",id:"124-\u4f9d\u8d56\u6ce8\u5165\u7684\u4e09\u79cd\u65b9\u5f0f",level:2},{value:"12.4.1 \u6784\u9020\u65b9\u6cd5\u6ce8\u5165",id:"1241-\u6784\u9020\u65b9\u6cd5\u6ce8\u5165",level:3},{value:"12.4.2 \u5c5e\u6027\u65b9\u5f0f\u6ce8\u5165",id:"1242-\u5c5e\u6027\u65b9\u5f0f\u6ce8\u5165",level:3},{value:"12.4.3 \u65b9\u6cd5\u53c2\u6570\u6ce8\u5165",id:"1243-\u65b9\u6cd5\u53c2\u6570\u6ce8\u5165",level:3},{value:"12.5 \u6ce8\u518c\u5bf9\u8c61\u751f\u5b58\u671f",id:"125-\u6ce8\u518c\u5bf9\u8c61\u751f\u5b58\u671f",level:2},{value:"12.5.1 \u6682\u65f6/\u77ac\u65f6 \u751f\u5b58\u671f",id:"1251-\u6682\u65f6\u77ac\u65f6-\u751f\u5b58\u671f",level:3},{value:"12.5.2 \u4f5c\u7528\u57df \u751f\u5b58\u671f",id:"1252-\u4f5c\u7528\u57df-\u751f\u5b58\u671f",level:3},{value:"12.5.3 \u5355\u4f8b \u751f\u5b58\u671f",id:"1253-\u5355\u4f8b-\u751f\u5b58\u671f",level:3},{value:"12.6 \u5185\u7f6e\u4f9d\u8d56\u63a5\u53e3",id:"126-\u5185\u7f6e\u4f9d\u8d56\u63a5\u53e3",level:2},{value:"12.7 \u5e38\u89c1\u4f7f\u7528",id:"127-\u5e38\u89c1\u4f7f\u7528",level:2},{value:"12.7.1 \u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"1271-\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:3},{value:"12.7.2 \u6ce8\u518c\u6cdb\u578b\u5b9e\u4f8b",id:"1272-\u6ce8\u518c\u6cdb\u578b\u5b9e\u4f8b",level:3},{value:"12.7.3 \u4e00\u4e2a\u63a5\u53e3\u591a\u4e2a\u5b9e\u73b0",id:"1273-\u4e00\u4e2a\u63a5\u53e3\u591a\u4e2a\u5b9e\u73b0",level:3},{value:"12.7.4 \u65e0\u63a5\u53e3\u65b9\u5f0f",id:"1274-\u65e0\u63a5\u53e3\u65b9\u5f0f",level:3},{value:"12.8 [Injection] \u7279\u6027\u914d\u7f6e",id:"128-injection-\u7279\u6027\u914d\u7f6e",level:2},{value:"12.9 \u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c",id:"129-\u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c",level:2},{value:"12.10 appsettings.json \u914d\u7f6e\u6ce8\u518c",id:"1210-appsettingsjson-\u914d\u7f6e\u6ce8\u518c",level:2},{value:"12.11 \u6ce8\u518c\u987a\u5e8f\u548c\u4f18\u5148\u7ea7",id:"1211-\u6ce8\u518c\u987a\u5e8f\u548c\u4f18\u5148\u7ea7",level:2},{value:"12.12 Aop \u6ce8\u518c\u62e6\u622a",id:"1212-aop-\u6ce8\u518c\u62e6\u622a",level:2},{value:"12.12.1 \u5168\u5c40Aop\u62e6\u622a",id:"12121-\u5168\u5c40aop\u62e6\u622a",level:3},{value:"12.12.2 AOP \u6ce8\u5165\u89e3\u6790\u670d\u52a1",id:"12122-aop-\u6ce8\u5165\u89e3\u6790\u670d\u52a1",level:3},{value:"12.12.3 AOP \u7684\u4f5c\u7528",id:"12123-aop-\u7684\u4f5c\u7528",level:3},{value:"12.13 \u5728\u975e Web \u6216\u591a\u7ebf\u7a0b\u89e3\u6790\u670d\u52a1",id:"1213-\u5728\u975e-web-\u6216\u591a\u7ebf\u7a0b\u89e3\u6790\u670d\u52a1",level:2},{value:"12.13.1 IServiceProvider \u65b9\u5f0f",id:"12131-iserviceprovider-\u65b9\u5f0f",level:3},{value:"12.13.2 IServiceScopeFactory \u65b9\u5f0f",id:"12132-iservicescopefactory-\u65b9\u5f0f",level:3},{value:"12.13.3 Scoped \u9759\u6001\u7c7b",id:"12133-scoped-\u9759\u6001\u7c7b",level:3},{value:"12.14 \u81ea\u5b9a\u4e49\u626b\u63cf/\u7b5b\u9009\u6ce8\u518c\u670d\u52a1",id:"1214-\u81ea\u5b9a\u4e49\u626b\u63cf\u7b5b\u9009\u6ce8\u518c\u670d\u52a1",level:2},{value:"12.15 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"1215-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:m};function k(e){var n=e.components,t=(0,r.Z)(e,o);return(0,a.kt)("wrapper",(0,i.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{title:"\u9605\u524d\u5fc5\u8bfb",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7531\u4e8e\u5f88\u591a\u670b\u53cb\u7b2c\u4e00\u6b21\u63a5\u89e6 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c")," \u7684\u67b6\u6784\u7406\u5ff5\uff0c\u6240\u4ee5\u6ca1\u641e\u660e\u767d ",(0,a.kt)("inlineCode",{parentName:"p"},"\u4f5c\u7528\u57df")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"\u591a\u7ebf\u7a0b\u89e3\u6790\u670d\u52a1")," \u7684\u95ee\u9898\uff0c\u4ece\u800c\u4e0d\u6b63\u786e\u7684\u4f7f\u7528\u5bfc\u81f4\u5185\u5b58\u4e0d\u65ad\u98d9\u9ad8\uff0c\u6b63\u786e\u7684\u65b9\u5f0f\u5e94\u8be5\u662f\uff1a"),(0,a.kt)("ul",{parentName:"admonition"},(0,a.kt)("li",{parentName:"ul"},"\u5c3d\u53ef\u80fd\u7684\u91c7\u7528\u6784\u9020\u51fd\u6570\u6ce8\u5165\uff08\u5982\u679c\u8fd9\u4e2a\u7c7b\u652f\u6301\uff09"),(0,a.kt)("li",{parentName:"ul"},"\u5728\u975e\u9759\u6001\u4e2d\uff08",(0,a.kt)("strong",{parentName:"li"},"\u4f46\u5728 Web \u8bf7\u6c42\u6709\u6548\u7684\u58f0\u660e\u5468\u671f\u5185"),"\uff09\u53ef\u5b89\u5168\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"li"},"App.GetService<>")," \u89e3\u6790\u670d\u52a1\uff0c\u5982\u679c\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"\u5355\u4f8b\u670d\u52a1"),"\uff0c\u4f18\u5148\u63a8\u8350\u6784\u9020\u51fd\u6570\u6ce8\u5165\u6216 ",(0,a.kt)("inlineCode",{parentName:"li"},"App.RootServices.GetService<>")," \u65b9\u5f0f"),(0,a.kt)("li",{parentName:"ul"},"\ud83e\udd10 ",(0,a.kt)("strong",{parentName:"li"},"\u5728\u975e ",(0,a.kt)("inlineCode",{parentName:"strong"},"Web")," \u73af\u5883\u3001\u591a\u7ebf\u7a0b\u73af\u5883\u3001\u7269\u8054\u7f51\u7b49\u73af\u5883\uff08\u542b\u4e8b\u4ef6\u603b\u7ebf\u3001\u5b9a\u65f6\u4efb\u52a1\u7b49\uff09\ud83c\udfd2 \u9664\u5355\u4f8b\u670d\u52a1\u4ee5\u5916 \ud83c\udfd2 \u5fc5\u987b\u91c7\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"Scoped.Create()")," \u65b9\u5f0f\u521b\u5efa\u4f5c\u7528\u57df\u4e14\u670d\u52a1\u5728\u5185\u90e8\u59d4\u6258\u4e2d\u89e3\u6790\uff01")," \ud83e\udd10"))),(0,a.kt)("h2",{id:"121-\u4f9d\u8d56\u6ce8\u5165"},"12.1 \u4f9d\u8d56\u6ce8\u5165"),(0,a.kt)("p",null,"\u6240\u8c13\u4f9d\u8d56\u6ce8\u5165\uff0c\u662f\u6307\u7a0b\u5e8f\u8fd0\u884c\u8fc7\u7a0b\u4e2d\uff0c\u5982\u679c\u9700\u8981\u8c03\u7528\u53e6\u4e00\u4e2a\u5bf9\u8c61\u534f\u52a9\u65f6\uff0c\u65e0\u987b\u5728\u4ee3\u7801\u4e2d\u521b\u5efa\u88ab\u8c03\u7528\u8005\uff0c\u800c\u662f\u4f9d\u8d56\u4e8e\u5916\u90e8\u7684\u6ce8\u5165\u3002"),(0,a.kt)("p",null,"\u901a\u4fd7\u6765\u8bb2\uff0c\u5c31\u662f\u628a\u6709\u4f9d\u8d56\u5173\u7cfb\u7684\u7c7b\u653e\u5230\u5bb9\u5668\u4e2d\uff0c\u7136\u540e\u5728\u6211\u4eec\u9700\u8981\u8fd9\u4e9b\u7c7b\u65f6\uff0c\u5bb9\u5668\u81ea\u52a8\u89e3\u6790\u51fa\u8fd9\u4e9b\u7c7b\u7684\u5b9e\u4f8b\u3002"),(0,a.kt)("p",null,"\u4f9d\u8d56\u6ce8\u5165\u6700\u5927\u7684\u597d\u5904\u65f6\u5b9e\u73b0\u7c7b\u7684\u89e3\u8026\uff0c\u5229\u4e8e\u7a0b\u5e8f\u62d3\u5c55\u3001\u5355\u5143\u6d4b\u8bd5\u3001\u81ea\u52a8\u5316\u6a21\u62df\u6d4b\u8bd5\u7b49\u3002"),(0,a.kt)("p",null,"\u4f9d\u8d56\u6ce8\u5165\u7684\u82f1\u6587\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"Dependency Injection"),"\uff0c\u7b80\u79f0 ",(0,a.kt)("inlineCode",{parentName:"p"},"DI")),(0,a.kt)("h2",{id:"122-\u63a7\u5236\u53cd\u8f6c"},"12.2 \u63a7\u5236\u53cd\u8f6c"),(0,a.kt)("p",null,"\u63a7\u5236\u53cd\u8f6c\u53ea\u662f\u4e00\u4e2a\u6982\u5ff5\uff0c\u4e5f\u5c31\u662f\u5c06\u521b\u5efa\u5bf9\u8c61\u5b9e\u4f8b\u7684\u63a7\u5236\u6743\uff08\u539f\u672c\u662f\u7a0b\u5e8f\u5458\uff09\u4ece\u4ee3\u7801\u63a7\u5236\u6743\u5265\u79bb\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"IOC \u5bb9\u5668")," \u4e2d\u63a7\u5236\u3002"),(0,a.kt)("p",null,"\u63a7\u5236\u53cd\u8f6c\u7684\u82f1\u6587\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"Inversion of Control"),"\uff0c\u7b80\u79f0 ",(0,a.kt)("inlineCode",{parentName:"p"},"IOC")),(0,a.kt)("h2",{id:"123-iocdi-\u4f18\u7f3a\u70b9"},"12.3 ",(0,a.kt)("inlineCode",{parentName:"h2"},"IOC/DI")," \u4f18\u7f3a\u70b9"),(0,a.kt)("p",null,"\u4f20\u7edf\u7684\u4ee3\u7801\uff0c\u6bcf\u4e2a\u5bf9\u8c61\u8d1f\u8d23\u7ba1\u7406\u4e0e\u81ea\u5df1\u9700\u8981\u4f9d\u8d56\u7684\u5bf9\u8c61\uff0c\u5bfc\u81f4\u5982\u679c\u9700\u8981\u5207\u6362\u4f9d\u8d56\u5bf9\u8c61\u7684\u5b9e\u73b0\u7c7b\u65f6\uff0c\u9700\u8981\u4fee\u6539\u591a\u5904\u5730\u65b9\u3002\u540c\u65f6\uff0c\u8fc7\u5ea6\u8026\u5408\u4e5f\u4f7f\u5f97\u5bf9\u8c61\u96be\u4ee5\u8fdb\u884c\u5355\u5143\u6d4b\u8bd5\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u4f18\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u4f9d\u8d56\u6ce8\u5165\u628a\u5bf9\u8c61\u7684\u521b\u9020\u4ea4\u7ed9\u5916\u90e8\u53bb\u7ba1\u7406,\u5f88\u597d\u7684\u89e3\u51b3\u4e86\u4ee3\u7801\u7d27\u8026\u5408\uff08tight couple\uff09\u7684\u95ee\u9898\uff0c\u662f\u4e00\u79cd\u8ba9\u4ee3\u7801\u5b9e\u73b0\u677e\u8026\u5408\uff08loose couple\uff09\u7684\u673a\u5236"),(0,a.kt)("li",{parentName:"ul"},"\u677e\u8026\u5408\u8ba9\u4ee3\u7801\u66f4\u5177\u7075\u6d3b\u6027\uff0c\u80fd\u66f4\u597d\u5730\u5e94\u5bf9\u9700\u6c42\u53d8\u52a8\uff0c\u4ee5\u53ca\u65b9\u4fbf\u5355\u5143\u6d4b\u8bd5"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u7f3a\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u76ee\u524d\u4e3b\u6d41\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"IOC/DI")," \u57fa\u672c\u91c7\u7528\u53cd\u5c04\u7684\u65b9\u5f0f\u6765\u5b9e\u73b0\u4f9d\u8d56\u6ce8\u5165\uff0c\u5728\u4e00\u5b9a\u7a0b\u5ea6\u4f1a\u5f71\u54cd\u6027\u80fd")))),(0,a.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u5728\u672c\u7ae0\u8282\u4e0d\u6253\u7b97\u7ec6\u8bb2 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c")," \u5177\u4f53\u5b9e\u73b0\u548c\u5e94\u7528\u573a\u666f\uff0c\u60f3\u4e86\u89e3\u66f4\u591a\u77e5\u8bc6\uff0c\u53ef\u67e5\u9605 \u3010",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0"},"ASP.NET Core \u4f9d\u8d56\u6ce8\u5165"),"\u3011 \u5b98\u65b9\u6587\u6863\u3002")),(0,a.kt)("h2",{id:"124-\u4f9d\u8d56\u6ce8\u5165\u7684\u4e09\u79cd\u65b9\u5f0f"},"12.4 \u4f9d\u8d56\u6ce8\u5165\u7684\u4e09\u79cd\u65b9\u5f0f"),(0,a.kt)("h3",{id:"1241-\u6784\u9020\u65b9\u6cd5\u6ce8\u5165"},"12.4.1 \u6784\u9020\u65b9\u6cd5\u6ce8\u5165"),(0,a.kt)("p",null,"\u76ee\u524d\u6784\u9020\u65b9\u6cd5\u6ce8\u5165\u662f\u4f9d\u8d56\u6ce8\u5165\u63a8\u8350\u4f7f\u7528\u65b9\u5f0f\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u4f18\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u5728\u6784\u9020\u65b9\u6cd5\u4e2d\u4f53\u73b0\u51fa\u5bf9\u5176\u4ed6\u7c7b\u7684\u4f9d\u8d56\uff0c\u4e00\u773c\u5c31\u80fd\u770b\u51fa\u8fd9\u4e2a\u7c7b\u9700\u8981\u4f9d\u8d56\u54ea\u4e9b\u7c7b\u624d\u80fd\u5de5\u4f5c"),(0,a.kt)("li",{parentName:"ul"},"\u8131\u79bb\u4e86 IOC \u6846\u67b6\uff0c\u8fd9\u4e2a\u7c7b\u4ecd\u7136\u53ef\u4ee5\u5de5\u4f5c\uff0cPOJO \u7684\u6982\u5ff5"),(0,a.kt)("li",{parentName:"ul"},"\u4e00\u65e6\u5bf9\u8c61\u521d\u59cb\u5316\u6210\u529f\u4e86\uff0c\u8fd9\u4e2a\u5bf9\u8c61\u7684\u72b6\u6001\u80af\u5b9a\u662f\u6b63\u786e\u7684"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u7f3a\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u6784\u9020\u51fd\u6570\u4f1a\u6709\u5f88\u591a\u53c2\u6570\uff08Bad smell\uff09"),(0,a.kt)("li",{parentName:"ul"},"\u6709\u4e9b\u7c7b\u662f\u9700\u8981\u9ed8\u8ba4\u6784\u9020\u51fd\u6570\u7684\uff0c\u6bd4\u5982 MVC \u6846\u67b6\u7684 Controller \u7c7b\uff0c\u4e00\u65e6\u4f7f\u7528\u6784\u9020\u51fd\u6570\u6ce8\u5165\uff0c\u5c31\u65e0\u6cd5\u4f7f\u7528\u9ed8\u8ba4\u6784\u9020\u51fd\u6570"),(0,a.kt)("li",{parentName:"ul"},"\u8fd9\u4e2a\u7c7b\u91cc\u9762\u7684\u6709\u4e9b\u65b9\u6cd5\u5e76\u4e0d\u9700\u8981\u7528\u5230\u8fd9\u4e9b\u4f9d\u8d56\uff08Bad smell\uff09")))),(0,a.kt)("p",null,"\u4ee3\u7801\u793a\u4f8b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"public class FurionService\n{\n private readonly IRepository _repository;\n public FurionService(IRepository repository)\n {\n _repository = repository;\n }\n}\n")),(0,a.kt)("h3",{id:"1242-\u5c5e\u6027\u65b9\u5f0f\u6ce8\u5165"},"12.4.2 \u5c5e\u6027\u65b9\u5f0f\u6ce8\u5165"),(0,a.kt)("admonition",{title:"\u7279\u522b\u58f0\u660e",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u65b0\u7248\u672c\u4e2d\uff0c\u5df2\u7ecf\u79fb\u9664\u5c5e\u6027\u6ce8\u5165\u529f\u80fd\uff0c\u5efa\u8bae\u4f7f\u7528\u6784\u9020\u51fd\u6570\u6216\u65b9\u6cd5\u65b9\u5f0f\u6ce8\u5165\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"App.GetService")," \u65b9\u5f0f\u6ce8\u5165\u3002")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u901a\u8fc7\u5c5e\u6027\u65b9\u5f0f\u6ce8\u5165\u5bb9\u6613\u548c\u7c7b\u7684\u5b9e\u4f8b\u5c5e\u6027\u6df7\u6dc6\uff0c\u4e0d\u5efa\u8bae\u4f7f\u7528\u3002")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u4f18\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u5728\u5bf9\u8c61\u7684\u6574\u4e2a\u751f\u547d\u5468\u671f\u5185\uff0c\u53ef\u4ee5\u968f\u65f6\u52a8\u6001\u7684\u6539\u53d8\u4f9d\u8d56"),(0,a.kt)("li",{parentName:"ul"},"\u975e\u5e38\u7075\u6d3b"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u7f3a\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u5bf9\u8c61\u5728\u521b\u5efa\u540e\uff0c\u88ab\u8bbe\u7f6e\u4f9d\u8d56\u5bf9\u8c61\u4e4b\u524d\u8fd9\u6bb5\u65f6\u95f4\u72b6\u6001\u662f\u4e0d\u5bf9\u7684"),(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u76f4\u89c2\uff0c\u65e0\u6cd5\u6e05\u6670\u5730\u8868\u793a\u54ea\u4e9b\u5c5e\u6027\u662f\u5fc5\u987b\u7684")))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public class FurionService\n{\n public IRepository Repository { get; set; }\n}\n")),(0,a.kt)("h3",{id:"1243-\u65b9\u6cd5\u53c2\u6570\u6ce8\u5165"},"12.4.3 \u65b9\u6cd5\u53c2\u6570\u6ce8\u5165"),(0,a.kt)("p",null,"\u65b9\u6cd5\u53c2\u6570\u6ce8\u5165\u7684\u610f\u601d\u662f\u5728\u521b\u5efa\u5bf9\u8c61\u540e\uff0c\u901a\u8fc7\u81ea\u52a8\u8c03\u7528\u67d0\u4e2a\u65b9\u6cd5\u6765\u6ce8\u5165\u4f9d\u8d56\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u4f18\u70b9\uff1a"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u6bd4\u8f83\u7075\u6d3b"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u7f3a\u70b9\uff1a"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u65b0\u52a0\u5165\u4f9d\u8d56\u65f6\u4f1a\u7834\u574f\u539f\u6709\u7684\u65b9\u6cd5\u7b7e\u540d\uff0c\u5982\u679c\u8fd9\u4e2a\u65b9\u6cd5\u5df2\u7ecf\u88ab\u5176\u4ed6\u5f88\u591a\u6a21\u5757\u7528\u5230\u5c31\u5f88\u9ebb\u70e6"),(0,a.kt)("li",{parentName:"ul"},"\u4e0e\u6784\u9020\u65b9\u6cd5\u6ce8\u5165\u4e00\u6837\uff0c\u4f1a\u6709\u5f88\u591a\u53c2\u6570")))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public class FurionService\n{\n public Person GetById([FromServices]IRepository repository, int id)\n {\n return repository.Find(id);\n }\n}\n")),(0,a.kt)("h2",{id:"125-\u6ce8\u518c\u5bf9\u8c61\u751f\u5b58\u671f"},"12.5 \u6ce8\u518c\u5bf9\u8c61\u751f\u5b58\u671f"),(0,a.kt)("h3",{id:"1251-\u6682\u65f6\u77ac\u65f6-\u751f\u5b58\u671f"},"12.5.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u6682\u65f6/\u77ac\u65f6")," \u751f\u5b58\u671f"),(0,a.kt)("p",null,"\u6682\u65f6\u751f\u5b58\u671f\u670d\u52a1\u662f\u6bcf\u6b21\u4ece\u670d\u52a1\u5bb9\u5668\u8fdb\u884c\u8bf7\u6c42\u65f6\u521b\u5efa\u7684\u3002 \u8fd9\u79cd\u751f\u5b58\u671f\u9002\u5408\u8f7b\u91cf\u7ea7\u3001 \u65e0\u72b6\u6001\u7684\u670d\u52a1\u3002"),(0,a.kt)("p",null,"\u5728\u5904\u7406\u8bf7\u6c42\u7684\u5e94\u7528\u4e2d\uff0c\u5728\u8bf7\u6c42\u7ed3\u675f\u65f6\u4f1a\u91ca\u653e\u6682\u65f6\u670d\u52a1\u3002"),(0,a.kt)("p",null,"\u901a\u5e38\u6211\u4eec\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"ITransient")," \u63a5\u53e3\u4f9d\u8d56\u8868\u793a\u8be5\u751f\u547d\u5468\u671f\u3002"),(0,a.kt)("h3",{id:"1252-\u4f5c\u7528\u57df-\u751f\u5b58\u671f"},"12.5.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u4f5c\u7528\u57df")," \u751f\u5b58\u671f"),(0,a.kt)("p",null,"\u4f5c\u7528\u57df\u751f\u5b58\u671f\u670d\u52a1\u9488\u5bf9\u6bcf\u4e2a\u5ba2\u6237\u7aef\u8bf7\u6c42\uff08\u8fde\u63a5\uff09\u521b\u5efa\u4e00\u6b21\u3002\u5728\u5904\u7406\u8bf7\u6c42\u7684\u5e94\u7528\u4e2d\uff0c\u5728\u8bf7\u6c42\u7ed3\u675f\u65f6\u4f1a\u91ca\u653e\u6709\u4f5c\u7528\u57df\u7684\u670d\u52a1\u3002"),(0,a.kt)("p",null,"\u901a\u5e38\u6211\u4eec\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IScoped")," \u63a5\u53e3\u4f9d\u8d56\u8868\u793a\u8be5\u751f\u547d\u5468\u671f\u3002"),(0,a.kt)("h3",{id:"1253-\u5355\u4f8b-\u751f\u5b58\u671f"},"12.5.3 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u5355\u4f8b")," \u751f\u5b58\u671f"),(0,a.kt)("p",null,"\u5728\u9996\u6b21\u8bf7\u6c42\u5b83\u4eec\u65f6\u8fdb\u884c\u521b\u5efa\uff0c\u4e4b\u540e\u6bcf\u4e2a\u540e\u7eed\u8bf7\u6c42\u90fd\u4f7f\u7528\u76f8\u540c\u7684\u5b9e\u4f8b\u3002"),(0,a.kt)("p",null,"\u901a\u5e38\u6211\u4eec\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"ISingleton")," \u63a5\u53e3\u4f9d\u8d56\u8868\u793a\u8be5\u751f\u547d\u5468\u671f\u3002"),(0,a.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u670d\u52a1\u751f\u5b58\u671f")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0#service-lifetimes"},"ASP.NET Core - \u4f9d\u8d56\u6ce8\u5165 - \u670d\u52a1\u751f\u5b58\u671f")," \u7ae0\u8282\u3002")),(0,a.kt)("h2",{id:"126-\u5185\u7f6e\u4f9d\u8d56\u63a5\u53e3"},"12.6 \u5185\u7f6e\u4f9d\u8d56\u63a5\u53e3"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e09\u4e2a\u63a5\u53e3\u4f9d\u8d56\u5206\u522b\u5bf9\u5e94\u4e0d\u540c\u7684\u670d\u52a1\u751f\u5b58\u671f\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ITransient"),"\uff1a\u5bf9\u5e94\u6682\u65f6/\u77ac\u65f6\u4f5c\u7528\u57df\u670d\u52a1\u751f\u5b58\u671f"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IScoped"),"\uff1a\u5bf9\u5e94\u8bf7\u6c42\u4f5c\u7528\u57df\u670d\u52a1\u751f\u5b58\u671f"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ISingleton"),"\uff1a\u5bf9\u5e94\u5355\u4f8b\u4f5c\u7528\u57df\u670d\u52a1\u751f\u5b58\u671f")),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0a\u4e09\u4e2a\u63a5\u53e3\u53ea\u80fd\u5b9e\u4f8b\u7c7b\u5b9e\u73b0\uff0c\u5176\u4ed6\u9759\u6001\u7c7b\u3001\u62bd\u8c61\u7c7b\u3001\u53ca\u63a5\u53e3\u4e0d\u80fd\u5b9e\u73b0\u3002")),(0,a.kt)("h2",{id:"127-\u5e38\u89c1\u4f7f\u7528"},"12.7 \u5e38\u89c1\u4f7f\u7528"),(0,a.kt)("h3",{id:"1271-\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"12.7.1 \u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,a.kt)("p",null,"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"IBusinessService")," \u63a5\u53e3\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"BusinessService")," \u5b9e\u73b0\u7c7b\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,12}",showLineNumbers:!0,"":!0,"{7,12}":!0},"using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing Furion.DependencyInjection;\n\nnamespace Furion.Application\n{\n public interface IBusinessService\n {\n Person Get(int id);\n }\n\n public class BusinessService : IBusinessService, ITransient\n {\n private readonly IRepository _personRepository;\n\n public BusinessService(IRepository personRepository)\n {\n _personRepository = personRepository;\n }\n\n public Person Get(int id)\n {\n return _personRepository.Find(id);\n }\n }\n}\n")),(0,a.kt)("p",null,"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"PersonController")," \u63a7\u5236\u5668\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11,19}",showLineNumbers:!0,"":!0,"{11,19}":!0},'using Furion.Application;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n [ApiController]\n public class PersonController : ControllerBase\n {\n private readonly IBusinessService _businessService;\n public PersonController(IBusinessService businessService)\n {\n _businessService = businessService;\n }\n\n [HttpGet]\n public IActionResult Get(int id)\n {\n var person = _businessService.Get(id);\n return new JsonResult(person);\n }\n }\n}\n')),(0,a.kt)("img",{src:(0,l.Z)("img/di1.gif")}),(0,a.kt)("hr",null),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u4f8b\u5b50\u89e3\u8bf4")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u4e14\u65b9\u4fbf\u7684\u5b9e\u73b0\u4f9d\u8d56\u6ce8\u5165\u7684\u65b9\u5f0f\uff0c\u53ea\u9700\u8981\u5b9e\u4f8b\u7c7b\u7ee7\u627f\u5bf9\u5e94\u751f\u5b58\u671f\u7684\u63a5\u53e3\u5373\u53ef\uff0c\u8fd9\u91cc\u7ee7\u627f\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"ITransient"),"\uff0c\u4e5f\u5c31\u8868\u660e\u4e86\u8fd9\u662f\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6682\u65f6/\u77ac\u65f6")," \u4f5c\u7528\u57df\u5b9e\u4f8b\u7c7b\u3002\u8be5\u7c7b\u5c31\u53ef\u4ee5\u4f5c\u4e3a\u88ab\u6ce8\u5165\u5bf9\u8c61\uff0c\u540c\u65f6\u4e5f\u80fd\u6ce8\u5165\u5176\u4ed6\u63a5\u53e3\u5bf9\u8c61\u3002"),(0,a.kt)("p",null,"\u4e0a\u9762\u7684\u4f8b\u5b50\u4e2d\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"BusinessService")," \u6ce8\u5165\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"IRepository")," \u4ed3\u50a8\u63a5\u53e3\uff0c\u540c\u65f6 ",(0,a.kt)("inlineCode",{parentName:"p"},"PersonController")," \u63a7\u5236\u5668\u6ce8\u5165\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"IBusinessService")," \u63a5\u53e3\u3002"),(0,a.kt)("p",null,"\u8fd9\u6837 ",(0,a.kt)("inlineCode",{parentName:"p"},"PersonController")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"BusinessService")," \u4e4b\u95f4\u5c31\u5b9e\u73b0\u4e86\u89e3\u8026\uff0c\u4e0d\u518d\u4f9d\u8d56\u4e8e\u5177\u4f53\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"BusinessService")," \u5b9e\u4f8b\u3002"),(0,a.kt)("p",null,"\u8fd9\u5c31\u662f\u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c\u6700\u7ecf\u5178\u7684\u4f8b\u5b50\u3002"),(0,a.kt)("h3",{id:"1272-\u6ce8\u518c\u6cdb\u578b\u5b9e\u4f8b"},"12.7.2 \u6ce8\u518c\u6cdb\u578b\u5b9e\u4f8b"),(0,a.kt)("p",null,"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"IBusinessService")," \u63a5\u53e3\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"BusinessService")," \u5b9e\u73b0\u7c7b\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,12}",showLineNumbers:!0,"":!0,"{7,12}":!0},"using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing Furion.DependencyInjection;\n\nnamespace Furion.Application\n{\n public interface IBusinessService\n {\n Person Get(int id);\n }\n\n public class BusinessService : IBusinessService, ITransient\n {\n private readonly IRepository _personRepository;\n\n public BusinessService(IRepository personRepository)\n {\n _personRepository = personRepository;\n }\n\n public Person Get(int id)\n {\n return _personRepository.Find(id);\n }\n }\n}\n")),(0,a.kt)("p",null,"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"PersonController")," \u63a7\u5236\u5668\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11,19}",showLineNumbers:!0,"":!0,"{11,19}":!0},'using Furion.Application;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n [ApiController]\n public class PersonController : ControllerBase\n {\n private readonly IBusinessService _businessService;\n public PersonController(IBusinessService businessService)\n {\n _businessService = businessService;\n }\n\n [HttpGet]\n public IActionResult Get(int id)\n {\n var person = _businessService.Get(id);\n return new JsonResult(person);\n }\n }\n}\n')),(0,a.kt)("h3",{id:"1273-\u4e00\u4e2a\u63a5\u53e3\u591a\u4e2a\u5b9e\u73b0"},"12.7.3 \u4e00\u4e2a\u63a5\u53e3\u591a\u4e2a\u5b9e\u73b0"),(0,a.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u4e00\u4e2a\u63a5\u53e3\u53ea\u5bf9\u5e94\u4e00\u4e2a\u5b9e\u73b0\u7c7b\uff0c\u4f46\u6709\u4e9b\u7279\u6b8a\u60c5\u51b5\uff0c\u9700\u8981\u591a\u4e2a\u5b9e\u73b0\u7c7b\u6ce8\u518c\u540c\u4e00\u4e2a\u63a5\u53e3\uff0c\u5982 ",(0,a.kt)("inlineCode",{parentName:"p"},"DbContext")," \u591a\u6570\u636e\u5e93\u60c5\u51b5\u3002"),(0,a.kt)("p",null,"\u8fd9\u4e2a\u65f6\u5019\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u4f9d\u8d56\u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"p"},"Func")," \u59d4\u6258\u6765\u89e3\u6790\u591a\u4e2a\u5b9e\u4f8b\uff0c\u5176\u4e2d\u59d4\u6258\u7684\u53c2\u6570\u5206\u522b\u4e3a\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u53c2\u6570 1\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u4e0d\u540c\u5b9e\u73b0\u7c7b\u552f\u4e00\u6807\u8bc6\uff0c\u9ed8\u8ba4\u4e3a ",(0,a.kt)("inlineCode",{parentName:"li"},"nameof(\u5b9e\u73b0\u7c7b)")," \u540d\u79f0"),(0,a.kt)("li",{parentName:"ul"},"\u53c2\u6570 2\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Type")," \u7c7b\u578b\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"IPrivateDependency")," \u6d3e\u751f\u63a5\u53e3\uff0c\u4e5f\u5c31\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"ITransient"),"\u3001",(0,a.kt)("inlineCode",{parentName:"li"},"IScoped"),"\u3001",(0,a.kt)("inlineCode",{parentName:"li"},"ISingleton")),(0,a.kt)("li",{parentName:"ul"},"\u8fd4\u56de\u503c\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"object")," \u7c7b\u578b\uff0c\u8fd4\u56de\u5177\u4f53\u7684\u5b9e\u73b0\u7c7b\u5b9e\u4f8b")),(0,a.kt)("p",null,"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"IBusinessService")," \u63a5\u53e3\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"BusinessService"),"\u3001",(0,a.kt)("inlineCode",{parentName:"p"},"OtherBusinessService")," \u4e24\u4e2a\u5b9e\u73b0\u7c7b\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,10,18}",showLineNumbers:!0,"":!0,"{5,10,18}":!0},'using Furion.DependencyInjection;\n\nnamespace Furion.Application\n{\n public interface IBusinessService\n {\n string GetName();\n }\n\n public class BusinessService : IBusinessService, ITransient\n {\n public string GetName()\n {\n return "\u6211\u662f\uff1a" + nameof(BusinessService);\n }\n }\n\n public class OtherBusinessService : IBusinessService, ITransient\n {\n public string GetName()\n {\n return "\u6211\u662f\uff1a" + nameof(OtherBusinessService);\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u65b0\u7248\u672c\uff0c\u63a8\u8350\u4f7f\u7528",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 3.8.6+")," \u7248\u672c\u4e4b\u540e\u65b0\u589e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"INamedServiceProvider")," \u670d\u52a1\u63a5\u53e3\uff0c\u53ef\u66ff\u4ee3 ",(0,a.kt)("inlineCode",{parentName:"p"},"Func")," \u65b9\u5f0f\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8,15-17,19-23}",showLineNumbers:!0,"{8,15-17,19-23}":!0},'using Furion.Application.Services;\n\nnamespace Furion.Application;\n\npublic class TestNamedServices : IDynamicApiController\n{\n private readonly INamedServiceProvider _namedServiceProvider;\n public TestNamedServices(INamedServiceProvider namedServiceProvider)\n {\n _namedServiceProvider = namedServiceProvider;\n }\n\n public string GetName()\n {\n // \u7b2c\u4e00\u79cd\u7528\u6cd5\uff0c\u901a\u8fc7\u53cd\u5c04\u89e3\u6790\u670d\u52a1\u5468\u671f\uff0c\u6027\u80fd\u6709\u635f\u8017\n var service1 = _namedServiceProvider.GetService(nameof(BusinessService));\n var service2 = _namedServiceProvider.GetService(nameof(OtherBusinessService));\n\n // \u7b2c\u4e8c\u79cd\u7528\u6cd5\uff0c\u65e0\u9700\u53cd\u5c04\uff0c\u6ce8\u610f\u4e0b\u9762\u7684\u6cdb\u578b\u53c2\u6570\u4f20\u5165\u7684\u662f\u751f\u547d\u5468\u671f\u4f9d\u8d56\u63a5\u53e3\uff0cITransient, IScoped, ISingleton\n var service3 = _namedServiceProvider.GetService(nameof(BusinessService));\n var service4 = _namedServiceProvider.GetService(nameof(OtherBusinessService));\n\n return service1.GetName() + "-" + service2.GetName() + "-" + service3.GetName() + "-" + service4.GetName();\n }\n}\n'))),(0,a.kt)("admonition",{type:"important"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u4e0d\u518d\u63a8\u8350 ",(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Func")," \u65b9\u5f0f"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {15,17,18}",showLineNumbers:!0,"":!0,"{15,17,18}":!0},'using Furion.Application;\nusing Furion.DependencyInjection;\nusing Microsoft.AspNetCore.Mvc;\nusing System;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n [ApiController]\n public class ValueController : ControllerBase\n {\n private readonly IBusinessService _businessService;\n private readonly IBusinessService _otherBusinessService;\n\n public ValueController(Func resolveNamed)\n {\n _businessService = resolveNamed("BusinessService", default) as IBusinessService;\n _otherBusinessService = resolveNamed("OtherBusinessService", default) as IBusinessService;\n }\n\n [HttpGet]\n public string GetName()\n {\n return _businessService.GetName() + "----------" + _otherBusinessService.GetName();\n }\n }\n}\n'))),(0,a.kt)("img",{src:(0,l.Z)("img/di2.gif")}),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u9700\u8981\u81ea\u5b9a\u4e49\u89e3\u6790\u540d\u79f0\uff0c\u53ea\u9700\u8981\u8d34 ",(0,a.kt)("inlineCode",{parentName:"p"},'[Injection(Named = "\u540d\u79f0")]')," \u5373\u53ef\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,11}",showLineNumbers:!0,"":!0,"{5,11}":!0},'using Furion.DependencyInjection;\n\nnamespace Furion.Application\n{\n [Injection(Named = "BusName1")]\n public class BusinessService : IBusinessService, ITransient\n {\n // ...\n }\n\n [Injection(Named = "BusName2")]\n public class OtherBusinessService : IBusinessService, ITransient\n {\n // ...\n }\n}\n')),(0,a.kt)("p",{parentName:"admonition"},"\u89e3\u6790\u670d\u52a1\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'_businessService = resolveNamed("BusName1", default) as IBusinessService;\n_otherBusinessService = resolveNamed("BusName2", default) as IBusinessService;\n'))),(0,a.kt)("h3",{id:"1274-\u65e0\u63a5\u53e3\u65b9\u5f0f"},"12.7.4 \u65e0\u63a5\u53e3\u65b9\u5f0f"),(0,a.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u4e0d\u60f3\u5b9a\u4e49\u63a5\u53e3\uff0c\u800c\u662f\u60f3\u628a\u5b9e\u4f8b\u7c7b\u4f5c\u4e3a\u53ef\u4f9d\u8d56\u6ce8\u5165\u7684\u5bf9\u8c61\uff0c\u5982 MVC \u4e2d\u7684\u63a7\u5236\u5668\u3002"),(0,a.kt)("p",null,"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"SelfService")," \u5b9e\u4f8b\u7c7b\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,11}",showLineNumbers:!0,"":!0,"{7,11}":!0},"using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing Furion.DependencyInjection;\n\nnamespace Furion.Application\n{\n public class SelfService : ITransient\n {\n private readonly IRepository _personRepository;\n\n public SelfService(IRepository personRepository)\n {\n _personRepository = personRepository;\n }\n\n public Person Get(int id)\n {\n return _personRepository.Find(id);\n }\n }\n}\n")),(0,a.kt)("p",null,"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"ValueController")," \u63a7\u5236\u5668\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,21}",showLineNumbers:!0,"":!0,"{13,21}":!0},'using Furion.Application;\nusing Furion.Core;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n [ApiController]\n public class ValueController : ControllerBase\n {\n private readonly SelfService _selfService;\n\n public ValueController(SelfService selfService)\n {\n _selfService = selfService;\n }\n\n [HttpGet]\n public Person Get(int id)\n {\n return _selfService.Get(id);\n }\n }\n}\n')),(0,a.kt)("h2",{id:"128-injection-\u7279\u6027\u914d\u7f6e"},"12.8 ",(0,a.kt)("inlineCode",{parentName:"h2"},"[Injection]")," \u7279\u6027\u914d\u7f6e"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b ",(0,a.kt)("inlineCode",{parentName:"p"},"[Injection]")," \u7279\u6027\u53ef\u4ee5\u6539\u53d8\u6ce8\u518c\u65b9\u5f0f\uff0c\u540c\u65f6\u8fd8\u80fd\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"p"},"AOP")," \u62e6\u622a\u3002"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"[Injection]")," \u63d0\u4f9b\u4ee5\u4e0b\u914d\u7f6e\u652f\u6301\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Action"),"\uff1a\u914d\u7f6e\u6ce8\u518c\u884c\u4e3a\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"InjectionActions")," \u7c7b\u578b\uff0c\u53ef\u9009\u503c\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Add"),"\uff1a",(0,a.kt)("strong",{parentName:"li"},"\u9ed8\u8ba4\u503c"),"\uff0c\u8868\u793a\u65e0\u9650\u5236\u6dfb\u52a0\u6ce8\u518c\u670d\u52a1\uff0c\u8be5\u65b9\u5f0f\u652f\u6301\u4e00\u4e2a\u63a5\u53e3\u591a\u4e2a\u5b9e\u73b0"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"TryAdd"),"\uff1a\u8868\u793a\u6ce8\u518c\u5df2\u5b58\u5728\u5219\u8df3\u8fc7\u6ce8\u518c"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Pattern"),"\uff1a\u914d\u7f6e\u6ce8\u518c\u9009\u9879\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"InjectionPatterns")," \u7c7b\u578b\uff0c\u53ef\u9009\u503c\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Self"),"\uff1a\u53ea\u6ce8\u518c\u81ea\u5df1"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"FirstInterface"),"\uff1a\u53ea\u6ce8\u518c\u7b2c\u4e00\u4e2a\u63a5\u53e3"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"SelfWithFirstInterface"),"\uff1a\u6ce8\u518c\u81ea\u5df1\u548c\u7b2c\u4e00\u4e2a\u63a5\u53e3"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ImplementedInterfaces"),"\uff1a\u6ce8\u518c\u6240\u6709\u63a5\u53e3"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"All"),"\uff1a\u6ce8\u518c\u81ea\u5df1\u5305\u62ec\u6240\u6709\u63a5\u53e3 \uff0c",(0,a.kt)("strong",{parentName:"li"},"\u9ed8\u8ba4\u503c")))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Named"),"\uff1a\u914d\u7f6e\u5b9e\u4f8b\u522b\u540d\uff0c\u901a\u8fc7\u522b\u540d\u53ef\u4ee5\u89e3\u6790\u63a5\u53e3\uff0c\u5982\u540c\u4e00\u4e2a\u63a5\u53e3\u6709\u591a\u4e2a\u5b9e\u73b0\uff0c\u90a3\u4e48\u53ef\u4ee5\u901a\u8fc7\u522b\u540d\u89e3\u6790\u4e0d\u540c\u7684\u5b9e\u73b0\uff0c\u9ed8\u8ba4\u53ea\u4e3a\u5b9e\u73b0\u7c7b\u7684\u7c7b\u540d"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Order"),"\uff1a\u6ce8\u518c\u6392\u5e8f\uff0c\u6570\u5b57\u8d8a\u5927\uff0c\u5219\u8d8a\u5728\u6700\u540e\u6ce8\u518c\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"0")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Proxy"),"\uff1a\u914d\u7f6e\u4ee3\u7406\u62e6\u622a\u7c7b\u578b\uff0c\u4e5f\u5c31\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"AOP"),"\uff0c",(0,a.kt)("strong",{parentName:"li"},"\u4ee3\u7406\u7c7b\u578b\u5fc5\u987b\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"strong"},"AspectDispatchProxy")," \u7c7b\u548c ",(0,a.kt)("inlineCode",{parentName:"strong"},"IDispatchProxy")," \u63a5\u53e3"),"\uff0c\u65e0\u9ed8\u8ba4\u503c"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ExpectInterfaces"),"\uff1a\u914d\u7f6e\u5ffd\u7565\u6ce8\u518c\u7684\u63a5\u53e3\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"Type[]")," \u7c7b\u578b")),(0,a.kt)("h2",{id:"129-\u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c"},"12.9 \u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c"),(0,a.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u7684\u6ce8\u518c\u65b9\u5f0f\u53ef\u4ee5\u6ee1\u8db3\u5927\u591a\u6570\u4f9d\u8d56\u6ce8\u5165\u7684\u9700\u6c42\uff0c\u5982\u6709\u7279\u522b\u6ce8\u518c\u9700\u6c42\uff0c\u53ea\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup")," \u4e2d\u914d\u7f6e\u5373\u53ef\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddScoped(typeof(ISpecService), provider = > {\n // \u81ea\u5b9a\u4e49\u4efb\u4f55\u521b\u5efa\u5b9e\u4f8b\u7684\u65b9\u5f0f\n var instance = new SpecService(); // \u6216\u8005\u53ef\u4ee5\u901a\u8fc7 AOP\u63d2\u4ef6\u8fd4\u56de\u4ee3\u7406\u5b9e\u4f8b\n\n return instance;\n});\n")),(0,a.kt)("admonition",{title:"\u8865\u5145\u8bf4\u660e",type:"note"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u8fd8\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},"ISqlDispatchProxy")," \u90fd\u662f\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\u521b\u5efa\u7684\u3002")),(0,a.kt)("admonition",{title:"\u77e5\u8bc6\u5bfc\u822a",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a\u81ea\u5b9a\u4e49\u9ad8\u7ea7\u4e2d\u6ce8\u518c\uff0c\u53ef\u67e5\u9605 \u3010",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0"},"ASP.NET Core \u4f9d\u8d56\u6ce8\u5165"),"\u3011 \u5b98\u65b9\u6587\u6863\u3002")),(0,a.kt)("h2",{id:"1210-appsettingsjson-\u914d\u7f6e\u6ce8\u518c"},"12.10 ",(0,a.kt)("inlineCode",{parentName:"h2"},"appsettings.json")," \u914d\u7f6e\u6ce8\u518c"),(0,a.kt)("p",null,"\u9664\u4e86\u5728\u4ee3\u7801\u4e2d\u5b9e\u73b0\u4f9d\u8d56\u6ce8\u5165\uff0c\u4e5f\u53ef\u4ee5\u5b9e\u73b0\u52a8\u6001\u4f9d\u8d56\u6ce8\u5165\uff0c\u65e0\u9700\u4fee\u6539\u4ee3\u7801\u6216\u91cd\u65b0\u7f16\u8bd1\u5373\u53ef\u5b9e\u73b0\u70ed\u63d2\u62d4\uff08\u63d2\u4ef6\uff09\u6548\u679c\u3002\u914d\u7f6e\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},'{\n "DependencyInjectionSettings": {\n "Definitions": [\n {\n "Interface": "Furion.Application;Furion.Application.ITestService",\n "Service": "Furion.Application;Furion.Application.TestService",\n "RegisterType": "Transient",\n "Action": "Add",\n "Pattern": "SelfWithFirstInterface",\n "Named": "TestService",\n "Order": 1,\n "Proxy": "Furion.Application;Furion.Application.LogDispathProxy"\n }\n ]\n }\n}\n')),(0,a.kt)("p",null,"\u914d\u7f6e\u8bf4\u660e\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"DependencyInjectionSettings"),"\uff1a\u4f9d\u8d56\u6ce8\u5165\u914d\u7f6e\u6839\u8282\u70b9",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Definitions"),"\uff1a\u52a8\u6001\u4f9d\u8d56\u6ce8\u5165\u914d\u7f6e\u8282\u70b9\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"ExternalService")," \u6570\u7ec4\u7c7b\u578b",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ExternalService"),"\uff1a\u914d\u7f6e\u5355\u4e2a\u4f9d\u8d56\u6ce8\u5165\u4fe1\u606f",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Interface"),"\uff1a\u914d\u7f6e\u4f9d\u8d56\u63a5\u53e3\u4fe1\u606f\uff0c\u683c\u5f0f\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"\u7a0b\u5e8f\u96c6\u540d\u79f0;\u63a5\u53e3\u5b8c\u6574\u540d\u79f0"),"\uff0c\u5982\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Furion.Application;Furion.Application.ITestService")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Service"),"\uff1a\u914d\u7f6e\u63a5\u53e3\u5b9e\u73b0\u4fe1\u606f\uff0c\u683c\u5f0f\u540c\u4e0a"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"RegisterType"),"\uff1a\u914d\u7f6e\u4f9d\u8d56\u6ce8\u5165\u7684\u5bf9\u8c61\u751f\u5b58\u671f\uff0c\u53d6\u503c\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Transient"),"\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"Scoped"),"\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"Singleton")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Action"),"\uff1a\u6ce8\u518c\u884c\u4e3a\uff0c\u53ef\u9009\u503c\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Add"),"\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"TryAdd"),"\uff0c\u53c2\u89c1 ",(0,a.kt)("a",{parentName:"li",href:"#128-injection-%E7%89%B9%E6%80%A7%E9%85%8D%E7%BD%AE"},"#128-injection-\u7279\u6027\u914d\u7f6e")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Pattern"),"\uff1a\u6ce8\u518c\u9009\u9879\uff0c\u53c2\u89c1 ",(0,a.kt)("a",{parentName:"li",href:"#128-injection-%E7%89%B9%E6%80%A7%E9%85%8D%E7%BD%AE"},"#128-injection-\u7279\u6027\u914d\u7f6e")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Named"),"\uff1a\u6ce8\u518c\u522b\u540d\uff0c\u53c2\u89c1 ",(0,a.kt)("a",{parentName:"li",href:"#128-injection-%E7%89%B9%E6%80%A7%E9%85%8D%E7%BD%AE"},"#128-injection-\u7279\u6027\u914d\u7f6e")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Order"),"\uff1a\u6ce8\u518c\u6392\u5e8f\uff0c\u53c2\u89c1 ",(0,a.kt)("a",{parentName:"li",href:"#128-injection-%E7%89%B9%E6%80%A7%E9%85%8D%E7%BD%AE"},"#128-injection-\u7279\u6027\u914d\u7f6e")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Proxy"),"\uff1a\u914d\u7f6e\u4ee3\u7406\u62e6\u622a\uff0c\u683c\u5f0f\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"\u7a0b\u5e8f\u96c6\u540d\u79f0;\u4ee3\u7406\u7c7b\u5b8c\u6574\u540d\u79f0"),"\uff0c\u53c2\u89c1 ",(0,a.kt)("a",{parentName:"li",href:"#128-injection-%E7%89%B9%E6%80%A7%E9%85%8D%E7%BD%AE"},"#128-injection-\u7279\u6027\u914d\u7f6e"))))))))),(0,a.kt)("admonition",{title:"\u5173\u4e8e\u5916\u90e8\u7a0b\u5e8f\u96c6",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u52a8\u6001\u6ce8\u5165\u7684\u5bf9\u8c61\u662f\u5916\u90e8\u7a0b\u5e8f\u96c6\uff0c\u90a3\u4e48\u9996\u5148\u5148\u6ce8\u518c\u5916\u90e8\u7a0b\u5e8f\u96c6\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "AppSettings": {\n "ExternalAssemblies": ["\u5916\u90e8\u7a0b\u5e8f\u96c6\u540d\u79f0", "Taobao.Pay"] // \u652f\u6301\u591a\u4e2a\n }\n}\n'))),(0,a.kt)("h2",{id:"1211-\u6ce8\u518c\u987a\u5e8f\u548c\u4f18\u5148\u7ea7"},"12.11 \u6ce8\u518c\u987a\u5e8f\u548c\u4f18\u5148\u7ea7"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u6ce8\u518c\u987a\u5e8f\u662f\u6309\u7167\u7a0b\u5e8f\u96c6\u626b\u63cf\u987a\u5e8f\u8fdb\u884c\u6ce8\u518c\uff0c\u5982\u679c\u9700\u8981\u6539\u53d8\u6ce8\u518c\u987a\u5e8f\uff0c\u53ef\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"[Injection(Order)]")," \u7279\u6027\u6307\u5b9a\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Order")," \u503c\u8d8a\u5927\uff0c\u5219\u8d8a\u5728\u6700\u540e\u6ce8\u518c\u3002"),(0,a.kt)("p",null,"\u53e6\u5916 ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u914d\u7f6e\u7684\u4f18\u5148\u7ea7\u6700\u5927\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u914d\u7f6e\u7684\u6ce8\u518c\u4f1a\u8986\u76d6\u4e4b\u524d\u6240\u6709\u6ce8\u518c\u3002"),(0,a.kt)("h2",{id:"1212-aop-\u6ce8\u518c\u62e6\u622a"},"12.12 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Aop")," \u6ce8\u518c\u62e6\u622a"),(0,a.kt)("admonition",{title:"\u5173\u4e8e\u52a8\u6001 API \u548c\u670d\u52a1\u7684\u533a\u522b",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u60a8\u7684\u670d\u52a1\u662f\u52a8\u6001 API\uff0c\u90a3\u4e48\u8bf7\u4f7f\u7528 ",(0,a.kt)("a",{parentName:"p",href:"/docs/dynamic-api-controller#511-%E5%85%B3%E4%BA%8E-aop-%E6%8B%A6%E6%88%AA"},"\u52a8\u6001 API - AOP \u62e6\u622a"),"\uff0c\u539f\u56e0\u662f\u52a8\u6001 API \u672c\u8d28\u662f\u63a7\u5236\u5668\uff0c\u6240\u4ee5\u91c7\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Filter")," \u65b9\u5f0f\u3002")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AOP")," \u662f\u975e\u5e38\u91cd\u8981\u7684\u601d\u60f3\u548c\u6280\u672f\uff0c\u4e5f\u5c31\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"\u9762\u5411\u5207\u9762")," \u7f16\u7a0b\uff0c\u53ef\u4ee5\u8ba9\u6211\u4eec\u5728\u4e0d\u6539\u52a8\u539f\u6765\u4ee3\u7801\u7684\u60c5\u51b5\u4e0b\u8fdb\u884c\u52a8\u6001\u7be1\u6539\u4e1a\u52a1\u4ee3\u7801\u3002"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5b9e\u73b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"Aop")," \u975e\u5e38\u7b80\u5355\uff0c\u5982\uff1a"),(0,a.kt)("p",null,"\u5047\u8bbe\u6211\u4eec\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},"ITestService")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"TestService")," \u4e24\u4e2a\u7c7b\u578b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public interface ITestService\n{\n string SayHello(string word);\n}\n")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public class TestService: ITestService, ITransient\n{\n public string SayHello(string word)\n {\n return $"Hello {word}";\n }\n}\n')),(0,a.kt)("p",null,"\u73b0\u5728\u6211\u4eec\u6709\u4e00\u4e2a\u9700\u6c42\uff0c\u6211\u4eec\u5e0c\u671b\u8c03\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"SayHello")," \u7684\u65f6\u5019\u53ef\u4ee5\u8bb0\u5f55\u65e5\u5fd7\u548c\u6743\u9650\u63a7\u5236\uff08\u4e4b\u524d\u6ca1\u6709\u8003\u8651\u5230\u7684\u9700\u6c42\uff09\u3002"),(0,a.kt)("p",null,"\u8fd9\u4e2a\u65f6\u5019\u6211\u4eec\u53ea\u9700\u8981\u521b\u5efa\u4e00\u4e2a\u4ee3\u7406\u7c7b\u5373\u53ef\uff0c\u5982 ",(0,a.kt)("inlineCode",{parentName:"p"},"LogDispatchProxy")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,7,25,37,48}",showLineNumbers:!0,"":!0,"{1,3,7,25,37,48}":!0},'using Furion.DependencyInjection;\nusing System;\nusing System.Reflection;\n\nnamespace Furion.Application\n{\n public class LogDispatchProxy : AspectDispatchProxy, IDispatchProxy\n {\n /// \n /// \u5f53\u524d\u670d\u52a1\u5b9e\u4f8b\n /// \n public object Target { get; set; }\n\n /// \n /// \u670d\u52a1\u63d0\u4f9b\u5668\uff0c\u53ef\u4ee5\u7528\u6765\u89e3\u6790\u670d\u52a1\uff0c\u5982\uff1aServices.GetService()\n /// \n public IServiceProvider Services { get; set; }\n\n /// \n /// \u62e6\u622a\u65b9\u6cd5\n /// \n /// \n /// \n /// \n public override object Invoke(MethodInfo method, object[] args)\n {\n Console.WriteLine("SayHello \u65b9\u6cd5\u88ab\u8c03\u7528\u4e86");\n\n var result = method.Invoke(Target, args);\n\n Console.WriteLine("SayHello \u65b9\u6cd5\u8fd4\u56de\u503c\uff1a" + result);\n\n return result;\n }\n\n // \u5f02\u6b65\u65e0\u8fd4\u56de\u503c\n public override async Task InvokeAsync(MethodInfo method, object[] args)\n {\n Console.WriteLine("SayHello \u65b9\u6cd5\u88ab\u8c03\u7528\u4e86");\n\n var task = method.Invoke(Target, args) as Task;\n await task;\n\n Console.WriteLine("SayHello \u65b9\u6cd5\u8c03\u7528\u5b8c\u6210");\n }\n\n // \u5f02\u6b65\u5e26\u8fd4\u56de\u503c\n public override async Task InvokeAsyncT(MethodInfo method, object[] args)\n {\n Console.WriteLine("SayHello \u65b9\u6cd5\u88ab\u8c03\u7528\u4e86");\n\n var taskT = method.Invoke(Target, args) as Task;\n var result = await taskT;\n\n Console.WriteLine("SayHello \u65b9\u6cd5\u8fd4\u56de\u503c\uff1a" + result);\n\n return result;\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u83b7\u53d6\u7279\u6027",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u9700\u8981\u83b7\u53d6\u65b9\u6cd5\u7684\u7279\u6027\uff0c\u53ea\u9700\u8981\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"method.GetActualCustomAttribute()")," \u5373\u53ef\u3002\u6240\u6709\u83b7\u53d6\u771f\u5b9e\u7684\u7279\u6027\u7edf\u4e00\u91c7\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"method.GetActual....()")," \u65b9\u6cd5\u5f00\u5934\u3002")),(0,a.kt)("p",null,"\u4e4b\u540e\u6211\u4eec\u53ea\u9700\u8981\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"TestService")," \u589e\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"[Injection]")," \u7279\u6027\u5373\u53ef\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'[Injection(Proxy = typeof(LogDispatchProxy))]\npublic class TestService: ITestService, ITransient\n{\n public string SayHello(string word)\n {\n return $"Hello {word}";\n }\n}\n')),(0,a.kt)("p",null,"\u4e4b\u540e ",(0,a.kt)("inlineCode",{parentName:"p"},"SayHello")," \u65b9\u6cd5\u88ab\u8c03\u7528\u7684\u65f6\u5019\u5c31\u53ef\u4ee5\u5b9e\u73b0\u52a8\u6001\u62e6\u622a\u4e86\uff0c\u6bd4\u5982\u8fd9\u91cc\u5199\u65e5\u5fd7\u3002"),(0,a.kt)("h3",{id:"12121-\u5168\u5c40aop\u62e6\u622a"},"12.12.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u5168\u5c40Aop\u62e6\u622a")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e5f\u63d0\u4f9b\u4e86\u5168\u5c40\u62e6\u622a\u7684\u65b9\u5f0f\uff0c\u53ea\u9700\u8981\u5c06 ",(0,a.kt)("inlineCode",{parentName:"p"},"IDispatchProxy")," \u4fee\u6539\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"IGlobalDispatchProxy")," \u5373\u53ef\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"using Furion;\nusing System.Reflection;\n\nnamespace Furion.Application\n{\n public class LogDispatchProxy : AspectDispatchProxy, IGlobalDispatchProxy\n {\n // ....\n }\n}\n")),(0,a.kt)("p",null,"\u8fd9\u6837\u5c31\u4f1a\u62e6\u622a\u6240\u6709\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Service"),"\uff0c\u5f53\u7136\u4e5f\u53ef\u4ee5\u901a\u8fc7\u7ed9\u7279\u5b9a\u7c7b\u8d34 ",(0,a.kt)("inlineCode",{parentName:"p"},"[SuppressProxy]")," \u8df3\u8fc7\u5168\u5c40\u62e6\u622a\u64cd\u4f5c\u3002"),(0,a.kt)("admonition",{title:"\u62e6\u622a\u4f18\u5148\u7ea7",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"[SuppressProxy]")," > ",(0,a.kt)("inlineCode",{parentName:"p"},"[Injection(Proxy = typeof(LogDispatchProxy))]")," > ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5168\u5c40\u62e6\u622a"),"\u3002")),(0,a.kt)("h3",{id:"12122-aop-\u6ce8\u5165\u89e3\u6790\u670d\u52a1"},"12.12.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AOP")," \u6ce8\u5165\u89e3\u6790\u670d\u52a1"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u672a\u63d0\u4f9b ",(0,a.kt)("inlineCode",{parentName:"p"},"Proxy")," \u6784\u9020\u51fd\u6570\u6ce8\u5165\u529f\u80fd\uff0c\u4f46\u662f\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"Services")," \u5c5e\u6027\uff0c\u5982\u679c\u9700\u8981\u89e3\u6790\u670d\u52a1\uff0c\u5219\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u65b9\u5f0f\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var someServices = Services.GetService(); // \u63a8\u8350\u65b9\u5f0f\n// \u6216\nvar someServices = App.GetService();\n")),(0,a.kt)("h3",{id:"12123-aop-\u7684\u4f5c\u7528"},"12.12.3 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AOP")," \u7684\u4f5c\u7528"),(0,a.kt)("p",null,"\u8fd9\u79cd\u9762\u5411\u5207\u9762\u7684\u80fd\u529b\uff08\u52a8\u6001\u62e6\u622a/\u4ee3\u7406\uff09\u53ef\u4ee5\u5b9e\u73b0\u5f88\u591a\u5f88\u591a\u529f\u80fd\uff0c\u5982\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u52a8\u6001\u65e5\u5fd7\u8bb0\u5f55"),(0,a.kt)("li",{parentName:"ul"},"\u52a8\u6001\u4fee\u6539\u53c2\u6570"),(0,a.kt)("li",{parentName:"ul"},"\u52a8\u6001\u4fee\u6539\u8fd4\u56de\u503c"),(0,a.kt)("li",{parentName:"ul"},"\u52a8\u6001\u65b9\u6cd5\u91cd\u5b9a\u5411"),(0,a.kt)("li",{parentName:"ul"},"\u52a8\u6001\u4fee\u6539\u4ee3\u7801\u903b\u8f91"),(0,a.kt)("li",{parentName:"ul"},"\u52a8\u6001\u5b9e\u73b0\u5f02\u5e38\u76d1\u542c")),(0,a.kt)("p",null,"\u8fd8\u53ef\u4ee5\u505a\u66f4\u591a\u66f4\u591a\u7684\u4e8b\u60c5\u3002"),(0,a.kt)("h2",{id:"1213-\u5728\u975e-web-\u6216\u591a\u7ebf\u7a0b\u89e3\u6790\u670d\u52a1"},"12.13 \u5728\u975e ",(0,a.kt)("inlineCode",{parentName:"h2"},"Web")," \u6216\u591a\u7ebf\u7a0b\u89e3\u6790\u670d\u52a1"),(0,a.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u8bf7\u6c42\u5f00\u59cb\u4e4b\u524d\u4f1a\u81ea\u52a8\u521b\u5efa\u8303\u56f4\u4f5c\u7528\u57df\uff0c\u8fd9\u4e2a\u4f5c\u7528\u57df\u7684\u751f\u5b58\u5468\u671f\u662f\u8bf7\u6c42\u4e4b\u524d\u548c\u54cd\u5e94\u4e4b\u540e\uff0c\u4e5f\u5c31\u662f\u5728\u8fd9\u4e2a\u4f5c\u7528\u57df\u5185\u7684\u6240\u6709\u670d\u52a1\u90fd\u5b9e\u73b0\u4e86\u81ea\u52a8\u7ba1\u7406\uff0c\u6bd4\u5982\u521b\u5efa\u670d\u52a1\u548c\u91ca\u653e\u670d\u52a1\u7684\u65f6\u673a\u3002"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u4f46\u5728\u975e ",(0,a.kt)("inlineCode",{parentName:"strong"},"Web")," \u6216\u591a\u7ebf\u7a0b\u4e2d\uff0c\u6846\u67b6\u5e76\u4e0d\u4f1a\u505a\u8fd9\u6837\u7684\u4e8b\u60c5\uff0c\u4e5f\u5c31\u662f\u6846\u67b6\u53ea\u8d1f\u8d23\u4e86\u670d\u52a1\u7684\u521b\u5efa\uff0c\u4f46\u662f\u6ca1\u6709\u8d1f\u8d23\u9500\u6bc1\uff0c\u539f\u56e0\u662f\u6846\u67b6\u65e0\u6cd5\u5f97\u77e5\u5177\u4f53\u7684\u9500\u6bc1\u65f6\u673a\uff0c\u8fd9\u6837\u5c31\u5bfc\u81f4\u4e86\u5185\u5b58\u6ea2\u51fa\u3002")),(0,a.kt)("p",null,"\u89e3\u51b3\u65b9\u5f0f\u662f\uff1a\u5728\u975e ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u6216\u591a\u7ebf\u7a0b\u4e2d\u4f7f\u7528\u670d\u52a1\uff0c\u5e94\u8be5\u4e3b\u52a8\u521b\u5efa\u4f5c\u7528\u57df\uff0c\u7c7b\u4f3c\u8fc7\u53bb\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using"),"\uff0c\u76ee\u524d\u6846\u67b6\u63d0\u4f9b\u4e86\u51e0\u79cd\u65b9\u5f0f\u3002"),(0,a.kt)("h3",{id:"12131-iserviceprovider-\u65b9\u5f0f"},"12.13.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"IServiceProvider")," \u65b9\u5f0f"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-2,5,8,11-12}",showLineNumbers:!0,"{1-2,5,8,11-12}":!0},"using var scope = serviceProvider.CreateScope();\nvar services = scope.ServiceProvider;\n\n// \u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\nvar dbContext = Db.GetDbContext(services);\n\n// \u83b7\u53d6\u4ed3\u50a8\nvar respository = Db.GetRepository(services);\n\n// \u89e3\u6790\u5176\u4ed6\u670d\u52a1\nvar otherService = services.GetService();\nvar otherService2 = App.GetService(services);\n")),(0,a.kt)("h3",{id:"12132-iservicescopefactory-\u65b9\u5f0f"},"12.13.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"IServiceScopeFactory")," \u65b9\u5f0f"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"using var scope = serviceScopeFactory.CreateScope();\nvar services = scope.ServiceProvider;\n")),(0,a.kt)("h3",{id:"12133-scoped-\u9759\u6001\u7c7b"},"12.13.3 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Scoped")," \u9759\u6001\u7c7b"),(0,a.kt)("p",null,"\u4e3a\u4e86\u65b9\u6cd5\u5feb\u901f\u521b\u5efa\u670d\u52a1\u4f5c\u7528\u57df\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"Scoped")," \u9759\u6001\u7c7b\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-2}",showLineNumbers:!0,"{1-2}":!0},"Scoped.Create((factory, scope) => {\n var services = scope.ServiceProvider;\n});\n")),(0,a.kt)("h2",{id:"1214-\u81ea\u5b9a\u4e49\u626b\u63cf\u7b5b\u9009\u6ce8\u518c\u670d\u52a1"},"12.14 \u81ea\u5b9a\u4e49\u626b\u63cf/\u7b5b\u9009\u6ce8\u518c\u670d\u52a1"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u5e76\u672a\u63d0\u4f9b\u5b8c\u5168\u81ea\u5b9a\u4e49\u4f9d\u8d56\u6ce8\u5165\u626b\u63cf\u7684\u673a\u5236\uff0c\u4f46\u63a8\u8350\u4e00\u4e2a\u975e\u5e38\u4f18\u79c0\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET Core")," \u4f9d\u8d56\u6ce8\u5165\u62d3\u5c55\u5e93\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"Scrutor"),"\uff0c\u4f7f\u7528\u975e\u5e38\u7b80\u5355\uff0c\u4e3b\u8981\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"FromAssemblyOf<>")," \u626b\u63cf\u7a0b\u5e8f\u96c6\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"AddClasses(o)")," \u8fdb\u884c\u7b5b\u9009\u6ce8\u518c\u3002"),(0,a.kt)("p",null,"\u4f7f\u7528\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,6,13,19,22}",showLineNumbers:!0,"{1,3,6,13,19,22}":!0},"services.Scan(scan => scan\n // \u626b\u63cf\u7279\u5b9a\u7c7b\u578b\u6240\u5728\u7684\u7a0b\u5e8f\u96c6\uff0c\u8fd9\u91cc\u662f ITransientService \u6240\u5728\u7684\u7a0b\u5e8f\u96c6\n .FromAssemblyOf()\n // .AddClasses \u5728\u4e0a\u9762\u83b7\u53d6\u5230\u7684\u7a0b\u5e8f\u96c6\u4e2d\u626b\u63cf\u6240\u6709\u516c\u5f00\u3001\u975e\u62bd\u8c61\u7c7b\u578b\n // \u4e4b\u540e\u53ef\u4ee5\u901a\u8fc7\u59d4\u6258\u8fdb\u884c\u7c7b\u578b\u7b5b\u9009\uff0c\u4f8b\u5982\u4e0b\u9762\u53ea\u626b\u63cf\u5b9e\u73b0 ITransientService \u7684\u7c7b\u578b\n .AddClasses(classes => classes.AssignableTo())\n // \u5c06\u4e0a\u9762\u7684\u7c7b\u578b\u4f5c\u4e3a\u5b83\u5b9e\u73b0\u7684\u6240\u6709\u63a5\u53e3\u8fdb\u884c\u6ce8\u518c\n // \u5982\u679c\u7c7b\u578b\u5b9e\u73b0\u4e86 N \u4e2a\u63a5\u53e3\uff0c\u90a3\u4e48\u5c31\u4f1a\u6709\u4e09\u4e2a\u72ec\u7acb\u7684\u6ce8\u518c\n .AsImplementedInterfaces()\n // \u6700\u540e\u6307\u5b9a\u6ce8\u518c\u7684\u751f\u5b58\u671f\uff0c\u5982\u77ac\u65f6\uff0c\u4f5c\u7528\u57df\uff0c\u8fd8\u662f\u5355\u4f8b\n .WithTransientLifetime()\n // \u91cd\u590d\u4e0a\u9762\u64cd\u4f5c\uff0c\u6bd4\u5982\u8fd9\u91cc\u626b\u63cf IScopedService \u6240\u5728\u7684\u7a0b\u5e8f\u96c6\n .AddClasses(classes => classes.AssignableTo())\n // \u8fd9\u91cc\u548c\u4e0a\u9762\u4e0d\u4e00\u6837\u7684\u662f\uff0c\u8fd9\u91cc\u6307\u5b9a\u53ea\u5b9e\u73b0\u7279\u5b9a\u7684\u51e0\u53e3\uff0c\u4e5f\u5c31\u662f\u53ea\u6ce8\u518c\u4e00\u6b21\n .As()\n // \u6307\u5b9a\u6ce8\u518c\u7684\u751f\u5b58\u671f\n .WithScopedLifetime()\n // \u4e5f\u652f\u6301\u6cdb\u578b\u6ce8\u518c\uff0c\u5355\u4e2a\u6cdb\u578b\u53c2\u6570\n .AddClasses(classes => classes.AssignableTo(typeof(IOpenGeneric<>)))\n .AsImplementedInterfaces()\n // \u591a\u4e2a\u6cdb\u578b\u53c2\u6570\n .AddClasses(classes => classes.AssignableTo(typeof(IQueryHandler<,>)))\n .AsImplementedInterfaces());\n")),(0,a.kt)("p",null,"\u8be6\u7ec6\u6587\u6863\u8bf7\u67e5\u9605 ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/khellang/Scrutor"},"https://github.com/khellang/Scrutor")),(0,a.kt)("h2",{id:"1215-\u53cd\u9988\u4e0e\u5efa\u8bae"},"12.15 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/a8677dec.d6c71cca.js b/handbook/build/assets/js/a8677dec.d6c71cca.js deleted file mode 100644 index eeff0a0303..0000000000 --- a/handbook/build/assets/js/a8677dec.d6c71cca.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4197],{6038:function(e,n,t){t.r(n),t.d(n,{assets:function(){return u},contentTitle:function(){return p},default:function(){return k},frontMatter:function(){return s},metadata:function(){return c},toc:function(){return m}});var i=t(3117),r=t(102),a=(t(7294),t(3905)),l=t(1402),o=["components"],s={id:"dependency-injection",title:"12. \u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c",sidebar_label:"12. \u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c"},p=void 0,c={unversionedId:"dependency-injection",id:"dependency-injection",title:"12. \u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c",description:"",source:"@site/docs/dependency-injection.mdx",sourceDirName:".",slug:"/dependency-injection",permalink:"/furion/docs/dependency-injection",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dependency-injection.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1660877813,formattedLastUpdatedAt:"Aug 19, 2022",frontMatter:{id:"dependency-injection",title:"12. \u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c",sidebar_label:"12. \u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c"},sidebar:"docs",previous:{title:"11. SaaS \u591a\u79df\u6237",permalink:"/furion/docs/saas"},next:{title:"13. \u5bf9\u8c61\u6570\u636e\u6620\u5c04 Mapper",permalink:"/furion/docs/object-mapper"}},u={},m=[{value:"12.1 \u4f9d\u8d56\u6ce8\u5165",id:"121-\u4f9d\u8d56\u6ce8\u5165",level:2},{value:"12.2 \u63a7\u5236\u53cd\u8f6c",id:"122-\u63a7\u5236\u53cd\u8f6c",level:2},{value:"12.3 IOC/DI \u4f18\u7f3a\u70b9",id:"123-iocdi-\u4f18\u7f3a\u70b9",level:2},{value:"12.4 \u4f9d\u8d56\u6ce8\u5165\u7684\u4e09\u79cd\u65b9\u5f0f",id:"124-\u4f9d\u8d56\u6ce8\u5165\u7684\u4e09\u79cd\u65b9\u5f0f",level:2},{value:"12.4.1 \u6784\u9020\u65b9\u6cd5\u6ce8\u5165",id:"1241-\u6784\u9020\u65b9\u6cd5\u6ce8\u5165",level:3},{value:"12.4.2 \u5c5e\u6027\u65b9\u5f0f\u6ce8\u5165",id:"1242-\u5c5e\u6027\u65b9\u5f0f\u6ce8\u5165",level:3},{value:"12.4.3 \u65b9\u6cd5\u53c2\u6570\u6ce8\u5165",id:"1243-\u65b9\u6cd5\u53c2\u6570\u6ce8\u5165",level:3},{value:"12.5 \u6ce8\u518c\u5bf9\u8c61\u751f\u5b58\u671f",id:"125-\u6ce8\u518c\u5bf9\u8c61\u751f\u5b58\u671f",level:2},{value:"12.5.1 \u6682\u65f6/\u77ac\u65f6 \u751f\u5b58\u671f",id:"1251-\u6682\u65f6\u77ac\u65f6-\u751f\u5b58\u671f",level:3},{value:"12.5.2 \u4f5c\u7528\u57df \u751f\u5b58\u671f",id:"1252-\u4f5c\u7528\u57df-\u751f\u5b58\u671f",level:3},{value:"12.5.3 \u5355\u4f8b \u751f\u5b58\u671f",id:"1253-\u5355\u4f8b-\u751f\u5b58\u671f",level:3},{value:"12.6 \u5185\u7f6e\u4f9d\u8d56\u63a5\u53e3",id:"126-\u5185\u7f6e\u4f9d\u8d56\u63a5\u53e3",level:2},{value:"12.7 \u5e38\u89c1\u4f7f\u7528",id:"127-\u5e38\u89c1\u4f7f\u7528",level:2},{value:"12.7.1 \u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"1271-\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:3},{value:"12.7.2 \u6ce8\u518c\u6cdb\u578b\u5b9e\u4f8b",id:"1272-\u6ce8\u518c\u6cdb\u578b\u5b9e\u4f8b",level:3},{value:"12.7.3 \u4e00\u4e2a\u63a5\u53e3\u591a\u4e2a\u5b9e\u73b0",id:"1273-\u4e00\u4e2a\u63a5\u53e3\u591a\u4e2a\u5b9e\u73b0",level:3},{value:"12.7.4 \u65e0\u63a5\u53e3\u65b9\u5f0f",id:"1274-\u65e0\u63a5\u53e3\u65b9\u5f0f",level:3},{value:"12.8 [Injection] \u7279\u6027\u914d\u7f6e",id:"128-injection-\u7279\u6027\u914d\u7f6e",level:2},{value:"12.9 \u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c",id:"129-\u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c",level:2},{value:"12.10 appsettings.json \u914d\u7f6e\u6ce8\u518c",id:"1210-appsettingsjson-\u914d\u7f6e\u6ce8\u518c",level:2},{value:"12.11 \u6ce8\u518c\u987a\u5e8f\u548c\u4f18\u5148\u7ea7",id:"1211-\u6ce8\u518c\u987a\u5e8f\u548c\u4f18\u5148\u7ea7",level:2},{value:"12.12 Aop \u6ce8\u518c\u62e6\u622a",id:"1212-aop-\u6ce8\u518c\u62e6\u622a",level:2},{value:"12.12.1 \u5168\u5c40Aop\u62e6\u622a",id:"12121-\u5168\u5c40aop\u62e6\u622a",level:3},{value:"12.12.2 AOP \u6ce8\u5165\u89e3\u6790\u670d\u52a1",id:"12122-aop-\u6ce8\u5165\u89e3\u6790\u670d\u52a1",level:3},{value:"12.12.3 AOP \u7684\u4f5c\u7528",id:"12123-aop-\u7684\u4f5c\u7528",level:3},{value:"12.13 \u5728\u975e Web \u6216\u591a\u7ebf\u7a0b\u89e3\u6790\u670d\u52a1",id:"1213-\u5728\u975e-web-\u6216\u591a\u7ebf\u7a0b\u89e3\u6790\u670d\u52a1",level:2},{value:"12.13.1 IServiceProvider \u65b9\u5f0f",id:"12131-iserviceprovider-\u65b9\u5f0f",level:3},{value:"12.13.2 IServiceScopeFactory \u65b9\u5f0f",id:"12132-iservicescopefactory-\u65b9\u5f0f",level:3},{value:"12.13.3 Scoped \u9759\u6001\u7c7b",id:"12133-scoped-\u9759\u6001\u7c7b",level:3},{value:"12.14 \u81ea\u5b9a\u4e49\u626b\u63cf/\u7b5b\u9009\u6ce8\u518c\u670d\u52a1",id:"1214-\u81ea\u5b9a\u4e49\u626b\u63cf\u7b5b\u9009\u6ce8\u518c\u670d\u52a1",level:2},{value:"12.15 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"1215-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:m};function k(e){var n=e.components,t=(0,r.Z)(e,o);return(0,a.kt)("wrapper",(0,i.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{title:"\u9605\u524d\u5fc5\u8bfb",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7531\u4e8e\u5f88\u591a\u670b\u53cb\u7b2c\u4e00\u6b21\u63a5\u89e6 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c")," \u7684\u67b6\u6784\u7406\u5ff5\uff0c\u6240\u4ee5\u6ca1\u641e\u660e\u767d ",(0,a.kt)("inlineCode",{parentName:"p"},"\u4f5c\u7528\u57df")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"\u591a\u7ebf\u7a0b\u89e3\u6790\u670d\u52a1")," \u7684\u95ee\u9898\uff0c\u4ece\u800c\u4e0d\u6b63\u786e\u7684\u4f7f\u7528\u5bfc\u81f4\u5185\u5b58\u4e0d\u65ad\u98d9\u9ad8\uff0c\u6b63\u786e\u7684\u65b9\u5f0f\u5e94\u8be5\u662f\uff1a"),(0,a.kt)("ul",{parentName:"admonition"},(0,a.kt)("li",{parentName:"ul"},"\u5c3d\u53ef\u80fd\u7684\u91c7\u7528\u6784\u9020\u51fd\u6570\u6ce8\u5165\uff08\u5982\u679c\u8fd9\u4e2a\u7c7b\u652f\u6301\uff09"),(0,a.kt)("li",{parentName:"ul"},"\u5728\u975e\u9759\u6001\u4e2d\uff08",(0,a.kt)("strong",{parentName:"li"},"\u4f46\u5728 Web \u8bf7\u6c42\u6709\u6548\u7684\u58f0\u660e\u5468\u671f\u5185"),"\uff09\u53ef\u5b89\u5168\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"li"},"App.GetService<>")," \u89e3\u6790\u670d\u52a1\uff0c\u5982\u679c\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"\u5355\u4f8b\u670d\u52a1"),"\uff0c\u4f18\u5148\u63a8\u8350\u6784\u9020\u51fd\u6570\u6ce8\u5165\u6216 ",(0,a.kt)("inlineCode",{parentName:"li"},"App.RootServices.GetService<>")," \u65b9\u5f0f"),(0,a.kt)("li",{parentName:"ul"},"\ud83e\udd10 ",(0,a.kt)("strong",{parentName:"li"},"\u5728\u975e ",(0,a.kt)("inlineCode",{parentName:"strong"},"Web")," \u73af\u5883\u3001\u591a\u7ebf\u7a0b\u73af\u5883\u3001\u7269\u8054\u7f51\u7b49\u73af\u5883\uff08\u542b\u4e8b\u4ef6\u603b\u7ebf\u3001\u5b9a\u65f6\u4efb\u52a1\u7b49\uff09\ud83c\udfd2 \u9664\u5355\u4f8b\u670d\u52a1\u4ee5\u5916 \ud83c\udfd2 \u5fc5\u987b\u91c7\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"Scoped.Create()")," \u65b9\u5f0f\u521b\u5efa\u4f5c\u7528\u57df\u4e14\u670d\u52a1\u5728\u5185\u90e8\u59d4\u6258\u4e2d\u89e3\u6790\uff01")," \ud83e\udd10"))),(0,a.kt)("h2",{id:"121-\u4f9d\u8d56\u6ce8\u5165"},"12.1 \u4f9d\u8d56\u6ce8\u5165"),(0,a.kt)("p",null,"\u6240\u8c13\u4f9d\u8d56\u6ce8\u5165\uff0c\u662f\u6307\u7a0b\u5e8f\u8fd0\u884c\u8fc7\u7a0b\u4e2d\uff0c\u5982\u679c\u9700\u8981\u8c03\u7528\u53e6\u4e00\u4e2a\u5bf9\u8c61\u534f\u52a9\u65f6\uff0c\u65e0\u987b\u5728\u4ee3\u7801\u4e2d\u521b\u5efa\u88ab\u8c03\u7528\u8005\uff0c\u800c\u662f\u4f9d\u8d56\u4e8e\u5916\u90e8\u7684\u6ce8\u5165\u3002"),(0,a.kt)("p",null,"\u901a\u4fd7\u6765\u8bb2\uff0c\u5c31\u662f\u628a\u6709\u4f9d\u8d56\u5173\u7cfb\u7684\u7c7b\u653e\u5230\u5bb9\u5668\u4e2d\uff0c\u7136\u540e\u5728\u6211\u4eec\u9700\u8981\u8fd9\u4e9b\u7c7b\u65f6\uff0c\u5bb9\u5668\u81ea\u52a8\u89e3\u6790\u51fa\u8fd9\u4e9b\u7c7b\u7684\u5b9e\u4f8b\u3002"),(0,a.kt)("p",null,"\u4f9d\u8d56\u6ce8\u5165\u6700\u5927\u7684\u597d\u5904\u65f6\u5b9e\u73b0\u7c7b\u7684\u89e3\u8026\uff0c\u5229\u4e8e\u7a0b\u5e8f\u62d3\u5c55\u3001\u5355\u5143\u6d4b\u8bd5\u3001\u81ea\u52a8\u5316\u6a21\u62df\u6d4b\u8bd5\u7b49\u3002"),(0,a.kt)("p",null,"\u4f9d\u8d56\u6ce8\u5165\u7684\u82f1\u6587\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"Dependency Injection"),"\uff0c\u7b80\u79f0 ",(0,a.kt)("inlineCode",{parentName:"p"},"DI")),(0,a.kt)("h2",{id:"122-\u63a7\u5236\u53cd\u8f6c"},"12.2 \u63a7\u5236\u53cd\u8f6c"),(0,a.kt)("p",null,"\u63a7\u5236\u53cd\u8f6c\u53ea\u662f\u4e00\u4e2a\u6982\u5ff5\uff0c\u4e5f\u5c31\u662f\u5c06\u521b\u5efa\u5bf9\u8c61\u5b9e\u4f8b\u7684\u63a7\u5236\u6743\uff08\u539f\u672c\u662f\u7a0b\u5e8f\u5458\uff09\u4ece\u4ee3\u7801\u63a7\u5236\u6743\u5265\u79bb\u5230 ",(0,a.kt)("inlineCode",{parentName:"p"},"IOC \u5bb9\u5668")," \u4e2d\u63a7\u5236\u3002"),(0,a.kt)("p",null,"\u63a7\u5236\u53cd\u8f6c\u7684\u82f1\u6587\u4e3a\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"Inversion of Control"),"\uff0c\u7b80\u79f0 ",(0,a.kt)("inlineCode",{parentName:"p"},"IOC")),(0,a.kt)("h2",{id:"123-iocdi-\u4f18\u7f3a\u70b9"},"12.3 ",(0,a.kt)("inlineCode",{parentName:"h2"},"IOC/DI")," \u4f18\u7f3a\u70b9"),(0,a.kt)("p",null,"\u4f20\u7edf\u7684\u4ee3\u7801\uff0c\u6bcf\u4e2a\u5bf9\u8c61\u8d1f\u8d23\u7ba1\u7406\u4e0e\u81ea\u5df1\u9700\u8981\u4f9d\u8d56\u7684\u5bf9\u8c61\uff0c\u5bfc\u81f4\u5982\u679c\u9700\u8981\u5207\u6362\u4f9d\u8d56\u5bf9\u8c61\u7684\u5b9e\u73b0\u7c7b\u65f6\uff0c\u9700\u8981\u4fee\u6539\u591a\u5904\u5730\u65b9\u3002\u540c\u65f6\uff0c\u8fc7\u5ea6\u8026\u5408\u4e5f\u4f7f\u5f97\u5bf9\u8c61\u96be\u4ee5\u8fdb\u884c\u5355\u5143\u6d4b\u8bd5\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u4f18\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u4f9d\u8d56\u6ce8\u5165\u628a\u5bf9\u8c61\u7684\u521b\u9020\u4ea4\u7ed9\u5916\u90e8\u53bb\u7ba1\u7406,\u5f88\u597d\u7684\u89e3\u51b3\u4e86\u4ee3\u7801\u7d27\u8026\u5408\uff08tight couple\uff09\u7684\u95ee\u9898\uff0c\u662f\u4e00\u79cd\u8ba9\u4ee3\u7801\u5b9e\u73b0\u677e\u8026\u5408\uff08loose couple\uff09\u7684\u673a\u5236"),(0,a.kt)("li",{parentName:"ul"},"\u677e\u8026\u5408\u8ba9\u4ee3\u7801\u66f4\u5177\u7075\u6d3b\u6027\uff0c\u80fd\u66f4\u597d\u5730\u5e94\u5bf9\u9700\u6c42\u53d8\u52a8\uff0c\u4ee5\u53ca\u65b9\u4fbf\u5355\u5143\u6d4b\u8bd5"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u7f3a\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u76ee\u524d\u4e3b\u6d41\u7684 ",(0,a.kt)("inlineCode",{parentName:"li"},"IOC/DI")," \u57fa\u672c\u91c7\u7528\u53cd\u5c04\u7684\u65b9\u5f0f\u6765\u5b9e\u73b0\u4f9d\u8d56\u6ce8\u5165\uff0c\u5728\u4e00\u5b9a\u7a0b\u5ea6\u4f1a\u5f71\u54cd\u6027\u80fd")))),(0,a.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u5728\u672c\u7ae0\u8282\u4e0d\u6253\u7b97\u7ec6\u8bb2 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c")," \u5177\u4f53\u5b9e\u73b0\u548c\u5e94\u7528\u573a\u666f\uff0c\u60f3\u4e86\u89e3\u66f4\u591a\u77e5\u8bc6\uff0c\u53ef\u67e5\u9605 \u3010",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0"},"ASP.NET Core \u4f9d\u8d56\u6ce8\u5165"),"\u3011 \u5b98\u65b9\u6587\u6863\u3002")),(0,a.kt)("h2",{id:"124-\u4f9d\u8d56\u6ce8\u5165\u7684\u4e09\u79cd\u65b9\u5f0f"},"12.4 \u4f9d\u8d56\u6ce8\u5165\u7684\u4e09\u79cd\u65b9\u5f0f"),(0,a.kt)("h3",{id:"1241-\u6784\u9020\u65b9\u6cd5\u6ce8\u5165"},"12.4.1 \u6784\u9020\u65b9\u6cd5\u6ce8\u5165"),(0,a.kt)("p",null,"\u76ee\u524d\u6784\u9020\u65b9\u6cd5\u6ce8\u5165\u662f\u4f9d\u8d56\u6ce8\u5165\u63a8\u8350\u4f7f\u7528\u65b9\u5f0f\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u4f18\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u5728\u6784\u9020\u65b9\u6cd5\u4e2d\u4f53\u73b0\u51fa\u5bf9\u5176\u4ed6\u7c7b\u7684\u4f9d\u8d56\uff0c\u4e00\u773c\u5c31\u80fd\u770b\u51fa\u8fd9\u4e2a\u7c7b\u9700\u8981\u4f9d\u8d56\u54ea\u4e9b\u7c7b\u624d\u80fd\u5de5\u4f5c"),(0,a.kt)("li",{parentName:"ul"},"\u8131\u79bb\u4e86 IOC \u6846\u67b6\uff0c\u8fd9\u4e2a\u7c7b\u4ecd\u7136\u53ef\u4ee5\u5de5\u4f5c\uff0cPOJO \u7684\u6982\u5ff5"),(0,a.kt)("li",{parentName:"ul"},"\u4e00\u65e6\u5bf9\u8c61\u521d\u59cb\u5316\u6210\u529f\u4e86\uff0c\u8fd9\u4e2a\u5bf9\u8c61\u7684\u72b6\u6001\u80af\u5b9a\u662f\u6b63\u786e\u7684"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u7f3a\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u6784\u9020\u51fd\u6570\u4f1a\u6709\u5f88\u591a\u53c2\u6570\uff08Bad smell\uff09"),(0,a.kt)("li",{parentName:"ul"},"\u6709\u4e9b\u7c7b\u662f\u9700\u8981\u9ed8\u8ba4\u6784\u9020\u51fd\u6570\u7684\uff0c\u6bd4\u5982 MVC \u6846\u67b6\u7684 Controller \u7c7b\uff0c\u4e00\u65e6\u4f7f\u7528\u6784\u9020\u51fd\u6570\u6ce8\u5165\uff0c\u5c31\u65e0\u6cd5\u4f7f\u7528\u9ed8\u8ba4\u6784\u9020\u51fd\u6570"),(0,a.kt)("li",{parentName:"ul"},"\u8fd9\u4e2a\u7c7b\u91cc\u9762\u7684\u6709\u4e9b\u65b9\u6cd5\u5e76\u4e0d\u9700\u8981\u7528\u5230\u8fd9\u4e9b\u4f9d\u8d56\uff08Bad smell\uff09")))),(0,a.kt)("p",null,"\u4ee3\u7801\u793a\u4f8b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"public class FurionService\n{\n private readonly IRepository _repository;\n public FurionService(IRepository repository)\n {\n _repository = repository;\n }\n}\n")),(0,a.kt)("h3",{id:"1242-\u5c5e\u6027\u65b9\u5f0f\u6ce8\u5165"},"12.4.2 \u5c5e\u6027\u65b9\u5f0f\u6ce8\u5165"),(0,a.kt)("admonition",{title:"\u7279\u522b\u58f0\u660e",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u65b0\u7248\u672c\u4e2d\uff0c\u5df2\u7ecf\u79fb\u9664\u5c5e\u6027\u6ce8\u5165\u529f\u80fd\uff0c\u5efa\u8bae\u4f7f\u7528\u6784\u9020\u51fd\u6570\u6216\u65b9\u6cd5\u65b9\u5f0f\u6ce8\u5165\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"App.GetService")," \u65b9\u5f0f\u6ce8\u5165\u3002")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u901a\u8fc7\u5c5e\u6027\u65b9\u5f0f\u6ce8\u5165\u5bb9\u6613\u548c\u7c7b\u7684\u5b9e\u4f8b\u5c5e\u6027\u6df7\u6dc6\uff0c\u4e0d\u5efa\u8bae\u4f7f\u7528\u3002")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u4f18\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u5728\u5bf9\u8c61\u7684\u6574\u4e2a\u751f\u547d\u5468\u671f\u5185\uff0c\u53ef\u4ee5\u968f\u65f6\u52a8\u6001\u7684\u6539\u53d8\u4f9d\u8d56"),(0,a.kt)("li",{parentName:"ul"},"\u975e\u5e38\u7075\u6d3b"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u7f3a\u70b9"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u5bf9\u8c61\u5728\u521b\u5efa\u540e\uff0c\u88ab\u8bbe\u7f6e\u4f9d\u8d56\u5bf9\u8c61\u4e4b\u524d\u8fd9\u6bb5\u65f6\u95f4\u72b6\u6001\u662f\u4e0d\u5bf9\u7684"),(0,a.kt)("li",{parentName:"ul"},"\u4e0d\u76f4\u89c2\uff0c\u65e0\u6cd5\u6e05\u6670\u5730\u8868\u793a\u54ea\u4e9b\u5c5e\u6027\u662f\u5fc5\u987b\u7684")))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public class FurionService\n{\n public IRepository Repository { get; set; }\n}\n")),(0,a.kt)("h3",{id:"1243-\u65b9\u6cd5\u53c2\u6570\u6ce8\u5165"},"12.4.3 \u65b9\u6cd5\u53c2\u6570\u6ce8\u5165"),(0,a.kt)("p",null,"\u65b9\u6cd5\u53c2\u6570\u6ce8\u5165\u7684\u610f\u601d\u662f\u5728\u521b\u5efa\u5bf9\u8c61\u540e\uff0c\u901a\u8fc7\u81ea\u52a8\u8c03\u7528\u67d0\u4e2a\u65b9\u6cd5\u6765\u6ce8\u5165\u4f9d\u8d56\u3002"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u4f18\u70b9\uff1a"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u6bd4\u8f83\u7075\u6d3b"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"\u7f3a\u70b9\uff1a"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\u65b0\u52a0\u5165\u4f9d\u8d56\u65f6\u4f1a\u7834\u574f\u539f\u6709\u7684\u65b9\u6cd5\u7b7e\u540d\uff0c\u5982\u679c\u8fd9\u4e2a\u65b9\u6cd5\u5df2\u7ecf\u88ab\u5176\u4ed6\u5f88\u591a\u6a21\u5757\u7528\u5230\u5c31\u5f88\u9ebb\u70e6"),(0,a.kt)("li",{parentName:"ul"},"\u4e0e\u6784\u9020\u65b9\u6cd5\u6ce8\u5165\u4e00\u6837\uff0c\u4f1a\u6709\u5f88\u591a\u53c2\u6570")))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public class FurionService\n{\n public Person GetById([FromServices]IRepository repository, int id)\n {\n return repository.Find(id);\n }\n}\n")),(0,a.kt)("h2",{id:"125-\u6ce8\u518c\u5bf9\u8c61\u751f\u5b58\u671f"},"12.5 \u6ce8\u518c\u5bf9\u8c61\u751f\u5b58\u671f"),(0,a.kt)("h3",{id:"1251-\u6682\u65f6\u77ac\u65f6-\u751f\u5b58\u671f"},"12.5.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u6682\u65f6/\u77ac\u65f6")," \u751f\u5b58\u671f"),(0,a.kt)("p",null,"\u6682\u65f6\u751f\u5b58\u671f\u670d\u52a1\u662f\u6bcf\u6b21\u4ece\u670d\u52a1\u5bb9\u5668\u8fdb\u884c\u8bf7\u6c42\u65f6\u521b\u5efa\u7684\u3002 \u8fd9\u79cd\u751f\u5b58\u671f\u9002\u5408\u8f7b\u91cf\u7ea7\u3001 \u65e0\u72b6\u6001\u7684\u670d\u52a1\u3002"),(0,a.kt)("p",null,"\u5728\u5904\u7406\u8bf7\u6c42\u7684\u5e94\u7528\u4e2d\uff0c\u5728\u8bf7\u6c42\u7ed3\u675f\u65f6\u4f1a\u91ca\u653e\u6682\u65f6\u670d\u52a1\u3002"),(0,a.kt)("p",null,"\u901a\u5e38\u6211\u4eec\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"ITransient")," \u63a5\u53e3\u4f9d\u8d56\u8868\u793a\u8be5\u751f\u547d\u5468\u671f\u3002"),(0,a.kt)("h3",{id:"1252-\u4f5c\u7528\u57df-\u751f\u5b58\u671f"},"12.5.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u4f5c\u7528\u57df")," \u751f\u5b58\u671f"),(0,a.kt)("p",null,"\u4f5c\u7528\u57df\u751f\u5b58\u671f\u670d\u52a1\u9488\u5bf9\u6bcf\u4e2a\u5ba2\u6237\u7aef\u8bf7\u6c42\uff08\u8fde\u63a5\uff09\u521b\u5efa\u4e00\u6b21\u3002\u5728\u5904\u7406\u8bf7\u6c42\u7684\u5e94\u7528\u4e2d\uff0c\u5728\u8bf7\u6c42\u7ed3\u675f\u65f6\u4f1a\u91ca\u653e\u6709\u4f5c\u7528\u57df\u7684\u670d\u52a1\u3002"),(0,a.kt)("p",null,"\u901a\u5e38\u6211\u4eec\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IScoped")," \u63a5\u53e3\u4f9d\u8d56\u8868\u793a\u8be5\u751f\u547d\u5468\u671f\u3002"),(0,a.kt)("h3",{id:"1253-\u5355\u4f8b-\u751f\u5b58\u671f"},"12.5.3 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u5355\u4f8b")," \u751f\u5b58\u671f"),(0,a.kt)("p",null,"\u5728\u9996\u6b21\u8bf7\u6c42\u5b83\u4eec\u65f6\u8fdb\u884c\u521b\u5efa\uff0c\u4e4b\u540e\u6bcf\u4e2a\u540e\u7eed\u8bf7\u6c42\u90fd\u4f7f\u7528\u76f8\u540c\u7684\u5b9e\u4f8b\u3002"),(0,a.kt)("p",null,"\u901a\u5e38\u6211\u4eec\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"ISingleton")," \u63a5\u53e3\u4f9d\u8d56\u8868\u793a\u8be5\u751f\u547d\u5468\u671f\u3002"),(0,a.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u670d\u52a1\u751f\u5b58\u671f")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0#service-lifetimes"},"ASP.NET Core - \u4f9d\u8d56\u6ce8\u5165 - \u670d\u52a1\u751f\u5b58\u671f")," \u7ae0\u8282\u3002")),(0,a.kt)("h2",{id:"126-\u5185\u7f6e\u4f9d\u8d56\u63a5\u53e3"},"12.6 \u5185\u7f6e\u4f9d\u8d56\u63a5\u53e3"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e09\u4e2a\u63a5\u53e3\u4f9d\u8d56\u5206\u522b\u5bf9\u5e94\u4e0d\u540c\u7684\u670d\u52a1\u751f\u5b58\u671f\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ITransient"),"\uff1a\u5bf9\u5e94\u6682\u65f6/\u77ac\u65f6\u4f5c\u7528\u57df\u670d\u52a1\u751f\u5b58\u671f"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IScoped"),"\uff1a\u5bf9\u5e94\u8bf7\u6c42\u4f5c\u7528\u57df\u670d\u52a1\u751f\u5b58\u671f"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ISingleton"),"\uff1a\u5bf9\u5e94\u5355\u4f8b\u4f5c\u7528\u57df\u670d\u52a1\u751f\u5b58\u671f")),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0a\u4e09\u4e2a\u63a5\u53e3\u53ea\u80fd\u5b9e\u4f8b\u7c7b\u5b9e\u73b0\uff0c\u5176\u4ed6\u9759\u6001\u7c7b\u3001\u62bd\u8c61\u7c7b\u3001\u53ca\u63a5\u53e3\u4e0d\u80fd\u5b9e\u73b0\u3002")),(0,a.kt)("h2",{id:"127-\u5e38\u89c1\u4f7f\u7528"},"12.7 \u5e38\u89c1\u4f7f\u7528"),(0,a.kt)("h3",{id:"1271-\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"12.7.1 \u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,a.kt)("p",null,"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"IBusinessService")," \u63a5\u53e3\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"BusinessService")," \u5b9e\u73b0\u7c7b\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,12}",showLineNumbers:!0,"":!0,"{7,12}":!0},"using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing Furion.DependencyInjection;\n\nnamespace Furion.Application\n{\n public interface IBusinessService\n {\n Person Get(int id);\n }\n\n public class BusinessService : IBusinessService, ITransient\n {\n private readonly IRepository _personRepository;\n\n public BusinessService(IRepository personRepository)\n {\n _personRepository = personRepository;\n }\n\n public Person Get(int id)\n {\n return _personRepository.Find(id);\n }\n }\n}\n")),(0,a.kt)("p",null,"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"PersonController")," \u63a7\u5236\u5668\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11,19}",showLineNumbers:!0,"":!0,"{11,19}":!0},'using Furion.Application;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n [ApiController]\n public class PersonController : ControllerBase\n {\n private readonly IBusinessService _businessService;\n public PersonController(IBusinessService businessService)\n {\n _businessService = businessService;\n }\n\n [HttpGet]\n public IActionResult Get(int id)\n {\n var person = _businessService.Get(id);\n return new JsonResult(person);\n }\n }\n}\n')),(0,a.kt)("img",{src:(0,l.Z)("img/di1.gif")}),(0,a.kt)("hr",null),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u4f8b\u5b50\u89e3\u8bf4")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u975e\u5e38\u7075\u6d3b\u4e14\u65b9\u4fbf\u7684\u5b9e\u73b0\u4f9d\u8d56\u6ce8\u5165\u7684\u65b9\u5f0f\uff0c\u53ea\u9700\u8981\u5b9e\u4f8b\u7c7b\u7ee7\u627f\u5bf9\u5e94\u751f\u5b58\u671f\u7684\u63a5\u53e3\u5373\u53ef\uff0c\u8fd9\u91cc\u7ee7\u627f\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"ITransient"),"\uff0c\u4e5f\u5c31\u8868\u660e\u4e86\u8fd9\u662f\u4e00\u4e2a ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6682\u65f6/\u77ac\u65f6")," \u4f5c\u7528\u57df\u5b9e\u4f8b\u7c7b\u3002\u8be5\u7c7b\u5c31\u53ef\u4ee5\u4f5c\u4e3a\u88ab\u6ce8\u5165\u5bf9\u8c61\uff0c\u540c\u65f6\u4e5f\u80fd\u6ce8\u5165\u5176\u4ed6\u63a5\u53e3\u5bf9\u8c61\u3002"),(0,a.kt)("p",null,"\u4e0a\u9762\u7684\u4f8b\u5b50\u4e2d\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"BusinessService")," \u6ce8\u5165\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"IRepository")," \u4ed3\u50a8\u63a5\u53e3\uff0c\u540c\u65f6 ",(0,a.kt)("inlineCode",{parentName:"p"},"PersonController")," \u63a7\u5236\u5668\u6ce8\u5165\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"IBusinessService")," \u63a5\u53e3\u3002"),(0,a.kt)("p",null,"\u8fd9\u6837 ",(0,a.kt)("inlineCode",{parentName:"p"},"PersonController")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"BusinessService")," \u4e4b\u95f4\u5c31\u5b9e\u73b0\u4e86\u89e3\u8026\uff0c\u4e0d\u518d\u4f9d\u8d56\u4e8e\u5177\u4f53\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"BusinessService")," \u5b9e\u4f8b\u3002"),(0,a.kt)("p",null,"\u8fd9\u5c31\u662f\u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c\u6700\u7ecf\u5178\u7684\u4f8b\u5b50\u3002"),(0,a.kt)("h3",{id:"1272-\u6ce8\u518c\u6cdb\u578b\u5b9e\u4f8b"},"12.7.2 \u6ce8\u518c\u6cdb\u578b\u5b9e\u4f8b"),(0,a.kt)("p",null,"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"IBusinessService")," \u63a5\u53e3\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"BusinessService")," \u5b9e\u73b0\u7c7b\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,12}",showLineNumbers:!0,"":!0,"{7,12}":!0},"using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing Furion.DependencyInjection;\n\nnamespace Furion.Application\n{\n public interface IBusinessService\n {\n Person Get(int id);\n }\n\n public class BusinessService : IBusinessService, ITransient\n {\n private readonly IRepository _personRepository;\n\n public BusinessService(IRepository personRepository)\n {\n _personRepository = personRepository;\n }\n\n public Person Get(int id)\n {\n return _personRepository.Find(id);\n }\n }\n}\n")),(0,a.kt)("p",null,"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"PersonController")," \u63a7\u5236\u5668\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {11,19}",showLineNumbers:!0,"":!0,"{11,19}":!0},'using Furion.Application;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n [ApiController]\n public class PersonController : ControllerBase\n {\n private readonly IBusinessService _businessService;\n public PersonController(IBusinessService businessService)\n {\n _businessService = businessService;\n }\n\n [HttpGet]\n public IActionResult Get(int id)\n {\n var person = _businessService.Get(id);\n return new JsonResult(person);\n }\n }\n}\n')),(0,a.kt)("h3",{id:"1273-\u4e00\u4e2a\u63a5\u53e3\u591a\u4e2a\u5b9e\u73b0"},"12.7.3 \u4e00\u4e2a\u63a5\u53e3\u591a\u4e2a\u5b9e\u73b0"),(0,a.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u4e00\u4e2a\u63a5\u53e3\u53ea\u5bf9\u5e94\u4e00\u4e2a\u5b9e\u73b0\u7c7b\uff0c\u4f46\u6709\u4e9b\u7279\u6b8a\u60c5\u51b5\uff0c\u9700\u8981\u591a\u4e2a\u5b9e\u73b0\u7c7b\u6ce8\u518c\u540c\u4e00\u4e2a\u63a5\u53e3\uff0c\u5982 ",(0,a.kt)("inlineCode",{parentName:"p"},"DbContext")," \u591a\u6570\u636e\u5e93\u60c5\u51b5\u3002"),(0,a.kt)("p",null,"\u8fd9\u4e2a\u65f6\u5019\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u4f9d\u8d56\u6ce8\u5165 ",(0,a.kt)("inlineCode",{parentName:"p"},"Func")," \u59d4\u6258\u6765\u89e3\u6790\u591a\u4e2a\u5b9e\u4f8b\uff0c\u5176\u4e2d\u59d4\u6258\u7684\u53c2\u6570\u5206\u522b\u4e3a\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u53c2\u6570 1\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u4e0d\u540c\u5b9e\u73b0\u7c7b\u552f\u4e00\u6807\u8bc6\uff0c\u9ed8\u8ba4\u4e3a ",(0,a.kt)("inlineCode",{parentName:"li"},"nameof(\u5b9e\u73b0\u7c7b)")," \u540d\u79f0"),(0,a.kt)("li",{parentName:"ul"},"\u53c2\u6570 2\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Type")," \u7c7b\u578b\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"IPrivateDependency")," \u6d3e\u751f\u63a5\u53e3\uff0c\u4e5f\u5c31\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"ITransient"),"\u3001",(0,a.kt)("inlineCode",{parentName:"li"},"IScoped"),"\u3001",(0,a.kt)("inlineCode",{parentName:"li"},"ISingleton")),(0,a.kt)("li",{parentName:"ul"},"\u8fd4\u56de\u503c\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"object")," \u7c7b\u578b\uff0c\u8fd4\u56de\u5177\u4f53\u7684\u5b9e\u73b0\u7c7b\u5b9e\u4f8b")),(0,a.kt)("p",null,"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"IBusinessService")," \u63a5\u53e3\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"BusinessService"),"\u3001",(0,a.kt)("inlineCode",{parentName:"p"},"OtherBusinessService")," \u4e24\u4e2a\u5b9e\u73b0\u7c7b\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,10,18}",showLineNumbers:!0,"":!0,"{5,10,18}":!0},'using Furion.DependencyInjection;\n\nnamespace Furion.Application\n{\n public interface IBusinessService\n {\n string GetName();\n }\n\n public class BusinessService : IBusinessService, ITransient\n {\n public string GetName()\n {\n return "\u6211\u662f\uff1a" + nameof(BusinessService);\n }\n }\n\n public class OtherBusinessService : IBusinessService, ITransient\n {\n public string GetName()\n {\n return "\u6211\u662f\uff1a" + nameof(OtherBusinessService);\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u65b0\u7248\u672c\uff0c\u63a8\u8350\u4f7f\u7528",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 3.8.6+")," \u7248\u672c\u4e4b\u540e\u65b0\u589e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"INamedServiceProvider")," \u670d\u52a1\u63a5\u53e3\uff0c\u53ef\u66ff\u4ee3 ",(0,a.kt)("inlineCode",{parentName:"p"},"Func")," \u65b9\u5f0f\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8,15-17,19-23}",showLineNumbers:!0,"{8,15-17,19-23}":!0},'using Furion.Application.Services;\n\nnamespace Furion.Application;\n\npublic class TestNamedServices : IDynamicApiController\n{\n private readonly INamedServiceProvider _namedServiceProvider;\n public TestNamedServices(INamedServiceProvider namedServiceProvider)\n {\n _namedServiceProvider = namedServiceProvider;\n }\n\n public string GetName()\n {\n // \u7b2c\u4e00\u79cd\u7528\u6cd5\uff0c\u901a\u8fc7\u53cd\u5c04\u89e3\u6790\u670d\u52a1\u5468\u671f\uff0c\u6027\u80fd\u6709\u635f\u8017\n var service1 = _namedServiceProvider.GetService(nameof(BusinessService));\n var service2 = _namedServiceProvider.GetService(nameof(OtherBusinessService));\n\n // \u7b2c\u4e8c\u79cd\u7528\u6cd5\uff0c\u65e0\u9700\u53cd\u5c04\uff0c\u6ce8\u610f\u4e0b\u9762\u7684\u6cdb\u578b\u53c2\u6570\u4f20\u5165\u7684\u662f\u751f\u547d\u5468\u671f\u4f9d\u8d56\u63a5\u53e3\uff0cITransient, IScoped, ISingleton\n var service3 = _namedServiceProvider.GetService(nameof(BusinessService));\n var service4 = _namedServiceProvider.GetService(nameof(OtherBusinessService));\n\n return service1.GetName() + "-" + service2.GetName() + "-" + service3.GetName() + "-" + service4.GetName();\n }\n}\n'))),(0,a.kt)("admonition",{type:"important"},(0,a.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u4e0d\u518d\u63a8\u8350 ",(0,a.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Func")," \u65b9\u5f0f"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {15,17,18}",showLineNumbers:!0,"":!0,"{15,17,18}":!0},'using Furion.Application;\nusing Furion.DependencyInjection;\nusing Microsoft.AspNetCore.Mvc;\nusing System;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n [ApiController]\n public class ValueController : ControllerBase\n {\n private readonly IBusinessService _businessService;\n private readonly IBusinessService _otherBusinessService;\n\n public ValueController(Func resolveNamed)\n {\n _businessService = resolveNamed("BusinessService", default) as IBusinessService;\n _otherBusinessService = resolveNamed("OtherBusinessService", default) as IBusinessService;\n }\n\n [HttpGet]\n public string GetName()\n {\n return _businessService.GetName() + "----------" + _otherBusinessService.GetName();\n }\n }\n}\n'))),(0,a.kt)("img",{src:(0,l.Z)("img/di2.gif")}),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u9700\u8981\u81ea\u5b9a\u4e49\u89e3\u6790\u540d\u79f0\uff0c\u53ea\u9700\u8981\u8d34 ",(0,a.kt)("inlineCode",{parentName:"p"},'[Injection(Named = "\u540d\u79f0")]')," \u5373\u53ef\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,11}",showLineNumbers:!0,"":!0,"{5,11}":!0},'using Furion.DependencyInjection;\n\nnamespace Furion.Application\n{\n [Injection(Named = "BusName1")]\n public class BusinessService : IBusinessService, ITransient\n {\n // ...\n }\n\n [Injection(Named = "BusName2")]\n public class OtherBusinessService : IBusinessService, ITransient\n {\n // ...\n }\n}\n')),(0,a.kt)("p",{parentName:"admonition"},"\u89e3\u6790\u670d\u52a1\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'_businessService = resolveNamed("BusName1", default) as IBusinessService;\n_otherBusinessService = resolveNamed("BusName2", default) as IBusinessService;\n'))),(0,a.kt)("h3",{id:"1274-\u65e0\u63a5\u53e3\u65b9\u5f0f"},"12.7.4 \u65e0\u63a5\u53e3\u65b9\u5f0f"),(0,a.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u4e0d\u60f3\u5b9a\u4e49\u63a5\u53e3\uff0c\u800c\u662f\u60f3\u628a\u5b9e\u4f8b\u7c7b\u4f5c\u4e3a\u53ef\u4f9d\u8d56\u6ce8\u5165\u7684\u5bf9\u8c61\uff0c\u5982 MVC \u4e2d\u7684\u63a7\u5236\u5668\u3002"),(0,a.kt)("p",null,"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"SelfService")," \u5b9e\u4f8b\u7c7b\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,11}",showLineNumbers:!0,"":!0,"{7,11}":!0},"using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing Furion.DependencyInjection;\n\nnamespace Furion.Application\n{\n public class SelfService : ITransient\n {\n private readonly IRepository _personRepository;\n\n public SelfService(IRepository personRepository)\n {\n _personRepository = personRepository;\n }\n\n public Person Get(int id)\n {\n return _personRepository.Find(id);\n }\n }\n}\n")),(0,a.kt)("p",null,"\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"ValueController")," \u63a7\u5236\u5668\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13,21}",showLineNumbers:!0,"":!0,"{13,21}":!0},'using Furion.Application;\nusing Furion.Core;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Web.Entry.Controllers\n{\n [Route("api/[controller]")]\n [ApiController]\n public class ValueController : ControllerBase\n {\n private readonly SelfService _selfService;\n\n public ValueController(SelfService selfService)\n {\n _selfService = selfService;\n }\n\n [HttpGet]\n public Person Get(int id)\n {\n return _selfService.Get(id);\n }\n }\n}\n')),(0,a.kt)("h2",{id:"128-injection-\u7279\u6027\u914d\u7f6e"},"12.8 ",(0,a.kt)("inlineCode",{parentName:"h2"},"[Injection]")," \u7279\u6027\u914d\u7f6e"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b ",(0,a.kt)("inlineCode",{parentName:"p"},"[Injection]")," \u7279\u6027\u53ef\u4ee5\u6539\u53d8\u6ce8\u518c\u65b9\u5f0f\uff0c\u540c\u65f6\u8fd8\u80fd\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"p"},"AOP")," \u62e6\u622a\u3002"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"[Injection]")," \u63d0\u4f9b\u4ee5\u4e0b\u914d\u7f6e\u652f\u6301\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Action"),"\uff1a\u914d\u7f6e\u6ce8\u518c\u884c\u4e3a\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"InjectionActions")," \u7c7b\u578b\uff0c\u53ef\u9009\u503c\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Add"),"\uff1a",(0,a.kt)("strong",{parentName:"li"},"\u9ed8\u8ba4\u503c"),"\uff0c\u8868\u793a\u65e0\u9650\u5236\u6dfb\u52a0\u6ce8\u518c\u670d\u52a1\uff0c\u8be5\u65b9\u5f0f\u652f\u6301\u4e00\u4e2a\u63a5\u53e3\u591a\u4e2a\u5b9e\u73b0"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"TryAdd"),"\uff1a\u8868\u793a\u6ce8\u518c\u5df2\u5b58\u5728\u5219\u8df3\u8fc7\u6ce8\u518c"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Pattern"),"\uff1a\u914d\u7f6e\u6ce8\u518c\u9009\u9879\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"InjectionPatterns")," \u7c7b\u578b\uff0c\u53ef\u9009\u503c\uff1a",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Self"),"\uff1a\u53ea\u6ce8\u518c\u81ea\u5df1"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"FirstInterface"),"\uff1a\u53ea\u6ce8\u518c\u7b2c\u4e00\u4e2a\u63a5\u53e3"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"SelfWithFirstInterface"),"\uff1a\u6ce8\u518c\u81ea\u5df1\u548c\u7b2c\u4e00\u4e2a\u63a5\u53e3"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ImplementedInterfaces"),"\uff1a\u6ce8\u518c\u6240\u6709\u63a5\u53e3"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"All"),"\uff1a\u6ce8\u518c\u81ea\u5df1\u5305\u62ec\u6240\u6709\u63a5\u53e3 \uff0c",(0,a.kt)("strong",{parentName:"li"},"\u9ed8\u8ba4\u503c")))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Named"),"\uff1a\u914d\u7f6e\u5b9e\u4f8b\u522b\u540d\uff0c\u901a\u8fc7\u522b\u540d\u53ef\u4ee5\u89e3\u6790\u63a5\u53e3\uff0c\u5982\u540c\u4e00\u4e2a\u63a5\u53e3\u6709\u591a\u4e2a\u5b9e\u73b0\uff0c\u90a3\u4e48\u53ef\u4ee5\u901a\u8fc7\u522b\u540d\u89e3\u6790\u4e0d\u540c\u7684\u5b9e\u73b0\uff0c\u9ed8\u8ba4\u53ea\u4e3a\u5b9e\u73b0\u7c7b\u7684\u7c7b\u540d"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Order"),"\uff1a\u6ce8\u518c\u6392\u5e8f\uff0c\u6570\u5b57\u8d8a\u5927\uff0c\u5219\u8d8a\u5728\u6700\u540e\u6ce8\u518c\uff0c\u9ed8\u8ba4 ",(0,a.kt)("inlineCode",{parentName:"li"},"0")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Proxy"),"\uff1a\u914d\u7f6e\u4ee3\u7406\u62e6\u622a\u7c7b\u578b\uff0c\u4e5f\u5c31\u662f ",(0,a.kt)("inlineCode",{parentName:"li"},"AOP"),"\uff0c",(0,a.kt)("strong",{parentName:"li"},"\u4ee3\u7406\u7c7b\u578b\u5fc5\u987b\u7ee7\u627f ",(0,a.kt)("inlineCode",{parentName:"strong"},"AspectDispatchProxy")," \u7c7b\u548c ",(0,a.kt)("inlineCode",{parentName:"strong"},"IDispatchProxy")," \u63a5\u53e3"),"\uff0c\u65e0\u9ed8\u8ba4\u503c"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ExpectInterfaces"),"\uff1a\u914d\u7f6e\u5ffd\u7565\u6ce8\u518c\u7684\u63a5\u53e3\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"Type[]")," \u7c7b\u578b")),(0,a.kt)("h2",{id:"129-\u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c"},"12.9 \u81ea\u5b9a\u4e49\u9ad8\u7ea7\u6ce8\u518c"),(0,a.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u7684\u6ce8\u518c\u65b9\u5f0f\u53ef\u4ee5\u6ee1\u8db3\u5927\u591a\u6570\u4f9d\u8d56\u6ce8\u5165\u7684\u9700\u6c42\uff0c\u5982\u6709\u7279\u522b\u6ce8\u518c\u9700\u6c42\uff0c\u53ea\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup")," \u4e2d\u914d\u7f6e\u5373\u53ef\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddScoped(typeof(ISpecService), provider = > {\n // \u81ea\u5b9a\u4e49\u4efb\u4f55\u521b\u5efa\u5b9e\u4f8b\u7684\u65b9\u5f0f\n var instance = new SpecService(); // \u6216\u8005\u53ef\u4ee5\u901a\u8fc7 AOP\u63d2\u4ef6\u8fd4\u56de\u4ee3\u7406\u5b9e\u4f8b\n\n return instance;\n});\n")),(0,a.kt)("admonition",{title:"\u8865\u5145\u8bf4\u660e",type:"note"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"AppDbContext")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u8fd8\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},"ISqlDispatchProxy")," \u90fd\u662f\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\u521b\u5efa\u7684\u3002")),(0,a.kt)("admonition",{title:"\u77e5\u8bc6\u5bfc\u822a",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a\u81ea\u5b9a\u4e49\u9ad8\u7ea7\u4e2d\u6ce8\u518c\uff0c\u53ef\u67e5\u9605 \u3010",(0,a.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0"},"ASP.NET Core \u4f9d\u8d56\u6ce8\u5165"),"\u3011 \u5b98\u65b9\u6587\u6863\u3002")),(0,a.kt)("h2",{id:"1210-appsettingsjson-\u914d\u7f6e\u6ce8\u518c"},"12.10 ",(0,a.kt)("inlineCode",{parentName:"h2"},"appsettings.json")," \u914d\u7f6e\u6ce8\u518c"),(0,a.kt)("p",null,"\u9664\u4e86\u5728\u4ee3\u7801\u4e2d\u5b9e\u73b0\u4f9d\u8d56\u6ce8\u5165\uff0c\u4e5f\u53ef\u4ee5\u5b9e\u73b0\u52a8\u6001\u4f9d\u8d56\u6ce8\u5165\uff0c\u65e0\u9700\u4fee\u6539\u4ee3\u7801\u6216\u91cd\u65b0\u7f16\u8bd1\u5373\u53ef\u5b9e\u73b0\u70ed\u63d2\u62d4\uff08\u63d2\u4ef6\uff09\u6548\u679c\u3002\u914d\u7f6e\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},'{\n "DependencyInjectionSettings": {\n "Definitions": [\n {\n "Interface": "Furion.Application;Furion.Application.ITestService",\n "Service": "Furion.Application;Furion.Application.TestService",\n "RegisterType": "Transient",\n "Action": "Add",\n "Pattern": "SelfWithFirstInterface",\n "Named": "TestService",\n "Order": 1,\n "Proxy": "Furion.Application;Furion.Application.LogDispathProxy"\n }\n ]\n }\n}\n')),(0,a.kt)("p",null,"\u914d\u7f6e\u8bf4\u660e\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"DependencyInjectionSettings"),"\uff1a\u4f9d\u8d56\u6ce8\u5165\u914d\u7f6e\u6839\u8282\u70b9",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Definitions"),"\uff1a\u52a8\u6001\u4f9d\u8d56\u6ce8\u5165\u914d\u7f6e\u8282\u70b9\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"ExternalService")," \u6570\u7ec4\u7c7b\u578b",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ExternalService"),"\uff1a\u914d\u7f6e\u5355\u4e2a\u4f9d\u8d56\u6ce8\u5165\u4fe1\u606f",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Interface"),"\uff1a\u914d\u7f6e\u4f9d\u8d56\u63a5\u53e3\u4fe1\u606f\uff0c\u683c\u5f0f\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"\u7a0b\u5e8f\u96c6\u540d\u79f0;\u63a5\u53e3\u5b8c\u6574\u540d\u79f0"),"\uff0c\u5982\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Furion.Application;Furion.Application.ITestService")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Service"),"\uff1a\u914d\u7f6e\u63a5\u53e3\u5b9e\u73b0\u4fe1\u606f\uff0c\u683c\u5f0f\u540c\u4e0a"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"RegisterType"),"\uff1a\u914d\u7f6e\u4f9d\u8d56\u6ce8\u5165\u7684\u5bf9\u8c61\u751f\u5b58\u671f\uff0c\u53d6\u503c\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Transient"),"\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"Scoped"),"\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"Singleton")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Action"),"\uff1a\u6ce8\u518c\u884c\u4e3a\uff0c\u53ef\u9009\u503c\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"Add"),"\uff0c",(0,a.kt)("inlineCode",{parentName:"li"},"TryAdd"),"\uff0c\u53c2\u89c1 ",(0,a.kt)("a",{parentName:"li",href:"#128-injection-%E7%89%B9%E6%80%A7%E9%85%8D%E7%BD%AE"},"#128-injection-\u7279\u6027\u914d\u7f6e")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Pattern"),"\uff1a\u6ce8\u518c\u9009\u9879\uff0c\u53c2\u89c1 ",(0,a.kt)("a",{parentName:"li",href:"#128-injection-%E7%89%B9%E6%80%A7%E9%85%8D%E7%BD%AE"},"#128-injection-\u7279\u6027\u914d\u7f6e")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Named"),"\uff1a\u6ce8\u518c\u522b\u540d\uff0c\u53c2\u89c1 ",(0,a.kt)("a",{parentName:"li",href:"#128-injection-%E7%89%B9%E6%80%A7%E9%85%8D%E7%BD%AE"},"#128-injection-\u7279\u6027\u914d\u7f6e")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Order"),"\uff1a\u6ce8\u518c\u6392\u5e8f\uff0c\u53c2\u89c1 ",(0,a.kt)("a",{parentName:"li",href:"#128-injection-%E7%89%B9%E6%80%A7%E9%85%8D%E7%BD%AE"},"#128-injection-\u7279\u6027\u914d\u7f6e")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Proxy"),"\uff1a\u914d\u7f6e\u4ee3\u7406\u62e6\u622a\uff0c\u683c\u5f0f\uff1a",(0,a.kt)("inlineCode",{parentName:"li"},"\u7a0b\u5e8f\u96c6\u540d\u79f0;\u4ee3\u7406\u7c7b\u5b8c\u6574\u540d\u79f0"),"\uff0c\u53c2\u89c1 ",(0,a.kt)("a",{parentName:"li",href:"#128-injection-%E7%89%B9%E6%80%A7%E9%85%8D%E7%BD%AE"},"#128-injection-\u7279\u6027\u914d\u7f6e"))))))))),(0,a.kt)("admonition",{title:"\u5173\u4e8e\u5916\u90e8\u7a0b\u5e8f\u96c6",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u52a8\u6001\u6ce8\u5165\u7684\u5bf9\u8c61\u662f\u5916\u90e8\u7a0b\u5e8f\u96c6\uff0c\u90a3\u4e48\u9996\u5148\u5148\u6ce8\u518c\u5916\u90e8\u7a0b\u5e8f\u96c6\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "AppSettings": {\n "ExternalAssemblies": ["\u5916\u90e8\u7a0b\u5e8f\u96c6\u540d\u79f0", "Taobao.Pay"] // \u652f\u6301\u591a\u4e2a\n }\n}\n'))),(0,a.kt)("h2",{id:"1211-\u6ce8\u518c\u987a\u5e8f\u548c\u4f18\u5148\u7ea7"},"12.11 \u6ce8\u518c\u987a\u5e8f\u548c\u4f18\u5148\u7ea7"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u6ce8\u518c\u987a\u5e8f\u662f\u6309\u7167\u7a0b\u5e8f\u96c6\u626b\u63cf\u987a\u5e8f\u8fdb\u884c\u6ce8\u518c\uff0c\u5982\u679c\u9700\u8981\u6539\u53d8\u6ce8\u518c\u987a\u5e8f\uff0c\u53ef\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"[Injection(Order)]")," \u7279\u6027\u6307\u5b9a\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Order")," \u503c\u8d8a\u5927\uff0c\u5219\u8d8a\u5728\u6700\u540e\u6ce8\u518c\u3002"),(0,a.kt)("p",null,"\u53e6\u5916 ",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u914d\u7f6e\u7684\u4f18\u5148\u7ea7\u6700\u5927\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u914d\u7f6e\u7684\u6ce8\u518c\u4f1a\u8986\u76d6\u4e4b\u524d\u6240\u6709\u6ce8\u518c\u3002"),(0,a.kt)("h2",{id:"1212-aop-\u6ce8\u518c\u62e6\u622a"},"12.12 ",(0,a.kt)("inlineCode",{parentName:"h2"},"Aop")," \u6ce8\u518c\u62e6\u622a"),(0,a.kt)("admonition",{title:"\u5173\u4e8e\u52a8\u6001 API \u548c\u670d\u52a1\u7684\u533a\u522b",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u60a8\u7684\u670d\u52a1\u662f\u52a8\u6001 API\uff0c\u90a3\u4e48\u8bf7\u4f7f\u7528 ",(0,a.kt)("a",{parentName:"p",href:"/docs/dynamic-api-controller#511-%E5%85%B3%E4%BA%8E-aop-%E6%8B%A6%E6%88%AA"},"\u52a8\u6001 API - AOP \u62e6\u622a"),"\uff0c\u539f\u56e0\u662f\u52a8\u6001 API \u672c\u8d28\u662f\u63a7\u5236\u5668\uff0c\u6240\u4ee5\u91c7\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Filter")," \u65b9\u5f0f\u3002")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"AOP")," \u662f\u975e\u5e38\u91cd\u8981\u7684\u601d\u60f3\u548c\u6280\u672f\uff0c\u4e5f\u5c31\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"\u9762\u5411\u5207\u9762")," \u7f16\u7a0b\uff0c\u53ef\u4ee5\u8ba9\u6211\u4eec\u5728\u4e0d\u6539\u52a8\u539f\u6765\u4ee3\u7801\u7684\u60c5\u51b5\u4e0b\u8fdb\u884c\u52a8\u6001\u7be1\u6539\u4e1a\u52a1\u4ee3\u7801\u3002"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5b9e\u73b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"Aop")," \u975e\u5e38\u7b80\u5355\uff0c\u5982\uff1a"),(0,a.kt)("p",null,"\u5047\u8bbe\u6211\u4eec\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},"ITestService")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"TestService")," \u4e24\u4e2a\u7c7b\u578b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public interface ITestService\n{\n string SayHello(string word);\n}\n")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public class TestService: ITestService, ITransient\n{\n public string SayHello(string word)\n {\n return $"Hello {word}";\n }\n}\n')),(0,a.kt)("p",null,"\u73b0\u5728\u6211\u4eec\u6709\u4e00\u4e2a\u9700\u6c42\uff0c\u6211\u4eec\u5e0c\u671b\u8c03\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"SayHello")," \u7684\u65f6\u5019\u53ef\u4ee5\u8bb0\u5f55\u65e5\u5fd7\u548c\u6743\u9650\u63a7\u5236\uff08\u4e4b\u524d\u6ca1\u6709\u8003\u8651\u5230\u7684\u9700\u6c42\uff09\u3002"),(0,a.kt)("p",null,"\u8fd9\u4e2a\u65f6\u5019\u6211\u4eec\u53ea\u9700\u8981\u521b\u5efa\u4e00\u4e2a\u4ee3\u7406\u7c7b\u5373\u53ef\uff0c\u5982 ",(0,a.kt)("inlineCode",{parentName:"p"},"LogDispatchProxy")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,7,25,37,48}",showLineNumbers:!0,"":!0,"{1,3,7,25,37,48}":!0},'using Furion.DependencyInjection;\nusing System;\nusing System.Reflection;\n\nnamespace Furion.Application\n{\n public class LogDispatchProxy : AspectDispatchProxy, IDispatchProxy\n {\n /// \n /// \u5f53\u524d\u670d\u52a1\u5b9e\u4f8b\n /// \n public object Target { get; set; }\n\n /// \n /// \u670d\u52a1\u63d0\u4f9b\u5668\uff0c\u53ef\u4ee5\u7528\u6765\u89e3\u6790\u670d\u52a1\uff0c\u5982\uff1aServices.GetService()\n /// \n public IServiceProvider Services { get; set; }\n\n /// \n /// \u62e6\u622a\u65b9\u6cd5\n /// \n /// \n /// \n /// \n public override object Invoke(MethodInfo method, object[] args)\n {\n Console.WriteLine("SayHello \u65b9\u6cd5\u88ab\u8c03\u7528\u4e86");\n\n var result = method.Invoke(Target, args);\n\n Console.WriteLine("SayHello \u65b9\u6cd5\u8fd4\u56de\u503c\uff1a" + result);\n\n return result;\n }\n\n // \u5f02\u6b65\u65e0\u8fd4\u56de\u503c\n public override async Task InvokeAsync(MethodInfo method, object[] args)\n {\n Console.WriteLine("SayHello \u65b9\u6cd5\u88ab\u8c03\u7528\u4e86");\n\n var task = method.Invoke(Target, args) as Task;\n await task;\n\n Console.WriteLine("SayHello \u65b9\u6cd5\u8c03\u7528\u5b8c\u6210");\n }\n\n // \u5f02\u6b65\u5e26\u8fd4\u56de\u503c\n public override async Task InvokeAsyncT(MethodInfo method, object[] args)\n {\n Console.WriteLine("SayHello \u65b9\u6cd5\u88ab\u8c03\u7528\u4e86");\n\n var taskT = method.Invoke(Target, args) as Task;\n var result = await taskT;\n\n Console.WriteLine("SayHello \u65b9\u6cd5\u8fd4\u56de\u503c\uff1a" + result);\n\n return result;\n }\n }\n}\n')),(0,a.kt)("admonition",{title:"\u83b7\u53d6\u7279\u6027",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u9700\u8981\u83b7\u53d6\u65b9\u6cd5\u7684\u7279\u6027\uff0c\u53ea\u9700\u8981\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"method.GetActualCustomAttribute()")," \u5373\u53ef\u3002\u6240\u6709\u83b7\u53d6\u771f\u5b9e\u7684\u7279\u6027\u7edf\u4e00\u91c7\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"method.GetActual....()")," \u65b9\u6cd5\u5f00\u5934\u3002")),(0,a.kt)("p",null,"\u4e4b\u540e\u6211\u4eec\u53ea\u9700\u8981\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"TestService")," \u589e\u52a0 ",(0,a.kt)("inlineCode",{parentName:"p"},"[Injection]")," \u7279\u6027\u5373\u53ef\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},'[Injection(Proxy = typeof(LogDispatchProxy))]\npublic class TestService: ITestService, ITransient\n{\n public string SayHello(string word)\n {\n return $"Hello {word}";\n }\n}\n')),(0,a.kt)("p",null,"\u4e4b\u540e ",(0,a.kt)("inlineCode",{parentName:"p"},"SayHello")," \u65b9\u6cd5\u88ab\u8c03\u7528\u7684\u65f6\u5019\u5c31\u53ef\u4ee5\u5b9e\u73b0\u52a8\u6001\u62e6\u622a\u4e86\uff0c\u6bd4\u5982\u8fd9\u91cc\u5199\u65e5\u5fd7\u3002"),(0,a.kt)("h3",{id:"12121-\u5168\u5c40aop\u62e6\u622a"},"12.12.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u5168\u5c40Aop\u62e6\u622a")),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e5f\u63d0\u4f9b\u4e86\u5168\u5c40\u62e6\u622a\u7684\u65b9\u5f0f\uff0c\u53ea\u9700\u8981\u5c06 ",(0,a.kt)("inlineCode",{parentName:"p"},"IDispatchProxy")," \u4fee\u6539\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"IGlobalDispatchProxy")," \u5373\u53ef\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"using Furion;\nusing System.Reflection;\n\nnamespace Furion.Application\n{\n public class LogDispatchProxy : AspectDispatchProxy, IGlobalDispatchProxy\n {\n // ....\n }\n}\n")),(0,a.kt)("p",null,"\u8fd9\u6837\u5c31\u4f1a\u62e6\u622a\u6240\u6709\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Service"),"\uff0c\u5f53\u7136\u4e5f\u53ef\u4ee5\u901a\u8fc7\u7ed9\u7279\u5b9a\u7c7b\u8d34 ",(0,a.kt)("inlineCode",{parentName:"p"},"[SuppressProxy]")," \u8df3\u8fc7\u5168\u5c40\u62e6\u622a\u64cd\u4f5c\u3002"),(0,a.kt)("admonition",{title:"\u62e6\u622a\u4f18\u5148\u7ea7",type:"important"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"[SuppressProxy]")," > ",(0,a.kt)("inlineCode",{parentName:"p"},"[Injection(Proxy = typeof(LogDispatchProxy))]")," > ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5168\u5c40\u62e6\u622a"),"\u3002")),(0,a.kt)("h3",{id:"12122-aop-\u6ce8\u5165\u89e3\u6790\u670d\u52a1"},"12.12.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AOP")," \u6ce8\u5165\u89e3\u6790\u670d\u52a1"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u672a\u63d0\u4f9b ",(0,a.kt)("inlineCode",{parentName:"p"},"Proxy")," \u6784\u9020\u51fd\u6570\u6ce8\u5165\u529f\u80fd\uff0c\u4f46\u662f\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"Services")," \u5c5e\u6027\uff0c\u5982\u679c\u9700\u8981\u89e3\u6790\u670d\u52a1\uff0c\u5219\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u65b9\u5f0f\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var someServices = Services.GetService(); // \u63a8\u8350\u65b9\u5f0f\n// \u6216\nvar someServices = App.GetService();\n")),(0,a.kt)("h3",{id:"12123-aop-\u7684\u4f5c\u7528"},"12.12.3 ",(0,a.kt)("inlineCode",{parentName:"h3"},"AOP")," \u7684\u4f5c\u7528"),(0,a.kt)("p",null,"\u8fd9\u79cd\u9762\u5411\u5207\u9762\u7684\u80fd\u529b\uff08\u52a8\u6001\u62e6\u622a/\u4ee3\u7406\uff09\u53ef\u4ee5\u5b9e\u73b0\u5f88\u591a\u5f88\u591a\u529f\u80fd\uff0c\u5982\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u52a8\u6001\u65e5\u5fd7\u8bb0\u5f55"),(0,a.kt)("li",{parentName:"ul"},"\u52a8\u6001\u4fee\u6539\u53c2\u6570"),(0,a.kt)("li",{parentName:"ul"},"\u52a8\u6001\u4fee\u6539\u8fd4\u56de\u503c"),(0,a.kt)("li",{parentName:"ul"},"\u52a8\u6001\u65b9\u6cd5\u91cd\u5b9a\u5411"),(0,a.kt)("li",{parentName:"ul"},"\u52a8\u6001\u4fee\u6539\u4ee3\u7801\u903b\u8f91"),(0,a.kt)("li",{parentName:"ul"},"\u52a8\u6001\u5b9e\u73b0\u5f02\u5e38\u76d1\u542c")),(0,a.kt)("p",null,"\u8fd8\u53ef\u4ee5\u505a\u66f4\u591a\u66f4\u591a\u7684\u4e8b\u60c5\u3002"),(0,a.kt)("h2",{id:"1213-\u5728\u975e-web-\u6216\u591a\u7ebf\u7a0b\u89e3\u6790\u670d\u52a1"},"12.13 \u5728\u975e ",(0,a.kt)("inlineCode",{parentName:"h2"},"Web")," \u6216\u591a\u7ebf\u7a0b\u89e3\u6790\u670d\u52a1"),(0,a.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u8bf7\u6c42\u5f00\u59cb\u4e4b\u524d\u4f1a\u81ea\u52a8\u521b\u5efa\u8303\u56f4\u4f5c\u7528\u57df\uff0c\u8fd9\u4e2a\u4f5c\u7528\u57df\u7684\u751f\u5b58\u5468\u671f\u662f\u8bf7\u6c42\u4e4b\u524d\u548c\u54cd\u5e94\u4e4b\u540e\uff0c\u4e5f\u5c31\u662f\u5728\u8fd9\u4e2a\u4f5c\u7528\u57df\u5185\u7684\u6240\u6709\u670d\u52a1\u90fd\u5b9e\u73b0\u4e86\u81ea\u52a8\u7ba1\u7406\uff0c\u6bd4\u5982\u521b\u5efa\u670d\u52a1\u548c\u91ca\u653e\u670d\u52a1\u7684\u65f6\u673a\u3002"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\u4f46\u5728\u975e ",(0,a.kt)("inlineCode",{parentName:"strong"},"Web")," \u6216\u591a\u7ebf\u7a0b\u4e2d\uff0c\u6846\u67b6\u5e76\u4e0d\u4f1a\u505a\u8fd9\u6837\u7684\u4e8b\u60c5\uff0c\u4e5f\u5c31\u662f\u6846\u67b6\u53ea\u8d1f\u8d23\u4e86\u670d\u52a1\u7684\u521b\u5efa\uff0c\u4f46\u662f\u6ca1\u6709\u8d1f\u8d23\u9500\u6bc1\uff0c\u539f\u56e0\u662f\u6846\u67b6\u65e0\u6cd5\u5f97\u77e5\u5177\u4f53\u7684\u9500\u6bc1\u65f6\u673a\uff0c\u8fd9\u6837\u5c31\u5bfc\u81f4\u4e86\u5185\u5b58\u6ea2\u51fa\u3002")),(0,a.kt)("p",null,"\u89e3\u51b3\u65b9\u5f0f\u662f\uff1a\u5728\u975e ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u6216\u591a\u7ebf\u7a0b\u4e2d\u4f7f\u7528\u670d\u52a1\uff0c\u5e94\u8be5\u4e3b\u52a8\u521b\u5efa\u4f5c\u7528\u57df\uff0c\u7c7b\u4f3c\u8fc7\u53bb\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"using"),"\uff0c\u76ee\u524d\u6846\u67b6\u63d0\u4f9b\u4e86\u51e0\u79cd\u65b9\u5f0f\u3002"),(0,a.kt)("h3",{id:"12131-iserviceprovider-\u65b9\u5f0f"},"12.13.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"IServiceProvider")," \u65b9\u5f0f"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-2,5,8,11-12}",showLineNumbers:!0,"{1-2,5,8,11-12}":!0},"using var scope = serviceProvider.CreateScope();\nvar services = scope.ServiceProvider;\n\n// \u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\nvar dbContext = Db.GetDbContext(services);\n\n// \u83b7\u53d6\u4ed3\u50a8\nvar respository = Db.GetRepository(services);\n\n// \u89e3\u6790\u5176\u4ed6\u670d\u52a1\nvar otherService = services.GetService();\nvar otherService2 = App.GetService(services);\n")),(0,a.kt)("h3",{id:"12132-iservicescopefactory-\u65b9\u5f0f"},"12.13.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"IServiceScopeFactory")," \u65b9\u5f0f"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"using var scope = serviceScopeFactory.CreateScope();\nvar services = scope.ServiceProvider;\n")),(0,a.kt)("h3",{id:"12133-scoped-\u9759\u6001\u7c7b"},"12.13.3 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Scoped")," \u9759\u6001\u7c7b"),(0,a.kt)("p",null,"\u4e3a\u4e86\u65b9\u6cd5\u5feb\u901f\u521b\u5efa\u670d\u52a1\u4f5c\u7528\u57df\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"Scoped")," \u9759\u6001\u7c7b\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-2}",showLineNumbers:!0,"{1-2}":!0},"Scoped.Create((factory, scope) => {\n var services = scope.ServiceProvider;\n});\n")),(0,a.kt)("h2",{id:"1214-\u81ea\u5b9a\u4e49\u626b\u63cf\u7b5b\u9009\u6ce8\u518c\u670d\u52a1"},"12.14 \u81ea\u5b9a\u4e49\u626b\u63cf/\u7b5b\u9009\u6ce8\u518c\u670d\u52a1"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u5e76\u672a\u63d0\u4f9b\u5b8c\u5168\u81ea\u5b9a\u4e49\u4f9d\u8d56\u6ce8\u5165\u626b\u63cf\u7684\u673a\u5236\uff0c\u4f46\u63a8\u8350\u4e00\u4e2a\u975e\u5e38\u4f18\u79c0\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},".NET Core")," \u4f9d\u8d56\u6ce8\u5165\u62d3\u5c55\u5e93\uff1a",(0,a.kt)("inlineCode",{parentName:"p"},"Scrutor"),"\uff0c\u4f7f\u7528\u975e\u5e38\u7b80\u5355\uff0c\u4e3b\u8981\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"FromAssemblyOf<>")," \u626b\u63cf\u7a0b\u5e8f\u96c6\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"AddClasses(o)")," \u8fdb\u884c\u7b5b\u9009\u6ce8\u518c\u3002"),(0,a.kt)("p",null,"\u4f7f\u7528\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,6,13,19,22}",showLineNumbers:!0,"{1,3,6,13,19,22}":!0},"services.Scan(scan => scan\n // \u626b\u63cf\u7279\u5b9a\u7c7b\u578b\u6240\u5728\u7684\u7a0b\u5e8f\u96c6\uff0c\u8fd9\u91cc\u662f ITransientService \u6240\u5728\u7684\u7a0b\u5e8f\u96c6\n .FromAssemblyOf()\n // .AddClasses \u5728\u4e0a\u9762\u83b7\u53d6\u5230\u7684\u7a0b\u5e8f\u96c6\u4e2d\u626b\u63cf\u6240\u6709\u516c\u5f00\u3001\u975e\u62bd\u8c61\u7c7b\u578b\n // \u4e4b\u540e\u53ef\u4ee5\u901a\u8fc7\u59d4\u6258\u8fdb\u884c\u7c7b\u578b\u7b5b\u9009\uff0c\u4f8b\u5982\u4e0b\u9762\u53ea\u626b\u63cf\u5b9e\u73b0 ITransientService \u7684\u7c7b\u578b\n .AddClasses(classes => classes.AssignableTo())\n // \u5c06\u4e0a\u9762\u7684\u7c7b\u578b\u4f5c\u4e3a\u5b83\u5b9e\u73b0\u7684\u6240\u6709\u63a5\u53e3\u8fdb\u884c\u6ce8\u518c\n // \u5982\u679c\u7c7b\u578b\u5b9e\u73b0\u4e86 N \u4e2a\u63a5\u53e3\uff0c\u90a3\u4e48\u5c31\u4f1a\u6709\u4e09\u4e2a\u72ec\u7acb\u7684\u6ce8\u518c\n .AsImplementedInterfaces()\n // \u6700\u540e\u6307\u5b9a\u6ce8\u518c\u7684\u751f\u5b58\u671f\uff0c\u5982\u77ac\u65f6\uff0c\u4f5c\u7528\u57df\uff0c\u8fd8\u662f\u5355\u4f8b\n .WithTransientLifetime()\n // \u91cd\u590d\u4e0a\u9762\u64cd\u4f5c\uff0c\u6bd4\u5982\u8fd9\u91cc\u626b\u63cf IScopedService \u6240\u5728\u7684\u7a0b\u5e8f\u96c6\n .AddClasses(classes => classes.AssignableTo())\n // \u8fd9\u91cc\u548c\u4e0a\u9762\u4e0d\u4e00\u6837\u7684\u662f\uff0c\u8fd9\u91cc\u6307\u5b9a\u53ea\u5b9e\u73b0\u7279\u5b9a\u7684\u51e0\u53e3\uff0c\u4e5f\u5c31\u662f\u53ea\u6ce8\u518c\u4e00\u6b21\n .As()\n // \u6307\u5b9a\u6ce8\u518c\u7684\u751f\u5b58\u671f\n .WithScopedLifetime()\n // \u4e5f\u652f\u6301\u6cdb\u578b\u6ce8\u518c\uff0c\u5355\u4e2a\u6cdb\u578b\u53c2\u6570\n .AddClasses(classes => classes.AssignableTo(typeof(IOpenGeneric<>)))\n .AsImplementedInterfaces()\n // \u591a\u4e2a\u6cdb\u578b\u53c2\u6570\n .AddClasses(classes => classes.AssignableTo(typeof(IQueryHandler<,>)))\n .AsImplementedInterfaces());\n")),(0,a.kt)("p",null,"\u8be6\u7ec6\u6587\u6863\u8bf7\u67e5\u9605 ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/khellang/Scrutor"},"https://github.com/khellang/Scrutor")),(0,a.kt)("h2",{id:"1215-\u53cd\u9988\u4e0e\u5efa\u8bae"},"12.15 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}k.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return c},kt:function(){return d}});var i=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function l(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=i.createContext({}),p=function(e){var n=i.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},c=function(e){var n=p(e.components);return i.createElement(s.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},m=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,s=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),m=p(t),d=r,k=m["".concat(s,".").concat(d)]||m[d]||u[d]||a;return t?i.createElement(k,l(l({ref:n},c),{},{components:t})):i.createElement(k,l({ref:n},c))}));function d(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,l=new Array(a);l[0]=m;var o={};for(var s in n)hasOwnProperty.call(n,s)&&(o[s]=n[s]);o.originalType=e,o.mdxType="string"==typeof e?e:r,l[1]=o;for(var p=2;p=0||(i[r]=e[r]);return i}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var l=t.createContext({}),p=function(e){var n=t.useContext(l),r=n;return e&&(r="function"==typeof e?e(n):a(a({},n),e)),r},c=function(e){var n=p(e.components);return t.createElement(l.Provider,{value:n},e.children)},k={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},u=t.forwardRef((function(e,n){var r=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=p(r),d=i,m=u["".concat(l,".").concat(d)]||u[d]||k[d]||o;return r?t.createElement(m,a(a({ref:n},c),{},{components:r})):t.createElement(m,a({ref:n},c))}));function d(e,n){var r=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var o=r.length,a=new Array(o);a[0]=u;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:i,a[1]=s;for(var p=2;pWorker Service \u65b9\u5f0f",id:"253-\u72ec\u7acb-worker-service-\u65b9\u5f0f",level:2},{value:"25.3.1 \u5982\u4f55\u521b\u5efa Worker Service",id:"2531-\u5982\u4f55\u521b\u5efa-worker-service",level:3},{value:"25.3.2 \u521b\u5efa Worker",id:"2532-\u521b\u5efa-worker",level:3},{value:"25.3.3 \u591a\u4e2a Worker",id:"2533-\u591a\u4e2a-worker",level:3},{value:"25.3.4 \u751f\u547d\u5468\u671f",id:"2534-\u751f\u547d\u5468\u671f",level:3},{value:"25.3.5 \u96c6\u6210 Furion",id:"2535-\u96c6\u6210-furion",level:3},{value:"25.3.6 \u6ce8\u518c\u670d\u52a1",id:"2536-\u6ce8\u518c\u670d\u52a1",level:3},{value:"25.4 \u5b9e\u73b0\u5b9a\u65f6\u4efb\u52a1",id:"254-\u5b9e\u73b0\u5b9a\u65f6\u4efb\u52a1",level:2},{value:"26.4.1 \u95f4\u9694\u6267\u884c\u65b9\u5f0f",id:"2641-\u95f4\u9694\u6267\u884c\u65b9\u5f0f",level:3},{value:"26.4.2 Cron \u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f",id:"2642-cron-\u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f",level:3},{value:"25.5 \u4f9d\u8d56\u6ce8\u5165\u4f7f\u7528",id:"255-\u4f9d\u8d56\u6ce8\u5165\u4f7f\u7528",level:2},{value:"25.6 \u5982\u4f55\u90e8\u7f72",id:"256-\u5982\u4f55\u90e8\u7f72",level:2},{value:"25.6.1 \u5171\u5bbf\u4e3b\u65b9\u5f0f",id:"2561-\u5171\u5bbf\u4e3b\u65b9\u5f0f",level:3},{value:"25.6.2 \u72ec\u7acb Worker Service \u65b9\u5f0f",id:"2562-\u72ec\u7acb-worker-service-\u65b9\u5f0f",level:3},{value:"\u90e8\u7f72\u5230 Windows Service",id:"\u90e8\u7f72\u5230-windows-service",level:4},{value:"\u90e8\u7f72\u5230 Linux \u5b88\u62a4\u7a0b\u5e8f",id:"\u90e8\u7f72\u5230-linux-\u5b88\u62a4\u7a0b\u5e8f",level:4},{value:"25.7 \u5173\u4e8e Windows \u90e8\u7f72\u65e5\u5fd7\u95ee\u9898",id:"257-\u5173\u4e8e-windows-\u90e8\u7f72\u65e5\u5fd7\u95ee\u9898",level:2},{value:"25.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"258-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:u};function m(e){var n=e.components,r=(0,i.Z)(e,s);return(0,o.kt)("wrapper",(0,t.Z)({},d,r,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"251-\u5173\u4e8e\u8f85\u52a9\u89d2\u8272\u670d\u52a1"},"25.1 \u5173\u4e8e\u8f85\u52a9\u89d2\u8272\u670d\u52a1"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},".NET Core 3.0")," \u65b0\u589e\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u7684\u65b0\u9879\u76ee\u6a21\u677f\uff0c",(0,o.kt)("strong",{parentName:"p"},"\u53ef\u4ee5\u7f16\u5199\u957f\u65f6\u95f4\u8fd0\u884c\u7684\u540e\u53f0\u670d\u52a1\uff0c\u5e76\u4e14\u80fd\u8f7b\u677e\u7684\u90e8\u7f72\u6210 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Windows\u670d\u52a1")," \u6216 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Linux \u5b88\u62a4\u7a0b\u5e8f")),"\u3002"),(0,o.kt)("p",null,"\u76ee\u524d\u5fae\u8f6f\u63d0\u4f9b\u4e86\u4e24\u79cd\u65b9\u5f0f\u521b\u5efa\u957f\u65f6\u95f4\u8fd0\u884c\u7684\u540e\u53f0\u670d\u52a1\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u5171\u5bbf\u4e3b\u65b9\u5f0f"),"\uff1a\u4e2d\u5c0f\u578b\u9879\u76ee\u63a8\u8350\uff0c\u65e0\u9700\u5355\u72ec\u90e8\u7f72 ",(0,o.kt)("inlineCode",{parentName:"li"},"Windows/Linux")," \u670d\u52a1"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u72ec\u7acb ",(0,o.kt)("inlineCode",{parentName:"strong"},"Worker Service")," \u65b9\u5f0f"),"\uff1a\u9700\u72ec\u7acb\u90e8\u7f72 ",(0,o.kt)("inlineCode",{parentName:"li"},"Windows/Linux")," \u670d\u52a1")),(0,o.kt)("h2",{id:"252-\u5171\u5bbf\u4e3b\u65b9\u5f0f"},"25.2 \u5171\u5bbf\u4e3b\u65b9\u5f0f"),(0,o.kt)("p",null,"\u5171\u5bbf\u4e3b\u65b9\u5f0f\u6307\u7684\u662f\u5728\u73b0\u6709\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Web")," \u6216\u5176\u4ed6\u5e94\u7528\u7a0b\u4e2d\u521b\u5efa\u7c7b\u6587\u4ef6\u5e76\u6d3e\u751f\u81ea ",(0,o.kt)("inlineCode",{parentName:"p"},"BackgroundService")," \u7c7b\u5373\u53ef\u3002",(0,o.kt)("strong",{parentName:"p"},"\u8fd9\u79cd\u65b9\u5f0f\u7684\u5178\u578b\u7279\u70b9\u5c31\u662f\u548c\u5e94\u7528\u5171\u751f\u5b58\u5468\u671f\uff0c\u5e94\u7528\u542f\u52a8\u65f6\u542f\u52a8\uff0c\u5e94\u7528\u7ed3\u675f\u505c\u6b62\u8fd0\u884c\u3002")),(0,o.kt)("admonition",{title:"\u63a8\u8350\u7b49\u7ea7",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u4e2d\u5c0f\u578b\u9879\u76ee\u4f7f\u7528\u8fd9\u79cd\u65b9\u5f0f\u3002")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8,11,12-17}",showLineNumbers:!0,"{8,11,12-17}":!0},"using Microsoft.Extensions.Hosting;\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace YourPoject.Web.Core;\n\npublic class Worker : BackgroundService\n{\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n Console.WriteLine(DateTime.Now);\n\n // \u5ef6\u8fdf 1 \u79d2\n await Task.Delay(1000, stoppingToken);\n }\n }\n}\n")),(0,o.kt)("p",null,"\u4e4b\u540e\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c\u5373\u53ef\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddHostedService();\n")),(0,o.kt)("h3",{id:"2521-\u6700\u4f73\u5b9e\u8df5"},"25.2.1 \u6700\u4f73\u5b9e\u8df5"),(0,o.kt)("p",null,"\u6700\u597d\u7684\u5b9e\u8df5\u65b9\u5f0f\u662f\u521b\u5efa\u72ec\u7acb\u7684\u7c7b\u5e93\u9879\u76ee\uff1a",(0,o.kt)("inlineCode",{parentName:"p"},"YourProject.BackgroundServices"),"\uff0c\u4e4b\u540e\u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"p"},"YourPoject.Application")," \u548c ",(0,o.kt)("inlineCode",{parentName:"p"},"YourPoject.Core")," \u5c42\u5f15\u7528\uff0c\u5c06\u6240\u6709\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u653e\u5728\u8be5\u5c42\uff0c\u540c\u65f6\u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7c7b\u8fdb\u884c ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u7edf\u4e00\u6ce8\u518c\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,7,9-10}",showLineNumbers:!0,"{5,7,9-10}":!0},"using Microsoft.Extensions.DependencyInjection;\n\nnamespace YourProject.BackgroundServices;\n\npublic sealed class Startup : AppStartup\n{\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddHostedService();\n services.AddHostedService();\n }\n}\n")),(0,o.kt)("h2",{id:"253-\u72ec\u7acb-worker-service-\u65b9\u5f0f"},"25.3 \u72ec\u7acb ",(0,o.kt)("inlineCode",{parentName:"h2"},"Worker Service")," \u65b9\u5f0f"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u72ec\u7acb ",(0,o.kt)("inlineCode",{parentName:"strong"},"Worker Service")," \u65b9\u5f0f\u7684\u4e3b\u8981\u7279\u70b9\u5c31\u662f\u5b83\u662f\u4e00\u4e2a\u72ec\u7acb\u7684\u9879\u76ee"),"\uff0c\u548c\u73b0\u6709\u7684\u9879\u76ee\u6ca1\u6709\u76f4\u63a5\u5173\u8054\u5173\u7cfb\uff0c",(0,o.kt)("strong",{parentName:"p"},"\u9700\u8981\u5206\u5f00\u72ec\u7acb\u90e8\u7f72"),"\u3002"),(0,o.kt)("admonition",{title:"\u63a8\u8350\u7b49\u7ea7",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u4e2d\u5927\u578b\u9879\u76ee\u4f7f\u7528\u8fd9\u79cd\u65b9\u5f0f\uff0c\u4e5f\u5c31\u662f\u72ec\u7acb\u90e8\u7f72\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"Windows Service")," \u6216\u8005 ",(0,o.kt)("inlineCode",{parentName:"p"},"Linux \u5b88\u62a4\u8fdb\u7a0b"),"\uff0c\u5177\u6709\u72ec\u7acb\u751f\u5b58\u5468\u671f\uff0c\u5373\u4f7f\u5e94\u7528\u6545\u969c\u4e86\u4e5f\u4e0d\u4f1a\u5f71\u54cd\u5b83\u7684\u8fd0\u884c\u3002")),(0,o.kt)("h3",{id:"2531-\u5982\u4f55\u521b\u5efa-worker-service"},"25.3.1 \u5982\u4f55\u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"h3"},"Worker Service")),(0,o.kt)("p",null,"\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019")," \u63d0\u4f9b\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u53ef\u76f4\u63a5\u521b\u5efa\u3002\u5982\u56fe\uff1a"),(0,o.kt)("img",{src:(0,a.Z)("img/wk.png")}),(0,o.kt)("h3",{id:"2532-\u521b\u5efa-worker"},"25.3.2 \u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"h3"},"Worker")),(0,o.kt)("p",null,"\u5f53\u6211\u4eec\u521b\u5efa\u597d ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u9879\u76ee\u65f6\uff0c\u5df2\u7ecf\u81ea\u5e26\u4e86\u4e00\u4e2a ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u7c7b\u5e76\u7ee7\u627f\u81ea ",(0,o.kt)("inlineCode",{parentName:"p"},"BackgroundService")," \u57fa\u7c7b\u3002"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u6b63\u662f\u6211\u4eec\u8f85\u52a9\u89d2\u8272\u7684\u4e3b\u8981\u5de5\u4f5c\u7c7b\uff0c\u5728\u8fd9\u91cc\u6211\u4eec\u7f16\u5199\u6211\u4eec\u6240\u6709\u7684\u4e1a\u52a1\u903b\u8f91\u3002\u901a\u5e38 ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u9ed8\u8ba4\u683c\u5f0f\u4e3a\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,18}",showLineNumbers:!0,"":!0,"{9,18}":!0},'using Microsoft.Extensions.Hosting;\nusing Microsoft.Extensions.Logging;\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace FurionWorkers\n{\n public class Worker : BackgroundService\n {\n private readonly ILogger _logger;\n\n public Worker(ILogger logger)\n {\n _logger = logger;\n }\n\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n await Task.Delay(1000, stoppingToken);\n }\n }\n }\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u5f53\u6211\u4eec\u521b\u5efa\u4e86 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Worker")," \u7c7b\u4e4b\u540e\uff0c\u9700\u8981\u5728 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Program.cs")," \u4e2d\u8fdb\u884c\u6ce8\u518c"),"\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {17}",showLineNumbers:!0,"":!0,"{17}":!0},"using Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace FurionWorkers\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args) =>\n Host.CreateDefaultBuilder(args)\n .ConfigureServices((hostContext, services) =>\n {\n services.AddHostedService();\n });\n }\n}\n")),(0,o.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\u540e\u53ef\u5b9e\u73b0\u81ea\u52a8\u6ce8\u518c\u3002")),(0,o.kt)("h3",{id:"2533-\u591a\u4e2a-worker"},"25.3.3 \u591a\u4e2a ",(0,o.kt)("inlineCode",{parentName:"h3"},"Worker")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u662f\u652f\u6301\u5b9a\u4e49\u591a\u4e2a ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u8fdb\u884c\u534f\u8c03\u5de5\u4f5c\u7684\uff0c\u6bcf\u4e2a ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u662f\u5b8c\u5168\u72ec\u7acb\u7684\u5de5\u4f5c\u73af\u5883\uff0c\u4f46\u53ef\u5171\u4eab\u540c\u4e00\u4e3b\u8fdb\u7a0b\u4fe1\u606f\u3002"),(0,o.kt)("h3",{id:"2534-\u751f\u547d\u5468\u671f"},"25.3.4 \u751f\u547d\u5468\u671f"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u63d0\u4f9b\u4e86\u4e09\u4e2a\u6267\u884c\u65b9\u6cd5\uff0c\u5206\u522b\u4ee3\u8868\u4e09\u4e2a\u751f\u547d\u5468\u671f\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"StartAsync"),"\uff1a\u8d1f\u8d23\u542f\u52a8 ",(0,o.kt)("inlineCode",{parentName:"li"},"Worker Service"),"\uff0c\u5982\u679c\u8c03\u7528 ",(0,o.kt)("inlineCode",{parentName:"li"},"StartAsync")," \u65b9\u6cd5\u7684\u7ebf\u7a0b\u88ab\u4e00\u76f4\u963b\u585e\u4e86\uff0c\u90a3\u4e48 ",(0,o.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u7684\u542f\u52a8\u5c31\u4e00\u76f4\u5b8c\u6210\u4e0d\u4e86"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ExecuteAsync"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u771f\u6b63\u5b9e\u73b0\u4e1a\u52a1\u903b\u8f91\u7684\u5730\u65b9\uff0c\u8fd9\u91cc\u4e0d\u80fd\u8c03\u7528\u963b\u585e\u4ee3\u7801\uff01\uff01\uff01"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"StopAsync"),"\uff1a\u8d1f\u8d23\u7ed3\u675f ",(0,o.kt)("inlineCode",{parentName:"li"},"Worker Service"),"\uff0c\u5982\u679c\u8c03\u7528 ",(0,o.kt)("inlineCode",{parentName:"li"},"StopAsync")," \u65b9\u6cd5\u7684\u7ebf\u7a0b\u88ab\u4e00\u76f4\u963b\u585e\u4e86\uff0c\u90a3\u4e48 ",(0,o.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u7684\u7ed3\u675f\u5c31\u4e00\u76f4\u5b8c\u6210\u4e0d\u4e86")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {19,25,35}",showLineNumbers:!0,"":!0,"{19,25,35}":!0},'using Microsoft.Extensions.Hosting;\nusing Microsoft.Extensions.Logging;\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace FurionWorkers\n{\n public class Worker : BackgroundService\n {\n private readonly ILogger _logger;\n\n public Worker(ILogger logger)\n {\n _logger = logger;\n }\n\n // \u542f\u52a8\n public override Task StartAsync(CancellationToken cancellationToken)\n {\n return base.StartAsync(cancellationToken);\n }\n\n // \u6267\u884c\u903b\u8f91\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n await Task.Delay(1000, stoppingToken);\n }\n }\n\n // \u505c\u6b62\n public override Task StopAsync(CancellationToken cancellationToken)\n {\n return base.StopAsync(cancellationToken);\n }\n }\n}\n')),(0,o.kt)("h3",{id:"2535-\u96c6\u6210-furion"},"25.3.5 \u96c6\u6210 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Furion")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u96c6\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u975e\u5e38\u65b9\u4fbf\uff0c\u53ea\u9700\u8981\u5b89\u88c5 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u7684\u5305\u5373\u53ef\uff0c\u5e76\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u8c03\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},".Inject()")," \u65b9\u6cd5\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {15}",showLineNumbers:!0,"":!0,"{15}":!0},"using Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace FurionWorkers\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args) =>\n Host.CreateDefaultBuilder(args)\n .Inject()\n .ConfigureServices((hostContext, services) =>\n {\n // \u4ee5\u4e0b\u4ee3\u7801\u53ef\u4e0d\u7528\u7f16\u5199\uff0cFurion \u5df2\u5b9e\u73b0\u81ea\u52a8\u6ce8\u518c Worker;\n // services.AddHostedService();\n });\n }\n}\n")),(0,o.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Inject()")," \u65b9\u6cd5\u6ce8\u518c\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"\u65e5\u5fd7\u3001\u7f13\u5b58\u3001\u4f9d\u8d56\u6ce8\u5165\u3001\u52a0\u8f7d\u914d\u7f6e\u3001\u81ea\u5b9a\u4e49 Startup")," \u529f\u80fd\u3002"),(0,o.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u96c6\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u540e\u4f1a\u81ea\u52a8\u626b\u63cf ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u7c7b\u5e76\u5b9e\u73b0\u81ea\u52a8\u6ce8\u518c\u3002")),(0,o.kt)("h3",{id:"2536-\u6ce8\u518c\u670d\u52a1"},"25.3.6 \u6ce8\u518c\u670d\u52a1"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u6ce8\u518c\u670d\u52a1\u548c ",(0,o.kt)("inlineCode",{parentName:"p"},"Web")," \u7565\u6709\u4e0d\u540c\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Web")," \u4e3b\u8981\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Starup.cs")," \u7c7b\u4e2d\u6ce8\u518c\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u542f\u52a8\u7c7b\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"ConfigureServices")," \u65b9\u6cd5\u4e2d\u6ce8\u518c\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {16-28}",showLineNumbers:!0,"":!0,"{16-28}":!0},"using Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace FurionWorkers\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args) =>\n Host.CreateDefaultBuilder(args)\n .Inject()\n .ConfigureServices((hostContext, services) =>\n {\n // \u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\n services.AddDatabaseAccessor(options =>\n {\n options.AddDb();\n });\n\n // \u6ce8\u518c\u8fdc\u7a0b\u8bf7\u6c42\n services.AddRemoteRequest();\n\n // \u7b49\u7b49\u5176\u4ed6\u670d\u52a1\u6ce8\u518c\n });\n }\n}\n")),(0,o.kt)("h2",{id:"254-\u5b9e\u73b0\u5b9a\u65f6\u4efb\u52a1"},"25.4 \u5b9e\u73b0\u5b9a\u65f6\u4efb\u52a1"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"BackgroundService")," \u63d0\u4f9b\u4e86\u5b9a\u65f6\u4efb\u52a1\u7684\u652f\u6301\u3002"),(0,o.kt)("h3",{id:"2641-\u95f4\u9694\u6267\u884c\u65b9\u5f0f"},"26.4.1 \u95f4\u9694\u6267\u884c\u65b9\u5f0f"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,18,20,30}",showLineNumbers:!0,"":!0,"{7,18,20,30}":!0},'namespace WorkerService;\n\npublic class Worker : BackgroundService\n{\n private readonly ILogger _logger;\n\n private const int delay = 1000;\n\n public Worker(ILogger logger)\n {\n _logger = logger;\n }\n\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);\n\n await taskFactory.StartNew(async () =>\n {\n // \u4f60\u7684\u4e1a\u52a1\u4ee3\u7801\u5199\u5230\u8fd9\u91cc\u9762\n\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n\n await Task.CompletedTask;\n\n }, stoppingToken);\n\n await Task.Delay(delay, stoppingToken);\n }\n }\n}\n')),(0,o.kt)("h3",{id:"2642-cron-\u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f"},"26.4.2 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,14,21,23,32}",showLineNumbers:!0,"":!0,"{9,14,21,23,32}":!0},'using Furion.TimeCrontab;\n\nnamespace WorkerService;\n\npublic class Worker : BackgroundService\n{\n private readonly ILogger _logger;\n\n private readonly Crontab _crontab;\n\n public Worker(ILogger logger)\n {\n _logger = logger;\n _crontab = Crontab.Parse("* * * * * *", CronStringFormat.WithSeconds);\n }\n\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);\n\n await taskFactory.StartNew(async () =>\n {\n // \u4f60\u7684\u4e1a\u52a1\u4ee3\u7801\u5199\u5230\u8fd9\u91cc\u9762\n\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n\n await Task.CompletedTask;\n }, stoppingToken);\n\n await Task.Delay(_crontab.GetSleepMilliseconds(DateTime.UtcNow), stoppingToken);\n }\n }\n}\n')),(0,o.kt)("h2",{id:"255-\u4f9d\u8d56\u6ce8\u5165\u4f7f\u7528"},"25.5 \u4f9d\u8d56\u6ce8\u5165\u4f7f\u7528"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u53ea\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u63d0\u4f9b\u4e86",(0,o.kt)("strong",{parentName:"p"},"\u5355\u4f8b\u4f5c\u7528\u57df"),"\u7684\u670d\u52a1\u6ce8\u5165\uff0c\u5982\u679c\u9700\u8981\u6ce8\u5165\u77ac\u65f6\u6216\u4f5c\u7528\u57df\u5bf9\u8c61\uff0c\u9700\u624b\u52a8\u521b\u5efa\u4f5c\u7528\u57df\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7-8,19-31}",showLineNumbers:!0,"":!0,"{7-8,19-31}":!0},"public class Worker : BackgroundService\n{\n // \u65e5\u5fd7\u5bf9\u8c61\n private readonly ILogger _logger;\n\n // \u670d\u52a1\u5de5\u5382\n private readonly IServiceScopeFactory _scopeFactory;\n public Worker(ILogger logger\n , IServiceScopeFactory scopeFactory)\n {\n _logger = logger;\n _scopeFactory = scopeFactory;\n }\n\n protected override Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n using (var scope = _scopeFactory.CreateScope())\n {\n var services = scope.ServiceProvider;\n\n // \u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n var dbContext = Db.GetDbContext(services);\n\n // \u83b7\u53d6\u4ed3\u50a8\n var respository = Db.GetRepository(services);\n\n // \u89e3\u6790\u5176\u4ed6\u670d\u52a1\n var otherService = services.GetService();\n }\n }\n\n return Task.CompletedTask;\n }\n}\n")),(0,o.kt)("h2",{id:"256-\u5982\u4f55\u90e8\u7f72"},"25.6 \u5982\u4f55\u90e8\u7f72"),(0,o.kt)("h3",{id:"2561-\u5171\u5bbf\u4e3b\u65b9\u5f0f"},"25.6.1 \u5171\u5bbf\u4e3b\u65b9\u5f0f"),(0,o.kt)("p",null,"\u5171\u5bbf\u4e3b\u65b9\u5f0f\u65b9\u5f0f\u90e8\u7f72\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700\u8981\u90e8\u7f72\u6240\u5728\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Web")," \u6216\u5176\u4ed6\u5e94\u7528\u7a0b\u5e8f\u9879\u76ee\u5373\u53ef\uff0c\u4f1a\u81ea\u52a8\u968f\u7740\u9879\u76ee\u542f\u52a8\u81ea\u52a8\u542f\u52a8\u3002"),(0,o.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u90e8\u7f72\u5230 ",(0,o.kt)("inlineCode",{parentName:"p"},"IIS")," \u4e2d\uff0c\u53ef\u80fd\u5b58\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u88ab\u56de\u6536\u7684\u60c5\u51b5\uff0c\u6bd5\u7adf\u662f\u548c\u7f51\u7ad9\u540c\u4e00\u4e2a\u5bbf\u4e3b\u3002")),(0,o.kt)("h3",{id:"2562-\u72ec\u7acb-worker-service-\u65b9\u5f0f"},"25.6.2 \u72ec\u7acb ",(0,o.kt)("inlineCode",{parentName:"h3"},"Worker Service")," \u65b9\u5f0f"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u652f\u6301\u90e8\u7f72\u5230 ",(0,o.kt)("inlineCode",{parentName:"p"},"Windows Service")," \u4e2d \u6216 ",(0,o.kt)("inlineCode",{parentName:"p"},"Linux \u5b88\u62a4\u8fdb\u7a0b\u4e2d")),(0,o.kt)("hr",null),(0,o.kt)("h4",{id:"\u90e8\u7f72\u5230-windows-service"},"\u90e8\u7f72\u5230 ",(0,o.kt)("inlineCode",{parentName:"h4"},"Windows Service")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"\u7b2c\u4e00\u6b65"),"\uff1a\u5b89\u88c5 ",(0,o.kt)("inlineCode",{parentName:"p"},"Microsoft.Extensions.Hosting.WindowsServices")," \u62d3\u5c55\u5305")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"\u7b2c\u4e8c\u6b65"),"\uff1a\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"p"},".UseWindowsService()")))),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {15}",showLineNumbers:!0,"":!0,"{15}":!0},"using Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace FurionWorkers\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args) =>\n Host.CreateDefaultBuilder(args)\n .UseWindowsService()\n .Inject()\n .ConfigureServices((hostContext, services) =>\n {\n // \u4ee5\u4e0b\u4ee3\u7801\u53ef\u4e0d\u7528\u7f16\u5199\uff0cFurion \u5df2\u5b9e\u73b0\u81ea\u52a8\u6ce8\u518c Worker;\n // services.AddHostedService();\n });\n }\n}\n")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u7b2c\u4e09\u6b65"),"\uff1a\u53d1\u5e03 ",(0,o.kt)("inlineCode",{parentName:"li"},"Worker Service"),"\uff0c\u53ef\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"li"},"dotnet publish -c Release -o C:\\FurionWorker")," \u547d\u4ee4\u53d1\u5e03\u6216\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"li"},"Visual Studio 2019")," \u53d1\u5e03\u3002")),(0,o.kt)("p",null,"\u72ec\u7acb\u53d1\u5e03\u4e0d\u4f9d\u8d56 SDK \u65b9\u5f0f ",(0,o.kt)("inlineCode",{parentName:"p"},"dotnet publish -c release -r win10-x64 --framework net6.0")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u7b2c\u56db\u6b65"),"\uff1a\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"li"},"sc.exe")," \u5de5\u5177\u6765\u7ba1\u7406\u5e76\u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"li"},"Windows")," \u670d\u52a1\uff0c\u901a\u8fc7 ",(0,o.kt)("strong",{parentName:"li"},"\u7ba1\u7406\u5458\u6a21\u5f0f")," \u5e76\u6253\u5f00\u63a7\u5236\u53f0\uff0c\u8f93\u5165\uff1a")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cmd"},"sc.exe create FurionWorkerServices binPath= C:\\FurionWorker\\FurionWorker.exe\n")),(0,o.kt)("p",null,"\u6ce8\u610f",(0,o.kt)("inlineCode",{parentName:"p"},"="),"\u540e\u9762\u8981\u6709\u4e00\u4e2a\u7a7a\u683c",(0,o.kt)("br",{parentName:"p"}),"\n","\u521b\u5efa\u6210\u529f\u540e\u53ef\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"sc.exe query FurionWorkerServices")," \u67e5\u770b\u670d\u52a1\u72b6\u6001\u3002"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u7b2c\u4e94\u6b65"))),(0,o.kt)("p",null,"\u542f\u52a8\u670d\u52a1\uff1a",(0,o.kt)("inlineCode",{parentName:"p"},"sc.exe start FurionWorkerServices"),"\uff0c\u542f\u52a8\u4e4b\u540e\u5c31\u53ef\u4ee5\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Windows")," \u670d\u52a1\u5de5\u5177\u4e2d\u67e5\u770b\u4e86\u3002"),(0,o.kt)("p",null,"\u505c\u6b62\u670d\u52a1\uff1a",(0,o.kt)("inlineCode",{parentName:"p"},"sc.exe stop NETCoreDemoWorkerService")),(0,o.kt)("p",null,"\u5220\u9664\u670d\u52a1\uff1a",(0,o.kt)("inlineCode",{parentName:"p"},"sc.exe delete NETCoreDemoWorkerService")),(0,o.kt)("admonition",{title:"\u7279\u522b\u63d0\u9192",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0a\u6240\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"sc.exe")," \u547d\u4ee4\u5fc5\u987b\u5728 ",(0,o.kt)("strong",{parentName:"p"},"\u7ba1\u7406\u5458")," \u6a21\u5f0f\u4e0b\u8fdb\u884c\u3002\nsc.exe delete NETCoreDemoWorkerService, \u6267\u884c\u5220\u9664\u65f6\u5019, \u628a",(0,o.kt)("inlineCode",{parentName:"p"},"Windows")," \u670d\u52a1\u5de5\u5177\u5173\u95ed, \u5426\u5219, \u7535\u8111\u91cd\u542f\u540e\u624d\u4f1a\u663e\u793a\u5220\u9664;")),(0,o.kt)("hr",null),(0,o.kt)("h4",{id:"\u90e8\u7f72\u5230-linux-\u5b88\u62a4\u7a0b\u5e8f"},"\u90e8\u7f72\u5230 ",(0,o.kt)("inlineCode",{parentName:"h4"},"Linux \u5b88\u62a4\u7a0b\u5e8f")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"\u7b2c\u4e00\u6b65"),"\uff1a\u5b89\u88c5 ",(0,o.kt)("inlineCode",{parentName:"p"},"Microsoft.Extensions.Hosting.Systemd")," \u62d3\u5c55\u5305")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"\u7b2c\u4e8c\u6b65"),"\uff1a\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"p"},".UseSystemd()")))),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {15}",showLineNumbers:!0,"":!0,"{15}":!0},"using Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace FurionWorkers\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args) =>\n Host.CreateDefaultBuilder(args)\n .UseSystemd()\n .Inject()\n .ConfigureServices((hostContext, services) =>\n {\n // \u4ee5\u4e0b\u4ee3\u7801\u53ef\u4e0d\u7528\u7f16\u5199\uff0cFurion \u5df2\u5b9e\u73b0\u81ea\u52a8\u6ce8\u518c Worker;\n // services.AddHostedService();\n });\n }\n}\n")),(0,o.kt)("p",null,"\u90e8\u7f72\u5230 ",(0,o.kt)("inlineCode",{parentName:"p"},"Linux \u5b88\u62a4\u8fdb\u7a0b")," \u5c31\u662f\u8fd9\u4e48\u7b80\u5355\u3002"),(0,o.kt)("h2",{id:"257-\u5173\u4e8e-windows-\u90e8\u7f72\u65e5\u5fd7\u95ee\u9898"},"25.7 \u5173\u4e8e ",(0,o.kt)("inlineCode",{parentName:"h2"},"Windows")," \u90e8\u7f72\u65e5\u5fd7\u95ee\u9898"),(0,o.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"Windows Services")," \u90e8\u7f72\u540e\uff0c\u65e5\u5fd7\u6587\u4ef6\u53ef\u80fd\u4f1a\u5728\u7cfb\u7edf\u76d8\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"System32")," \u4e0b\u3002"),(0,o.kt)("img",{src:(0,a.Z)("img/rjs.jpg")}),(0,o.kt)("h2",{id:"258-\u53cd\u9988\u4e0e\u5efa\u8bae"},"25.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/aa7bdd74.3b76ce8d.js b/handbook/build/assets/js/aa7bdd74.3b76ce8d.js deleted file mode 100644 index 807163156a..0000000000 --- a/handbook/build/assets/js/aa7bdd74.3b76ce8d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4572],{8820:function(e,n,r){r.r(n),r.d(n,{assets:function(){return k},contentTitle:function(){return p},default:function(){return m},frontMatter:function(){return l},metadata:function(){return c},toc:function(){return u}});var t=r(3117),i=r(102),o=(r(7294),r(3905)),a=r(1402),s=["components"],l={id:"process-service",title:"25. \u8f85\u52a9\u89d2\u8272\u670d\u52a1",sidebar_label:"25. \u8f85\u52a9\u89d2\u8272\u670d\u52a1 (Worker Service)"},p=void 0,c={unversionedId:"process-service",id:"process-service",title:"25. \u8f85\u52a9\u89d2\u8272\u670d\u52a1",description:"",source:"@site/docs/process-service.mdx",sourceDirName:".",slug:"/process-service",permalink:"/furion/docs/process-service",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/process-service.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1661854115,formattedLastUpdatedAt:"Aug 30, 2022",frontMatter:{id:"process-service",title:"25. \u8f85\u52a9\u89d2\u8272\u670d\u52a1",sidebar_label:"25. \u8f85\u52a9\u89d2\u8272\u670d\u52a1 (Worker Service)"},sidebar:"docs",previous:{title:"24. \u5373\u65f6\u901a\u8baf",permalink:"/furion/docs/signalr"},next:{title:"26. \u5b9a\u65f6\u4efb\u52a1/\u540e\u53f0\u4efb\u52a1",permalink:"/furion/docs/job"}},k={},u=[{value:"25.1 \u5173\u4e8e\u8f85\u52a9\u89d2\u8272\u670d\u52a1",id:"251-\u5173\u4e8e\u8f85\u52a9\u89d2\u8272\u670d\u52a1",level:2},{value:"25.2 \u5171\u5bbf\u4e3b\u65b9\u5f0f",id:"252-\u5171\u5bbf\u4e3b\u65b9\u5f0f",level:2},{value:"25.2.1 \u6700\u4f73\u5b9e\u8df5",id:"2521-\u6700\u4f73\u5b9e\u8df5",level:3},{value:"25.3 \u72ec\u7acb Worker Service \u65b9\u5f0f",id:"253-\u72ec\u7acb-worker-service-\u65b9\u5f0f",level:2},{value:"25.3.1 \u5982\u4f55\u521b\u5efa Worker Service",id:"2531-\u5982\u4f55\u521b\u5efa-worker-service",level:3},{value:"25.3.2 \u521b\u5efa Worker",id:"2532-\u521b\u5efa-worker",level:3},{value:"25.3.3 \u591a\u4e2a Worker",id:"2533-\u591a\u4e2a-worker",level:3},{value:"25.3.4 \u751f\u547d\u5468\u671f",id:"2534-\u751f\u547d\u5468\u671f",level:3},{value:"25.3.5 \u96c6\u6210 Furion",id:"2535-\u96c6\u6210-furion",level:3},{value:"25.3.6 \u6ce8\u518c\u670d\u52a1",id:"2536-\u6ce8\u518c\u670d\u52a1",level:3},{value:"25.4 \u5b9e\u73b0\u5b9a\u65f6\u4efb\u52a1",id:"254-\u5b9e\u73b0\u5b9a\u65f6\u4efb\u52a1",level:2},{value:"26.4.1 \u95f4\u9694\u6267\u884c\u65b9\u5f0f",id:"2641-\u95f4\u9694\u6267\u884c\u65b9\u5f0f",level:3},{value:"26.4.2 Cron \u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f",id:"2642-cron-\u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f",level:3},{value:"25.5 \u4f9d\u8d56\u6ce8\u5165\u4f7f\u7528",id:"255-\u4f9d\u8d56\u6ce8\u5165\u4f7f\u7528",level:2},{value:"25.6 \u5982\u4f55\u90e8\u7f72",id:"256-\u5982\u4f55\u90e8\u7f72",level:2},{value:"25.6.1 \u5171\u5bbf\u4e3b\u65b9\u5f0f",id:"2561-\u5171\u5bbf\u4e3b\u65b9\u5f0f",level:3},{value:"25.6.2 \u72ec\u7acb Worker Service \u65b9\u5f0f",id:"2562-\u72ec\u7acb-worker-service-\u65b9\u5f0f",level:3},{value:"\u90e8\u7f72\u5230 Windows Service",id:"\u90e8\u7f72\u5230-windows-service",level:4},{value:"\u90e8\u7f72\u5230 Linux \u5b88\u62a4\u7a0b\u5e8f",id:"\u90e8\u7f72\u5230-linux-\u5b88\u62a4\u7a0b\u5e8f",level:4},{value:"25.7 \u5173\u4e8e Windows \u90e8\u7f72\u65e5\u5fd7\u95ee\u9898",id:"257-\u5173\u4e8e-windows-\u90e8\u7f72\u65e5\u5fd7\u95ee\u9898",level:2},{value:"25.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"258-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:u};function m(e){var n=e.components,r=(0,i.Z)(e,s);return(0,o.kt)("wrapper",(0,t.Z)({},d,r,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"251-\u5173\u4e8e\u8f85\u52a9\u89d2\u8272\u670d\u52a1"},"25.1 \u5173\u4e8e\u8f85\u52a9\u89d2\u8272\u670d\u52a1"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},".NET Core 3.0")," \u65b0\u589e\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u7684\u65b0\u9879\u76ee\u6a21\u677f\uff0c",(0,o.kt)("strong",{parentName:"p"},"\u53ef\u4ee5\u7f16\u5199\u957f\u65f6\u95f4\u8fd0\u884c\u7684\u540e\u53f0\u670d\u52a1\uff0c\u5e76\u4e14\u80fd\u8f7b\u677e\u7684\u90e8\u7f72\u6210 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Windows\u670d\u52a1")," \u6216 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Linux \u5b88\u62a4\u7a0b\u5e8f")),"\u3002"),(0,o.kt)("p",null,"\u76ee\u524d\u5fae\u8f6f\u63d0\u4f9b\u4e86\u4e24\u79cd\u65b9\u5f0f\u521b\u5efa\u957f\u65f6\u95f4\u8fd0\u884c\u7684\u540e\u53f0\u670d\u52a1\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u5171\u5bbf\u4e3b\u65b9\u5f0f"),"\uff1a\u4e2d\u5c0f\u578b\u9879\u76ee\u63a8\u8350\uff0c\u65e0\u9700\u5355\u72ec\u90e8\u7f72 ",(0,o.kt)("inlineCode",{parentName:"li"},"Windows/Linux")," \u670d\u52a1"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u72ec\u7acb ",(0,o.kt)("inlineCode",{parentName:"strong"},"Worker Service")," \u65b9\u5f0f"),"\uff1a\u9700\u72ec\u7acb\u90e8\u7f72 ",(0,o.kt)("inlineCode",{parentName:"li"},"Windows/Linux")," \u670d\u52a1")),(0,o.kt)("h2",{id:"252-\u5171\u5bbf\u4e3b\u65b9\u5f0f"},"25.2 \u5171\u5bbf\u4e3b\u65b9\u5f0f"),(0,o.kt)("p",null,"\u5171\u5bbf\u4e3b\u65b9\u5f0f\u6307\u7684\u662f\u5728\u73b0\u6709\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Web")," \u6216\u5176\u4ed6\u5e94\u7528\u7a0b\u4e2d\u521b\u5efa\u7c7b\u6587\u4ef6\u5e76\u6d3e\u751f\u81ea ",(0,o.kt)("inlineCode",{parentName:"p"},"BackgroundService")," \u7c7b\u5373\u53ef\u3002",(0,o.kt)("strong",{parentName:"p"},"\u8fd9\u79cd\u65b9\u5f0f\u7684\u5178\u578b\u7279\u70b9\u5c31\u662f\u548c\u5e94\u7528\u5171\u751f\u5b58\u5468\u671f\uff0c\u5e94\u7528\u542f\u52a8\u65f6\u542f\u52a8\uff0c\u5e94\u7528\u7ed3\u675f\u505c\u6b62\u8fd0\u884c\u3002")),(0,o.kt)("admonition",{title:"\u63a8\u8350\u7b49\u7ea7",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u4e2d\u5c0f\u578b\u9879\u76ee\u4f7f\u7528\u8fd9\u79cd\u65b9\u5f0f\u3002")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {8,11,12-17}",showLineNumbers:!0,"{8,11,12-17}":!0},"using Microsoft.Extensions.Hosting;\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace YourPoject.Web.Core;\n\npublic class Worker : BackgroundService\n{\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n Console.WriteLine(DateTime.Now);\n\n // \u5ef6\u8fdf 1 \u79d2\n await Task.Delay(1000, stoppingToken);\n }\n }\n}\n")),(0,o.kt)("p",null,"\u4e4b\u540e\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c\u5373\u53ef\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddHostedService();\n")),(0,o.kt)("h3",{id:"2521-\u6700\u4f73\u5b9e\u8df5"},"25.2.1 \u6700\u4f73\u5b9e\u8df5"),(0,o.kt)("p",null,"\u6700\u597d\u7684\u5b9e\u8df5\u65b9\u5f0f\u662f\u521b\u5efa\u72ec\u7acb\u7684\u7c7b\u5e93\u9879\u76ee\uff1a",(0,o.kt)("inlineCode",{parentName:"p"},"YourProject.BackgroundServices"),"\uff0c\u4e4b\u540e\u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"p"},"YourPoject.Application")," \u548c ",(0,o.kt)("inlineCode",{parentName:"p"},"YourPoject.Core")," \u5c42\u5f15\u7528\uff0c\u5c06\u6240\u6709\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u653e\u5728\u8be5\u5c42\uff0c\u540c\u65f6\u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u7c7b\u8fdb\u884c ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u7edf\u4e00\u6ce8\u518c\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,7,9-10}",showLineNumbers:!0,"{5,7,9-10}":!0},"using Microsoft.Extensions.DependencyInjection;\n\nnamespace YourProject.BackgroundServices;\n\npublic sealed class Startup : AppStartup\n{\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddHostedService();\n services.AddHostedService();\n }\n}\n")),(0,o.kt)("h2",{id:"253-\u72ec\u7acb-worker-service-\u65b9\u5f0f"},"25.3 \u72ec\u7acb ",(0,o.kt)("inlineCode",{parentName:"h2"},"Worker Service")," \u65b9\u5f0f"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u72ec\u7acb ",(0,o.kt)("inlineCode",{parentName:"strong"},"Worker Service")," \u65b9\u5f0f\u7684\u4e3b\u8981\u7279\u70b9\u5c31\u662f\u5b83\u662f\u4e00\u4e2a\u72ec\u7acb\u7684\u9879\u76ee"),"\uff0c\u548c\u73b0\u6709\u7684\u9879\u76ee\u6ca1\u6709\u76f4\u63a5\u5173\u8054\u5173\u7cfb\uff0c",(0,o.kt)("strong",{parentName:"p"},"\u9700\u8981\u5206\u5f00\u72ec\u7acb\u90e8\u7f72"),"\u3002"),(0,o.kt)("admonition",{title:"\u63a8\u8350\u7b49\u7ea7",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u4e2d\u5927\u578b\u9879\u76ee\u4f7f\u7528\u8fd9\u79cd\u65b9\u5f0f\uff0c\u4e5f\u5c31\u662f\u72ec\u7acb\u90e8\u7f72\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"Windows Service")," \u6216\u8005 ",(0,o.kt)("inlineCode",{parentName:"p"},"Linux \u5b88\u62a4\u8fdb\u7a0b"),"\uff0c\u5177\u6709\u72ec\u7acb\u751f\u5b58\u5468\u671f\uff0c\u5373\u4f7f\u5e94\u7528\u6545\u969c\u4e86\u4e5f\u4e0d\u4f1a\u5f71\u54cd\u5b83\u7684\u8fd0\u884c\u3002")),(0,o.kt)("h3",{id:"2531-\u5982\u4f55\u521b\u5efa-worker-service"},"25.3.1 \u5982\u4f55\u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"h3"},"Worker Service")),(0,o.kt)("p",null,"\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019")," \u63d0\u4f9b\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u53ef\u76f4\u63a5\u521b\u5efa\u3002\u5982\u56fe\uff1a"),(0,o.kt)("img",{src:(0,a.Z)("img/wk.png")}),(0,o.kt)("h3",{id:"2532-\u521b\u5efa-worker"},"25.3.2 \u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"h3"},"Worker")),(0,o.kt)("p",null,"\u5f53\u6211\u4eec\u521b\u5efa\u597d ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u9879\u76ee\u65f6\uff0c\u5df2\u7ecf\u81ea\u5e26\u4e86\u4e00\u4e2a ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u7c7b\u5e76\u7ee7\u627f\u81ea ",(0,o.kt)("inlineCode",{parentName:"p"},"BackgroundService")," \u57fa\u7c7b\u3002"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u6b63\u662f\u6211\u4eec\u8f85\u52a9\u89d2\u8272\u7684\u4e3b\u8981\u5de5\u4f5c\u7c7b\uff0c\u5728\u8fd9\u91cc\u6211\u4eec\u7f16\u5199\u6211\u4eec\u6240\u6709\u7684\u4e1a\u52a1\u903b\u8f91\u3002\u901a\u5e38 ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u9ed8\u8ba4\u683c\u5f0f\u4e3a\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,18}",showLineNumbers:!0,"":!0,"{9,18}":!0},'using Microsoft.Extensions.Hosting;\nusing Microsoft.Extensions.Logging;\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace FurionWorkers\n{\n public class Worker : BackgroundService\n {\n private readonly ILogger _logger;\n\n public Worker(ILogger logger)\n {\n _logger = logger;\n }\n\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n await Task.Delay(1000, stoppingToken);\n }\n }\n }\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u5f53\u6211\u4eec\u521b\u5efa\u4e86 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Worker")," \u7c7b\u4e4b\u540e\uff0c\u9700\u8981\u5728 ",(0,o.kt)("inlineCode",{parentName:"strong"},"Program.cs")," \u4e2d\u8fdb\u884c\u6ce8\u518c"),"\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {17}",showLineNumbers:!0,"":!0,"{17}":!0},"using Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace FurionWorkers\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args) =>\n Host.CreateDefaultBuilder(args)\n .ConfigureServices((hostContext, services) =>\n {\n services.AddHostedService();\n });\n }\n}\n")),(0,o.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\u540e\u53ef\u5b9e\u73b0\u81ea\u52a8\u6ce8\u518c\u3002")),(0,o.kt)("h3",{id:"2533-\u591a\u4e2a-worker"},"25.3.3 \u591a\u4e2a ",(0,o.kt)("inlineCode",{parentName:"h3"},"Worker")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u662f\u652f\u6301\u5b9a\u4e49\u591a\u4e2a ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u8fdb\u884c\u534f\u8c03\u5de5\u4f5c\u7684\uff0c\u6bcf\u4e2a ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u662f\u5b8c\u5168\u72ec\u7acb\u7684\u5de5\u4f5c\u73af\u5883\uff0c\u4f46\u53ef\u5171\u4eab\u540c\u4e00\u4e3b\u8fdb\u7a0b\u4fe1\u606f\u3002"),(0,o.kt)("h3",{id:"2534-\u751f\u547d\u5468\u671f"},"25.3.4 \u751f\u547d\u5468\u671f"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u63d0\u4f9b\u4e86\u4e09\u4e2a\u6267\u884c\u65b9\u6cd5\uff0c\u5206\u522b\u4ee3\u8868\u4e09\u4e2a\u751f\u547d\u5468\u671f\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"StartAsync"),"\uff1a\u8d1f\u8d23\u542f\u52a8 ",(0,o.kt)("inlineCode",{parentName:"li"},"Worker Service"),"\uff0c\u5982\u679c\u8c03\u7528 ",(0,o.kt)("inlineCode",{parentName:"li"},"StartAsync")," \u65b9\u6cd5\u7684\u7ebf\u7a0b\u88ab\u4e00\u76f4\u963b\u585e\u4e86\uff0c\u90a3\u4e48 ",(0,o.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u7684\u542f\u52a8\u5c31\u4e00\u76f4\u5b8c\u6210\u4e0d\u4e86"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ExecuteAsync"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u771f\u6b63\u5b9e\u73b0\u4e1a\u52a1\u903b\u8f91\u7684\u5730\u65b9\uff0c\u8fd9\u91cc\u4e0d\u80fd\u8c03\u7528\u963b\u585e\u4ee3\u7801\uff01\uff01\uff01"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"StopAsync"),"\uff1a\u8d1f\u8d23\u7ed3\u675f ",(0,o.kt)("inlineCode",{parentName:"li"},"Worker Service"),"\uff0c\u5982\u679c\u8c03\u7528 ",(0,o.kt)("inlineCode",{parentName:"li"},"StopAsync")," \u65b9\u6cd5\u7684\u7ebf\u7a0b\u88ab\u4e00\u76f4\u963b\u585e\u4e86\uff0c\u90a3\u4e48 ",(0,o.kt)("inlineCode",{parentName:"li"},"Worker Service")," \u7684\u7ed3\u675f\u5c31\u4e00\u76f4\u5b8c\u6210\u4e0d\u4e86")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {19,25,35}",showLineNumbers:!0,"":!0,"{19,25,35}":!0},'using Microsoft.Extensions.Hosting;\nusing Microsoft.Extensions.Logging;\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace FurionWorkers\n{\n public class Worker : BackgroundService\n {\n private readonly ILogger _logger;\n\n public Worker(ILogger logger)\n {\n _logger = logger;\n }\n\n // \u542f\u52a8\n public override Task StartAsync(CancellationToken cancellationToken)\n {\n return base.StartAsync(cancellationToken);\n }\n\n // \u6267\u884c\u903b\u8f91\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n await Task.Delay(1000, stoppingToken);\n }\n }\n\n // \u505c\u6b62\n public override Task StopAsync(CancellationToken cancellationToken)\n {\n return base.StopAsync(cancellationToken);\n }\n }\n}\n')),(0,o.kt)("h3",{id:"2535-\u96c6\u6210-furion"},"25.3.5 \u96c6\u6210 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Furion")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u96c6\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u975e\u5e38\u65b9\u4fbf\uff0c\u53ea\u9700\u8981\u5b89\u88c5 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u7684\u5305\u5373\u53ef\uff0c\u5e76\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u8c03\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},".Inject()")," \u65b9\u6cd5\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {15}",showLineNumbers:!0,"":!0,"{15}":!0},"using Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace FurionWorkers\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args) =>\n Host.CreateDefaultBuilder(args)\n .Inject()\n .ConfigureServices((hostContext, services) =>\n {\n // \u4ee5\u4e0b\u4ee3\u7801\u53ef\u4e0d\u7528\u7f16\u5199\uff0cFurion \u5df2\u5b9e\u73b0\u81ea\u52a8\u6ce8\u518c Worker;\n // services.AddHostedService();\n });\n }\n}\n")),(0,o.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Inject()")," \u65b9\u6cd5\u6ce8\u518c\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"\u65e5\u5fd7\u3001\u7f13\u5b58\u3001\u4f9d\u8d56\u6ce8\u5165\u3001\u52a0\u8f7d\u914d\u7f6e\u3001\u81ea\u5b9a\u4e49 Startup")," \u529f\u80fd\u3002"),(0,o.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u96c6\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u540e\u4f1a\u81ea\u52a8\u626b\u63cf ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u7c7b\u5e76\u5b9e\u73b0\u81ea\u52a8\u6ce8\u518c\u3002")),(0,o.kt)("h3",{id:"2536-\u6ce8\u518c\u670d\u52a1"},"25.3.6 \u6ce8\u518c\u670d\u52a1"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u6ce8\u518c\u670d\u52a1\u548c ",(0,o.kt)("inlineCode",{parentName:"p"},"Web")," \u7565\u6709\u4e0d\u540c\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Web")," \u4e3b\u8981\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Starup.cs")," \u7c7b\u4e2d\u6ce8\u518c\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u542f\u52a8\u7c7b\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"ConfigureServices")," \u65b9\u6cd5\u4e2d\u6ce8\u518c\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {16-28}",showLineNumbers:!0,"":!0,"{16-28}":!0},"using Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace FurionWorkers\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args) =>\n Host.CreateDefaultBuilder(args)\n .Inject()\n .ConfigureServices((hostContext, services) =>\n {\n // \u6ce8\u518c\u6570\u636e\u5e93\u670d\u52a1\n services.AddDatabaseAccessor(options =>\n {\n options.AddDb();\n });\n\n // \u6ce8\u518c\u8fdc\u7a0b\u8bf7\u6c42\n services.AddRemoteRequest();\n\n // \u7b49\u7b49\u5176\u4ed6\u670d\u52a1\u6ce8\u518c\n });\n }\n}\n")),(0,o.kt)("h2",{id:"254-\u5b9e\u73b0\u5b9a\u65f6\u4efb\u52a1"},"25.4 \u5b9e\u73b0\u5b9a\u65f6\u4efb\u52a1"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"BackgroundService")," \u63d0\u4f9b\u4e86\u5b9a\u65f6\u4efb\u52a1\u7684\u652f\u6301\u3002"),(0,o.kt)("h3",{id:"2641-\u95f4\u9694\u6267\u884c\u65b9\u5f0f"},"26.4.1 \u95f4\u9694\u6267\u884c\u65b9\u5f0f"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7,18,20,30}",showLineNumbers:!0,"":!0,"{7,18,20,30}":!0},'namespace WorkerService;\n\npublic class Worker : BackgroundService\n{\n private readonly ILogger _logger;\n\n private const int delay = 1000;\n\n public Worker(ILogger logger)\n {\n _logger = logger;\n }\n\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);\n\n await taskFactory.StartNew(async () =>\n {\n // \u4f60\u7684\u4e1a\u52a1\u4ee3\u7801\u5199\u5230\u8fd9\u91cc\u9762\n\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n\n await Task.CompletedTask;\n\n }, stoppingToken);\n\n await Task.Delay(delay, stoppingToken);\n }\n }\n}\n')),(0,o.kt)("h3",{id:"2642-cron-\u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f"},"26.4.2 ",(0,o.kt)("inlineCode",{parentName:"h3"},"Cron")," \u8868\u8fbe\u5f0f\u6267\u884c\u65b9\u5f0f"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,14,21,23,32}",showLineNumbers:!0,"":!0,"{9,14,21,23,32}":!0},'using Furion.TimeCrontab;\n\nnamespace WorkerService;\n\npublic class Worker : BackgroundService\n{\n private readonly ILogger _logger;\n\n private readonly Crontab _crontab;\n\n public Worker(ILogger logger)\n {\n _logger = logger;\n _crontab = Crontab.Parse("* * * * * *", CronStringFormat.WithSeconds);\n }\n\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);\n\n await taskFactory.StartNew(async () =>\n {\n // \u4f60\u7684\u4e1a\u52a1\u4ee3\u7801\u5199\u5230\u8fd9\u91cc\u9762\n\n _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);\n\n await Task.CompletedTask;\n }, stoppingToken);\n\n await Task.Delay(_crontab.GetSleepMilliseconds(DateTime.UtcNow), stoppingToken);\n }\n }\n}\n')),(0,o.kt)("h2",{id:"255-\u4f9d\u8d56\u6ce8\u5165\u4f7f\u7528"},"25.5 \u4f9d\u8d56\u6ce8\u5165\u4f7f\u7528"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u53ea\u4e3a ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker")," \u63d0\u4f9b\u4e86",(0,o.kt)("strong",{parentName:"p"},"\u5355\u4f8b\u4f5c\u7528\u57df"),"\u7684\u670d\u52a1\u6ce8\u5165\uff0c\u5982\u679c\u9700\u8981\u6ce8\u5165\u77ac\u65f6\u6216\u4f5c\u7528\u57df\u5bf9\u8c61\uff0c\u9700\u624b\u52a8\u521b\u5efa\u4f5c\u7528\u57df\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {7-8,19-31}",showLineNumbers:!0,"":!0,"{7-8,19-31}":!0},"public class Worker : BackgroundService\n{\n // \u65e5\u5fd7\u5bf9\u8c61\n private readonly ILogger _logger;\n\n // \u670d\u52a1\u5de5\u5382\n private readonly IServiceScopeFactory _scopeFactory;\n public Worker(ILogger logger\n , IServiceScopeFactory scopeFactory)\n {\n _logger = logger;\n _scopeFactory = scopeFactory;\n }\n\n protected override Task ExecuteAsync(CancellationToken stoppingToken)\n {\n while (!stoppingToken.IsCancellationRequested)\n {\n using (var scope = _scopeFactory.CreateScope())\n {\n var services = scope.ServiceProvider;\n\n // \u83b7\u53d6\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\n var dbContext = Db.GetDbContext(services);\n\n // \u83b7\u53d6\u4ed3\u50a8\n var respository = Db.GetRepository(services);\n\n // \u89e3\u6790\u5176\u4ed6\u670d\u52a1\n var otherService = services.GetService();\n }\n }\n\n return Task.CompletedTask;\n }\n}\n")),(0,o.kt)("h2",{id:"256-\u5982\u4f55\u90e8\u7f72"},"25.6 \u5982\u4f55\u90e8\u7f72"),(0,o.kt)("h3",{id:"2561-\u5171\u5bbf\u4e3b\u65b9\u5f0f"},"25.6.1 \u5171\u5bbf\u4e3b\u65b9\u5f0f"),(0,o.kt)("p",null,"\u5171\u5bbf\u4e3b\u65b9\u5f0f\u65b9\u5f0f\u90e8\u7f72\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700\u8981\u90e8\u7f72\u6240\u5728\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"Web")," \u6216\u5176\u4ed6\u5e94\u7528\u7a0b\u5e8f\u9879\u76ee\u5373\u53ef\uff0c\u4f1a\u81ea\u52a8\u968f\u7740\u9879\u76ee\u542f\u52a8\u81ea\u52a8\u542f\u52a8\u3002"),(0,o.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u5982\u679c\u90e8\u7f72\u5230 ",(0,o.kt)("inlineCode",{parentName:"p"},"IIS")," \u4e2d\uff0c\u53ef\u80fd\u5b58\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u88ab\u56de\u6536\u7684\u60c5\u51b5\uff0c\u6bd5\u7adf\u662f\u548c\u7f51\u7ad9\u540c\u4e00\u4e2a\u5bbf\u4e3b\u3002")),(0,o.kt)("h3",{id:"2562-\u72ec\u7acb-worker-service-\u65b9\u5f0f"},"25.6.2 \u72ec\u7acb ",(0,o.kt)("inlineCode",{parentName:"h3"},"Worker Service")," \u65b9\u5f0f"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Worker Service")," \u652f\u6301\u90e8\u7f72\u5230 ",(0,o.kt)("inlineCode",{parentName:"p"},"Windows Service")," \u4e2d \u6216 ",(0,o.kt)("inlineCode",{parentName:"p"},"Linux \u5b88\u62a4\u8fdb\u7a0b\u4e2d")),(0,o.kt)("hr",null),(0,o.kt)("h4",{id:"\u90e8\u7f72\u5230-windows-service"},"\u90e8\u7f72\u5230 ",(0,o.kt)("inlineCode",{parentName:"h4"},"Windows Service")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"\u7b2c\u4e00\u6b65"),"\uff1a\u5b89\u88c5 ",(0,o.kt)("inlineCode",{parentName:"p"},"Microsoft.Extensions.Hosting.WindowsServices")," \u62d3\u5c55\u5305")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"\u7b2c\u4e8c\u6b65"),"\uff1a\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"p"},".UseWindowsService()")))),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {15}",showLineNumbers:!0,"":!0,"{15}":!0},"using Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace FurionWorkers\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args) =>\n Host.CreateDefaultBuilder(args)\n .UseWindowsService()\n .Inject()\n .ConfigureServices((hostContext, services) =>\n {\n // \u4ee5\u4e0b\u4ee3\u7801\u53ef\u4e0d\u7528\u7f16\u5199\uff0cFurion \u5df2\u5b9e\u73b0\u81ea\u52a8\u6ce8\u518c Worker;\n // services.AddHostedService();\n });\n }\n}\n")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u7b2c\u4e09\u6b65"),"\uff1a\u53d1\u5e03 ",(0,o.kt)("inlineCode",{parentName:"li"},"Worker Service"),"\uff0c\u53ef\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"li"},"dotnet publish -c Release -o C:\\FurionWorker")," \u547d\u4ee4\u53d1\u5e03\u6216\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"li"},"Visual Studio 2019")," \u53d1\u5e03\u3002")),(0,o.kt)("p",null,"\u72ec\u7acb\u53d1\u5e03\u4e0d\u4f9d\u8d56 SDK \u65b9\u5f0f ",(0,o.kt)("inlineCode",{parentName:"p"},"dotnet publish -c release -r win10-x64 --framework net6.0")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u7b2c\u56db\u6b65"),"\uff1a\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"li"},"sc.exe")," \u5de5\u5177\u6765\u7ba1\u7406\u5e76\u521b\u5efa ",(0,o.kt)("inlineCode",{parentName:"li"},"Windows")," \u670d\u52a1\uff0c\u901a\u8fc7 ",(0,o.kt)("strong",{parentName:"li"},"\u7ba1\u7406\u5458\u6a21\u5f0f")," \u5e76\u6253\u5f00\u63a7\u5236\u53f0\uff0c\u8f93\u5165\uff1a")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cmd"},"sc.exe create FurionWorkerServices binPath= C:\\FurionWorker\\FurionWorker.exe\n")),(0,o.kt)("p",null,"\u6ce8\u610f",(0,o.kt)("inlineCode",{parentName:"p"},"="),"\u540e\u9762\u8981\u6709\u4e00\u4e2a\u7a7a\u683c",(0,o.kt)("br",{parentName:"p"}),"\n","\u521b\u5efa\u6210\u529f\u540e\u53ef\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"p"},"sc.exe query FurionWorkerServices")," \u67e5\u770b\u670d\u52a1\u72b6\u6001\u3002"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"\u7b2c\u4e94\u6b65"))),(0,o.kt)("p",null,"\u542f\u52a8\u670d\u52a1\uff1a",(0,o.kt)("inlineCode",{parentName:"p"},"sc.exe start FurionWorkerServices"),"\uff0c\u542f\u52a8\u4e4b\u540e\u5c31\u53ef\u4ee5\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Windows")," \u670d\u52a1\u5de5\u5177\u4e2d\u67e5\u770b\u4e86\u3002"),(0,o.kt)("p",null,"\u505c\u6b62\u670d\u52a1\uff1a",(0,o.kt)("inlineCode",{parentName:"p"},"sc.exe stop NETCoreDemoWorkerService")),(0,o.kt)("p",null,"\u5220\u9664\u670d\u52a1\uff1a",(0,o.kt)("inlineCode",{parentName:"p"},"sc.exe delete NETCoreDemoWorkerService")),(0,o.kt)("admonition",{title:"\u7279\u522b\u63d0\u9192",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0a\u6240\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"sc.exe")," \u547d\u4ee4\u5fc5\u987b\u5728 ",(0,o.kt)("strong",{parentName:"p"},"\u7ba1\u7406\u5458")," \u6a21\u5f0f\u4e0b\u8fdb\u884c\u3002\nsc.exe delete NETCoreDemoWorkerService, \u6267\u884c\u5220\u9664\u65f6\u5019, \u628a",(0,o.kt)("inlineCode",{parentName:"p"},"Windows")," \u670d\u52a1\u5de5\u5177\u5173\u95ed, \u5426\u5219, \u7535\u8111\u91cd\u542f\u540e\u624d\u4f1a\u663e\u793a\u5220\u9664;")),(0,o.kt)("hr",null),(0,o.kt)("h4",{id:"\u90e8\u7f72\u5230-linux-\u5b88\u62a4\u7a0b\u5e8f"},"\u90e8\u7f72\u5230 ",(0,o.kt)("inlineCode",{parentName:"h4"},"Linux \u5b88\u62a4\u7a0b\u5e8f")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"\u7b2c\u4e00\u6b65"),"\uff1a\u5b89\u88c5 ",(0,o.kt)("inlineCode",{parentName:"p"},"Microsoft.Extensions.Hosting.Systemd")," \u62d3\u5c55\u5305")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"\u7b2c\u4e8c\u6b65"),"\uff1a\u5728 ",(0,o.kt)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u6dfb\u52a0 ",(0,o.kt)("inlineCode",{parentName:"p"},".UseSystemd()")))),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {15}",showLineNumbers:!0,"":!0,"{15}":!0},"using Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace FurionWorkers\n{\n public class Program\n {\n public static void Main(string[] args)\n {\n CreateHostBuilder(args).Build().Run();\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args) =>\n Host.CreateDefaultBuilder(args)\n .UseSystemd()\n .Inject()\n .ConfigureServices((hostContext, services) =>\n {\n // \u4ee5\u4e0b\u4ee3\u7801\u53ef\u4e0d\u7528\u7f16\u5199\uff0cFurion \u5df2\u5b9e\u73b0\u81ea\u52a8\u6ce8\u518c Worker;\n // services.AddHostedService();\n });\n }\n}\n")),(0,o.kt)("p",null,"\u90e8\u7f72\u5230 ",(0,o.kt)("inlineCode",{parentName:"p"},"Linux \u5b88\u62a4\u8fdb\u7a0b")," \u5c31\u662f\u8fd9\u4e48\u7b80\u5355\u3002"),(0,o.kt)("h2",{id:"257-\u5173\u4e8e-windows-\u90e8\u7f72\u65e5\u5fd7\u95ee\u9898"},"25.7 \u5173\u4e8e ",(0,o.kt)("inlineCode",{parentName:"h2"},"Windows")," \u90e8\u7f72\u65e5\u5fd7\u95ee\u9898"),(0,o.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u4f7f\u7528 ",(0,o.kt)("inlineCode",{parentName:"p"},"Windows Services")," \u90e8\u7f72\u540e\uff0c\u65e5\u5fd7\u6587\u4ef6\u53ef\u80fd\u4f1a\u5728\u7cfb\u7edf\u76d8\u7684 ",(0,o.kt)("inlineCode",{parentName:"p"},"System32")," \u4e0b\u3002"),(0,o.kt)("img",{src:(0,a.Z)("img/rjs.jpg")}),(0,o.kt)("h2",{id:"258-\u53cd\u9988\u4e0e\u5efa\u8bae"},"25.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}m.isMDXComponent=!0},3905:function(e,n,r){r.d(n,{Zo:function(){return c},kt:function(){return d}});var t=r(7294);function i(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function o(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function a(e){for(var n=1;n=0||(i[r]=e[r]);return i}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var l=t.createContext({}),p=function(e){var n=t.useContext(l),r=n;return e&&(r="function"==typeof e?e(n):a(a({},n),e)),r},c=function(e){var n=p(e.components);return t.createElement(l.Provider,{value:n},e.children)},k={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},u=t.forwardRef((function(e,n){var r=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=p(r),d=i,m=u["".concat(l,".").concat(d)]||u[d]||k[d]||o;return r?t.createElement(m,a(a({ref:n},c),{},{components:r})):t.createElement(m,a({ref:n},c))}));function d(e,n){var r=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var o=r.length,a=new Array(o);a[0]=u;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:i,a[1]=s;for(var p=2;p child <"+("string"==typeof e.type?e.type:e.type.name)+'>: all children of the component should be , and every should have a unique "value" prop.')})),v=null!=T?T:P.map((function(e){var t=e.props;return{value:t.value,label:t.label,attributes:t.attributes}})),y=(0,i.l)(v,(function(e,t){return e.value===t.value}));if(y.length>0)throw new Error('Docusaurus error: Duplicate values "'+y.map((function(e){return e.value})).join(", ")+'" found in . Every value needs to be unique.');var q=null===m?m:null!=(t=null!=m?m:null==(n=P.find((function(e){return e.props.default})))?void 0:n.props.value)?t:P[0].props.value;if(null!==q&&!v.some((function(e){return e.value===q})))throw new Error('Docusaurus error: The has a defaultValue "'+q+'" but none of its children has the corresponding value. Available values are: '+v.map((function(e){return e.value})).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");var b=(0,s.U)(),S=b.tabGroupChoices,_=b.setTabGroupChoices,g=(0,l.useState)(q),h=g[0],f=g[1],R=[],C=(0,u.o5)().blockElementScrollPositionUntilNextRender;if(null!=N){var x=S[N];null!=x&&x!==h&&v.some((function(e){return e.value===x}))&&f(x)}var O=function(e){var t=e.currentTarget,n=R.indexOf(t),r=v[n].value;r!==h&&(C(t),f(r),null!=N&&_(N,String(r)))},w=function(e){var t,n=null;switch(e.key){case"ArrowRight":var r,l=R.indexOf(e.currentTarget)+1;n=null!=(r=R[l])?r:R[0];break;case"ArrowLeft":var o,a=R.indexOf(e.currentTarget)-1;n=null!=(o=R[a])?o:R[R.length-1]}null==(t=n)||t.focus()};return l.createElement("div",{className:(0,o.Z)("tabs-container",p)},l.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":d},k)},v.map((function(e){var t=e.value,n=e.label,a=e.attributes;return l.createElement("li",(0,r.Z)({role:"tab",tabIndex:h===t?0:-1,"aria-selected":h===t,key:t,ref:function(e){return R.push(e)},onKeyDown:w,onFocus:O,onClick:O},a,{className:(0,o.Z)("tabs__item",c,null==a?void 0:a.className,{"tabs__item--active":h===t})}),null!=n?n:t)}))),a?(0,l.cloneElement)(P.filter((function(e){return e.props.value===h}))[0],{className:"margin-top--md"}):l.createElement("div",{className:"margin-top--md"},P.map((function(e,t){return(0,l.cloneElement)(e,{key:t,hidden:e.props.value!==h})}))))}function m(e){var t=(0,a.Z)();return l.createElement(d,(0,r.Z)({key:String(t)},e))}},5906:function(e,t,n){n.r(t),n.d(t,{assets:function(){return d},contentTitle:function(){return p},default:function(){return N},frontMatter:function(){return u},metadata:function(){return c},toc:function(){return m}});var r=n(3117),l=n(102),o=(n(7294),n(3905)),a=(n(1402),n(5559)),i=n(433),s=["components"],u={id:"dbcontext-proc",title:"9.13 \u5b58\u50a8\u8fc7\u7a0b\u64cd\u4f5c",sidebar_label:"9.13 \u5b58\u50a8\u8fc7\u7a0b\u64cd\u4f5c"},p=void 0,c={unversionedId:"dbcontext-proc",id:"dbcontext-proc",title:"9.13 \u5b58\u50a8\u8fc7\u7a0b\u64cd\u4f5c",description:"\u63a8\u8350\u4f7f\u7528 \u300a9.17 Sql \u9ad8\u7ea7\u4ee3\u7406\u300b\u4ee3\u66ff\u672c\u7ae0\u8282\u529f\u80fd\u3002Sql \u9ad8\u7ea7\u4ee3\u7406 \u80fd\u591f\u63d0\u4f9b\u66f4\u5bb9\u6613\u4e14\u66f4\u6613\u7ef4\u62a4\u7684\u65b9\u5f0f\u3002",source:"@site/docs/dbcontext-proc.mdx",sourceDirName:".",slug:"/dbcontext-proc",permalink:"/furion/docs/dbcontext-proc",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-proc.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"dbcontext-proc",title:"9.13 \u5b58\u50a8\u8fc7\u7a0b\u64cd\u4f5c",sidebar_label:"9.13 \u5b58\u50a8\u8fc7\u7a0b\u64cd\u4f5c"},sidebar:"docs",previous:{title:"9.12 \u89c6\u56fe\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-view"},next:{title:"9.14 \u51fd\u6570\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-function"}},d={},m=[{value:"9.13.1 \u5173\u4e8e\u5b58\u50a8\u8fc7\u7a0b",id:"9131-\u5173\u4e8e\u5b58\u50a8\u8fc7\u7a0b",level:2},{value:"9.13.2.0 \u652f\u6301\u5b58\u50a8\u8fc7\u7a0b\u7684\u6570\u636e\u5e93",id:"91320-\u652f\u6301\u5b58\u50a8\u8fc7\u7a0b\u7684\u6570\u636e\u5e93",level:3},{value:"9.13.2 \u5b58\u50a8\u8fc7\u7a0b\u4f7f\u7528",id:"9132-\u5b58\u50a8\u8fc7\u7a0b\u4f7f\u7528",level:2},{value:"9.13.2.1 \u521d\u59cb\u5316\u65b9\u5f0f",id:"91321-\u521d\u59cb\u5316\u65b9\u5f0f",level:3},{value:"9.13.2.2 \u8fd4\u56de DataTable",id:"91322-\u8fd4\u56de-datatable",level:3},{value:"9.13.2.3 \u8fd4\u56de DataSet",id:"91323-\u8fd4\u56de-dataset",level:3},{value:"9.13.2.4 \u8fd4\u56de List<T>",id:"91324-\u8fd4\u56de-listt",level:3},{value:"9.13.2.5 \u8fd4\u56de Tuple<T1,...T8>",id:"91325-\u8fd4\u56de-tuplet1t8",level:3},{value:"9.13.2.6 \u8fd4\u56de \u5355\u884c\u5355\u5217 object",id:"91326-\u8fd4\u56de-\u5355\u884c\u5355\u5217-object",level:3},{value:"9.13.2.7 \u8fd4\u56de \u5355\u884c\u5355\u5217 <T>",id:"91327-\u8fd4\u56de-\u5355\u884c\u5355\u5217-t",level:3},{value:"9.13.2.8 \u6267\u884c\u4f46\u65e0\u8fd4\u56de",id:"91328-\u6267\u884c\u4f46\u65e0\u8fd4\u56de",level:3},{value:"9.13.3 \u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b",id:"9133-\u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b",level:2},{value:"9.13.3.1 \u521b\u5efa\u53c2\u6570\u6a21\u578b",id:"91331-\u521b\u5efa\u53c2\u6570\u6a21\u578b",level:3},{value:"9.13.3.2 \u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b",id:"91332-\u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b",level:3},{value:"9.13.3 \u5173\u4e8e [DbParameter]",id:"9133-\u5173\u4e8e-dbparameter",level:2},{value:"9.13.4 \u5173\u4e8e ProcedureOutputResult",id:"9134-\u5173\u4e8e-procedureoutputresult",level:2},{value:"9.13.5 \u5b58\u50a8\u8fc7\u7a0b\u53c2\u6570",id:"9135-\u5b58\u50a8\u8fc7\u7a0b\u53c2\u6570",level:2},{value:"9.13.6 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9136-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],T={toc:m};function N(e){var t=e.components,n=(0,l.Z)(e,s);return(0,o.kt)("wrapper",(0,r.Z)({},T,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{title:"\u6e29\u99a8\u63d0\u793a",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u4f7f\u7528 \u300a",(0,o.kt)("a",{parentName:"p",href:"/furion/docs/dbcontext-sql-proxy"},"9.17 Sql \u9ad8\u7ea7\u4ee3\u7406"),"\u300b\u4ee3\u66ff\u672c\u7ae0\u8282\u529f\u80fd\u3002",(0,o.kt)("inlineCode",{parentName:"p"},"Sql \u9ad8\u7ea7\u4ee3\u7406")," \u80fd\u591f\u63d0\u4f9b\u66f4\u5bb9\u6613\u4e14\u66f4\u6613\u7ef4\u62a4\u7684\u65b9\u5f0f\u3002")),(0,o.kt)("h2",{id:"9131-\u5173\u4e8e\u5b58\u50a8\u8fc7\u7a0b"},"9.13.1 \u5173\u4e8e\u5b58\u50a8\u8fc7\u7a0b"),(0,o.kt)("p",null,"\u5f15\u7528\u767e\u5ea6\u767e\u79d1\uff1a"),(0,o.kt)("blockquote",null,(0,o.kt)("p",{parentName:"blockquote"},"\u5b58\u50a8\u8fc7\u7a0b\uff08Stored Procedure\uff09\u662f\u5728\u5927\u578b\u6570\u636e\u5e93\u7cfb\u7edf\u4e2d\uff0c\u4e00\u7ec4\u4e3a\u4e86\u5b8c\u6210\u7279\u5b9a\u529f\u80fd\u7684 SQL \u8bed\u53e5\u96c6\uff0c\u5b83\u5b58\u50a8\u5728\u6570\u636e\u5e93\u4e2d\uff0c\u4e00\u6b21\u7f16\u8bd1\u540e\u6c38\u4e45\u6709\u6548\uff0c\u7528\u6237\u901a\u8fc7\u6307\u5b9a\u5b58\u50a8\u8fc7\u7a0b\u7684\u540d\u5b57\u5e76\u7ed9\u51fa\u53c2\u6570\uff08\u5982\u679c\u8be5\u5b58\u50a8\u8fc7\u7a0b\u5e26\u6709\u53c2\u6570\uff09\u6765\u6267\u884c\u5b83\u3002"),(0,o.kt)("p",{parentName:"blockquote"},"\u5b58\u50a8\u8fc7\u7a0b\u662f\u6570\u636e\u5e93\u4e2d\u7684\u4e00\u4e2a\u91cd\u8981\u5bf9\u8c61\u3002\u5728\u6570\u636e\u91cf\u7279\u522b\u5e9e\u5927\u7684\u60c5\u51b5\u4e0b\u5229\u7528\u5b58\u50a8\u8fc7\u7a0b\u80fd\u8fbe\u5230\u500d\u901f\u7684\u6548\u7387\u63d0\u5347\u3002")),(0,o.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u5b58\u50a8\u8fc7\u7a0b\u5c31\u662f\u5173\u7cfb\u578b\u6570\u636e\u5e93\u4e2d\uff08",(0,o.kt)("inlineCode",{parentName:"p"},"Sqlite")," \u9664\u5916\uff09\u4e2d\u7f16\u5199\u903b\u8f91\u7684\u51fd\u6570/\u65b9\u6cd5\uff0c\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\uff0c\u53ef\u4ee5\u5c06 ",(0,o.kt)("inlineCode",{parentName:"p"},"sql")," \u7f16\u8bd1\u7f13\u5b58\u8d77\u6765\uff0c\u5927\u5927\u63d0\u9ad8\u5b58\u50a8\u8fc7\u7a0b\u7684\u6267\u884c\u6548\u7387\u3002"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u8fd9\u91cc\u4e0d\u8ba8\u8bba\u5b58\u50a8\u8fc7\u7a0b\u7684\u4f18\u7f3a\u70b9\u3002")),(0,o.kt)("h3",{id:"91320-\u652f\u6301\u5b58\u50a8\u8fc7\u7a0b\u7684\u6570\u636e\u5e93"},"9.13.2.0 \u652f\u6301\u5b58\u50a8\u8fc7\u7a0b\u7684\u6570\u636e\u5e93"),(0,o.kt)("table",null,(0,o.kt)("thead",{parentName:"table"},(0,o.kt)("tr",{parentName:"thead"},(0,o.kt)("th",{parentName:"tr",align:null},"SqlServer"),(0,o.kt)("th",{parentName:"tr",align:null},"Sqlite"),(0,o.kt)("th",{parentName:"tr",align:null},"Cosmos"),(0,o.kt)("th",{parentName:"tr",align:null},"InMemoryDatabase"),(0,o.kt)("th",{parentName:"tr",align:null},"MySql"),(0,o.kt)("th",{parentName:"tr",align:null},"PostgreSQL"),(0,o.kt)("th",{parentName:"tr",align:null},"Oracle"),(0,o.kt)("th",{parentName:"tr",align:null},"Firebird"),(0,o.kt)("th",{parentName:"tr",align:null},"Dm"))),(0,o.kt)("tbody",{parentName:"table"},(0,o.kt)("tr",{parentName:"tbody"},(0,o.kt)("td",{parentName:"tr",align:null},"\u2714"),(0,o.kt)("td",{parentName:"tr",align:null}),(0,o.kt)("td",{parentName:"tr",align:null},"\u2714"),(0,o.kt)("td",{parentName:"tr",align:null}),(0,o.kt)("td",{parentName:"tr",align:null},"\u2714"),(0,o.kt)("td",{parentName:"tr",align:null},"\u2714"),(0,o.kt)("td",{parentName:"tr",align:null},"\u2714"),(0,o.kt)("td",{parentName:"tr",align:null},"\u2714"),(0,o.kt)("td",{parentName:"tr",align:null},"\u2714")))),(0,o.kt)("h2",{id:"9132-\u5b58\u50a8\u8fc7\u7a0b\u4f7f\u7528"},"9.13.2 \u5b58\u50a8\u8fc7\u7a0b\u4f7f\u7528"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u63d0\u4f9b\u4e86\u591a\u79cd\u5b58\u50a8\u8fc7\u7a0b\u64cd\u4f5c\u65b9\u5f0f\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ISqlRepository"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8\uff0c\u53ef\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"li"},"\u4f9d\u8d56\u6ce8\u5165")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ISqlDispatchProxy"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Sql")," \u4ee3\u7406\u65b9\u5f0f\uff08\u9ad8\u7ea7\u7528\u6cd5\uff0c\u63a8\u8350\uff09"),(0,o.kt)("li",{parentName:"ul"},"\u901a\u8fc7\u4efb\u610f\u5b9e\u4f53\u4ed3\u50a8\u64cd\u4f5c\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"personRepository.SqlProcedureQuery(procName)")),(0,o.kt)("li",{parentName:"ul"},"\u901a\u8fc7\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u6cd5\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"procName.SqlProcedureQuery()")),(0,o.kt)("li",{parentName:"ul"},"\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"li"},"repository.Sql().SqlProcedureQuery()")," \u65b9\u5f0f")),(0,o.kt)("h3",{id:"91321-\u521d\u59cb\u5316\u65b9\u5f0f"},"9.13.2.1 \u521d\u59cb\u5316\u65b9\u5f0f"),(0,o.kt)(a.Z,{defaultValue:"one",values:[{label:"ISqlRepository",value:"one"},{label:"ISqlDispatchProxy",value:"two"},{label:"\u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f",value:"three"},{label:"\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u5f0f",value:"four"}],mdxType:"Tabs"},(0,o.kt)(i.Z,{value:"one",mdxType:"TabItem"},(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,9-12}",showLineNumbers:!0,"":!0,"{1,9-12}":!0},"using Furion.DatabaseAccessor;\nusing Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [DynamicApiController]\n public class SqlService\n {\n private ISqlRepository _sqlRepository;\n public SqlService(ISqlRepository sqlRepository)\n {\n _sqlRepository = sqlRepository;\n }\n }\n}\n"))),(0,o.kt)(i.Z,{value:"two",mdxType:"TabItem"},(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,7,9-10}",showLineNumbers:!0,"":!0,"{2,7,9-10}":!0},'using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing System.Collections.Generic;\n\nnamespace Furion.Application\n{\n public interface ISqlExecuteProxy : ISqlDispatchProxy\n {\n [SqlProcedure("proc_GetPersons")]\n List GetPersons(string keyword);\n }\n}\n')),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9-12}",showLineNumbers:!0,"":!0,"{9-12}":!0},"using Furion.DatabaseAccessor;\nusing Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [DynamicApiController]\n public class SqlService\n {\n private ISqlExecuteProxy _sqlExecuteProxy;\n public SqlService(ISqlExecuteProxy sqlExecuteProxy)\n {\n _sqlExecuteProxy = sqlExecuteProxy;\n }\n }\n}\n"))),(0,o.kt)(i.Z,{value:"three",mdxType:"TabItem"},(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var persons = personRepository.SqlProcedureQuery("proc_GetPersons");\n'))),(0,o.kt)(i.Z,{value:"four",mdxType:"TabItem"},(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var persons = "proc_GetPersons".SqlProcedureQuery();\n')))),(0,o.kt)("h3",{id:"91322-\u8fd4\u56de-datatable"},"9.13.2.2 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"DataTable")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\nvar dataTable = _sqlRepository.SqlProcedureQuery("proc_GetPersons");\n\n// ISqlDispatchProxy \u65b9\u5f0f\nvar dataTable = _sqlExecuteProxy.GetPersons(); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\nvar dataTable = _personRepository.SqlProcedureQuery("proc_GetPersons");\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\nvar dataTable = _repository.Sql().SqlProcedureQuery("proc_GetPersons");\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\nvar dataTable = "proc_GetPersons".SqlProcedureQuery();\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h3",{id:"91323-\u8fd4\u56de-dataset"},"9.13.2.3 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"DataSet")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\nvar dataSet = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// ISqlDispatchProxy \u65b9\u5f0f\nvar dataSet = _sqlExecuteProxy.GetPersons(); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\nvar dataSet = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\nvar dataSet = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\nvar dataSet = "proc_GetPersons".SqlProcedureQueries();\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h3",{id:"91324-\u8fd4\u56de-listt"},"9.13.2.4 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"List")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\nvar list = _sqlRepository.SqlProcedureQuery("proc_GetPersons");\n\n// ISqlDispatchProxy \u65b9\u5f0f\nvar list = _sqlExecuteProxy.GetPersons(); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\nvar list = _personRepository.SqlProcedureQuery("proc_GetPersons");\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\nvar list = _repository.Sql().SqlProcedureQuery("proc_GetPersons");\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\nvar list = "proc_GetPersons".SqlProcedureQuery();\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h3",{id:"91325-\u8fd4\u56de-tuplet1t8"},"9.13.2.5 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"Tuple")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u5927\u5927\u5229\u7528\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"Tuple")," \u7684\u7279\u6027\uff0c\u5c06\u8fd4\u56de\u591a\u4e2a\u7ed3\u679c\u96c6\u8f6c\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"Tuple")," \u7c7b\u578b"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\n\n// \u8fd4\u56de\u4e00\u4e2a\u7ed3\u679c\u96c6\nvar list1 = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e24\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2) = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e09\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3) = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u56db\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4) = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e94\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5) = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u516d\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6) = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e03\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7) = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u516b\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7, list8) = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// ==================================\n\n// ISqlDispatchProxy \u65b9\u5f0f\uff0c\u63a8\u8350\u65b9\u5f0f\uff0c\u81ea\u52a8\u5904\u7406\u591a\u4e2a\u7ed3\u679c\u96c6\n\n// \u8fd4\u56de\u4e00\u4e2a\u7ed3\u679c\u96c6\nvar list1 = _sqlRepository.GetDatas();\n\n// \u8fd4\u56de\u4e24\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2) = _sqlRepository.GetDatas();\n\n// \u8fd4\u56de\u4e09\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3) = _sqlRepository.GetDatas();\n\n// \u8fd4\u56de\u56db\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4) = _sqlRepository.GetDatas();\n\n// \u8fd4\u56de\u4e94\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5) = _sqlRepository.GetDatas();\n\n// \u8fd4\u56de\u516d\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6) = _sqlRepository.GetDatas();\n\n// \u8fd4\u56de\u4e03\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7) = _sqlRepository.GetDatas();\n\n// \u8fd4\u56de\u516b\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7, list8) = _sqlRepository.GetDatas();\n\n// ==================================\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\n\n// \u8fd4\u56de\u4e00\u4e2a\u7ed3\u679c\u96c6\nvar list1 = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e24\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2) = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e09\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3) = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u56db\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4) = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e94\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5) = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u516d\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6) = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e03\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7) = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u516b\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7, list8) = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// ==================================\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\n\n// \u8fd4\u56de\u4e00\u4e2a\u7ed3\u679c\u96c6\nvar list1 = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e24\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2) = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e09\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3) = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u56db\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4) = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e94\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5) = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u516d\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6) = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e03\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7) = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u516b\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7, list8) = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// ==================================\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\n\n// \u8fd4\u56de\u4e00\u4e2a\u7ed3\u679c\u96c6\nvar list1 = "proc_GetPersons".SqlProcedureQueries();\n\n// \u8fd4\u56de\u4e24\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2) = "proc_GetPersons".SqlProcedureQueries();\n\n// \u8fd4\u56de\u4e09\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3) = "proc_GetPersons".SqlProcedureQueries();\n\n// \u8fd4\u56de\u56db\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4) = "proc_GetPersons".SqlProcedureQueries();\n\n// \u8fd4\u56de\u4e94\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5) = "proc_GetPersons".SqlProcedureQueries();\n\n// \u8fd4\u56de\u516d\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6) = "proc_GetPersons".SqlProcedureQueries();\n\n// \u8fd4\u56de\u4e03\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7) = "proc_GetPersons".SqlProcedureQueries();\n\n// \u8fd4\u56de\u516b\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7, list8) = "proc_GetPersons".SqlProcedureQueries();\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h3",{id:"91326-\u8fd4\u56de-\u5355\u884c\u5355\u5217-object"},"9.13.2.6 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"\u5355\u884c\u5355\u5217 object")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\nvar value = _sqlRepository.SqlProcedureScalar("proc_GetName");\n\n// ISqlDispatchProxy \u65b9\u5f0f\nvar value = _sqlExecuteProxy.GetName(); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\nvar value = _personRepository.SqlProcedureScalar("proc_GetName");\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\nvar value = _repository.Sql().SqlProcedureScalar("proc_GetName");\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\nvar value = "proc_GetName".SqlProcedureScalar();\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h3",{id:"91327-\u8fd4\u56de-\u5355\u884c\u5355\u5217-t"},"9.13.2.7 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"\u5355\u884c\u5355\u5217 ")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\nvar value = _sqlRepository.SqlProcedureScalar("proc_GetName");\n\n// ISqlDispatchProxy \u65b9\u5f0f\nvar value = _sqlExecuteProxy.GetName(); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\nvar value = _personRepository.SqlProcedureScalar("proc_GetName");\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\nvar value = _repository.Sql().SqlProcedureScalar("proc_GetName");\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\nvar value = "proc_GetName".SqlProcedureScalar();\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h3",{id:"91328-\u6267\u884c\u4f46\u65e0\u8fd4\u56de"},"9.13.2.8 \u6267\u884c\u4f46\u65e0\u8fd4\u56de"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\n_sqlRepository.SqlProcedureNonQuery("proc_UpdateData");\n\n// ISqlDispatchProxy \u65b9\u5f0f\n_sqlExecuteProxy.UpdateData(); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\n_personRepository.SqlProcedureNonQuery("proc_UpdateData");\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\n_repository.Sql().SqlProcedureNonQuery("proc_UpdateData");\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\n"proc_UpdateData".SqlProcedureNonQuery();\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h2",{id:"9133-\u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b"},"9.13.3 \u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b"),(0,o.kt)("p",null,"\u5728\u5b58\u50a8\u8fc7\u7a0b\u4e2d\uff0c\u6709\u4e00\u79cd\u4f8b\u5b50\u975e\u5e38\u590d\u6742\uff0c\u90a3\u5c31\u662f\u65e2\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"INPUT")," \u53c2\u6570\uff0c\u53c8\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"OUTPUT")," \u53c2\u6570\uff0c\u8fd8\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"RETURN")," \u53c2\u6570\uff0c\u540c\u65f6\u8fd8\u8f93\u51fa \u7ed3\u679c\u96c6 \ud83d\udca5\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sql",metastring:"showLineNumbers {3,4,10-12,15-17,22}",showLineNumbers:!0,"":!0,"{3,4,10-12,15-17,22}":!0},"CREATE PROC PROC_Output\n @Id INT, // \u8f93\u5165\u53c2\u6570\n @Name NVARCHAR(32) OUTPUT, // \u8f93\u51fa\u53c2\u6570\uff0c\u8fd8\u5e26\u957f\u5ea6\n @Age INT OUTPUT // \u8f93\u51fa\u53c2\u6570\nAS\nBEGIN\n SET @Name = 'Furion Output';\n\n // \u8f93\u51fa\u7ed3\u679c\u96c6\n SELECT *\n FROM dbo.Test\n WHERE Id > @Id;\n\n // \u8f93\u51fa\u7ed3\u679c\u96c6\n SELECT TOP 10\n *\n FROM dbo.Test;\n\n SET @Age = 27;\n\n // \u5e26 RETURN \u8fd4\u56de\n RETURN 10;\nEND;\n")),(0,o.kt)("h3",{id:"91331-\u521b\u5efa\u53c2\u6570\u6a21\u578b"},"9.13.3.1 \u521b\u5efa\u53c2\u6570\u6a21\u578b"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,10,13,16}",showLineNumbers:!0,"":!0,"{1,10,13,16}":!0},"using Furion.DatabaseAccessor;\nusing System.Data;\n\nnamespace Furion.Application\n{\n public class ProcOutputModel\n {\n public int Id { get; set; } // \u8f93\u5165\u53c2\u6570\n\n [DbParameter(ParameterDirection.Output, Size = 32)]\n public string Name { get; set; } // \u8f93\u51fa\u53c2\u6570\n\n [DbParameter(ParameterDirection.Output)]\n public int Age { get; set; } // \u8f93\u51fa\u53c2\u6570\n\n [DbParameter(ParameterDirection.ReturnValue)]\n public int ReturnValue { get; set; } // \u8fd4\u56de\u503c\n }\n}\n")),(0,o.kt)("h3",{id:"91332-\u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b"},"9.13.3.2 \u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"}," ",(0,o.kt)("inlineCode",{parentName:"strong"},"DataSet")," ")," \u65b9\u5f0f")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\nProcedureOutputResult result = _sqlRepository.SqlProcedureOutput("proc_Complex", new ProcOutputModel{});\n\n// ISqlDispatchProxy \u65b9\u5f0f\nProcedureOutputResult result = _sqlExecuteProxy.Complex(new ProcOutputModel{}); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\nProcedureOutputResult result = _personRepository.SqlProcedureOutput("proc_Complex", new ProcOutputModel{});\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\nProcedureOutputResult result = _repository.Sql().SqlProcedureOutput("proc_Complex", new ProcOutputModel{});\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\nProcedureOutputResult result = "proc_Complex".SqlProcedureOutput(new ProcOutputModel{});\n')),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u83b7\u53d6 OUTPUT \u53c2\u6570\u503c\nvar outputs = result.OutputValues;\n\n// \u83b7\u53d6 RETURN \u8fd4\u56de\u503c\nvar reval = result.ReturnValue;\n\n// \u83b7\u53d6\u8fd4\u56de\u7ed3\u679c\u96c6\nvar dataSet = result.Result;\n")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Tuple")," \u65b9\u5f0f")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\nProcedureOutputResult<(List, List)> result = _sqlRepository.SqlProcedureOutput<(List, List)>("proc_Complex", new ProcOutputModel{});\n\n// ISqlDispatchProxy \u65b9\u5f0f\nProcedureOutputResult<(List, List)> result = _sqlExecuteProxy.Complex(new ProcOutputModel{}); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\nProcedureOutputResult<(List, List)> result = _personRepository.SqlProcedureOutput<(List, List)>("proc_Complex", new ProcOutputModel{});\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\nProcedureOutputResult<(List, List)> result = _repository.Sql().SqlProcedureOutput<(List, List)>("proc_Complex", new ProcOutputModel{});\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\nProcedureOutputResult<(List, List)> result = "proc_Complex".SqlProcedureOutput<(List, List)>(new ProcOutputModel{});\n')),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u83b7\u53d6 OUTPUT \u53c2\u6570\u503c\nvar outputs = result.OutputValues;\n\n// \u83b7\u53d6 RETURN \u8fd4\u56de\u503c\nvar reval = result.ReturnValue;\n\n// \u83b7\u53d6\u8fd4\u56de\u7ed3\u679c\u96c6\nvar (list1,list2) = result.Result;\n")),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h2",{id:"9133-\u5173\u4e8e-dbparameter"},"9.13.3 \u5173\u4e8e ",(0,o.kt)("inlineCode",{parentName:"h2"},"[DbParameter]")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"[DbParameter]")," \u7279\u6027\u662f\u7528\u6765\u6807\u6ce8 ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql"),"\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"\u51fd\u6570"),"\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"\u5b58\u50a8\u8fc7\u7a0b")," \u53c2\u6570\u7684\uff0c\u53ef\u914d\u7f6e\u5c5e\u6027\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Direction"),"\uff1a\u8bbe\u7f6e\u53c2\u6570\u65b9\u5411\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"ParameterDirection")," \u679a\u4e3e\u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"ParameterDirection.Input")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"DbType"),"\uff1a\u8bbe\u7f6e\u53c2\u6570\u7c7b\u578b\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"DbType")," \u679a\u4e3e\u7c7b\u578b\uff0c\u65e0\u9ed8\u8ba4"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Size"),"\uff1a\u8bbe\u7f6e\u53c2\u6570\u957f\u5ea6\u7684\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"int")," \u7c7b\u578b")),(0,o.kt)("p",null,"\u5176\u4e2d ",(0,o.kt)("inlineCode",{parentName:"p"},"Direction")," \u5c5e\u6027\u662f\u9ed8\u8ba4\u6784\u9020\u51fd\u6570\u53c2\u6570\u3002"),(0,o.kt)("h2",{id:"9134-\u5173\u4e8e-procedureoutputresult"},"9.13.4 \u5173\u4e8e ",(0,o.kt)("inlineCode",{parentName:"h2"},"ProcedureOutputResult")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"ProcedureOutputResult")," \u548c ",(0,o.kt)("inlineCode",{parentName:"p"},"ProcedureOutputResult")," \u662f\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b\u6267\u884c\u8fd4\u56de\u6a21\u578b\u7c7b\uff0c\u6709\u4ee5\u4e0b\u5c5e\u6027\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"OutputValues"),"\uff1a\u591a\u4e2a\u8f93\u51fa\u503c\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"ProcedureOutputValue")," \u7c7b\u578b"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ReturnValue"),"\uff1a\u8fd4\u56de\u503c\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"object")," \u7c7b\u578b"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Result"),"\uff1a\u7ed3\u679c\u96c6\uff0c\u975e\u6cdb\u578b\u7248\u672c\u662f ",(0,o.kt)("inlineCode",{parentName:"li"},"DataSet"),"\u7c7b\u578b\uff0c\u5426\u5219\u662f \u6cdb\u578b\u7c7b\u578b")),(0,o.kt)("h2",{id:"9135-\u5b58\u50a8\u8fc7\u7a0b\u53c2\u6570"},"9.13.5 \u5b58\u50a8\u8fc7\u7a0b\u53c2\u6570"),(0,o.kt)("p",null,"\u6240\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"sql")," \u53c2\u6570\u90fd\u652f\u6301\u56db\u79cd\u65b9\u5f0f\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"DbParameter[]"),"\uff1a\u6570\u7ec4\u7c7b\u578b"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"new {}"),"\uff1a\u533f\u540d\u7c7b\u578b"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"new Class{}"),"\uff1a\u5f3a\u7c7b\u578b\u7c7b\u578b\uff08\u652f\u6301\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b\u53c2\u6570\uff09"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Dictionary")," \u7c7b\u578b")),(0,o.kt)("h2",{id:"9136-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.13.6 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}N.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return p},kt:function(){return m}});var r=n(7294);function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}var s=r.createContext({}),u=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p=function(e){var t=u(e.components);return r.createElement(s.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,l=e.mdxType,o=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),d=u(n),m=l,T=d["".concat(s,".").concat(m)]||d[m]||c[m]||o;return n?r.createElement(T,a(a({ref:t},p),{},{components:n})):r.createElement(T,a({ref:t},p))}));function m(e,t){var n=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var o=n.length,a=new Array(o);a[0]=d;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:l,a[1]=i;for(var u=2;u=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}var s=r.createContext({}),u=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p=function(e){var t=u(e.components);return r.createElement(s.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,l=e.mdxType,o=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),d=u(n),m=l,T=d["".concat(s,".").concat(m)]||d[m]||c[m]||o;return n?r.createElement(T,a(a({ref:t},p),{},{components:n})):r.createElement(T,a({ref:t},p))}));function m(e,t){var n=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var o=n.length,a=new Array(o);a[0]=d;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:l,a[1]=i;for(var u=2;u child <"+("string"==typeof e.type?e.type:e.type.name)+'>: all children of the component should be , and every should have a unique "value" prop.')})),v=null!=T?T:P.map((function(e){var t=e.props;return{value:t.value,label:t.label,attributes:t.attributes}})),y=(0,i.l)(v,(function(e,t){return e.value===t.value}));if(y.length>0)throw new Error('Docusaurus error: Duplicate values "'+y.map((function(e){return e.value})).join(", ")+'" found in . Every value needs to be unique.');var q=null===m?m:null!=(t=null!=m?m:null==(n=P.find((function(e){return e.props.default})))?void 0:n.props.value)?t:P[0].props.value;if(null!==q&&!v.some((function(e){return e.value===q})))throw new Error('Docusaurus error: The has a defaultValue "'+q+'" but none of its children has the corresponding value. Available values are: '+v.map((function(e){return e.value})).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");var b=(0,s.U)(),S=b.tabGroupChoices,_=b.setTabGroupChoices,g=(0,l.useState)(q),h=g[0],f=g[1],R=[],C=(0,u.o5)().blockElementScrollPositionUntilNextRender;if(null!=N){var x=S[N];null!=x&&x!==h&&v.some((function(e){return e.value===x}))&&f(x)}var O=function(e){var t=e.currentTarget,n=R.indexOf(t),r=v[n].value;r!==h&&(C(t),f(r),null!=N&&_(N,String(r)))},w=function(e){var t,n=null;switch(e.key){case"ArrowRight":var r,l=R.indexOf(e.currentTarget)+1;n=null!=(r=R[l])?r:R[0];break;case"ArrowLeft":var o,a=R.indexOf(e.currentTarget)-1;n=null!=(o=R[a])?o:R[R.length-1]}null==(t=n)||t.focus()};return l.createElement("div",{className:(0,o.Z)("tabs-container",p)},l.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":d},k)},v.map((function(e){var t=e.value,n=e.label,a=e.attributes;return l.createElement("li",(0,r.Z)({role:"tab",tabIndex:h===t?0:-1,"aria-selected":h===t,key:t,ref:function(e){return R.push(e)},onKeyDown:w,onFocus:O,onClick:O},a,{className:(0,o.Z)("tabs__item",c,null==a?void 0:a.className,{"tabs__item--active":h===t})}),null!=n?n:t)}))),a?(0,l.cloneElement)(P.filter((function(e){return e.props.value===h}))[0],{className:"margin-top--md"}):l.createElement("div",{className:"margin-top--md"},P.map((function(e,t){return(0,l.cloneElement)(e,{key:t,hidden:e.props.value!==h})}))))}function m(e){var t=(0,a.Z)();return l.createElement(d,(0,r.Z)({key:String(t)},e))}},2746:function(e,t,n){n.r(t),n.d(t,{assets:function(){return d},contentTitle:function(){return p},default:function(){return N},frontMatter:function(){return u},metadata:function(){return c},toc:function(){return m}});var r=n(3117),l=n(102),o=(n(7294),n(3905)),a=(n(4996),n(5488)),i=n(5162),s=["components"],u={id:"dbcontext-proc",title:"9.13 \u5b58\u50a8\u8fc7\u7a0b\u64cd\u4f5c",sidebar_label:"9.13 \u5b58\u50a8\u8fc7\u7a0b\u64cd\u4f5c"},p=void 0,c={unversionedId:"dbcontext-proc",id:"dbcontext-proc",title:"9.13 \u5b58\u50a8\u8fc7\u7a0b\u64cd\u4f5c",description:"\u63a8\u8350\u4f7f\u7528 \u300a9.17 Sql \u9ad8\u7ea7\u4ee3\u7406\u300b\u4ee3\u66ff\u672c\u7ae0\u8282\u529f\u80fd\u3002Sql \u9ad8\u7ea7\u4ee3\u7406 \u80fd\u591f\u63d0\u4f9b\u66f4\u5bb9\u6613\u4e14\u66f4\u6613\u7ef4\u62a4\u7684\u65b9\u5f0f\u3002",source:"@site/docs/dbcontext-proc.mdx",sourceDirName:".",slug:"/dbcontext-proc",permalink:"/furion/docs/dbcontext-proc",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-proc.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"dbcontext-proc",title:"9.13 \u5b58\u50a8\u8fc7\u7a0b\u64cd\u4f5c",sidebar_label:"9.13 \u5b58\u50a8\u8fc7\u7a0b\u64cd\u4f5c"},sidebar:"docs",previous:{title:"9.12 \u89c6\u56fe\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-view"},next:{title:"9.14 \u51fd\u6570\u64cd\u4f5c",permalink:"/furion/docs/dbcontext-function"}},d={},m=[{value:"9.13.1 \u5173\u4e8e\u5b58\u50a8\u8fc7\u7a0b",id:"9131-\u5173\u4e8e\u5b58\u50a8\u8fc7\u7a0b",level:2},{value:"9.13.2.0 \u652f\u6301\u5b58\u50a8\u8fc7\u7a0b\u7684\u6570\u636e\u5e93",id:"91320-\u652f\u6301\u5b58\u50a8\u8fc7\u7a0b\u7684\u6570\u636e\u5e93",level:3},{value:"9.13.2 \u5b58\u50a8\u8fc7\u7a0b\u4f7f\u7528",id:"9132-\u5b58\u50a8\u8fc7\u7a0b\u4f7f\u7528",level:2},{value:"9.13.2.1 \u521d\u59cb\u5316\u65b9\u5f0f",id:"91321-\u521d\u59cb\u5316\u65b9\u5f0f",level:3},{value:"9.13.2.2 \u8fd4\u56de DataTable",id:"91322-\u8fd4\u56de-datatable",level:3},{value:"9.13.2.3 \u8fd4\u56de DataSet",id:"91323-\u8fd4\u56de-dataset",level:3},{value:"9.13.2.4 \u8fd4\u56de List<T>",id:"91324-\u8fd4\u56de-listt",level:3},{value:"9.13.2.5 \u8fd4\u56de Tuple<T1,...T8>",id:"91325-\u8fd4\u56de-tuplet1t8",level:3},{value:"9.13.2.6 \u8fd4\u56de \u5355\u884c\u5355\u5217 object",id:"91326-\u8fd4\u56de-\u5355\u884c\u5355\u5217-object",level:3},{value:"9.13.2.7 \u8fd4\u56de \u5355\u884c\u5355\u5217 <T>",id:"91327-\u8fd4\u56de-\u5355\u884c\u5355\u5217-t",level:3},{value:"9.13.2.8 \u6267\u884c\u4f46\u65e0\u8fd4\u56de",id:"91328-\u6267\u884c\u4f46\u65e0\u8fd4\u56de",level:3},{value:"9.13.3 \u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b",id:"9133-\u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b",level:2},{value:"9.13.3.1 \u521b\u5efa\u53c2\u6570\u6a21\u578b",id:"91331-\u521b\u5efa\u53c2\u6570\u6a21\u578b",level:3},{value:"9.13.3.2 \u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b",id:"91332-\u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b",level:3},{value:"9.13.3 \u5173\u4e8e [DbParameter]",id:"9133-\u5173\u4e8e-dbparameter",level:2},{value:"9.13.4 \u5173\u4e8e ProcedureOutputResult",id:"9134-\u5173\u4e8e-procedureoutputresult",level:2},{value:"9.13.5 \u5b58\u50a8\u8fc7\u7a0b\u53c2\u6570",id:"9135-\u5b58\u50a8\u8fc7\u7a0b\u53c2\u6570",level:2},{value:"9.13.6 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9136-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],T={toc:m};function N(e){var t=e.components,n=(0,l.Z)(e,s);return(0,o.kt)("wrapper",(0,r.Z)({},T,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{title:"\u6e29\u99a8\u63d0\u793a",type:"important"},(0,o.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u4f7f\u7528 \u300a",(0,o.kt)("a",{parentName:"p",href:"/furion/docs/dbcontext-sql-proxy"},"9.17 Sql \u9ad8\u7ea7\u4ee3\u7406"),"\u300b\u4ee3\u66ff\u672c\u7ae0\u8282\u529f\u80fd\u3002",(0,o.kt)("inlineCode",{parentName:"p"},"Sql \u9ad8\u7ea7\u4ee3\u7406")," \u80fd\u591f\u63d0\u4f9b\u66f4\u5bb9\u6613\u4e14\u66f4\u6613\u7ef4\u62a4\u7684\u65b9\u5f0f\u3002")),(0,o.kt)("h2",{id:"9131-\u5173\u4e8e\u5b58\u50a8\u8fc7\u7a0b"},"9.13.1 \u5173\u4e8e\u5b58\u50a8\u8fc7\u7a0b"),(0,o.kt)("p",null,"\u5f15\u7528\u767e\u5ea6\u767e\u79d1\uff1a"),(0,o.kt)("blockquote",null,(0,o.kt)("p",{parentName:"blockquote"},"\u5b58\u50a8\u8fc7\u7a0b\uff08Stored Procedure\uff09\u662f\u5728\u5927\u578b\u6570\u636e\u5e93\u7cfb\u7edf\u4e2d\uff0c\u4e00\u7ec4\u4e3a\u4e86\u5b8c\u6210\u7279\u5b9a\u529f\u80fd\u7684 SQL \u8bed\u53e5\u96c6\uff0c\u5b83\u5b58\u50a8\u5728\u6570\u636e\u5e93\u4e2d\uff0c\u4e00\u6b21\u7f16\u8bd1\u540e\u6c38\u4e45\u6709\u6548\uff0c\u7528\u6237\u901a\u8fc7\u6307\u5b9a\u5b58\u50a8\u8fc7\u7a0b\u7684\u540d\u5b57\u5e76\u7ed9\u51fa\u53c2\u6570\uff08\u5982\u679c\u8be5\u5b58\u50a8\u8fc7\u7a0b\u5e26\u6709\u53c2\u6570\uff09\u6765\u6267\u884c\u5b83\u3002"),(0,o.kt)("p",{parentName:"blockquote"},"\u5b58\u50a8\u8fc7\u7a0b\u662f\u6570\u636e\u5e93\u4e2d\u7684\u4e00\u4e2a\u91cd\u8981\u5bf9\u8c61\u3002\u5728\u6570\u636e\u91cf\u7279\u522b\u5e9e\u5927\u7684\u60c5\u51b5\u4e0b\u5229\u7528\u5b58\u50a8\u8fc7\u7a0b\u80fd\u8fbe\u5230\u500d\u901f\u7684\u6548\u7387\u63d0\u5347\u3002")),(0,o.kt)("p",null,"\u7b80\u5355\u6765\u8bf4\uff0c\u5b58\u50a8\u8fc7\u7a0b\u5c31\u662f\u5173\u7cfb\u578b\u6570\u636e\u5e93\u4e2d\uff08",(0,o.kt)("inlineCode",{parentName:"p"},"Sqlite")," \u9664\u5916\uff09\u4e2d\u7f16\u5199\u903b\u8f91\u7684\u51fd\u6570/\u65b9\u6cd5\uff0c\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\uff0c\u53ef\u4ee5\u5c06 ",(0,o.kt)("inlineCode",{parentName:"p"},"sql")," \u7f16\u8bd1\u7f13\u5b58\u8d77\u6765\uff0c\u5927\u5927\u63d0\u9ad8\u5b58\u50a8\u8fc7\u7a0b\u7684\u6267\u884c\u6548\u7387\u3002"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"\u8fd9\u91cc\u4e0d\u8ba8\u8bba\u5b58\u50a8\u8fc7\u7a0b\u7684\u4f18\u7f3a\u70b9\u3002")),(0,o.kt)("h3",{id:"91320-\u652f\u6301\u5b58\u50a8\u8fc7\u7a0b\u7684\u6570\u636e\u5e93"},"9.13.2.0 \u652f\u6301\u5b58\u50a8\u8fc7\u7a0b\u7684\u6570\u636e\u5e93"),(0,o.kt)("table",null,(0,o.kt)("thead",{parentName:"table"},(0,o.kt)("tr",{parentName:"thead"},(0,o.kt)("th",{parentName:"tr",align:null},"SqlServer"),(0,o.kt)("th",{parentName:"tr",align:null},"Sqlite"),(0,o.kt)("th",{parentName:"tr",align:null},"Cosmos"),(0,o.kt)("th",{parentName:"tr",align:null},"InMemoryDatabase"),(0,o.kt)("th",{parentName:"tr",align:null},"MySql"),(0,o.kt)("th",{parentName:"tr",align:null},"PostgreSQL"),(0,o.kt)("th",{parentName:"tr",align:null},"Oracle"),(0,o.kt)("th",{parentName:"tr",align:null},"Firebird"),(0,o.kt)("th",{parentName:"tr",align:null},"Dm"))),(0,o.kt)("tbody",{parentName:"table"},(0,o.kt)("tr",{parentName:"tbody"},(0,o.kt)("td",{parentName:"tr",align:null},"\u2714"),(0,o.kt)("td",{parentName:"tr",align:null}),(0,o.kt)("td",{parentName:"tr",align:null},"\u2714"),(0,o.kt)("td",{parentName:"tr",align:null}),(0,o.kt)("td",{parentName:"tr",align:null},"\u2714"),(0,o.kt)("td",{parentName:"tr",align:null},"\u2714"),(0,o.kt)("td",{parentName:"tr",align:null},"\u2714"),(0,o.kt)("td",{parentName:"tr",align:null},"\u2714"),(0,o.kt)("td",{parentName:"tr",align:null},"\u2714")))),(0,o.kt)("h2",{id:"9132-\u5b58\u50a8\u8fc7\u7a0b\u4f7f\u7528"},"9.13.2 \u5b58\u50a8\u8fc7\u7a0b\u4f7f\u7528"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u63d0\u4f9b\u4e86\u591a\u79cd\u5b58\u50a8\u8fc7\u7a0b\u64cd\u4f5c\u65b9\u5f0f\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ISqlRepository"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\u4ed3\u50a8\uff0c\u53ef\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"li"},"\u4f9d\u8d56\u6ce8\u5165")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ISqlDispatchProxy"),"\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"Sql")," \u4ee3\u7406\u65b9\u5f0f\uff08\u9ad8\u7ea7\u7528\u6cd5\uff0c\u63a8\u8350\uff09"),(0,o.kt)("li",{parentName:"ul"},"\u901a\u8fc7\u4efb\u610f\u5b9e\u4f53\u4ed3\u50a8\u64cd\u4f5c\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"personRepository.SqlProcedureQuery(procName)")),(0,o.kt)("li",{parentName:"ul"},"\u901a\u8fc7\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u6cd5\uff1a",(0,o.kt)("inlineCode",{parentName:"li"},"procName.SqlProcedureQuery()")),(0,o.kt)("li",{parentName:"ul"},"\u901a\u8fc7 ",(0,o.kt)("inlineCode",{parentName:"li"},"repository.Sql().SqlProcedureQuery()")," \u65b9\u5f0f")),(0,o.kt)("h3",{id:"91321-\u521d\u59cb\u5316\u65b9\u5f0f"},"9.13.2.1 \u521d\u59cb\u5316\u65b9\u5f0f"),(0,o.kt)(a.Z,{defaultValue:"one",values:[{label:"ISqlRepository",value:"one"},{label:"ISqlDispatchProxy",value:"two"},{label:"\u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f",value:"three"},{label:"\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u5f0f",value:"four"}],mdxType:"Tabs"},(0,o.kt)(i.Z,{value:"one",mdxType:"TabItem"},(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,9-12}",showLineNumbers:!0,"":!0,"{1,9-12}":!0},"using Furion.DatabaseAccessor;\nusing Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [DynamicApiController]\n public class SqlService\n {\n private ISqlRepository _sqlRepository;\n public SqlService(ISqlRepository sqlRepository)\n {\n _sqlRepository = sqlRepository;\n }\n }\n}\n"))),(0,o.kt)(i.Z,{value:"two",mdxType:"TabItem"},(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,7,9-10}",showLineNumbers:!0,"":!0,"{2,7,9-10}":!0},'using Furion.Core;\nusing Furion.DatabaseAccessor;\nusing System.Collections.Generic;\n\nnamespace Furion.Application\n{\n public interface ISqlExecuteProxy : ISqlDispatchProxy\n {\n [SqlProcedure("proc_GetPersons")]\n List GetPersons(string keyword);\n }\n}\n')),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9-12}",showLineNumbers:!0,"":!0,"{9-12}":!0},"using Furion.DatabaseAccessor;\nusing Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [DynamicApiController]\n public class SqlService\n {\n private ISqlExecuteProxy _sqlExecuteProxy;\n public SqlService(ISqlExecuteProxy sqlExecuteProxy)\n {\n _sqlExecuteProxy = sqlExecuteProxy;\n }\n }\n}\n"))),(0,o.kt)(i.Z,{value:"three",mdxType:"TabItem"},(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var persons = personRepository.SqlProcedureQuery("proc_GetPersons");\n'))),(0,o.kt)(i.Z,{value:"four",mdxType:"TabItem"},(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var persons = "proc_GetPersons".SqlProcedureQuery();\n')))),(0,o.kt)("h3",{id:"91322-\u8fd4\u56de-datatable"},"9.13.2.2 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"DataTable")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\nvar dataTable = _sqlRepository.SqlProcedureQuery("proc_GetPersons");\n\n// ISqlDispatchProxy \u65b9\u5f0f\nvar dataTable = _sqlExecuteProxy.GetPersons(); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\nvar dataTable = _personRepository.SqlProcedureQuery("proc_GetPersons");\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\nvar dataTable = _repository.Sql().SqlProcedureQuery("proc_GetPersons");\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\nvar dataTable = "proc_GetPersons".SqlProcedureQuery();\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h3",{id:"91323-\u8fd4\u56de-dataset"},"9.13.2.3 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"DataSet")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\nvar dataSet = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// ISqlDispatchProxy \u65b9\u5f0f\nvar dataSet = _sqlExecuteProxy.GetPersons(); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\nvar dataSet = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\nvar dataSet = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\nvar dataSet = "proc_GetPersons".SqlProcedureQueries();\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h3",{id:"91324-\u8fd4\u56de-listt"},"9.13.2.4 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"List")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\nvar list = _sqlRepository.SqlProcedureQuery("proc_GetPersons");\n\n// ISqlDispatchProxy \u65b9\u5f0f\nvar list = _sqlExecuteProxy.GetPersons(); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\nvar list = _personRepository.SqlProcedureQuery("proc_GetPersons");\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\nvar list = _repository.Sql().SqlProcedureQuery("proc_GetPersons");\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\nvar list = "proc_GetPersons".SqlProcedureQuery();\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h3",{id:"91325-\u8fd4\u56de-tuplet1t8"},"9.13.2.5 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"Tuple")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u5927\u5927\u5229\u7528\u4e86 ",(0,o.kt)("inlineCode",{parentName:"p"},"Tuple")," \u7684\u7279\u6027\uff0c\u5c06\u8fd4\u56de\u591a\u4e2a\u7ed3\u679c\u96c6\u8f6c\u6210 ",(0,o.kt)("inlineCode",{parentName:"p"},"Tuple")," \u7c7b\u578b"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\n\n// \u8fd4\u56de\u4e00\u4e2a\u7ed3\u679c\u96c6\nvar list1 = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e24\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2) = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e09\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3) = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u56db\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4) = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e94\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5) = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u516d\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6) = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e03\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7) = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u516b\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7, list8) = _sqlRepository.SqlProcedureQueries("proc_GetPersons");\n\n// ==================================\n\n// ISqlDispatchProxy \u65b9\u5f0f\uff0c\u63a8\u8350\u65b9\u5f0f\uff0c\u81ea\u52a8\u5904\u7406\u591a\u4e2a\u7ed3\u679c\u96c6\n\n// \u8fd4\u56de\u4e00\u4e2a\u7ed3\u679c\u96c6\nvar list1 = _sqlRepository.GetDatas();\n\n// \u8fd4\u56de\u4e24\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2) = _sqlRepository.GetDatas();\n\n// \u8fd4\u56de\u4e09\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3) = _sqlRepository.GetDatas();\n\n// \u8fd4\u56de\u56db\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4) = _sqlRepository.GetDatas();\n\n// \u8fd4\u56de\u4e94\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5) = _sqlRepository.GetDatas();\n\n// \u8fd4\u56de\u516d\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6) = _sqlRepository.GetDatas();\n\n// \u8fd4\u56de\u4e03\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7) = _sqlRepository.GetDatas();\n\n// \u8fd4\u56de\u516b\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7, list8) = _sqlRepository.GetDatas();\n\n// ==================================\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\n\n// \u8fd4\u56de\u4e00\u4e2a\u7ed3\u679c\u96c6\nvar list1 = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e24\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2) = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e09\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3) = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u56db\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4) = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e94\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5) = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u516d\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6) = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e03\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7) = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u516b\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7, list8) = _personRepository.SqlProcedureQueries("proc_GetPersons");\n\n// ==================================\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\n\n// \u8fd4\u56de\u4e00\u4e2a\u7ed3\u679c\u96c6\nvar list1 = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e24\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2) = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e09\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3) = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u56db\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4) = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e94\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5) = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u516d\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6) = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u4e03\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7) = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// \u8fd4\u56de\u516b\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7, list8) = _repository.Sql().SqlProcedureQueries("proc_GetPersons");\n\n// ==================================\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\n\n// \u8fd4\u56de\u4e00\u4e2a\u7ed3\u679c\u96c6\nvar list1 = "proc_GetPersons".SqlProcedureQueries();\n\n// \u8fd4\u56de\u4e24\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2) = "proc_GetPersons".SqlProcedureQueries();\n\n// \u8fd4\u56de\u4e09\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3) = "proc_GetPersons".SqlProcedureQueries();\n\n// \u8fd4\u56de\u56db\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4) = "proc_GetPersons".SqlProcedureQueries();\n\n// \u8fd4\u56de\u4e94\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5) = "proc_GetPersons".SqlProcedureQueries();\n\n// \u8fd4\u56de\u516d\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6) = "proc_GetPersons".SqlProcedureQueries();\n\n// \u8fd4\u56de\u4e03\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7) = "proc_GetPersons".SqlProcedureQueries();\n\n// \u8fd4\u56de\u516b\u4e2a\u7ed3\u679c\u96c6\nvar (list1, list2, list3, list4, list5, list6, list7, list8) = "proc_GetPersons".SqlProcedureQueries();\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h3",{id:"91326-\u8fd4\u56de-\u5355\u884c\u5355\u5217-object"},"9.13.2.6 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"\u5355\u884c\u5355\u5217 object")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\nvar value = _sqlRepository.SqlProcedureScalar("proc_GetName");\n\n// ISqlDispatchProxy \u65b9\u5f0f\nvar value = _sqlExecuteProxy.GetName(); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\nvar value = _personRepository.SqlProcedureScalar("proc_GetName");\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\nvar value = _repository.Sql().SqlProcedureScalar("proc_GetName");\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\nvar value = "proc_GetName".SqlProcedureScalar();\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h3",{id:"91327-\u8fd4\u56de-\u5355\u884c\u5355\u5217-t"},"9.13.2.7 \u8fd4\u56de ",(0,o.kt)("inlineCode",{parentName:"h3"},"\u5355\u884c\u5355\u5217 ")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\nvar value = _sqlRepository.SqlProcedureScalar("proc_GetName");\n\n// ISqlDispatchProxy \u65b9\u5f0f\nvar value = _sqlExecuteProxy.GetName(); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\nvar value = _personRepository.SqlProcedureScalar("proc_GetName");\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\nvar value = _repository.Sql().SqlProcedureScalar("proc_GetName");\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\nvar value = "proc_GetName".SqlProcedureScalar();\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h3",{id:"91328-\u6267\u884c\u4f46\u65e0\u8fd4\u56de"},"9.13.2.8 \u6267\u884c\u4f46\u65e0\u8fd4\u56de"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\n_sqlRepository.SqlProcedureNonQuery("proc_UpdateData");\n\n// ISqlDispatchProxy \u65b9\u5f0f\n_sqlExecuteProxy.UpdateData(); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\n_personRepository.SqlProcedureNonQuery("proc_UpdateData");\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\n_repository.Sql().SqlProcedureNonQuery("proc_UpdateData");\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\n"proc_UpdateData".SqlProcedureNonQuery();\n')),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h2",{id:"9133-\u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b"},"9.13.3 \u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b"),(0,o.kt)("p",null,"\u5728\u5b58\u50a8\u8fc7\u7a0b\u4e2d\uff0c\u6709\u4e00\u79cd\u4f8b\u5b50\u975e\u5e38\u590d\u6742\uff0c\u90a3\u5c31\u662f\u65e2\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"INPUT")," \u53c2\u6570\uff0c\u53c8\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"OUTPUT")," \u53c2\u6570\uff0c\u8fd8\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"RETURN")," \u53c2\u6570\uff0c\u540c\u65f6\u8fd8\u8f93\u51fa \u7ed3\u679c\u96c6 \ud83d\udca5\uff0c\u5982\uff1a"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sql",metastring:"showLineNumbers {3,4,10-12,15-17,22}",showLineNumbers:!0,"":!0,"{3,4,10-12,15-17,22}":!0},"CREATE PROC PROC_Output\n @Id INT, // \u8f93\u5165\u53c2\u6570\n @Name NVARCHAR(32) OUTPUT, // \u8f93\u51fa\u53c2\u6570\uff0c\u8fd8\u5e26\u957f\u5ea6\n @Age INT OUTPUT // \u8f93\u51fa\u53c2\u6570\nAS\nBEGIN\n SET @Name = 'Furion Output';\n\n // \u8f93\u51fa\u7ed3\u679c\u96c6\n SELECT *\n FROM dbo.Test\n WHERE Id > @Id;\n\n // \u8f93\u51fa\u7ed3\u679c\u96c6\n SELECT TOP 10\n *\n FROM dbo.Test;\n\n SET @Age = 27;\n\n // \u5e26 RETURN \u8fd4\u56de\n RETURN 10;\nEND;\n")),(0,o.kt)("h3",{id:"91331-\u521b\u5efa\u53c2\u6570\u6a21\u578b"},"9.13.3.1 \u521b\u5efa\u53c2\u6570\u6a21\u578b"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,10,13,16}",showLineNumbers:!0,"":!0,"{1,10,13,16}":!0},"using Furion.DatabaseAccessor;\nusing System.Data;\n\nnamespace Furion.Application\n{\n public class ProcOutputModel\n {\n public int Id { get; set; } // \u8f93\u5165\u53c2\u6570\n\n [DbParameter(ParameterDirection.Output, Size = 32)]\n public string Name { get; set; } // \u8f93\u51fa\u53c2\u6570\n\n [DbParameter(ParameterDirection.Output)]\n public int Age { get; set; } // \u8f93\u51fa\u53c2\u6570\n\n [DbParameter(ParameterDirection.ReturnValue)]\n public int ReturnValue { get; set; } // \u8fd4\u56de\u503c\n }\n}\n")),(0,o.kt)("h3",{id:"91332-\u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b"},"9.13.3.2 \u6267\u884c\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"}," ",(0,o.kt)("inlineCode",{parentName:"strong"},"DataSet")," ")," \u65b9\u5f0f")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\nProcedureOutputResult result = _sqlRepository.SqlProcedureOutput("proc_Complex", new ProcOutputModel{});\n\n// ISqlDispatchProxy \u65b9\u5f0f\nProcedureOutputResult result = _sqlExecuteProxy.Complex(new ProcOutputModel{}); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\nProcedureOutputResult result = _personRepository.SqlProcedureOutput("proc_Complex", new ProcOutputModel{});\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\nProcedureOutputResult result = _repository.Sql().SqlProcedureOutput("proc_Complex", new ProcOutputModel{});\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\nProcedureOutputResult result = "proc_Complex".SqlProcedureOutput(new ProcOutputModel{});\n')),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u83b7\u53d6 OUTPUT \u53c2\u6570\u503c\nvar outputs = result.OutputValues;\n\n// \u83b7\u53d6 RETURN \u8fd4\u56de\u503c\nvar reval = result.ReturnValue;\n\n// \u83b7\u53d6\u8fd4\u56de\u7ed3\u679c\u96c6\nvar dataSet = result.Result;\n")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Tuple")," \u65b9\u5f0f")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ISqlRepository \u65b9\u6cd5\nProcedureOutputResult<(List, List)> result = _sqlRepository.SqlProcedureOutput<(List, List)>("proc_Complex", new ProcOutputModel{});\n\n// ISqlDispatchProxy \u65b9\u5f0f\nProcedureOutputResult<(List, List)> result = _sqlExecuteProxy.Complex(new ProcOutputModel{}); // \u63a8\u8350\u65b9\u5f0f\n\n// \u5b9e\u4f53\u4ed3\u50a8\u65b9\u5f0f\nProcedureOutputResult<(List, List)> result = _personRepository.SqlProcedureOutput<(List, List)>("proc_Complex", new ProcOutputModel{});\n\n// IRepository \u975e\u6cdb\u578b\u65b9\u5f0f\nProcedureOutputResult<(List, List)> result = _repository.Sql().SqlProcedureOutput<(List, List)>("proc_Complex", new ProcOutputModel{});\n\n// \u53d8\u6001\u61d2\u4eba\u65b9\u5f0f\uff0c\u76f4\u63a5\u901a\u8fc7\u5b58\u50a8\u8fc7\u7a0b\u540d\u6267\u884c\nProcedureOutputResult<(List, List)> result = "proc_Complex".SqlProcedureOutput<(List, List)>(new ProcOutputModel{});\n')),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u83b7\u53d6 OUTPUT \u53c2\u6570\u503c\nvar outputs = result.OutputValues;\n\n// \u83b7\u53d6 RETURN \u8fd4\u56de\u503c\nvar reval = result.ReturnValue;\n\n// \u83b7\u53d6\u8fd4\u56de\u7ed3\u679c\u96c6\nvar (list1,list2) = result.Result;\n")),(0,o.kt)("admonition",{title:"\u5173\u4e8e\u5f02\u6b65",type:"note"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\u90fd\u652f\u6301\u5f02\u6b65\u65b9\u5f0f\uff0c\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u5c31\u4e0d\u5217\u4e3e\u5f02\u6b65\u65b9\u5f0f\u4e86\u3002")),(0,o.kt)("h2",{id:"9133-\u5173\u4e8e-dbparameter"},"9.13.3 \u5173\u4e8e ",(0,o.kt)("inlineCode",{parentName:"h2"},"[DbParameter]")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"[DbParameter]")," \u7279\u6027\u662f\u7528\u6765\u6807\u6ce8 ",(0,o.kt)("inlineCode",{parentName:"p"},"Sql"),"\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"\u51fd\u6570"),"\uff0c",(0,o.kt)("inlineCode",{parentName:"p"},"\u5b58\u50a8\u8fc7\u7a0b")," \u53c2\u6570\u7684\uff0c\u53ef\u914d\u7f6e\u5c5e\u6027\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Direction"),"\uff1a\u8bbe\u7f6e\u53c2\u6570\u65b9\u5411\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"ParameterDirection")," \u679a\u4e3e\u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,o.kt)("inlineCode",{parentName:"li"},"ParameterDirection.Input")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"DbType"),"\uff1a\u8bbe\u7f6e\u53c2\u6570\u7c7b\u578b\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"DbType")," \u679a\u4e3e\u7c7b\u578b\uff0c\u65e0\u9ed8\u8ba4"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Size"),"\uff1a\u8bbe\u7f6e\u53c2\u6570\u957f\u5ea6\u7684\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"int")," \u7c7b\u578b")),(0,o.kt)("p",null,"\u5176\u4e2d ",(0,o.kt)("inlineCode",{parentName:"p"},"Direction")," \u5c5e\u6027\u662f\u9ed8\u8ba4\u6784\u9020\u51fd\u6570\u53c2\u6570\u3002"),(0,o.kt)("h2",{id:"9134-\u5173\u4e8e-procedureoutputresult"},"9.13.4 \u5173\u4e8e ",(0,o.kt)("inlineCode",{parentName:"h2"},"ProcedureOutputResult")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"ProcedureOutputResult")," \u548c ",(0,o.kt)("inlineCode",{parentName:"p"},"ProcedureOutputResult")," \u662f\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b\u6267\u884c\u8fd4\u56de\u6a21\u578b\u7c7b\uff0c\u6709\u4ee5\u4e0b\u5c5e\u6027\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"OutputValues"),"\uff1a\u591a\u4e2a\u8f93\u51fa\u503c\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"ProcedureOutputValue")," \u7c7b\u578b"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"ReturnValue"),"\uff1a\u8fd4\u56de\u503c\uff0c",(0,o.kt)("inlineCode",{parentName:"li"},"object")," \u7c7b\u578b"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Result"),"\uff1a\u7ed3\u679c\u96c6\uff0c\u975e\u6cdb\u578b\u7248\u672c\u662f ",(0,o.kt)("inlineCode",{parentName:"li"},"DataSet"),"\u7c7b\u578b\uff0c\u5426\u5219\u662f \u6cdb\u578b\u7c7b\u578b")),(0,o.kt)("h2",{id:"9135-\u5b58\u50a8\u8fc7\u7a0b\u53c2\u6570"},"9.13.5 \u5b58\u50a8\u8fc7\u7a0b\u53c2\u6570"),(0,o.kt)("p",null,"\u6240\u6709 ",(0,o.kt)("inlineCode",{parentName:"p"},"sql")," \u53c2\u6570\u90fd\u652f\u6301\u56db\u79cd\u65b9\u5f0f\uff1a"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"DbParameter[]"),"\uff1a\u6570\u7ec4\u7c7b\u578b"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"new {}"),"\uff1a\u533f\u540d\u7c7b\u578b"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"new Class{}"),"\uff1a\u5f3a\u7c7b\u578b\u7c7b\u578b\uff08\u652f\u6301\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b\u53c2\u6570\uff09"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Dictionary")," \u7c7b\u578b")),(0,o.kt)("h2",{id:"9136-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.13.6 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,o.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,o.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}N.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/ab6beea0.0f966ba6.js b/handbook/build/assets/js/ab6beea0.0f966ba6.js deleted file mode 100644 index 5f5021b8a9..0000000000 --- a/handbook/build/assets/js/ab6beea0.0f966ba6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[6229],{433:function(e,t,n){n.d(t,{Z:function(){return r}});var a=n(7294),i=n(4334),s="tabItem_Ymn6";function r(e){var t=e.children,n=e.hidden,r=e.className;return a.createElement("div",{role:"tabpanel",className:(0,i.Z)(s,r),hidden:n},t)}},5559:function(e,t,n){n.d(t,{Z:function(){return m}});var a=n(3117),i=n(7294),s=n(4334),r=n(5730),l=n(636),p=n(6602),o=n(3735),u="tabList__CuJ",c="tabItem_LNqP";function d(e){var t,n,r=e.lazy,d=e.block,m=e.defaultValue,k=e.values,w=e.groupId,N=e.className,h=i.Children.map(e.children,(function(e){if((0,i.isValidElement)(e)&&"value"in e.props)return e;throw new Error("Docusaurus error: Bad child <"+("string"==typeof e.type?e.type:e.type.name)+'>: all children of the component should be , and every should have a unique "value" prop.')})),g=null!=k?k:h.map((function(e){var t=e.props;return{value:t.value,label:t.label,attributes:t.attributes}})),b=(0,l.l)(g,(function(e,t){return e.value===t.value}));if(b.length>0)throw new Error('Docusaurus error: Duplicate values "'+b.map((function(e){return e.value})).join(", ")+'" found in . Every value needs to be unique.');var C=null===m?m:null!=(t=null!=m?m:null==(n=h.find((function(e){return e.props.default})))?void 0:n.props.value)?t:h[0].props.value;if(null!==C&&!g.some((function(e){return e.value===C})))throw new Error('Docusaurus error: The has a defaultValue "'+C+'" but none of its children has the corresponding value. Available values are: '+g.map((function(e){return e.value})).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");var y=(0,p.U)(),v=y.tabGroupChoices,f=y.setTabGroupChoices,H=(0,i.useState)(C),A=H[0],S=H[1],L=[],P=(0,o.o5)().blockElementScrollPositionUntilNextRender;if(null!=w){var X=v[w];null!=X&&X!==A&&g.some((function(e){return e.value===X}))&&S(X)}var T=function(e){var t=e.currentTarget,n=L.indexOf(t),a=g[n].value;a!==A&&(P(t),S(a),null!=w&&f(w,String(a)))},R=function(e){var t,n=null;switch(e.key){case"ArrowRight":var a,i=L.indexOf(e.currentTarget)+1;n=null!=(a=L[i])?a:L[0];break;case"ArrowLeft":var s,r=L.indexOf(e.currentTarget)-1;n=null!=(s=L[r])?s:L[L.length-1]}null==(t=n)||t.focus()};return i.createElement("div",{className:(0,s.Z)("tabs-container",u)},i.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,s.Z)("tabs",{"tabs--block":d},N)},g.map((function(e){var t=e.value,n=e.label,r=e.attributes;return i.createElement("li",(0,a.Z)({role:"tab",tabIndex:A===t?0:-1,"aria-selected":A===t,key:t,ref:function(e){return L.push(e)},onKeyDown:R,onFocus:T,onClick:T},r,{className:(0,s.Z)("tabs__item",c,null==r?void 0:r.className,{"tabs__item--active":A===t})}),null!=n?n:t)}))),r?(0,i.cloneElement)(h.filter((function(e){return e.props.value===A}))[0],{className:"margin-top--md"}):i.createElement("div",{className:"margin-top--md"},h.map((function(e,t){return(0,i.cloneElement)(e,{key:t,hidden:e.props.value!==A})}))))}function m(e){var t=(0,r.Z)();return i.createElement(d,(0,a.Z)({key:String(t)},e))}},7114:function(e,t,n){n.r(t),n.d(t,{assets:function(){return d},contentTitle:function(){return u},default:function(){return w},frontMatter:function(){return o},metadata:function(){return c},toc:function(){return m}});var a=n(3117),i=n(102),s=(n(7294),n(3905)),r=n(5559),l=n(433),p=["components"],o={id:"http",title:"19. \u8fdc\u7a0b\u8bf7\u6c42",sidebar_label:"19. \u8fdc\u7a0b\u8bf7\u6c42 (HttpClient)"},u=void 0,c={unversionedId:"http",id:"http",title:"19. \u8fdc\u7a0b\u8bf7\u6c42",description:"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 Furion 1.16.0 + \u7248\u672c\u4f7f\u7528\u3002",source:"@site/docs/http.mdx",sourceDirName:".",slug:"/http",permalink:"/furion/docs/http",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/http.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1662086183,formattedLastUpdatedAt:"Sep 2, 2022",frontMatter:{id:"http",title:"19. \u8fdc\u7a0b\u8bf7\u6c42",sidebar_label:"19. \u8fdc\u7a0b\u8bf7\u6c42 (HttpClient)"},sidebar:"docs",previous:{title:"18. \u65e5\u5fd7\u8bb0\u5f55",permalink:"/furion/docs/logging"},next:{title:"20. \u6570\u636e\u52a0\u89e3\u5bc6",permalink:"/furion/docs/encryption"}},d={},m=[{value:"19.1 \u5173\u4e8e\u8fdc\u7a0b\u8bf7\u6c42",id:"191-\u5173\u4e8e\u8fdc\u7a0b\u8bf7\u6c42",level:2},{value:"19.2 \u8fdc\u7a0b\u8bf7\u6c42\u7684\u4f5c\u7528",id:"192-\u8fdc\u7a0b\u8bf7\u6c42\u7684\u4f5c\u7528",level:2},{value:"19.3 \u57fa\u7840\u4f7f\u7528",id:"193-\u57fa\u7840\u4f7f\u7528",level:2},{value:"19.3.1 \u6ce8\u518c\u670d\u52a1",id:"1931-\u6ce8\u518c\u670d\u52a1",level:3},{value:"19.3.2 \u4f7f\u7528\u65b9\u5f0f",id:"1932-\u4f7f\u7528\u65b9\u5f0f",level:3},{value:"19.4 \u5b57\u7b26\u4e32\u65b9\u5f0f\u4f7f\u7528\u793a\u4f8b",id:"194-\u5b57\u7b26\u4e32\u65b9\u5f0f\u4f7f\u7528\u793a\u4f8b",level:2},{value:"19.4.1 \u5185\u7f6e\u8bf7\u6c42\u65b9\u5f0f",id:"1941-\u5185\u7f6e\u8bf7\u6c42\u65b9\u5f0f",level:3},{value:"19.4.2 \u8bbe\u7f6e\u8bf7\u6c42\u5730\u5740",id:"1942-\u8bbe\u7f6e\u8bf7\u6c42\u5730\u5740",level:3},{value:"19.4.3 \u8bbe\u7f6e\u8bf7\u6c42\u65b9\u5f0f",id:"1943-\u8bbe\u7f6e\u8bf7\u6c42\u65b9\u5f0f",level:3},{value:"19.4.4 \u8bbe\u7f6e\u5730\u5740\u6a21\u677f",id:"1944-\u8bbe\u7f6e\u5730\u5740\u6a21\u677f",level:3},{value:"19.4.5 \u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934",id:"1945-\u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934",level:3},{value:"19.4.6 \u8bbe\u7f6e URL \u5730\u5740\u53c2\u6570",id:"1946-\u8bbe\u7f6e-url-\u5730\u5740\u53c2\u6570",level:3},{value:"19.4.7 \u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef",id:"1947-\u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef",level:3},{value:"19.4.8 \u8bbe\u7f6e Body \u53c2\u6570",id:"1948-\u8bbe\u7f6e-body-\u53c2\u6570",level:3},{value:"19.4.9 \u8bbe\u7f6e Content-Type",id:"1949-\u8bbe\u7f6e-content-type",level:3},{value:"19.4.10 \u8bbe\u7f6e\u5185\u5bb9\u7f16\u7801",id:"19410-\u8bbe\u7f6e\u5185\u5bb9\u7f16\u7801",level:3},{value:"19.4.11 \u8bbe\u7f6e JSON \u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f",id:"19411-\u8bbe\u7f6e-json-\u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f",level:3},{value:"19.4.12 \u542f\u7528 Body \u53c2\u6570\u9a8c\u8bc1",id:"19412-\u542f\u7528-body-\u53c2\u6570\u9a8c\u8bc1",level:3},{value:"19.4.13 \u8bf7\u6c42\u62e6\u622a",id:"19413-\u8bf7\u6c42\u62e6\u622a",level:3},{value:"19.4.14 HttpClient \u62e6\u622a",id:"19414-httpclient-\u62e6\u622a",level:3},{value:"19.4.15 \u8bf7\u6c42\u4e4b\u524d\u62e6\u622a",id:"19415-\u8bf7\u6c42\u4e4b\u524d\u62e6\u622a",level:3},{value:"19.4.16 \u6210\u529f\u8bf7\u6c42\u62e6\u622a",id:"19416-\u6210\u529f\u8bf7\u6c42\u62e6\u622a",level:3},{value:"19.4.17 \u8bf7\u6c42\u5f02\u5e38\u62e6\u622a",id:"19417-\u8bf7\u6c42\u5f02\u5e38\u62e6\u622a",level:3},{value:"19.4.18 \u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406",id:"19418-\u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406",level:3},{value:"19.4.19 \u8bbe\u7f6e Byte[] \u7c7b\u578b/\u4e0a\u4f20\u6587\u4ef6",id:"19419-\u8bbe\u7f6e-byte-\u7c7b\u578b\u4e0a\u4f20\u6587\u4ef6",level:3},{value:"19.4.20 \u8bbe\u7f6e IServiceProvider",id:"19420-\u8bbe\u7f6e-iserviceprovider",level:3},{value:"19.4.21 \u8bbe\u7f6e Timeout \u8d85\u65f6\u65f6\u95f4",id:"19421-\u8bbe\u7f6e-timeout-\u8d85\u65f6\u65f6\u95f4",level:3},{value:"19.4.22 \u652f\u6301\u6a21\u677f\u914d\u7f6e",id:"19422-\u652f\u6301\u6a21\u677f\u914d\u7f6e",level:3},{value:"19.4.23 \u91cd\u8bd5\u7b56\u7565",id:"19423-\u91cd\u8bd5\u7b56\u7565",level:3},{value:"19.4.24 \u652f\u6301 GZip \u538b\u7f29",id:"19424-\u652f\u6301-gzip-\u538b\u7f29",level:3},{value:"19.4.25 \u8bbe\u7f6e Url \u8f6c\u7801",id:"19425-\u8bbe\u7f6e-url-\u8f6c\u7801",level:3},{value:"19.5 IHttpDispatchProxy \u4ee3\u7406\u65b9\u5f0f",id:"195-ihttpdispatchproxy-\u4ee3\u7406\u65b9\u5f0f",level:2},{value:"19.5.1 \u652f\u6301\u591a\u79cd\u4ee3\u7406\u65b9\u5f0f",id:"1951-\u652f\u6301\u591a\u79cd\u4ee3\u7406\u65b9\u5f0f",level:3},{value:"19.5.2 \u8bbe\u7f6e\u5730\u5740\u6a21\u677f",id:"1952-\u8bbe\u7f6e\u5730\u5740\u6a21\u677f",level:3},{value:"19.5.3 \u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934",id:"1953-\u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934",level:3},{value:"19.5.4 \u8bbe\u7f6e URL \u5730\u5740\u53c2\u6570",id:"1954-\u8bbe\u7f6e-url-\u5730\u5740\u53c2\u6570",level:3},{value:"19.5.5 \u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef",id:"1955-\u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef",level:3},{value:"19.5.6 \u8bbe\u7f6e Body \u53c2\u6570",id:"1956-\u8bbe\u7f6e-body-\u53c2\u6570",level:3},{value:"19.5.7 \u8bbe\u7f6e JSON \u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f",id:"1957-\u8bbe\u7f6e-json-\u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f",level:3},{value:"19.5.8 \u53c2\u6570\u9a8c\u8bc1",id:"1958-\u53c2\u6570\u9a8c\u8bc1",level:3},{value:"19.5.9 \u8bf7\u6c42\u62e6\u622a",id:"1959-\u8bf7\u6c42\u62e6\u622a",level:3},{value:"19.5.10 HttpClient \u62e6\u622a",id:"19510-httpclient-\u62e6\u622a",level:3},{value:"19.5.11 \u8bf7\u6c42\u4e4b\u524d\u62e6\u622a",id:"19511-\u8bf7\u6c42\u4e4b\u524d\u62e6\u622a",level:3},{value:"19.5.12 \u6210\u529f\u8bf7\u6c42\u62e6\u622a",id:"19512-\u6210\u529f\u8bf7\u6c42\u62e6\u622a",level:3},{value:"19.5.13 \u8bf7\u6c42\u5f02\u5e38\u62e6\u622a",id:"19513-\u8bf7\u6c42\u5f02\u5e38\u62e6\u622a",level:3},{value:"19.5.14 \u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406",id:"19514-\u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406",level:3},{value:"19.5.15 \u8bbe\u7f6e Byte[] \u7c7b\u578b/\u4e0a\u4f20\u6587\u4ef6",id:"19515-\u8bbe\u7f6e-byte-\u7c7b\u578b\u4e0a\u4f20\u6587\u4ef6",level:3},{value:"19.5.16 \u8bbe\u7f6e Timeout \u8d85\u65f6\u65f6\u95f4",id:"19516-\u8bbe\u7f6e-timeout-\u8d85\u65f6\u65f6\u95f4",level:3},{value:"19.5.17 \u652f\u6301\u6a21\u677f\u914d\u7f6e",id:"19517-\u652f\u6301\u6a21\u677f\u914d\u7f6e",level:3},{value:"19.5.18 \u91cd\u8bd5\u7b56\u7565",id:"19518-\u91cd\u8bd5\u7b56\u7565",level:3},{value:"19.5.19 \u652f\u6301 GZip",id:"19519-\u652f\u6301-gzip",level:3},{value:"19.5.20 \u8bbe\u7f6e Url \u8f6c\u7801",id:"19520-\u8bbe\u7f6e-url-\u8f6c\u7801",level:3},{value:"19.6 \u8bf7\u6c42\u5ba2\u6237\u7aef\u914d\u7f6e",id:"196-\u8bf7\u6c42\u5ba2\u6237\u7aef\u914d\u7f6e",level:2},{value:"19.6.1 Startup.cs \u7edf\u4e00\u914d\u7f6e",id:"1961-startupcs-\u7edf\u4e00\u914d\u7f6e",level:3},{value:"19.6.2 \u81ea\u5b9a\u4e49 Client \u7c7b\u65b9\u5f0f",id:"1962-\u81ea\u5b9a\u4e49-client-\u7c7b\u65b9\u5f0f",level:3},{value:"19.6.3 \u81ea\u5b9a\u4e49 Client \u7c7b + \u63a5\u53e3\u65b9\u5f0f",id:"1963-\u81ea\u5b9a\u4e49-client-\u7c7b--\u63a5\u53e3\u65b9\u5f0f",level:3},{value:"19.7 SSL/https \u8bc1\u4e66\u914d\u7f6e",id:"197-sslhttps-\u8bc1\u4e66\u914d\u7f6e",level:2},{value:"19.7.1 \u5ffd\u7565\u7279\u5b9a\u5ba2\u6237\u7aef SSL \u8bc1\u4e66\u68c0\u67e5",id:"1971-\u5ffd\u7565\u7279\u5b9a\u5ba2\u6237\u7aef-ssl-\u8bc1\u4e66\u68c0\u67e5",level:3},{value:"19.7.2 \u624b\u52a8\u6307\u5b9a SSL \u8bc1\u4e66",id:"1972-\u624b\u52a8\u6307\u5b9a-ssl-\u8bc1\u4e66",level:3},{value:"19.7.3 \u5ffd\u7565\u6240\u6709\u5ba2\u6237\u7aef\u8bc1\u4e66\u68c0\u67e5",id:"1973-\u5ffd\u7565\u6240\u6709\u5ba2\u6237\u7aef\u8bc1\u4e66\u68c0\u67e5",level:3},{value:"19.8 \u5173\u4e8e\u8fd4\u56de\u503c\u975e 200 \u65f6\u5ffd\u7565 Http\u72b6\u6001",id:"198-\u5173\u4e8e\u8fd4\u56de\u503c\u975e-200-\u65f6\u5ffd\u7565-http\u72b6\u6001",level:2},{value:"19.9 \u5173\u4e8e\u540c\u6b65\u8bf7\u6c42",id:"199-\u5173\u4e8e\u540c\u6b65\u8bf7\u6c42",level:2},{value:"19.10 \u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df",id:"1910-\u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df",level:2},{value:"19.11 \u9759\u6001 Default \u65b9\u5f0f\u6784\u5efa",id:"1911-\u9759\u6001-default-\u65b9\u5f0f\u6784\u5efa",level:2},{value:"19.12 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"1912-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],k={toc:m};function w(e){var t=e.components,n=(0,i.Z)(e,p);return(0,s.kt)("wrapper",(0,a.Z)({},k,n,{components:t,mdxType:"MDXLayout"}),(0,s.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,s.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion 1.16.0 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,s.kt)("h2",{id:"191-\u5173\u4e8e\u8fdc\u7a0b\u8bf7\u6c42"},"19.1 \u5173\u4e8e\u8fdc\u7a0b\u8bf7\u6c42"),(0,s.kt)("p",null,"\u5728\u4e92\u8054\u7f51\u5927\u6570\u636e\u7684\u9a71\u52a8\u4e0b\uff0c\u5e73\u53f0\u6216\u7cfb\u7edf\u514d\u4e0d\u4e86\u9700\u8981\u548c\u7b2c\u4e09\u65b9\u8fdb\u884c\u6570\u636e\u4ea4\u4e92\uff0c\u800c\u7b2c\u4e09\u65b9\u5f80\u5f80\u63d0\u4f9b\u4e86 ",(0,s.kt)("inlineCode",{parentName:"p"},"RESTful API")," \u63a5\u53e3\u89c4\u8303\uff0c\u8fd9\u4e2a\u65f6\u5019\u5c31\u9700\u8981\u901a\u8fc7 ",(0,s.kt)("inlineCode",{parentName:"p"},"Http")," \u8bf7\u6c42\u7b2c\u4e09\u65b9\u63a5\u53e3\u8fdb\u884c\u6570\u636e\u4f20\u8f93\u4ea4\u4e92\u3002"),(0,s.kt)("p",null,"\u4e5f\u5c31\u662f\u672c\u7ae0\u8282\u6240\u8bf4\u7684\u8fdc\u7a0b\u8bf7\u6c42\u3002"),(0,s.kt)("h2",{id:"192-\u8fdc\u7a0b\u8bf7\u6c42\u7684\u4f5c\u7528"},"19.2 \u8fdc\u7a0b\u8bf7\u6c42\u7684\u4f5c\u7528"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u8de8\u7cfb\u7edf\u3001\u8de8\u8bbe\u5907\u901a\u4fe1"),(0,s.kt)("li",{parentName:"ul"},"\u5b9e\u73b0\u591a\u4e2a\u7cfb\u7edf\u6570\u636e\u4f20\u8f93\u4ea4\u4e92"),(0,s.kt)("li",{parentName:"ul"},"\u8de8\u7f16\u7a0b\u8bed\u8a00\u534f\u540c\u5f00\u53d1")),(0,s.kt)("h2",{id:"193-\u57fa\u7840\u4f7f\u7528"},"19.3 \u57fa\u7840\u4f7f\u7528"),(0,s.kt)("h3",{id:"1931-\u6ce8\u518c\u670d\u52a1"},"19.3.1 \u6ce8\u518c\u670d\u52a1"),(0,s.kt)("p",null,"\u4f7f\u7528\u4e4b\u524d\u9700\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u6ce8\u518c ",(0,s.kt)("inlineCode",{parentName:"p"},"\u8fdc\u7a0b\u8bf7\u6c42\u670d\u52a1")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public void ConfigureServices(IServiceCollection services)\n{\n services.AddRemoteRequest();\n}\n")),(0,s.kt)("h3",{id:"1932-\u4f7f\u7528\u65b9\u5f0f"},"19.3.2 \u4f7f\u7528\u65b9\u5f0f"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e24\u79cd\u65b9\u5f0f\u8bbf\u95ee\u53d1\u9001\u8fdc\u7a0b\u8bf7\u6c42\u3002"),(0,s.kt)(r.Z,{defaultValue:"IHttpDispatchProxy \u4ee3\u7406\u65b9\u5f0f",values:[{label:"IHttpDispatchProxy \u4ee3\u7406\u65b9\u5f0f",value:"IHttpDispatchProxy \u4ee3\u7406\u65b9\u5f0f"},{label:"\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u5f0f",value:"\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u5f0f"}],mdxType:"Tabs"},(0,s.kt)(l.Z,{value:"IHttpDispatchProxy \u4ee3\u7406\u65b9\u5f0f",mdxType:"TabItem"},(0,s.kt)("p",null,"\u5b9a\u4e49\u4ee3\u7406\u8bf7\u6c42\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"\u63a5\u53e3")," \u5e76\u7ee7\u627f ",(0,s.kt)("inlineCode",{parentName:"p"},"IHttpDispatchProxy")," \u63a5\u53e3"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,6,9,12,15,18}",showLineNumbers:!0,"":!0,"{1,3,6,9,12,15,18}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Get("https://www.furion.icu/get")]\n Task GetXXXAsync();\n\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync();\n\n [Put("https://www.furion.icu/put")]\n Task PutXXXAsync();\n\n [Delete("https://www.furion.icu/delete")]\n Task DeleteXXXAsync();\n\n [Patch("https://www.furion.icu/patch")]\n Task PatchXXXAsync();\n\n [Head("https://www.furion.icu/head")]\n Task HeadXXXAsync();\n}\n')),(0,s.kt)("p",null,"\u901a\u8fc7\u6784\u9020\u51fd\u6570\u6ce8\u5165 ",(0,s.kt)("inlineCode",{parentName:"p"},"\u63a5\u53e3")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,16}",showLineNumbers:!0,"":!0,"{9,16}":!0},"using Furion.DynamicApiController;\nusing Furion.RemoteRequest.Extensions;\n\nnamespace Furion.Application\n{\n public class RemoteRequestService : IDynamicApiController\n {\n private readonly IHttp _http;\n public RemoteRequestService(IHttp http)\n {\n _http = http;\n }\n\n public async Task GetData()\n {\n var data = await _http.GetXXXAsync();\n }\n }\n}\n"))),(0,s.kt)(l.Z,{value:"\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u5f0f",mdxType:"TabItem"},(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var response = await "https://www.furion.icu/get".GetAsync();\n\nvar response = await "https://www.furion.icu/post".PostAsync();\n\nvar response = await "https://www.furion.icu/put".PutAsync();\n\nvar response = await "https://www.furion.icu/delete".DeleteAsync();\n\nvar response = await "https://www.furion.icu/patch".PatchAsync();\n\nvar response = await "https://www.furion.icu/head".HeadAsync();\n')),(0,s.kt)("p",null,"\u9700\u5f15\u5165 ",(0,s.kt)("inlineCode",{parentName:"p"},"using Furion.RemoteRequest.Extensions")," \u547d\u540d\u7a7a\u95f4\u3002"))),(0,s.kt)("h2",{id:"194-\u5b57\u7b26\u4e32\u65b9\u5f0f\u4f7f\u7528\u793a\u4f8b"},"19.4 \u5b57\u7b26\u4e32\u65b9\u5f0f\u4f7f\u7528\u793a\u4f8b"),(0,s.kt)("h3",{id:"1941-\u5185\u7f6e\u8bf7\u6c42\u65b9\u5f0f"},"19.4.1 \u5185\u7f6e\u8bf7\u6c42\u65b9\u5f0f"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u53d1\u9001 Get \u8bf7\u6c42\nvar response = await "https://www.furion.icu/get".GetAsync();\n\n// \u53d1\u9001 Post \u8bf7\u6c42\nvar response = await "https://www.furion.icu/post".PostAsync();\n\n// \u53d1\u9001 Put \u8bf7\u6c42\nvar response = await "https://www.furion.icu/put".PutAsync();\n\n// \u53d1\u9001 Delete \u8bf7\u6c42\nvar response = await "https://www.furion.icu/delete".DeleteAsync();\n\n// \u53d1\u9001 Patch \u8bf7\u6c42\nvar response = await "https://www.furion.icu/patch".PatchAsync();\n\n// \u53d1\u9001 Head \u8bf7\u6c42\nvar response = await "https://www.furion.icu/head".HeadAsync();\n\n// \u624b\u52a8\u6307\u5b9a\u53d1\u9001\u7279\u5b9a\u8bf7\u6c42\nvar response = await "https://www.furion.icu/post".SetHttpMethod(HttpMethod.Post)\n .SendAsync();\n')),(0,s.kt)("h3",{id:"1942-\u8bbe\u7f6e\u8bf7\u6c42\u5730\u5740"},"19.4.2 \u8bbe\u7f6e\u8bf7\u6c42\u5730\u5740"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u8be5\u65b9\u5f0f\u5728 Furion v3.0.0 \u5df2\u79fb\u9664\uff0c\u591a\u6b64\u4e00\u4e3e\u4e86\nawait "".SetRequestUrl("https://www.furion.icu/");\n')),(0,s.kt)("h3",{id:"1943-\u8bbe\u7f6e\u8bf7\u6c42\u65b9\u5f0f"},"19.4.3 \u8bbe\u7f6e\u8bf7\u6c42\u65b9\u5f0f"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/post".SetHttpMethod(HttpMethod.Get);\n')),(0,s.kt)("h3",{id:"1944-\u8bbe\u7f6e\u5730\u5740\u6a21\u677f"},"19.4.4 \u8bbe\u7f6e\u5730\u5740\u6a21\u677f"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u5b57\u5178\u65b9\u5f0f\nawait "https://www.furion.icu/post/{id}?name={name}&id={p.Id}".SetTemplates(new Dictionary {\n { "id", 1 },\n { "name", "Furion" },\n { "p.Id", new Person { Id = 1 } }\n});\n\n// \u5bf9\u8c61/\u533f\u540d\u5bf9\u8c61\u65b9\u5f0f\nawait "https://www.furion.icu/post/{id}?name={name}".SetTemplates(new {\n id = 1,\n name = "Furion"\n});\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u6ce8\uff1a\u6a21\u677f\u66ff\u6362\u533a\u5206\u5927\u5c0f\u5199\u3002")),(0,s.kt)("h3",{id:"1945-\u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934"},"19.4.5 \u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u5b57\u5178\u65b9\u5f0f\nawait "https://www.furion.icu/post".SetHeaders(new Dictionary {\n { "Authorization", "Bearer \u4f60\u7684token"},\n { "X-Authorization", "Bearer \u4f60\u7684\u5237\u65b0token"}\n});\n\n// \u5bf9\u8c61/\u533f\u540d\u5bf9\u8c61\u65b9\u5f0f\nawait "https://www.furion.icu/post".SetHeaders(new {\n Authorization = "Bearer \u4f60\u7684token"\n});\n')),(0,s.kt)("h3",{id:"1946-\u8bbe\u7f6e-url-\u5730\u5740\u53c2\u6570"},"19.4.6 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"URL")," \u5730\u5740\u53c2\u6570"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u5b57\u5178\u65b9\u5f0f\nawait "https://www.furion.icu/get".SetQueries(new Dictionary {\n { "id", 1 },\n { "name", "Furion"}\n});\n\n// \u5bf9\u8c61/\u533f\u540d\u5bf9\u8c61\u65b9\u5f0f\nawait "https://www.furion.icu/get".SetQueries(new {\n id = 1,\n name = "Furion"\n});\n')),(0,s.kt)("p",null,"\u6700\u7ec8\u8f93\u51fa\u683c\u5f0f\u4e3a\uff1a",(0,s.kt)("inlineCode",{parentName:"p"},"https://www.furion.icu/get?id=1&name=Furion"),"\u3002"),(0,s.kt)("h3",{id:"1947-\u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef"},"19.4.7 \u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("strong",{parentName:"li"},"\u5168\u5c40\u914d\u7f6e\u65b9\u5f0f"))),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3-4,12}",showLineNumbers:!0,"":!0,"{1,3-4,12}":!0},'services.AddRemoteRequest(options=>\n{\n // \u914d\u7f6e Github \u57fa\u672c\u4fe1\u606f\n options.AddHttpClient("github", c =>\n {\n c.BaseAddress = new Uri("https://api.github.com/");\n c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");\n c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");\n });\n});\n\nawait "get".SetClient("github");\n')),(0,s.kt)("p",null,"\u6700\u7ec8\u751f\u6210\u8bf7\u6c42\u5730\u5740\u4e3a\uff1a",(0,s.kt)("inlineCode",{parentName:"p"},"https://api.github.com/get"),"\u3002"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("strong",{parentName:"li"},"\u5c40\u90e8\u914d\u7f6e\u65b9\u5f0f"))),(0,s.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,s.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion 4.3.8 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu".SetClient(() => new HttpClient());\n')),(0,s.kt)("h3",{id:"1948-\u8bbe\u7f6e-body-\u53c2\u6570"},"19.4.8 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Body")," \u53c2\u6570"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u4f20\u5165\u5bf9\u8c61\nawait "https://www.furion.icu/api/user/add".SetBody(new User { Id = 1, Name = "Furion" });\n\n// \u914d\u7f6e Content-Type\nawait "https://www.furion.icu/api/user/add".SetBody(new { Id = 1, Name = "Furion" }, "application/json");\n\n// \u8bbe\u7f6e Encoding \u7f16\u7801\nawait "https://www.furion.icu/api/user/add".SetBody(new User { Id = 1, Name = "Furion" }, "application/json", Encoding.UTF8);\n\n// \u5904\u7406 application/x-www-form-urlencoded \u8bf7\u6c42\nawait "https://www.furion.icu/api/user/add".SetBody(new Dictionary {\n { "Id", 1 },\n { "Name", "Furion"}\n}, "application/x-www-form-urlencoded");\n\n// \u5904\u7406 application/xml\u3001text/xml\nawait "https://www.furion.icu/api/user/add".SetBody("somevalue", "application/xml");\n')),(0,s.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,s.kt)("p",{parentName:"admonition"},"\u5982\u679c\u8bf7\u6c42 ",(0,s.kt)("inlineCode",{parentName:"p"},"Content-Type")," \u8bbe\u7f6e\u4e3a ",(0,s.kt)("inlineCode",{parentName:"p"},"application/x-www-form-urlencoded")," \u7c7b\u578b\uff0c\u90a3\u4e48\u5e95\u5c42\u81ea\u52a8\u5c06\u6570\u636e\u8fdb\u884c ",(0,s.kt)("inlineCode",{parentName:"p"},"UrlEncode")," \u7f16\u7801\u5904\u7406\uff0c\u65e0\u9700\u5916\u90e8\u5904\u7406\u3002")),(0,s.kt)("h3",{id:"1949-\u8bbe\u7f6e-content-type"},"19.4.9 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Content-Type")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/post".SetContentType("application/json");\n')),(0,s.kt)("h3",{id:"19410-\u8bbe\u7f6e\u5185\u5bb9\u7f16\u7801"},"19.4.10 \u8bbe\u7f6e\u5185\u5bb9\u7f16\u7801"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/post".SetContentEncoding(Encoding.UTF8);\n')),(0,s.kt)("h3",{id:"19411-\u8bbe\u7f6e-json-\u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f"},"19.4.11 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"JSON")," \u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u9ed8\u8ba4\u60c5\u51b5\u4e0b\u91c7\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"System.Text.Json")," \u8fdb\u884c ",(0,s.kt)("inlineCode",{parentName:"p"},"JSON")," \u5e8f\u5217\u5316\u5904\u7406\uff0c\u5982\u9700\u8bbe\u7f6e\u7b2c\u4e09\u65b9 ",(0,s.kt)("inlineCode",{parentName:"p"},"JSON")," \u63d0\u4f9b\u5668\uff0c\u5219\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u6cdb\u578b\u65b9\u5f0f\nawait "https://www.furion.icu/api/user/add".SetJsonSerialization();\n\n// \u975e\u6cdb\u578b\u65b9\u5f0f\nawait "https://www.furion.icu/api/user/add".SetJsonSerialization(typeof(NewtonsoftJsonSerializerProvider));\n\n// \u6dfb\u52a0\u66f4\u591a\u914d\u7f6e\nawait "https://www.furion.icu/api/user/add".SetJsonSerialization(new JsonSerializerSettings {\n\n});\n')),(0,s.kt)("admonition",{type:"important"},(0,s.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u5173\u4e8e ",(0,s.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"JSON")," \u5e8f\u5217\u5316\u63d0\u4f9b\u5668"),(0,s.kt)("p",{parentName:"admonition"},"\u5982\u9700\u4e86\u89e3\u66f4\u591a ",(0,s.kt)("inlineCode",{parentName:"p"},"JSON")," \u5e8f\u5217\u5316\u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,s.kt)("a",{parentName:"p",href:"json-serialization#2351-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BA%8F%E5%88%97%E5%8C%96%E6%8F%90%E4%BE%9B%E5%99%A8"},"23. JSON \u5e8f\u5217\u5316")," \u7ae0\u8282")),(0,s.kt)("h3",{id:"19412-\u542f\u7528-body-\u53c2\u6570\u9a8c\u8bc1"},"19.4.12 \u542f\u7528 ",(0,s.kt)("inlineCode",{parentName:"h3"},"Body")," \u53c2\u6570\u9a8c\u8bc1"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/api/user/add".SetValidationState();\n\n// \u8bbe\u7f6e\u4e0d\u9a8c\u8bc1 null \u503c\nawait "https://www.furion.icu/api/user/add".SetValidationState(includeNull: true);\n')),(0,s.kt)("p",null,"\u652f\u6301\u7c7b\u4e2d ",(0,s.kt)("inlineCode",{parentName:"p"},"[Required]")," \u7b49\u5b8c\u6574\u6a21\u578b\u9a8c\u8bc1\u7279\u6027\u3002"),(0,s.kt)("h3",{id:"19413-\u8bf7\u6c42\u62e6\u622a"},"19.4.13 \u8bf7\u6c42\u62e6\u622a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/".OnRequesting((client, req) => {\n // req \u4e3a HttpRequestMessage \u5bf9\u8c61\n // \u8ffd\u52a0\u66f4\u591a\u53c2\u6570\n req.AppendQueries(new Dictionary {\n { "access_token", "xxxx"}\n });\n});\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19414-httpclient-\u62e6\u622a"},"19.4.14 ",(0,s.kt)("inlineCode",{parentName:"h3"},"HttpClient")," \u62e6\u622a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/".OnClientCreating(client => {\n // client \u4e3a HttpClient \u5bf9\u8c61\n client.Timeout = 30000; // \u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4\n});\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19415-\u8bf7\u6c42\u4e4b\u524d\u62e6\u622a"},"19.4.15 \u8bf7\u6c42\u4e4b\u524d\u62e6\u622a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/".OnRequesting((client, req) => {\n // req \u4e3a HttpRequestMessage \u5bf9\u8c61\n});\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19416-\u6210\u529f\u8bf7\u6c42\u62e6\u622a"},"19.4.16 \u6210\u529f\u8bf7\u6c42\u62e6\u622a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/".OnResponsing((client, res) => {\n // res \u4e3a HttpResponseMessage \u5bf9\u8c61\n});\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19417-\u8bf7\u6c42\u5f02\u5e38\u62e6\u622a"},"19.4.17 \u8bf7\u6c42\u5f02\u5e38\u62e6\u622a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/".OnException((client, res, errors) => {\n // res \u4e3a HttpResponseMessage \u5bf9\u8c61\n});\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19418-\u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406"},"19.4.18 \u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fdc\u7a0b\u8bf7\u6c42\u9ed8\u8ba4\u63d0\u4f9b\u56db\u79cd\u8fd4\u56de\u503c\u7c7b\u578b\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"HttpResponseMessage"),"\uff1a\u8bf7\u6c42\u54cd\u5e94\u6d88\u606f\u7c7b\u578b"),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"Stream"),"\uff1a\u6d41\u7c7b\u578b"),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"T"),"\uff1a\u6cdb\u578b ",(0,s.kt)("inlineCode",{parentName:"li"},"T")," \u7c7b\u578b"),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"String"),"\uff1a\u5b57\u7b26\u4e32\u7c7b\u578b\uff0c\u4e5f\u5c31\u662f\u76f4\u63a5\u5c06\u7f51\u7edc\u8bf7\u6c42\u7ed3\u679c\u5185\u5bb9\u5b57\u7b26\u4e32\u5316"),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"Byte[]"),"\uff1a\u5b57\u8282\u6570\u7ec4\u7c7b\u578b")),(0,s.kt)("p",null,"\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// HttpResponseMessage\nvar res = await "https://www.furion.icu/".GetAsync();\n\n// Stream\nvar stream = await "https://www.furion.icu/".GetAsStreamAsync();\n\n// T\nvar user = await "https://www.furion.icu/".GetAsAsync();\n\n// String\nvar str = await "https://www.baidu.com".GetAsStringAsync();\n')),(0,s.kt)("h3",{id:"19419-\u8bbe\u7f6e-byte-\u7c7b\u578b\u4e0a\u4f20\u6587\u4ef6"},"19.4.19 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Byte[]")," \u7c7b\u578b/\u4e0a\u4f20\u6587\u4ef6"),(0,s.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u4e0a\u4f20\u6587\u4ef6\uff0c\u9700\u8981\u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"p"},"Content-Type")," \u4e3a ",(0,s.kt)("inlineCode",{parentName:"p"},"multipart/form-data")," \u7c7b\u578b\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// bytes \u53ef\u4ee5\u901a\u8fc7 File.ReadAllBytes(\u6587\u4ef6\u8def\u5f84) \u83b7\u53d6\nvar res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")\n .SetBodyBytes(("\u952e", bytes, "\u6587\u4ef6\u540d")).PostAsync();\n\n// \u652f\u6301\u591a\u4e2a\u6587\u4ef6\nvar res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")\n .SetBodyBytes(("\u952e", bytes, "\u6587\u4ef6\u540d"),("\u952e", bytes, "\u6587\u4ef6\u540d")).PostAsync();\n')),(0,s.kt)("admonition",{title:"\u5173\u4e8e\u5fae\u4fe1\u4e0a\u4f20\u63a5\u53e3",type:"note"},(0,s.kt)("p",{parentName:"admonition"},"\u5982\u679c\u9047\u5230\u5fae\u4fe1\u4e0a\u4f20\u51fa\u73b0\u95ee\u9898\uff0c\u5219\u53ef\u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"p"},"Content-Type")," \u4e3a\uff1a",(0,s.kt)("inlineCode",{parentName:"p"},"application/octet-stream"),"\uff0c\u5982\uff1a"),(0,s.kt)("pre",{parentName:"admonition"},(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = await $"https://api.weixin.qq.com/wxa/img_sec_check?access_token={token}"\n .SetBodyBytes(("media", bytes, Path.GetFileName(imgPath)))\n .SetContentType("application/octet-stream")\n .PostAsStringAsync();\n'))),(0,s.kt)("h3",{id:"19420-\u8bbe\u7f6e-iserviceprovider"},"19.4.20 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"IServiceProvider")),(0,s.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u6784\u5efa\u4e00\u4e2a\u4f5c\u7528\u57df\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"IServiceProvider"),"\uff0c\u8fd9\u65f6\u53ea\u9700\u8981\u8bbe\u7f6e\u5373\u53ef\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var res = await "https://www.furion.icu/upload".SetRequestScoped(services);\n')),(0,s.kt)("h3",{id:"19421-\u8bbe\u7f6e-timeout-\u8d85\u65f6\u65f6\u95f4"},"19.4.21 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Timeout")," \u8d85\u65f6\u65f6\u95f4"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var res = await "https://www.furion.icu/upload".SetClientTimeout(10); // \u5355\u4f4d\u79d2\n')),(0,s.kt)("h3",{id:"19422-\u652f\u6301\u6a21\u677f\u914d\u7f6e"},"19.4.22 \u652f\u6301\u6a21\u677f\u914d\u7f6e"),(0,s.kt)("p",null,"\u6a21\u677f\u683c\u5f0f\u4e3a\uff1a",(0,s.kt)("inlineCode",{parentName:"p"},"#(\u914d\u7f6e\u8def\u5f84)")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var res = await "#(Furion:Address)/upload".GetAsync();\n')),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "Furion": {\n "Address": "https://www.furion.icu"\n }\n}\n')),(0,s.kt)("h3",{id:"19423-\u91cd\u8bd5\u7b56\u7565"},"19.4.23 \u91cd\u8bd5\u7b56\u7565"),(0,s.kt)("p",null,"\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion v2.18+")," \u7248\u672c\u652f\u6301\u914d\u7f6e\u91cd\u8bd5\u7b56\u7565\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var res = await "https://www.furion.icu".SetRetryPolicy(3, 1000).GetAsync();\n')),(0,s.kt)("p",null,"\u4ee5\u4e0a\u4ee3\u7801\u8868\u793a\u8bf7\u6c42\u5931\u8d25\u91cd\u8bd5 ",(0,s.kt)("inlineCode",{parentName:"p"},"3")," \u6b21\uff0c\u6bcf\u6b21\u5ef6\u8fdf ",(0,s.kt)("inlineCode",{parentName:"p"},"1000ms")," \u3002"),(0,s.kt)("h3",{id:"19424-\u652f\u6301-gzip-\u538b\u7f29"},"19.4.24 \u652f\u6301 ",(0,s.kt)("inlineCode",{parentName:"h3"},"GZip")," \u538b\u7f29"),(0,s.kt)("p",null,"\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion v3.2.0+")," \u7248\u672c\u652f\u6301",(0,s.kt)("inlineCode",{parentName:"p"},"GZip")," \u538b\u7f29\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var res = await "https://www.furion.icu".WithGZip().GetAsync();\n')),(0,s.kt)("h3",{id:"19425-\u8bbe\u7f6e-url-\u8f6c\u7801"},"19.4.25 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Url")," \u8f6c\u7801"),(0,s.kt)("p",null,"\u8fc7\u53bb\u7248\u672c\u4f1a\u5bf9\u6240\u6709\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"Url")," \u8fdb\u884c ",(0,s.kt)("inlineCode",{parentName:"p"},"Uri.EscapeDataString")," \u8f6c\u7801\uff0c\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion v3.8.0+")," \u7248\u672c\u652f\u6301 ",(0,s.kt)("inlineCode",{parentName:"p"},"Url")," \u8f6c\u7801\u8bbe\u7f6e\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var res = await "https://www.furion.icu".WithEncodeUrl(false).GetAsync();\n')),(0,s.kt)("h2",{id:"195-ihttpdispatchproxy-\u4ee3\u7406\u65b9\u5f0f"},"19.5 ",(0,s.kt)("inlineCode",{parentName:"h2"},"IHttpDispatchProxy")," \u4ee3\u7406\u65b9\u5f0f"),(0,s.kt)("h3",{id:"1951-\u652f\u6301\u591a\u79cd\u4ee3\u7406\u65b9\u5f0f"},"19.5.1 \u652f\u6301\u591a\u79cd\u4ee3\u7406\u65b9\u5f0f"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public interface IHttp : IHttpDispatchProxy\n{\n // \u53d1\u9001 Get \u8bf7\u6c42\n [Get("https://www.furion.icu/get")]\n Task GetXXXAsync();\n\n // \u53d1\u9001 Post \u8bf7\u6c42\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync();\n\n // \u53d1\u9001 Put \u8bf7\u6c42\n [Put("https://www.furion.icu/put")]\n Task PutXXXAsync();\n\n // \u53d1\u9001 Delete \u8bf7\u6c42\n [Delete("https://www.furion.icu/delete")]\n Task DeleteXXXAsync();\n\n // \u53d1\u9001 Patch \u8bf7\u6c42\n [Patch("https://www.furion.icu/patch")]\n Task PatchXXXAsync();\n\n // \u53d1\u9001 Head \u8bf7\u6c42\n [Head("https://www.furion.icu/head")]\n Task HeadXXXAsync();\n}\n')),(0,s.kt)("h3",{id:"1952-\u8bbe\u7f6e\u5730\u5740\u6a21\u677f"},"19.5.2 \u8bbe\u7f6e\u5730\u5740\u6a21\u677f"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Get("https://www.furion.icu/get/{id}?name={name}&number={p.PersonDetail.PhonNumber}")]\n Task GetXXXAsync(int id, string name, Person p);\n}\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u6ce8\uff1a\u6a21\u677f\u66ff\u6362\u533a\u5206\u5927\u5c0f\u5199\u3002")),(0,s.kt)("h3",{id:"1953-\u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934"},"19.5.3 \u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u6a21\u5f0f\u63d0\u4f9b\u4e09\u79cd\u65b9\u5f0f\u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u652f\u6301\u5728\u63a5\u53e3\u4e2d\u58f0\u660e"),(0,s.kt)("li",{parentName:"ul"},"\u652f\u6301\u5728\u65b9\u6cd5\u4e2d\u58f0\u660e"),(0,s.kt)("li",{parentName:"ul"},"\u652f\u6301\u5728\u53c2\u6570\u4e2d\u58f0\u660e")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-2,5,9,12}",showLineNumbers:!0,"":!0,"{1-2,5,9,12}":!0},'[Headers("key","value")]\n[Headers("key1","value2")] // \u8bbe\u7f6e\u591a\u4e2a\npublic interface IHttp : IHttpDispatchProxy\n{\n [Get("https://www.furion.icu/get/{id}?name={name}"), Headers("key2","value2")]\n Task GetXXXAsync(int id, string name);\n\n [Get("https://www.furion.icu")]\n Task GetXXX2Async(int id, [Headers]string token = default);\n\n [Get("https://www.furion.icu")]\n Task GetXXX2Async(int id, string name, [Headers("\u522b\u540d")]string token = default);\n}\n')),(0,s.kt)("h3",{id:"1954-\u8bbe\u7f6e-url-\u5730\u5740\u53c2\u6570"},"19.5.4 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"URL")," \u5730\u5740\u53c2\u6570"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,7,10,13}",showLineNumbers:!0,"":!0,"{4,7,10,13}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Get("https://www.furion.icu/get/{id}?name={name}")]\n Task GetXXXAsync(int id, string name);\n\n [Get("https://www.furion.icu/get/{p.Id}?name={p.Name}")]\n Task GetXXXAsync(Person p);\n\n [Get("https://www.furion.icu/get")]\n Task GetXXXAsync([QueryString]int id, [QueryString]string name);\n\n [Get("https://www.furion.icu/get")]\n Task GetXXXAsync([QueryString]int id, [QueryString("\u522b\u540d")]string name);\n}\n')),(0,s.kt)("p",null,"\u6700\u7ec8\u8f93\u51fa\u683c\u5f0f\u4e3a\uff1a",(0,s.kt)("inlineCode",{parentName:"p"},"https://www.furion.icu/get?id=1&name=Furion"),"\u3002"),(0,s.kt)("h3",{id:"1955-\u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef"},"19.5.5 \u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("strong",{parentName:"li"},"\u5168\u5c40\u914d\u7f6e\u65b9\u5f0f"))),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3-4,14}",showLineNumbers:!0,"":!0,"{1,3-4,14}":!0},'services.AddRemoteRequest(options=>\n{\n // \u914d\u7f6e Github \u57fa\u672c\u4fe1\u606f\n options.AddHttpClient("github", c =>\n {\n c.BaseAddress = new Uri("https://api.github.com/");\n c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");\n c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");\n });\n});\n\npublic interface IHttp : IHttpDispatchProxy\n{\n [Get("get"), Client("github")]\n Task GetXXXAsync();\n}\n')),(0,s.kt)("p",null,"\u6700\u7ec8\u751f\u6210\u8bf7\u6c42\u5730\u5740\u4e3a\uff1a",(0,s.kt)("inlineCode",{parentName:"p"},"https://api.github.com/get"),"\u3002"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("strong",{parentName:"li"},"\u5c40\u90e8\u914d\u7f6e\u65b9\u5f0f"))),(0,s.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,s.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion 4.3.8 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,7-11}",showLineNumbers:!0,"{5,7-11}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n // \u5c40\u90e8\u65b9\u5f0f\n [Get("get")]\n Task GetXXXAsync([Interceptor(InterceptorTypes.Initiate)]Func clientProvider);\n\n // \u5168\u5c40\u9759\u6001\u65b9\u5f0f\n [Interceptor(InterceptorTypes.Initiate)]\n static HttpClient CreateHttpClient()\n {\n return new HttpClient(...);\n }\n}\n')),(0,s.kt)("h3",{id:"1956-\u8bbe\u7f6e-body-\u53c2\u6570"},"19.5.6 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Body")," \u53c2\u6570"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,6,9}",showLineNumbers:!0,"":!0,"{3,6,9}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Body]User user);\n\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Body("application/x-www-form-urlencoded")]User user);\n\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Body("application/x-www-form-urlencoded", "UTF-8")]User user);\n}\n')),(0,s.kt)("h3",{id:"1957-\u8bbe\u7f6e-json-\u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f"},"19.5.7 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"JSON")," \u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u9ed8\u8ba4\u60c5\u51b5\u4e0b\u91c7\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"System.Text.Json")," \u8fdb\u884c ",(0,s.kt)("inlineCode",{parentName:"p"},"JSON")," \u5e8f\u5217\u5316\u5904\u7406\uff0c\u5982\u9700\u8bbe\u7f6e\u7b2c\u4e09\u65b9 ",(0,s.kt)("inlineCode",{parentName:"p"},"JSON")," \u63d0\u4f9b\u5668\uff0c\u5219\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,6-7}",showLineNumbers:!0,"":!0,"{3,6-7}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu/post"), JsonSerialization(typeof(NewtonsoftJsonSerializerProvider))]\n Task PostXXXAsync([Body]User user);\n\n [Post("https://www.furion.icu/post"), JsonSerialization(typeof(NewtonsoftJsonSerializerProvider))]\n Task PostXXXAsync([Body]User user, [JsonSerializerOptions]object jsonSerializerOptions = default);\n\n /// \n /// \u7f3a\u7701\u5e8f\u5217\u5316\u914d\u7f6e\n /// \n /// \n [JsonSerializerOptions]\n static object GetJsonSerializerOptions()\n {\n // \u8fd9\u91cc\u4e5f\u53ef\u4ee5\u901a\u8fc7 JSON.GetSerializerOptions() \u83b7\u53d6 Startup.cs \u4e2d\u7684\u914d\u7f6e\n return new JsonSerializerOptions\n {\n\n };\n }\n}\n')),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"[JsonSerializerOptions]")," \u53ef\u4ee5\u6807\u8bb0\u53c2\u6570\u662f\u4e00\u4e2a ",(0,s.kt)("inlineCode",{parentName:"p"},"JSON")," \u5e8f\u5217\u5316\u914d\u7f6e\u53c2\u6570\u3002"),(0,s.kt)("admonition",{type:"important"},(0,s.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u5173\u4e8e ",(0,s.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"JSON")," \u5e8f\u5217\u5316\u63d0\u4f9b\u5668"),(0,s.kt)("p",{parentName:"admonition"},"\u5982\u9700\u4e86\u89e3\u66f4\u591a ",(0,s.kt)("inlineCode",{parentName:"p"},"JSON")," \u5e8f\u5217\u5316\u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,s.kt)("a",{parentName:"p",href:"json-serialization#2351-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BA%8F%E5%88%97%E5%8C%96%E6%8F%90%E4%BE%9B%E5%99%A8"},"23. JSON \u5e8f\u5217\u5316")," \u7ae0\u8282")),(0,s.kt)("h3",{id:"1958-\u53c2\u6570\u9a8c\u8bc1"},"19.5.8 \u53c2\u6570\u9a8c\u8bc1"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,7}",showLineNumbers:!0,"":!0,"{4,7}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Range(1,10)]int id, [Required, MaxLength(10)]string name);\n\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Required]User user); // \u5bf9\u8c61\u7c7b\u578b\u652f\u6301\u5c5e\u6027\u914d\u7f6e\u7279\u6027\u9a8c\u8bc1\n}\n')),(0,s.kt)("h3",{id:"1959-\u8bf7\u6c42\u62e6\u622a"},"19.5.9 \u8bf7\u6c42\u62e6\u622a"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u65b9\u5f0f\u63d0\u4f9b\u4e24\u79cd\u62e6\u622a\u65b9\u5f0f\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u63a5\u53e3\u9759\u6001\u65b9\u6cd5\u62e6\u622a"),(0,s.kt)("li",{parentName:"ul"},"\u53c2\u6570\u6807\u8bb0\u62e6\u622a")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8,18}",showLineNumbers:!0,"":!0,"{5,8,18}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n // \u901a\u8fc7\u53c2\u6570\u62e6\u622a\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Interceptor(InterceptorTypes.Request)] Action action = default);\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Request)]\n static void OnRequesting1(HttpClient client, HttpRequestMessage req)\n {\n // \u8ffd\u52a0\u66f4\u591a\u53c2\u6570\n req.AppendQueries(new Dictionary {\n { "access_token", "xxxx"}\n });\n }\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Request)]\n static void OnRequesting2(HttpClient client, HttpRequestMessage req)\n {\n\n }\n}\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19510-httpclient-\u62e6\u622a"},"19.5.10 ",(0,s.kt)("inlineCode",{parentName:"h3"},"HttpClient")," \u62e6\u622a"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u65b9\u5f0f\u63d0\u4f9b\u4e24\u79cd\u62e6\u622a\u65b9\u5f0f\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u63a5\u53e3\u9759\u6001\u65b9\u6cd5\u62e6\u622a"),(0,s.kt)("li",{parentName:"ul"},"\u53c2\u6570\u6807\u8bb0\u62e6\u622a")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8,15}",showLineNumbers:!0,"":!0,"{5,8,15}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n // \u901a\u8fc7\u53c2\u6570\u62e6\u622a\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Interceptor(InterceptorTypes.Client)] Action action = default);\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Client)]\n static void onClientCreating1(HttpClient client)\n {\n\n }\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Client)]\n static void onClientCreating2(HttpClient client)\n {\n\n }\n}\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19511-\u8bf7\u6c42\u4e4b\u524d\u62e6\u622a"},"19.5.11 \u8bf7\u6c42\u4e4b\u524d\u62e6\u622a"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u65b9\u5f0f\u63d0\u4f9b\u4e24\u79cd\u62e6\u622a\u65b9\u5f0f\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u63a5\u53e3\u9759\u6001\u65b9\u6cd5\u62e6\u622a"),(0,s.kt)("li",{parentName:"ul"},"\u53c2\u6570\u6807\u8bb0\u62e6\u622a")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8,15}",showLineNumbers:!0,"":!0,"{5,8,15}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n // \u901a\u8fc7\u53c2\u6570\u62e6\u622a\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Interceptor(InterceptorTypes.Request)] Action action = default);\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Request)]\n static void OnRequest1(HttpClient client, HttpRequestMessage req)\n {\n\n }\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Request)]\n static void OnRequest2(HttpClient client, HttpRequestMessage req)\n {\n\n }\n}\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19512-\u6210\u529f\u8bf7\u6c42\u62e6\u622a"},"19.5.12 \u6210\u529f\u8bf7\u6c42\u62e6\u622a"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u65b9\u5f0f\u63d0\u4f9b\u4e24\u79cd\u62e6\u622a\u65b9\u5f0f\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u63a5\u53e3\u9759\u6001\u65b9\u6cd5\u62e6\u622a"),(0,s.kt)("li",{parentName:"ul"},"\u53c2\u6570\u6807\u8bb0\u62e6\u622a")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8,15}",showLineNumbers:!0,"":!0,"{5,8,15}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n // \u901a\u8fc7\u53c2\u6570\u62e6\u622a\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Interceptor(InterceptorTypes.Response)] Action action = default);\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Response)]\n static void OnResponsing1(HttpClien client, HttpResponseMessage res)\n {\n\n }\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Response)]\n static void OnResponsing2(HttpClien client, HttpResponseMessage res)\n {\n\n }\n}\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19513-\u8bf7\u6c42\u5f02\u5e38\u62e6\u622a"},"19.5.13 \u8bf7\u6c42\u5f02\u5e38\u62e6\u622a"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u65b9\u5f0f\u63d0\u4f9b\u4e24\u79cd\u62e6\u622a\u65b9\u5f0f\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u63a5\u53e3\u9759\u6001\u65b9\u6cd5\u62e6\u622a"),(0,s.kt)("li",{parentName:"ul"},"\u53c2\u6570\u6807\u8bb0\u62e6\u622a")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8,15}",showLineNumbers:!0,"":!0,"{5,8,15}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n // \u901a\u8fc7\u53c2\u6570\u62e6\u622a\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Interceptor(InterceptorTypes.Exception)] Action action = default);\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Exception)]\n static void OnException1(HttpClient client, HttpResponseMessage res, string errors)\n {\n\n }\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Exception)]\n static void OnException2(HttpClient client, HttpResponseMessage res, string errors)\n {\n\n }\n}\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19514-\u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406"},"19.5.14 \u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fdc\u7a0b\u8bf7\u6c42\u9ed8\u8ba4\u63d0\u4f9b\u56db\u79cd\u8fd4\u56de\u503c\u7c7b\u578b\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"HttpResponseMessage"),"\uff1a\u8bf7\u6c42\u54cd\u5e94\u6d88\u606f\u7c7b\u578b"),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"Stream"),"\uff1a\u6d41\u7c7b\u578b"),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"T"),"\uff1a\u6cdb\u578b ",(0,s.kt)("inlineCode",{parentName:"li"},"T")," \u7c7b\u578b"),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"String"),"\uff1a\u5b57\u7b26\u4e32\u7c7b\u578b\uff0c\u4e5f\u5c31\u662f\u76f4\u63a5\u5c06\u7f51\u7edc\u8bf7\u6c42\u7ed3\u679c\u5185\u5bb9\u5b57\u7b26\u4e32\u5316")),(0,s.kt)("p",null,"\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync();\n\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync();\n\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync();\n\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync();\n}\n')),(0,s.kt)("h3",{id:"19515-\u8bbe\u7f6e-byte-\u7c7b\u578b\u4e0a\u4f20\u6587\u4ef6"},"19.5.15 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Byte[]")," \u7c7b\u578b/\u4e0a\u4f20\u6587\u4ef6"),(0,s.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u4e0a\u4f20\u6587\u4ef6\uff0c\u9700\u8981\u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"p"},"Content-Type")," \u4e3a ",(0,s.kt)("inlineCode",{parentName:"p"},"multipart/form-data")," \u7c7b\u578b\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,4}",showLineNumbers:!0,"{3,4}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")] // bytes \u53ef\u4ee5\u901a\u8fc7 File.ReadAllBytes(\u6587\u4ef6\u8def\u5f84) \u83b7\u53d6\n Task PostXXXAsync([BodyBytes("\u952e","\u6587\u4ef6\u540d")]Byte[] bytes);\n\n // \u652f\u6301\u591a\u4e2a\u6587\u4ef6\n [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")] // bytes \u53ef\u4ee5\u901a\u8fc7 File.ReadAllBytes(\u6587\u4ef6\u8def\u5f84) \u83b7\u53d6\n Task PostXXXAsync([BodyBytes("\u952e","\u6587\u4ef6\u540d")]Byte[] bytes,[BodyBytes("\u952e","\u6587\u4ef6\u540d")]Byte[] bytes2);\n}\n')),(0,s.kt)("h3",{id:"19516-\u8bbe\u7f6e-timeout-\u8d85\u65f6\u65f6\u95f4"},"19.5.16 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Timeout")," \u8d85\u65f6\u65f6\u95f4"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[Timeout(1000)]\npublic interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu/upload"), Timeout(500)] // \u5355\u4f4d\u79d2\n Task PostXXXAsync([Body]User user);\n}\n')),(0,s.kt)("h3",{id:"19517-\u652f\u6301\u6a21\u677f\u914d\u7f6e"},"19.5.17 \u652f\u6301\u6a21\u677f\u914d\u7f6e"),(0,s.kt)("p",null,"\u6a21\u677f\u683c\u5f0f\u4e3a\uff1a",(0,s.kt)("inlineCode",{parentName:"p"},"#(\u914d\u7f6e\u8def\u5f84)")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("#(Furion:Address)/upload")]\n Task PostXXXAsync([Body]User user);\n}\n')),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "Furion": {\n "Address": "https://www.furion.icu"\n }\n}\n')),(0,s.kt)("p",null,"\u65b9\u6cd5\u7684\u4f18\u5148\u7ea7\u9ad8\u4e8e\u63a5\u53e3\u5b9a\u4e49\u7684\u4f18\u5148\u7ea7\u3002"),(0,s.kt)("h3",{id:"19518-\u91cd\u8bd5\u7b56\u7565"},"19.5.18 \u91cd\u8bd5\u7b56\u7565"),(0,s.kt)("p",null,"\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion v2.18+")," \u7248\u672c\u652f\u6301\u914d\u7f6e\u91cd\u8bd5\u7b56\u7565\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[RetryPolicy(3, 1000)] // \u652f\u6301\u5168\u5c40\npublic interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu"), RetryPolicy(3, 1000)] // \u652f\u6301\u5c40\u90e8\n Task PostXXXAsync([Body]User user);\n}\n')),(0,s.kt)("p",null,"\u4ee5\u4e0a\u4ee3\u7801\u8868\u793a\u8bf7\u6c42\u5931\u8d25\u91cd\u8bd5 ",(0,s.kt)("inlineCode",{parentName:"p"},"3")," \u6b21\uff0c\u6bcf\u6b21\u5ef6\u8fdf ",(0,s.kt)("inlineCode",{parentName:"p"},"1000ms")," \u3002"),(0,s.kt)("h3",{id:"19519-\u652f\u6301-gzip"},"19.5.19 \u652f\u6301 ",(0,s.kt)("inlineCode",{parentName:"h3"},"GZip")),(0,s.kt)("p",null,"\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion v3.2.0+")," \u7248\u672c\u652f\u6301 ",(0,s.kt)("inlineCode",{parentName:"p"},"GZip"),"\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu", WithGZip = true)]\n Task PostXXXAsync([Body]User user);\n}\n')),(0,s.kt)("h3",{id:"19520-\u8bbe\u7f6e-url-\u8f6c\u7801"},"19.5.20 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Url")," \u8f6c\u7801"),(0,s.kt)("p",null,"\u8fc7\u53bb\u7248\u672c\u4f1a\u5bf9\u6240\u6709\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"Url")," \u8fdb\u884c ",(0,s.kt)("inlineCode",{parentName:"p"},"Uri.EscapeDataString")," \u8f6c\u7801\uff0c\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion v3.8.0+")," \u7248\u672c\u652f\u6301 ",(0,s.kt)("inlineCode",{parentName:"p"},"Url")," \u8f6c\u7801\u8bbe\u7f6e\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu", WithEncodeUrl = false)]\n Task PostXXXAsync([Body]User user);\n}\n')),(0,s.kt)("h2",{id:"196-\u8bf7\u6c42\u5ba2\u6237\u7aef\u914d\u7f6e"},"19.6 \u8bf7\u6c42\u5ba2\u6237\u7aef\u914d\u7f6e"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e5f\u63d0\u4f9b\u4e86\u591a\u4e2a\u8bf7\u6c42\u5ba2\u6237\u7aef\u914d\u7f6e\uff0c\u53ef\u4ee5\u4e3a\u591a\u4e2a\u5ba2\u6237\u7aef\u8bf7\u6c42\u914d\u7f6e\u9ed8\u8ba4\u8bf7\u6c42\u4fe1\u606f\uff0c\u76ee\u524d\u652f\u6301\u56db\u79cd\u6a21\u5f0f\u8fdb\u884c\u914d\u7f6e\u3002"),(0,s.kt)("h3",{id:"1961-startupcs-\u7edf\u4e00\u914d\u7f6e"},"19.6.1 ",(0,s.kt)("inlineCode",{parentName:"h3"},"Startup.cs")," \u7edf\u4e00\u914d\u7f6e"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,9}",showLineNumbers:!0,"":!0,"{4,9}":!0},'services.AddRemoteRequest(options=>\n{\n // \u914d\u7f6e\u9ed8\u8ba4 HttpClient\n options.AddHttpClient(string.Empty, c => {\n // \u5176\u4ed6\u914d\u7f6e\n });\n\n // \u914d\u7f6e\u7279\u5b9a\u5ba2\u6237\u7aef\n options.AddHttpClient("github", c =>\n {\n c.BaseAddress = new Uri("https://api.github.com/");\n c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");\n c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");\n });\n})\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u914d\u7f6e\u4e86\u547d\u540d\u5ba2\u6237\u7aef\u540e\uff0c\u6bcf\u6b21\u8bf7\u6c42\u90fd\u4f1a\u81ea\u52a8\u52a0\u4e0a\u8fd9\u4e9b\u914d\u7f6e\u3002")),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u5728 ",(0,s.kt)("inlineCode",{parentName:"li"},"\u4ee3\u7406\u8bf7\u6c42")," \u4f7f\u7528")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[Get("api/getdata"), Client("github")]\nTask GetData();\n\n[Put("api/getdata"), Client("facebook")]\nTask GetData();\n')),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u5728 ",(0,s.kt)("inlineCode",{parentName:"li"},"\u5b57\u7b26\u4e32\u62d3\u5c55")," \u4f7f\u7528")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u8bbe\u7f6e\u8bf7\u6c42\u62e6\u622a\nvar response = await "http://47.100.247.61/api/sysdata/categories".SetClient("github").PostAsync();\n')),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u5728 ",(0,s.kt)("inlineCode",{parentName:"li"},"IHttpClientFactory")," \u4e2d\u4f7f\u7528")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,13}",showLineNumbers:!0,"{3,13}":!0},'public class ValuesController : Controller\n{\n private readonly IHttpClientFactory _httpClientFactory;\n\n public ValuesController(IHttpClientFactory httpClientFactory)\n {\n _httpClientFactory = httpClientFactory;\n }\n\n [HttpGet]\n public async Task Get()\n {\n var client = _httpClientFactory.CreateClient("github");\n string result = await client.GetStringAsync("/");\n return Ok(result);\n }\n}\n')),(0,s.kt)("h3",{id:"1962-\u81ea\u5b9a\u4e49-client-\u7c7b\u65b9\u5f0f"},"19.6.2 \u81ea\u5b9a\u4e49 ",(0,s.kt)("inlineCode",{parentName:"h3"},"Client")," \u7c7b\u65b9\u5f0f"),(0,s.kt)("p",null,"\u6211\u4eec\u53ef\u4ee5\u6309\u7167\u4e00\u5b9a\u7684\u89c4\u5219\u7f16\u5199\u7279\u5b9a\u670d\u52a1\u7684\u8bf7\u6c42\u5ba2\u6237\u7aef\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,5}",showLineNumbers:!0,"{1,3,5}":!0},'public class GitHubClient\n{\n public HttpClient Client { get; private set; }\n\n public GitHubClient(HttpClient httpClient)\n {\n httpClient.BaseAddress = new Uri("https://api.github.com/");\n httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");\n httpClient.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");\n Client = httpClient;\n }\n}\n')),(0,s.kt)("p",null,"\u7136\u540e\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddHttpClient();\n")),(0,s.kt)("p",null,"\u4f7f\u7528\u5982\u4e0b\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,13}",showLineNumbers:!0,"{3,13}":!0},'public class ValuesController : Controller\n{\n private readonly GitHubClient _gitHubClient;;\n\n public ValuesController(GitHubClient gitHubClient)\n {\n _gitHubClient = gitHubClient;\n }\n\n [HttpGet]\n public async Task Get()\n {\n string result = await _gitHubClient.Client.GetStringAsync("/");\n return Ok(result);\n }\n}\n')),(0,s.kt)("h3",{id:"1963-\u81ea\u5b9a\u4e49-client-\u7c7b--\u63a5\u53e3\u65b9\u5f0f"},"19.6.3 \u81ea\u5b9a\u4e49 ",(0,s.kt)("inlineCode",{parentName:"h3"},"Client")," \u7c7b + \u63a5\u53e3\u65b9\u5f0f"),(0,s.kt)("p",null,"\u6211\u4eec\u4e5f\u53ef\u4ee5\u5b9a\u4e49\u63a5\u53e3\uff0c\u901a\u8fc7\u63a5\u53e3\u7684\u63d0\u4f9b\u5177\u4f53\u7684\u670d\u52a1 ",(0,s.kt)("inlineCode",{parentName:"p"},"API")," \u64cd\u4f5c\uff0c\u65e0\u9700\u624b\u52a8\u914d\u7f6e ",(0,s.kt)("inlineCode",{parentName:"p"},"Url"),"\uff0c\u5982\u4e0a\u9762\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},'GetStringAsync("/")'),"\u3002"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,6,10,18-21}",showLineNumbers:!0,"{1,3,6,10,18-21}":!0},'public interface IGitHubClient\n{\n Task GetData();\n}\n\npublic class GitHubClient : IGitHubClient\n{\n private readonly HttpClient _client;\n\n public GitHubClient(HttpClient httpClient)\n {\n httpClient.BaseAddress = new Uri("https://api.github.com/");\n httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");\n httpClient.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");\n _client = httpClient;\n }\n\n public async Task GetData()\n {\n return await _client.GetStringAsync("/");\n }\n}\n')),(0,s.kt)("p",null,"\u7136\u540e\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddHttpClient();\n")),(0,s.kt)("p",null,"\u4f7f\u7528\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,13}",showLineNumbers:!0,"{3,13}":!0},"public class ValuesController : Controller\n{\n private readonly IGitHubClient _gitHubClient;;\n\n public ValuesController(IGitHubClient gitHubClient)\n {\n _gitHubClient = gitHubClient;\n }\n\n [HttpGet]\n public async Task Get()\n {\n string result = await _gitHubClient.GetData();\n return Ok(result);\n }\n}\n")),(0,s.kt)("h2",{id:"197-sslhttps-\u8bc1\u4e66\u914d\u7f6e"},"19.7 ",(0,s.kt)("inlineCode",{parentName:"h2"},"SSL/https")," \u8bc1\u4e66\u914d\u7f6e"),(0,s.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u8bf7\u6c42\u8fdc\u7a0b\u63a5\u53e3\u65f6\u4f1a\u9047\u5230 ",(0,s.kt)("inlineCode",{parentName:"p"},"The SSL connection could not be established, see inner exception.")," \u8fd9\u6837\u7684\u9519\u8bef\uff0c\u539f\u56e0\u662f\u8bc1\u4e66\u914d\u7f6e\u4e0d\u6b63\u786e\u95ee\u9898\uff0c\u4e0b\u9762\u6709\u51e0\u79cd\u89e3\u51b3\u65b9\u6cd5\u3002"),(0,s.kt)("h3",{id:"1971-\u5ffd\u7565\u7279\u5b9a\u5ba2\u6237\u7aef-ssl-\u8bc1\u4e66\u68c0\u67e5"},"19.7.1 \u5ffd\u7565\u7279\u5b9a\u5ba2\u6237\u7aef ",(0,s.kt)("inlineCode",{parentName:"h3"},"SSL")," \u8bc1\u4e66\u68c0\u67e5"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,7,12,14}",showLineNumbers:!0,"{5,7,12,14}":!0},'services.AddRemoteRequest(options=>\n{\n // \u9ed8\u8ba4 HttpClient \u5728 Furion \u6846\u67b6\u5185\u90e8\u5df2\u7ecf\u914d\u7f6e\u4e86\u8be5\u64cd\u4f5c\n options.AddHttpClient(string.Empty)\n .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler\n {\n ServerCertificateCustomValidationCallback = (_, _, _, _) => true,\n });\n\n // \u914d\u7f6e\u7279\u5b9a\u5ba2\u6237\u7aef\n options.AddHttpClient("github", c => { /*\u5176\u4ed6\u914d\u7f6e*/ })\n .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler\n {\n ServerCertificateCustomValidationCallback = (_, _, _, _) => true,\n });\n});\n')),(0,s.kt)("admonition",{type:"tip"},(0,s.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u5173\u4e8e ",(0,s.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"HttpClientHandler")," \u548c ",(0,s.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"SocketsHttpHandler")),(0,s.kt)("p",{parentName:"admonition"},"\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},".NET6")," \u4e4b\u540e\u9ed8\u8ba4\u4f7f\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"SocketsHttpHandler ")," \u4f5c\u4e3a\u9ed8\u8ba4\u5e95\u5c42\u7f51\u7edc\u901a\u4fe1\uff0c\u4f46\u6bd4 ",(0,s.kt)("inlineCode",{parentName:"p"},"HttpClientHandler")," \u63d0\u4f9b\u4e86\u66f4\u591a\u5e73\u53f0\u65e0\u5dee\u5f02\u7684\u529f\u80fd\uff0c\u5bf9 ",(0,s.kt)("inlineCode",{parentName:"p"},"HttpClientHandler")," \u7684\u4efb\u4f55\u8bbe\u7f6e\u90fd\u4f1a\u8f6c\u53d1\u5230 ",(0,s.kt)("inlineCode",{parentName:"p"},"SocketsHttpHandler")," \u4e2d\uff0c\u5982\u9700\u4f7f\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"SocketsHttpHandler")," \u914d\u7f6e\u53ef\u53c2\u8003\uff1a"),(0,s.kt)("pre",{parentName:"admonition"},(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5-8}",showLineNumbers:!0,"{3,5-8}":!0},"// \u5ffd\u7565 SSL \u4e0d\u5b89\u5168\u68c0\u67e5\uff0c\u6216 https \u4e0d\u5b89\u5168\u6216 https \u8bc1\u4e66\u6709\u8bef\noptions.AddHttpClient(string.Empty)\n .ConfigurePrimaryHttpMessageHandler(u => new SocketsHttpHandler\n {\n SslOptions = new SslClientAuthenticationOptions\n {\n RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true\n }\n });\n"))),(0,s.kt)("h3",{id:"1972-\u624b\u52a8\u6307\u5b9a-ssl-\u8bc1\u4e66"},"19.7.2 \u624b\u52a8\u6307\u5b9a ",(0,s.kt)("inlineCode",{parentName:"h3"},"SSL")," \u8bc1\u4e66"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8-13}",showLineNumbers:!0,"{5,8-13}":!0},'services.AddRemoteRequest(options=>\n{\n // \u914d\u7f6e\u7279\u5b9a\u5ba2\u6237\u7aef\n options.AddHttpClient("github", c => { /*\u5176\u4ed6\u914d\u7f6e*/ })\n .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler\n {\n // \u624b\u52a8\u914d\u7f6e\u8bc1\u4e66\n ClientCertificateOptions = ClientCertificateOption.Manual,\n ClientCertificates = {\n new X509Certificate2("...","..."),\n new X509Certificate2("...","..."),\n new X509Certificate2("...","...")\n }\n });\n});\n')),(0,s.kt)("h3",{id:"1973-\u5ffd\u7565\u6240\u6709\u5ba2\u6237\u7aef\u8bc1\u4e66\u68c0\u67e5"},"19.7.3 \u5ffd\u7565\u6240\u6709\u5ba2\u6237\u7aef\u8bc1\u4e66\u68c0\u67e5"),(0,s.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,s.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion v3.6.6+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4}",showLineNumbers:!0,"{1,4}":!0},"services.AddRemoteRequest(options=>\n{\n // \u9700\u5728\u6240\u6709\u5ba2\u6237\u7aef\u6ce8\u518c\u4e4b\u524d\u6ce8\u518c\n options.ApproveAllCerts();\n});\n")),(0,s.kt)("h2",{id:"198-\u5173\u4e8e\u8fd4\u56de\u503c\u975e-200-\u65f6\u5ffd\u7565-http\u72b6\u6001"},"19.8 \u5173\u4e8e\u8fd4\u56de\u503c\u975e ",(0,s.kt)("inlineCode",{parentName:"h2"},"200")," \u65f6\u5ffd\u7565 ",(0,s.kt)("inlineCode",{parentName:"h2"},"Http\u72b6\u6001")),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u975e\u5e38\u65b9\u4fbf\u7684\u8bf7\u6c42\u5e76\u4e14\u5e8f\u5217\u5316\u8bf7\u6c42\u7ed3\u679c ",(0,s.kt)("inlineCode",{parentName:"p"},"PostAsAsync"),"\n\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"2.8.8")," \u53ca\u4ee5\u4e0b\u7248\u672c\uff0c\u5f53\u8fd4\u56de\u7ed3\u679c\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"Http")," \u72b6\u6001\u4e3a\u975e ",(0,s.kt)("inlineCode",{parentName:"p"},"200")," \u65f6\uff0c\u4f1a\u76f4\u63a5\u622a\u65ad\u3002\u8003\u8651\u5230\u8bf7\u6c42\u63a5\u53e3\u7684\u591a\u6837\u6027\uff0c\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"2.8.9")," \u53ca\u4ee5\u4e0a\u7248\u672c\u589e\u52a0\u5ffd\u7565\u8fd4\u56de ",(0,s.kt)("inlineCode",{parentName:"p"},"Http")," \u72b6\u6001\uff0c\u76f4\u63a5\u5e8f\u5217\u5316\u7ed3\u679c\u7684\u65b9\u5f0f\u3002"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'//\u8bf7\u6c42\u5e76\u4e14\u5e8f\u5217\u5316\u8bf7\u6c42\u7ed3\u679c\nvar result = await "https://api.facebook.com/"\n //\u5982\u679c\u4e0d\u52a0OnException\uff0c\u5219\u4f1a\u76f4\u63a5\u622a\u65ad\n .OnException((res,errors)=> {\n //\u6fc0\u6d3b\u5f02\u6b65\u62e6\u622a \u6b64\u5904\u53ef\u4ee5\u505a\u8bb0\u5f55\u65e5\u5fd7\u64cd\u4f5c \u4e5f\u53ef\u4fdd\u6301\u73b0\u72b6\n })\n .PostAsAsync();\n')),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"PostAsStringAsync()")," \u4e5f\u4f7f\u7528\u540c\u6837\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"OnException")," \u64cd\u4f5c\u4f7f\u5f97\u5ffd\u7565\u8fd4\u56de ",(0,s.kt)("inlineCode",{parentName:"p"},"Http")," \u72b6\u6001,\u539f\u6837\u8fd4\u56de ",(0,s.kt)("inlineCode",{parentName:"p"},"Http")," \u8bf7\u6c42\u7ed3\u679c"),(0,s.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,s.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4e0d\u52a0 ",(0,s.kt)("inlineCode",{parentName:"p"},"OnException"),"\uff0c\u5219\u4f1a\u76f4\u63a5\u622a\u65ad\u3002\n\u5982\u679c\u9700\u8981\u590d\u6742\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"Http Post")," \u8bf7\u6c42\uff0c\u5efa\u8bae\u76f4\u63a5\u4f7f\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"PostAsync"),",\u8fd4\u56de\u503c\u4e3a ",(0,s.kt)("inlineCode",{parentName:"p"},"HttpResponseMessage"),"\uff0c\u53ef\u4ee5\u66f4\u7075\u6d3b\u7684\u63a7\u5236\u7ed3\u679c\u3002")),(0,s.kt)("h2",{id:"199-\u5173\u4e8e\u540c\u6b65\u8bf7\u6c42"},"19.9 \u5173\u4e8e\u540c\u6b65\u8bf7\u6c42"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u5185\u90e8\u9ed8\u8ba4\u4e0d\u63d0\u4f9b\u540c\u6b65\u8bf7\u6c42\u64cd\u4f5c\uff0c\u5efa\u8bae\u603b\u662f\u4f7f\u7528\u5f02\u6b65\u7684\u65b9\u5f0f\u8bf7\u6c42\u3002\u5982\u5728\u4e0d\u80fd\u4f7f\u7528\u5f02\u6b65\u7684\u60c5\u51b5\u4e0b\uff0c\u53ef\u81ea\u884c\u8f6c\u6362\u4e3a\u540c\u6b65\u6267\u884c\u3002"),(0,s.kt)("h2",{id:"1910-\u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df"},"19.10 \u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df"),(0,s.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u6240\u6709\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"\u5b57\u7b26\u4e32")," \u548c ",(0,s.kt)("inlineCode",{parentName:"p"},"\u5b9e\u4f53")," \u62d3\u5c55\u90fd\u6709\u81ea\u5df1\u72ec\u7acb\u7ef4\u62a4\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"ServiceProvider")," \u4f5c\u7528\u57df\u3002"),(0,s.kt)("p",null,"\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Web")," \u8bf7\u6c42\u4e2d\uff0c\u9ed8\u8ba4\u662f ",(0,s.kt)("inlineCode",{parentName:"p"},"HttpContext.RequestServices"),"\uff0c\u4f46\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"\u975e Web"),"\uff0c\u5982\u591a\u7ebf\u7a0b\u64cd\u4f5c\uff0c\u540e\u53f0\u4efb\u52a1\uff0c\u4e8b\u4ef6\u603b\u7ebf\u7b49\u573a\u666f\u4e0b\u4f1a\u81ea\u52a8\u521b\u5efa\u65b0\u7684\u4f5c\u7528\u57df\uff0c\u5b9e\u9645\u4e0a\u8fd9\u662f\u975e\u5e38\u4e0d\u5fc5\u8981\u7684\u5185\u5b58\u5f00\u9500\u3002"),(0,s.kt)("p",null,"\u8fd9\u65f6\uff0c\u6211\u4eec\u53ea\u9700\u8981\u901a\u8fc7 ",(0,s.kt)("inlineCode",{parentName:"p"},".SetXXXScoped(service)")," \u5171\u4eab\u5f53\u524d\u670d\u52a1\u63d0\u4f9b\u5668\u4f5c\u7528\u57df\u5373\u53ef\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'Scoped.Create(async (fac, scope) => {\n var response = await "https://www.furion.icu".SetRequestScoped(scope.ServiceProvider).PostAsync();\n});\n')),(0,s.kt)("h2",{id:"1911-\u9759\u6001-default-\u65b9\u5f0f\u6784\u5efa"},"19.11 \u9759\u6001 ",(0,s.kt)("inlineCode",{parentName:"h2"},"Default")," \u65b9\u5f0f\u6784\u5efa"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await HttpRequestPart.Default.SetRequestUrl("https://www.baidu.com").GetAsStringAsync();\n')),(0,s.kt)("h2",{id:"1912-\u53cd\u9988\u4e0e\u5efa\u8bae"},"19.12 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,s.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,s.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,s.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,s.kt)("hr",null),(0,s.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,s.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,s.kt)("inlineCode",{parentName:"p"},"HttpClient")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,s.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/http-requests?view=aspnetcore-5.0"},"ASP.NET Core - HTTP \u8bf7\u6c42")," \u7ae0\u8282")))}w.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return u},kt:function(){return m}});var a=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function r(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var p=a.createContext({}),o=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},u=function(e){var t=o(e.components);return a.createElement(p.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,s=e.originalType,p=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=o(n),m=i,k=d["".concat(p,".").concat(m)]||d[m]||c[m]||s;return n?a.createElement(k,r(r({ref:t},u),{},{components:n})):a.createElement(k,r({ref:t},u))}));function m(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var s=n.length,r=new Array(s);r[0]=d;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l.mdxType="string"==typeof e?e:i,r[1]=l;for(var o=2;o=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=i.createContext({}),l=function(e){var t=i.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},u=function(e){var t=l(e.components);return i.createElement(p.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},d=i.forwardRef((function(e,t){var n=e.components,a=e.mdxType,s=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),d=l(n),m=a,k=d["".concat(p,".").concat(m)]||d[m]||c[m]||s;return n?i.createElement(k,r(r({ref:t},u),{},{components:n})):i.createElement(k,r({ref:t},u))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var s=n.length,r=new Array(s);r[0]=d;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,r[1]=o;for(var l=2;l child <"+("string"==typeof e.type?e.type:e.type.name)+'>: all children of the component should be , and every should have a unique "value" prop.')})),g=null!=k?k:h.map((function(e){var t=e.props;return{value:t.value,label:t.label,attributes:t.attributes}})),C=(0,o.l)(g,(function(e,t){return e.value===t.value}));if(C.length>0)throw new Error('Docusaurus error: Duplicate values "'+C.map((function(e){return e.value})).join(", ")+'" found in . Every value needs to be unique.');var y=null===m?m:null!=(t=null!=m?m:null==(n=h.find((function(e){return e.props.default})))?void 0:n.props.value)?t:h[0].props.value;if(null!==y&&!g.some((function(e){return e.value===y})))throw new Error('Docusaurus error: The has a defaultValue "'+y+'" but none of its children has the corresponding value. Available values are: '+g.map((function(e){return e.value})).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");var b=(0,p.U)(),v=b.tabGroupChoices,f=b.setTabGroupChoices,H=(0,a.useState)(y),A=H[0],S=H[1],P=[],L=(0,l.o5)().blockElementScrollPositionUntilNextRender;if(null!=w){var T=v[w];null!=T&&T!==A&&g.some((function(e){return e.value===T}))&&S(T)}var X=function(e){var t=e.currentTarget,n=P.indexOf(t),i=g[n].value;i!==A&&(L(t),S(i),null!=w&&f(w,String(i)))},R=function(e){var t,n=null;switch(e.key){case"ArrowRight":var i,a=P.indexOf(e.currentTarget)+1;n=null!=(i=P[a])?i:P[0];break;case"ArrowLeft":var s,r=P.indexOf(e.currentTarget)-1;n=null!=(s=P[r])?s:P[P.length-1]}null==(t=n)||t.focus()};return a.createElement("div",{className:(0,s.Z)("tabs-container",u)},a.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,s.Z)("tabs",{"tabs--block":d},N)},g.map((function(e){var t=e.value,n=e.label,r=e.attributes;return a.createElement("li",(0,i.Z)({role:"tab",tabIndex:A===t?0:-1,"aria-selected":A===t,key:t,ref:function(e){return P.push(e)},onKeyDown:R,onFocus:X,onClick:X},r,{className:(0,s.Z)("tabs__item",c,null==r?void 0:r.className,{"tabs__item--active":A===t})}),null!=n?n:t)}))),r?(0,a.cloneElement)(h.filter((function(e){return e.props.value===A}))[0],{className:"margin-top--md"}):a.createElement("div",{className:"margin-top--md"},h.map((function(e,t){return(0,a.cloneElement)(e,{key:t,hidden:e.props.value!==A})}))))}function m(e){var t=(0,r.Z)();return a.createElement(d,(0,i.Z)({key:String(t)},e))}},2133:function(e,t,n){n.r(t),n.d(t,{assets:function(){return d},contentTitle:function(){return u},default:function(){return w},frontMatter:function(){return l},metadata:function(){return c},toc:function(){return m}});var i=n(3117),a=n(102),s=(n(7294),n(3905)),r=n(5488),o=n(5162),p=["components"],l={id:"http",title:"19. \u8fdc\u7a0b\u8bf7\u6c42",sidebar_label:"19. \u8fdc\u7a0b\u8bf7\u6c42 (HttpClient)"},u=void 0,c={unversionedId:"http",id:"http",title:"19. \u8fdc\u7a0b\u8bf7\u6c42",description:"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 Furion 1.16.0 + \u7248\u672c\u4f7f\u7528\u3002",source:"@site/docs/http.mdx",sourceDirName:".",slug:"/http",permalink:"/furion/docs/http",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/http.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1662345609,formattedLastUpdatedAt:"Sep 5, 2022",frontMatter:{id:"http",title:"19. \u8fdc\u7a0b\u8bf7\u6c42",sidebar_label:"19. \u8fdc\u7a0b\u8bf7\u6c42 (HttpClient)"},sidebar:"docs",previous:{title:"18. \u65e5\u5fd7\u8bb0\u5f55",permalink:"/furion/docs/logging"},next:{title:"20. \u6570\u636e\u52a0\u89e3\u5bc6",permalink:"/furion/docs/encryption"}},d={},m=[{value:"19.1 \u5173\u4e8e\u8fdc\u7a0b\u8bf7\u6c42",id:"191-\u5173\u4e8e\u8fdc\u7a0b\u8bf7\u6c42",level:2},{value:"19.2 \u8fdc\u7a0b\u8bf7\u6c42\u7684\u4f5c\u7528",id:"192-\u8fdc\u7a0b\u8bf7\u6c42\u7684\u4f5c\u7528",level:2},{value:"19.3 \u57fa\u7840\u4f7f\u7528",id:"193-\u57fa\u7840\u4f7f\u7528",level:2},{value:"19.3.1 \u6ce8\u518c\u670d\u52a1",id:"1931-\u6ce8\u518c\u670d\u52a1",level:3},{value:"19.3.2 \u4f7f\u7528\u65b9\u5f0f",id:"1932-\u4f7f\u7528\u65b9\u5f0f",level:3},{value:"19.4 \u5b57\u7b26\u4e32\u65b9\u5f0f\u4f7f\u7528\u793a\u4f8b",id:"194-\u5b57\u7b26\u4e32\u65b9\u5f0f\u4f7f\u7528\u793a\u4f8b",level:2},{value:"19.4.1 \u5185\u7f6e\u8bf7\u6c42\u65b9\u5f0f",id:"1941-\u5185\u7f6e\u8bf7\u6c42\u65b9\u5f0f",level:3},{value:"19.4.2 \u8bbe\u7f6e\u8bf7\u6c42\u5730\u5740",id:"1942-\u8bbe\u7f6e\u8bf7\u6c42\u5730\u5740",level:3},{value:"19.4.3 \u8bbe\u7f6e\u8bf7\u6c42\u65b9\u5f0f",id:"1943-\u8bbe\u7f6e\u8bf7\u6c42\u65b9\u5f0f",level:3},{value:"19.4.4 \u8bbe\u7f6e\u5730\u5740\u6a21\u677f",id:"1944-\u8bbe\u7f6e\u5730\u5740\u6a21\u677f",level:3},{value:"19.4.5 \u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934",id:"1945-\u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934",level:3},{value:"19.4.6 \u8bbe\u7f6e URL \u5730\u5740\u53c2\u6570",id:"1946-\u8bbe\u7f6e-url-\u5730\u5740\u53c2\u6570",level:3},{value:"19.4.7 \u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef",id:"1947-\u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef",level:3},{value:"19.4.8 \u8bbe\u7f6e Body \u53c2\u6570",id:"1948-\u8bbe\u7f6e-body-\u53c2\u6570",level:3},{value:"19.4.9 \u8bbe\u7f6e Content-Type",id:"1949-\u8bbe\u7f6e-content-type",level:3},{value:"19.4.10 \u8bbe\u7f6e\u5185\u5bb9\u7f16\u7801",id:"19410-\u8bbe\u7f6e\u5185\u5bb9\u7f16\u7801",level:3},{value:"19.4.11 \u8bbe\u7f6e JSON \u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f",id:"19411-\u8bbe\u7f6e-json-\u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f",level:3},{value:"19.4.12 \u542f\u7528 Body \u53c2\u6570\u9a8c\u8bc1",id:"19412-\u542f\u7528-body-\u53c2\u6570\u9a8c\u8bc1",level:3},{value:"19.4.13 \u8bf7\u6c42\u62e6\u622a",id:"19413-\u8bf7\u6c42\u62e6\u622a",level:3},{value:"19.4.14 HttpClient \u62e6\u622a",id:"19414-httpclient-\u62e6\u622a",level:3},{value:"19.4.15 \u8bf7\u6c42\u4e4b\u524d\u62e6\u622a",id:"19415-\u8bf7\u6c42\u4e4b\u524d\u62e6\u622a",level:3},{value:"19.4.16 \u6210\u529f\u8bf7\u6c42\u62e6\u622a",id:"19416-\u6210\u529f\u8bf7\u6c42\u62e6\u622a",level:3},{value:"19.4.17 \u8bf7\u6c42\u5f02\u5e38\u62e6\u622a",id:"19417-\u8bf7\u6c42\u5f02\u5e38\u62e6\u622a",level:3},{value:"19.4.18 \u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406",id:"19418-\u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406",level:3},{value:"19.4.19 \u8bbe\u7f6e Byte[] \u7c7b\u578b/\u4e0a\u4f20\u6587\u4ef6",id:"19419-\u8bbe\u7f6e-byte-\u7c7b\u578b\u4e0a\u4f20\u6587\u4ef6",level:3},{value:"19.4.20 \u8bbe\u7f6e IServiceProvider",id:"19420-\u8bbe\u7f6e-iserviceprovider",level:3},{value:"19.4.21 \u8bbe\u7f6e Timeout \u8d85\u65f6\u65f6\u95f4",id:"19421-\u8bbe\u7f6e-timeout-\u8d85\u65f6\u65f6\u95f4",level:3},{value:"19.4.22 \u652f\u6301\u6a21\u677f\u914d\u7f6e",id:"19422-\u652f\u6301\u6a21\u677f\u914d\u7f6e",level:3},{value:"19.4.23 \u91cd\u8bd5\u7b56\u7565",id:"19423-\u91cd\u8bd5\u7b56\u7565",level:3},{value:"19.4.24 \u652f\u6301 GZip \u538b\u7f29",id:"19424-\u652f\u6301-gzip-\u538b\u7f29",level:3},{value:"19.4.25 \u8bbe\u7f6e Url \u8f6c\u7801",id:"19425-\u8bbe\u7f6e-url-\u8f6c\u7801",level:3},{value:"19.5 IHttpDispatchProxy \u4ee3\u7406\u65b9\u5f0f",id:"195-ihttpdispatchproxy-\u4ee3\u7406\u65b9\u5f0f",level:2},{value:"19.5.1 \u652f\u6301\u591a\u79cd\u4ee3\u7406\u65b9\u5f0f",id:"1951-\u652f\u6301\u591a\u79cd\u4ee3\u7406\u65b9\u5f0f",level:3},{value:"19.5.2 \u8bbe\u7f6e\u5730\u5740\u6a21\u677f",id:"1952-\u8bbe\u7f6e\u5730\u5740\u6a21\u677f",level:3},{value:"19.5.3 \u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934",id:"1953-\u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934",level:3},{value:"19.5.4 \u8bbe\u7f6e URL \u5730\u5740\u53c2\u6570",id:"1954-\u8bbe\u7f6e-url-\u5730\u5740\u53c2\u6570",level:3},{value:"19.5.5 \u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef",id:"1955-\u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef",level:3},{value:"19.5.6 \u8bbe\u7f6e Body \u53c2\u6570",id:"1956-\u8bbe\u7f6e-body-\u53c2\u6570",level:3},{value:"19.5.7 \u8bbe\u7f6e JSON \u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f",id:"1957-\u8bbe\u7f6e-json-\u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f",level:3},{value:"19.5.8 \u53c2\u6570\u9a8c\u8bc1",id:"1958-\u53c2\u6570\u9a8c\u8bc1",level:3},{value:"19.5.9 \u8bf7\u6c42\u62e6\u622a",id:"1959-\u8bf7\u6c42\u62e6\u622a",level:3},{value:"19.5.10 HttpClient \u62e6\u622a",id:"19510-httpclient-\u62e6\u622a",level:3},{value:"19.5.11 \u8bf7\u6c42\u4e4b\u524d\u62e6\u622a",id:"19511-\u8bf7\u6c42\u4e4b\u524d\u62e6\u622a",level:3},{value:"19.5.12 \u6210\u529f\u8bf7\u6c42\u62e6\u622a",id:"19512-\u6210\u529f\u8bf7\u6c42\u62e6\u622a",level:3},{value:"19.5.13 \u8bf7\u6c42\u5f02\u5e38\u62e6\u622a",id:"19513-\u8bf7\u6c42\u5f02\u5e38\u62e6\u622a",level:3},{value:"19.5.14 \u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406",id:"19514-\u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406",level:3},{value:"19.5.15 \u8bbe\u7f6e Byte[] \u7c7b\u578b/\u4e0a\u4f20\u6587\u4ef6",id:"19515-\u8bbe\u7f6e-byte-\u7c7b\u578b\u4e0a\u4f20\u6587\u4ef6",level:3},{value:"19.5.16 \u8bbe\u7f6e Timeout \u8d85\u65f6\u65f6\u95f4",id:"19516-\u8bbe\u7f6e-timeout-\u8d85\u65f6\u65f6\u95f4",level:3},{value:"19.5.17 \u652f\u6301\u6a21\u677f\u914d\u7f6e",id:"19517-\u652f\u6301\u6a21\u677f\u914d\u7f6e",level:3},{value:"19.5.18 \u91cd\u8bd5\u7b56\u7565",id:"19518-\u91cd\u8bd5\u7b56\u7565",level:3},{value:"19.5.19 \u652f\u6301 GZip",id:"19519-\u652f\u6301-gzip",level:3},{value:"19.5.20 \u8bbe\u7f6e Url \u8f6c\u7801",id:"19520-\u8bbe\u7f6e-url-\u8f6c\u7801",level:3},{value:"19.6 \u8bf7\u6c42\u5ba2\u6237\u7aef\u914d\u7f6e",id:"196-\u8bf7\u6c42\u5ba2\u6237\u7aef\u914d\u7f6e",level:2},{value:"19.6.1 Startup.cs \u7edf\u4e00\u914d\u7f6e",id:"1961-startupcs-\u7edf\u4e00\u914d\u7f6e",level:3},{value:"19.6.2 \u81ea\u5b9a\u4e49 Client \u7c7b\u65b9\u5f0f",id:"1962-\u81ea\u5b9a\u4e49-client-\u7c7b\u65b9\u5f0f",level:3},{value:"19.6.3 \u81ea\u5b9a\u4e49 Client \u7c7b + \u63a5\u53e3\u65b9\u5f0f",id:"1963-\u81ea\u5b9a\u4e49-client-\u7c7b--\u63a5\u53e3\u65b9\u5f0f",level:3},{value:"19.7 SSL/https \u8bc1\u4e66\u914d\u7f6e",id:"197-sslhttps-\u8bc1\u4e66\u914d\u7f6e",level:2},{value:"19.7.1 \u5ffd\u7565\u7279\u5b9a\u5ba2\u6237\u7aef SSL \u8bc1\u4e66\u68c0\u67e5",id:"1971-\u5ffd\u7565\u7279\u5b9a\u5ba2\u6237\u7aef-ssl-\u8bc1\u4e66\u68c0\u67e5",level:3},{value:"19.7.2 \u624b\u52a8\u6307\u5b9a SSL \u8bc1\u4e66",id:"1972-\u624b\u52a8\u6307\u5b9a-ssl-\u8bc1\u4e66",level:3},{value:"19.7.3 \u5ffd\u7565\u6240\u6709\u5ba2\u6237\u7aef\u8bc1\u4e66\u68c0\u67e5",id:"1973-\u5ffd\u7565\u6240\u6709\u5ba2\u6237\u7aef\u8bc1\u4e66\u68c0\u67e5",level:3},{value:"19.8 \u5173\u4e8e\u8fd4\u56de\u503c\u975e 200 \u65f6\u5ffd\u7565 Http\u72b6\u6001",id:"198-\u5173\u4e8e\u8fd4\u56de\u503c\u975e-200-\u65f6\u5ffd\u7565-http\u72b6\u6001",level:2},{value:"19.9 \u5173\u4e8e\u540c\u6b65\u8bf7\u6c42",id:"199-\u5173\u4e8e\u540c\u6b65\u8bf7\u6c42",level:2},{value:"19.10 \u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df",id:"1910-\u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df",level:2},{value:"19.11 \u9759\u6001 Default \u65b9\u5f0f\u6784\u5efa",id:"1911-\u9759\u6001-default-\u65b9\u5f0f\u6784\u5efa",level:2},{value:"19.12 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"1912-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],k={toc:m};function w(e){var t=e.components,n=(0,a.Z)(e,p);return(0,s.kt)("wrapper",(0,i.Z)({},k,n,{components:t,mdxType:"MDXLayout"}),(0,s.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,s.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion 1.16.0 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,s.kt)("h2",{id:"191-\u5173\u4e8e\u8fdc\u7a0b\u8bf7\u6c42"},"19.1 \u5173\u4e8e\u8fdc\u7a0b\u8bf7\u6c42"),(0,s.kt)("p",null,"\u5728\u4e92\u8054\u7f51\u5927\u6570\u636e\u7684\u9a71\u52a8\u4e0b\uff0c\u5e73\u53f0\u6216\u7cfb\u7edf\u514d\u4e0d\u4e86\u9700\u8981\u548c\u7b2c\u4e09\u65b9\u8fdb\u884c\u6570\u636e\u4ea4\u4e92\uff0c\u800c\u7b2c\u4e09\u65b9\u5f80\u5f80\u63d0\u4f9b\u4e86 ",(0,s.kt)("inlineCode",{parentName:"p"},"RESTful API")," \u63a5\u53e3\u89c4\u8303\uff0c\u8fd9\u4e2a\u65f6\u5019\u5c31\u9700\u8981\u901a\u8fc7 ",(0,s.kt)("inlineCode",{parentName:"p"},"Http")," \u8bf7\u6c42\u7b2c\u4e09\u65b9\u63a5\u53e3\u8fdb\u884c\u6570\u636e\u4f20\u8f93\u4ea4\u4e92\u3002"),(0,s.kt)("p",null,"\u4e5f\u5c31\u662f\u672c\u7ae0\u8282\u6240\u8bf4\u7684\u8fdc\u7a0b\u8bf7\u6c42\u3002"),(0,s.kt)("h2",{id:"192-\u8fdc\u7a0b\u8bf7\u6c42\u7684\u4f5c\u7528"},"19.2 \u8fdc\u7a0b\u8bf7\u6c42\u7684\u4f5c\u7528"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u8de8\u7cfb\u7edf\u3001\u8de8\u8bbe\u5907\u901a\u4fe1"),(0,s.kt)("li",{parentName:"ul"},"\u5b9e\u73b0\u591a\u4e2a\u7cfb\u7edf\u6570\u636e\u4f20\u8f93\u4ea4\u4e92"),(0,s.kt)("li",{parentName:"ul"},"\u8de8\u7f16\u7a0b\u8bed\u8a00\u534f\u540c\u5f00\u53d1")),(0,s.kt)("h2",{id:"193-\u57fa\u7840\u4f7f\u7528"},"19.3 \u57fa\u7840\u4f7f\u7528"),(0,s.kt)("h3",{id:"1931-\u6ce8\u518c\u670d\u52a1"},"19.3.1 \u6ce8\u518c\u670d\u52a1"),(0,s.kt)("p",null,"\u4f7f\u7528\u4e4b\u524d\u9700\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u6ce8\u518c ",(0,s.kt)("inlineCode",{parentName:"p"},"\u8fdc\u7a0b\u8bf7\u6c42\u670d\u52a1")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public void ConfigureServices(IServiceCollection services)\n{\n services.AddRemoteRequest();\n}\n")),(0,s.kt)("h3",{id:"1932-\u4f7f\u7528\u65b9\u5f0f"},"19.3.2 \u4f7f\u7528\u65b9\u5f0f"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e24\u79cd\u65b9\u5f0f\u8bbf\u95ee\u53d1\u9001\u8fdc\u7a0b\u8bf7\u6c42\u3002"),(0,s.kt)(r.Z,{defaultValue:"IHttpDispatchProxy \u4ee3\u7406\u65b9\u5f0f",values:[{label:"IHttpDispatchProxy \u4ee3\u7406\u65b9\u5f0f",value:"IHttpDispatchProxy \u4ee3\u7406\u65b9\u5f0f"},{label:"\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u5f0f",value:"\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u5f0f"}],mdxType:"Tabs"},(0,s.kt)(o.Z,{value:"IHttpDispatchProxy \u4ee3\u7406\u65b9\u5f0f",mdxType:"TabItem"},(0,s.kt)("p",null,"\u5b9a\u4e49\u4ee3\u7406\u8bf7\u6c42\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"\u63a5\u53e3")," \u5e76\u7ee7\u627f ",(0,s.kt)("inlineCode",{parentName:"p"},"IHttpDispatchProxy")," \u63a5\u53e3"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,6,9,12,15,18}",showLineNumbers:!0,"":!0,"{1,3,6,9,12,15,18}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Get("https://www.furion.icu/get")]\n Task GetXXXAsync();\n\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync();\n\n [Put("https://www.furion.icu/put")]\n Task PutXXXAsync();\n\n [Delete("https://www.furion.icu/delete")]\n Task DeleteXXXAsync();\n\n [Patch("https://www.furion.icu/patch")]\n Task PatchXXXAsync();\n\n [Head("https://www.furion.icu/head")]\n Task HeadXXXAsync();\n}\n')),(0,s.kt)("p",null,"\u901a\u8fc7\u6784\u9020\u51fd\u6570\u6ce8\u5165 ",(0,s.kt)("inlineCode",{parentName:"p"},"\u63a5\u53e3")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9,16}",showLineNumbers:!0,"":!0,"{9,16}":!0},"using Furion.DynamicApiController;\nusing Furion.RemoteRequest.Extensions;\n\nnamespace Furion.Application\n{\n public class RemoteRequestService : IDynamicApiController\n {\n private readonly IHttp _http;\n public RemoteRequestService(IHttp http)\n {\n _http = http;\n }\n\n public async Task GetData()\n {\n var data = await _http.GetXXXAsync();\n }\n }\n}\n"))),(0,s.kt)(o.Z,{value:"\u5b57\u7b26\u4e32\u62d3\u5c55\u65b9\u5f0f",mdxType:"TabItem"},(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var response = await "https://www.furion.icu/get".GetAsync();\n\nvar response = await "https://www.furion.icu/post".PostAsync();\n\nvar response = await "https://www.furion.icu/put".PutAsync();\n\nvar response = await "https://www.furion.icu/delete".DeleteAsync();\n\nvar response = await "https://www.furion.icu/patch".PatchAsync();\n\nvar response = await "https://www.furion.icu/head".HeadAsync();\n')),(0,s.kt)("p",null,"\u9700\u5f15\u5165 ",(0,s.kt)("inlineCode",{parentName:"p"},"using Furion.RemoteRequest.Extensions")," \u547d\u540d\u7a7a\u95f4\u3002"))),(0,s.kt)("h2",{id:"194-\u5b57\u7b26\u4e32\u65b9\u5f0f\u4f7f\u7528\u793a\u4f8b"},"19.4 \u5b57\u7b26\u4e32\u65b9\u5f0f\u4f7f\u7528\u793a\u4f8b"),(0,s.kt)("h3",{id:"1941-\u5185\u7f6e\u8bf7\u6c42\u65b9\u5f0f"},"19.4.1 \u5185\u7f6e\u8bf7\u6c42\u65b9\u5f0f"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u53d1\u9001 Get \u8bf7\u6c42\nvar response = await "https://www.furion.icu/get".GetAsync();\n\n// \u53d1\u9001 Post \u8bf7\u6c42\nvar response = await "https://www.furion.icu/post".PostAsync();\n\n// \u53d1\u9001 Put \u8bf7\u6c42\nvar response = await "https://www.furion.icu/put".PutAsync();\n\n// \u53d1\u9001 Delete \u8bf7\u6c42\nvar response = await "https://www.furion.icu/delete".DeleteAsync();\n\n// \u53d1\u9001 Patch \u8bf7\u6c42\nvar response = await "https://www.furion.icu/patch".PatchAsync();\n\n// \u53d1\u9001 Head \u8bf7\u6c42\nvar response = await "https://www.furion.icu/head".HeadAsync();\n\n// \u624b\u52a8\u6307\u5b9a\u53d1\u9001\u7279\u5b9a\u8bf7\u6c42\nvar response = await "https://www.furion.icu/post".SetHttpMethod(HttpMethod.Post)\n .SendAsync();\n')),(0,s.kt)("h3",{id:"1942-\u8bbe\u7f6e\u8bf7\u6c42\u5730\u5740"},"19.4.2 \u8bbe\u7f6e\u8bf7\u6c42\u5730\u5740"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u8be5\u65b9\u5f0f\u5728 Furion v3.0.0 \u5df2\u79fb\u9664\uff0c\u591a\u6b64\u4e00\u4e3e\u4e86\nawait "".SetRequestUrl("https://www.furion.icu/");\n')),(0,s.kt)("h3",{id:"1943-\u8bbe\u7f6e\u8bf7\u6c42\u65b9\u5f0f"},"19.4.3 \u8bbe\u7f6e\u8bf7\u6c42\u65b9\u5f0f"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/post".SetHttpMethod(HttpMethod.Get);\n')),(0,s.kt)("h3",{id:"1944-\u8bbe\u7f6e\u5730\u5740\u6a21\u677f"},"19.4.4 \u8bbe\u7f6e\u5730\u5740\u6a21\u677f"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u5b57\u5178\u65b9\u5f0f\nawait "https://www.furion.icu/post/{id}?name={name}&id={p.Id}".SetTemplates(new Dictionary {\n { "id", 1 },\n { "name", "Furion" },\n { "p.Id", new Person { Id = 1 } }\n});\n\n// \u5bf9\u8c61/\u533f\u540d\u5bf9\u8c61\u65b9\u5f0f\nawait "https://www.furion.icu/post/{id}?name={name}".SetTemplates(new {\n id = 1,\n name = "Furion"\n});\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u6ce8\uff1a\u6a21\u677f\u66ff\u6362\u533a\u5206\u5927\u5c0f\u5199\u3002")),(0,s.kt)("h3",{id:"1945-\u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934"},"19.4.5 \u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u5b57\u5178\u65b9\u5f0f\nawait "https://www.furion.icu/post".SetHeaders(new Dictionary {\n { "Authorization", "Bearer \u4f60\u7684token"},\n { "X-Authorization", "Bearer \u4f60\u7684\u5237\u65b0token"}\n});\n\n// \u5bf9\u8c61/\u533f\u540d\u5bf9\u8c61\u65b9\u5f0f\nawait "https://www.furion.icu/post".SetHeaders(new {\n Authorization = "Bearer \u4f60\u7684token"\n});\n')),(0,s.kt)("h3",{id:"1946-\u8bbe\u7f6e-url-\u5730\u5740\u53c2\u6570"},"19.4.6 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"URL")," \u5730\u5740\u53c2\u6570"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u5b57\u5178\u65b9\u5f0f\nawait "https://www.furion.icu/get".SetQueries(new Dictionary {\n { "id", 1 },\n { "name", "Furion"}\n});\n\n// \u5bf9\u8c61/\u533f\u540d\u5bf9\u8c61\u65b9\u5f0f\nawait "https://www.furion.icu/get".SetQueries(new {\n id = 1,\n name = "Furion"\n});\n')),(0,s.kt)("p",null,"\u6700\u7ec8\u8f93\u51fa\u683c\u5f0f\u4e3a\uff1a",(0,s.kt)("inlineCode",{parentName:"p"},"https://www.furion.icu/get?id=1&name=Furion"),"\u3002"),(0,s.kt)("h3",{id:"1947-\u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef"},"19.4.7 \u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("strong",{parentName:"li"},"\u5168\u5c40\u914d\u7f6e\u65b9\u5f0f"))),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3-4,12}",showLineNumbers:!0,"":!0,"{1,3-4,12}":!0},'services.AddRemoteRequest(options=>\n{\n // \u914d\u7f6e Github \u57fa\u672c\u4fe1\u606f\n options.AddHttpClient("github", c =>\n {\n c.BaseAddress = new Uri("https://api.github.com/");\n c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");\n c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");\n });\n});\n\nawait "get".SetClient("github");\n')),(0,s.kt)("p",null,"\u6700\u7ec8\u751f\u6210\u8bf7\u6c42\u5730\u5740\u4e3a\uff1a",(0,s.kt)("inlineCode",{parentName:"p"},"https://api.github.com/get"),"\u3002"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("strong",{parentName:"li"},"\u5c40\u90e8\u914d\u7f6e\u65b9\u5f0f"))),(0,s.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,s.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion 4.3.8 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu".SetClient(() => new HttpClient());\n')),(0,s.kt)("h3",{id:"1948-\u8bbe\u7f6e-body-\u53c2\u6570"},"19.4.8 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Body")," \u53c2\u6570"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u4f20\u5165\u5bf9\u8c61\nawait "https://www.furion.icu/api/user/add".SetBody(new User { Id = 1, Name = "Furion" });\n\n// \u914d\u7f6e Content-Type\nawait "https://www.furion.icu/api/user/add".SetBody(new { Id = 1, Name = "Furion" }, "application/json");\n\n// \u8bbe\u7f6e Encoding \u7f16\u7801\nawait "https://www.furion.icu/api/user/add".SetBody(new User { Id = 1, Name = "Furion" }, "application/json", Encoding.UTF8);\n\n// \u5904\u7406 application/x-www-form-urlencoded \u8bf7\u6c42\nawait "https://www.furion.icu/api/user/add".SetBody(new Dictionary {\n { "Id", 1 },\n { "Name", "Furion"}\n}, "application/x-www-form-urlencoded");\n\n// \u5904\u7406 application/xml\u3001text/xml\nawait "https://www.furion.icu/api/user/add".SetBody("somevalue", "application/xml");\n')),(0,s.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,s.kt)("p",{parentName:"admonition"},"\u5982\u679c\u8bf7\u6c42 ",(0,s.kt)("inlineCode",{parentName:"p"},"Content-Type")," \u8bbe\u7f6e\u4e3a ",(0,s.kt)("inlineCode",{parentName:"p"},"application/x-www-form-urlencoded")," \u7c7b\u578b\uff0c\u90a3\u4e48\u5e95\u5c42\u81ea\u52a8\u5c06\u6570\u636e\u8fdb\u884c ",(0,s.kt)("inlineCode",{parentName:"p"},"UrlEncode")," \u7f16\u7801\u5904\u7406\uff0c\u65e0\u9700\u5916\u90e8\u5904\u7406\u3002")),(0,s.kt)("h3",{id:"1949-\u8bbe\u7f6e-content-type"},"19.4.9 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Content-Type")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/post".SetContentType("application/json");\n')),(0,s.kt)("h3",{id:"19410-\u8bbe\u7f6e\u5185\u5bb9\u7f16\u7801"},"19.4.10 \u8bbe\u7f6e\u5185\u5bb9\u7f16\u7801"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/post".SetContentEncoding(Encoding.UTF8);\n')),(0,s.kt)("h3",{id:"19411-\u8bbe\u7f6e-json-\u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f"},"19.4.11 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"JSON")," \u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u9ed8\u8ba4\u60c5\u51b5\u4e0b\u91c7\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"System.Text.Json")," \u8fdb\u884c ",(0,s.kt)("inlineCode",{parentName:"p"},"JSON")," \u5e8f\u5217\u5316\u5904\u7406\uff0c\u5982\u9700\u8bbe\u7f6e\u7b2c\u4e09\u65b9 ",(0,s.kt)("inlineCode",{parentName:"p"},"JSON")," \u63d0\u4f9b\u5668\uff0c\u5219\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u6cdb\u578b\u65b9\u5f0f\nawait "https://www.furion.icu/api/user/add".SetJsonSerialization();\n\n// \u975e\u6cdb\u578b\u65b9\u5f0f\nawait "https://www.furion.icu/api/user/add".SetJsonSerialization(typeof(NewtonsoftJsonSerializerProvider));\n\n// \u6dfb\u52a0\u66f4\u591a\u914d\u7f6e\nawait "https://www.furion.icu/api/user/add".SetJsonSerialization(new JsonSerializerSettings {\n\n});\n')),(0,s.kt)("admonition",{type:"important"},(0,s.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u5173\u4e8e ",(0,s.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"JSON")," \u5e8f\u5217\u5316\u63d0\u4f9b\u5668"),(0,s.kt)("p",{parentName:"admonition"},"\u5982\u9700\u4e86\u89e3\u66f4\u591a ",(0,s.kt)("inlineCode",{parentName:"p"},"JSON")," \u5e8f\u5217\u5316\u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,s.kt)("a",{parentName:"p",href:"json-serialization#2351-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BA%8F%E5%88%97%E5%8C%96%E6%8F%90%E4%BE%9B%E5%99%A8"},"23. JSON \u5e8f\u5217\u5316")," \u7ae0\u8282")),(0,s.kt)("h3",{id:"19412-\u542f\u7528-body-\u53c2\u6570\u9a8c\u8bc1"},"19.4.12 \u542f\u7528 ",(0,s.kt)("inlineCode",{parentName:"h3"},"Body")," \u53c2\u6570\u9a8c\u8bc1"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/api/user/add".SetValidationState();\n\n// \u8bbe\u7f6e\u4e0d\u9a8c\u8bc1 null \u503c\nawait "https://www.furion.icu/api/user/add".SetValidationState(includeNull: true);\n')),(0,s.kt)("p",null,"\u652f\u6301\u7c7b\u4e2d ",(0,s.kt)("inlineCode",{parentName:"p"},"[Required]")," \u7b49\u5b8c\u6574\u6a21\u578b\u9a8c\u8bc1\u7279\u6027\u3002"),(0,s.kt)("h3",{id:"19413-\u8bf7\u6c42\u62e6\u622a"},"19.4.13 \u8bf7\u6c42\u62e6\u622a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/".OnRequesting((client, req) => {\n // req \u4e3a HttpRequestMessage \u5bf9\u8c61\n // \u8ffd\u52a0\u66f4\u591a\u53c2\u6570\n req.AppendQueries(new Dictionary {\n { "access_token", "xxxx"}\n });\n});\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19414-httpclient-\u62e6\u622a"},"19.4.14 ",(0,s.kt)("inlineCode",{parentName:"h3"},"HttpClient")," \u62e6\u622a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/".OnClientCreating(client => {\n // client \u4e3a HttpClient \u5bf9\u8c61\n client.Timeout = 30000; // \u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4\n});\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19415-\u8bf7\u6c42\u4e4b\u524d\u62e6\u622a"},"19.4.15 \u8bf7\u6c42\u4e4b\u524d\u62e6\u622a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/".OnRequesting((client, req) => {\n // req \u4e3a HttpRequestMessage \u5bf9\u8c61\n});\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19416-\u6210\u529f\u8bf7\u6c42\u62e6\u622a"},"19.4.16 \u6210\u529f\u8bf7\u6c42\u62e6\u622a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/".OnResponsing((client, res) => {\n // res \u4e3a HttpResponseMessage \u5bf9\u8c61\n});\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19417-\u8bf7\u6c42\u5f02\u5e38\u62e6\u622a"},"19.4.17 \u8bf7\u6c42\u5f02\u5e38\u62e6\u622a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await "https://www.furion.icu/".OnException((client, res, errors) => {\n // res \u4e3a HttpResponseMessage \u5bf9\u8c61\n});\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19418-\u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406"},"19.4.18 \u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fdc\u7a0b\u8bf7\u6c42\u9ed8\u8ba4\u63d0\u4f9b\u56db\u79cd\u8fd4\u56de\u503c\u7c7b\u578b\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"HttpResponseMessage"),"\uff1a\u8bf7\u6c42\u54cd\u5e94\u6d88\u606f\u7c7b\u578b"),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"Stream"),"\uff1a\u6d41\u7c7b\u578b"),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"T"),"\uff1a\u6cdb\u578b ",(0,s.kt)("inlineCode",{parentName:"li"},"T")," \u7c7b\u578b"),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"String"),"\uff1a\u5b57\u7b26\u4e32\u7c7b\u578b\uff0c\u4e5f\u5c31\u662f\u76f4\u63a5\u5c06\u7f51\u7edc\u8bf7\u6c42\u7ed3\u679c\u5185\u5bb9\u5b57\u7b26\u4e32\u5316"),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"Byte[]"),"\uff1a\u5b57\u8282\u6570\u7ec4\u7c7b\u578b")),(0,s.kt)("p",null,"\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// HttpResponseMessage\nvar res = await "https://www.furion.icu/".GetAsync();\n\n// Stream\nvar stream = await "https://www.furion.icu/".GetAsStreamAsync();\n\n// T\nvar user = await "https://www.furion.icu/".GetAsAsync();\n\n// String\nvar str = await "https://www.baidu.com".GetAsStringAsync();\n')),(0,s.kt)("h3",{id:"19419-\u8bbe\u7f6e-byte-\u7c7b\u578b\u4e0a\u4f20\u6587\u4ef6"},"19.4.19 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Byte[]")," \u7c7b\u578b/\u4e0a\u4f20\u6587\u4ef6"),(0,s.kt)("admonition",{type:"warning"},(0,s.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,s.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Furion 4.4.0")," \u4ee5\u4e0b\u7248\u672c"),(0,s.kt)("p",{parentName:"admonition"},"\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion 4.4.0+")," \u7248\u672c\u79fb\u9664\u4e86 ",(0,s.kt)("inlineCode",{parentName:"p"},".SetBodyBytes")," \u65b9\u5f0f\uff0c\u539f\u56e0\u662f\u62d3\u5c55\u6027\u592a\u5dee\uff0c",(0,s.kt)("strong",{parentName:"p"},"\u65b0\u7248\u672c\u8bf7\u4f7f\u7528 ",(0,s.kt)("inlineCode",{parentName:"strong"},".SetFiles")," \u65b9\u5f0f"),"\u3002")),(0,s.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u4e0a\u4f20\u6587\u4ef6\uff0c\u9700\u8981\u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"p"},"Content-Type")," \u4e3a ",(0,s.kt)("inlineCode",{parentName:"p"},"multipart/form-data")," \u7c7b\u578b\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,7}",showLineNumbers:!0,"{3,7}":!0},'// bytes \u53ef\u4ee5\u901a\u8fc7 File.ReadAllBytes(\u6587\u4ef6\u8def\u5f84) \u83b7\u53d6\nvar res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")\n .SetBodyBytes(("\u952e", bytes, "\u6587\u4ef6\u540d")).PostAsync();\n\n// \u652f\u6301\u591a\u4e2a\u6587\u4ef6\nvar res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")\n .SetBodyBytes(("\u952e", bytes, "\u6587\u4ef6\u540d"),("\u952e", bytes, "\u6587\u4ef6\u540d")).PostAsync();\n')),(0,s.kt)("admonition",{title:"\u5173\u4e8e\u5fae\u4fe1\u4e0a\u4f20\u63a5\u53e3",type:"note"},(0,s.kt)("p",{parentName:"admonition"},"\u5982\u679c\u9047\u5230\u5fae\u4fe1\u4e0a\u4f20\u51fa\u73b0\u95ee\u9898\uff0c\u5219\u53ef\u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"p"},"Content-Type")," \u4e3a\uff1a",(0,s.kt)("inlineCode",{parentName:"p"},"application/octet-stream"),"\uff0c\u5982\uff1a"),(0,s.kt)("pre",{parentName:"admonition"},(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var result = await $"https://api.weixin.qq.com/wxa/img_sec_check?access_token={token}"\n .SetBodyBytes(("media", bytes, Path.GetFileName(imgPath)))\n .SetContentType("application/octet-stream")\n .PostAsStringAsync();\n'))),(0,s.kt)("admonition",{type:"tip"},(0,s.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,s.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Furion 4.4.0+")," \u7248\u672c"),(0,s.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion 4.4.0+")," \u7248\u672c\uff0c\u8bf7\u4f7f\u7528\u4ee5\u4e0b\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},".SetFiles")," \u66ff\u4ee3 ",(0,s.kt)("inlineCode",{parentName:"p"},".SetBodyBytes")," \u64cd\u4f5c\u3002")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,7}",showLineNumbers:!0,"{3,7}":!0},'// bytes \u53ef\u4ee5\u901a\u8fc7 File.ReadAllBytes(\u6587\u4ef6\u8def\u5f84) \u83b7\u53d6\nvar res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")\n .SetFiles(HttpFile.Create("file", bytes, "image.png")).PostAsync();\n\n// \u652f\u6301\u591a\u4e2a\u6587\u4ef6\nvar res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")\n .SetFiles(HttpFile.CreateMultiple("files", (bytes, "image1.png"), (bytes, "image2.png"))).PostAsync();\n')),(0,s.kt)("h3",{id:"19420-\u8bbe\u7f6e-iserviceprovider"},"19.4.20 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"IServiceProvider")),(0,s.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u6784\u5efa\u4e00\u4e2a\u4f5c\u7528\u57df\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"IServiceProvider"),"\uff0c\u8fd9\u65f6\u53ea\u9700\u8981\u8bbe\u7f6e\u5373\u53ef\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var res = await "https://www.furion.icu/upload".SetRequestScoped(services);\n')),(0,s.kt)("h3",{id:"19421-\u8bbe\u7f6e-timeout-\u8d85\u65f6\u65f6\u95f4"},"19.4.21 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Timeout")," \u8d85\u65f6\u65f6\u95f4"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var res = await "https://www.furion.icu/upload".SetClientTimeout(10); // \u5355\u4f4d\u79d2\n')),(0,s.kt)("h3",{id:"19422-\u652f\u6301\u6a21\u677f\u914d\u7f6e"},"19.4.22 \u652f\u6301\u6a21\u677f\u914d\u7f6e"),(0,s.kt)("p",null,"\u6a21\u677f\u683c\u5f0f\u4e3a\uff1a",(0,s.kt)("inlineCode",{parentName:"p"},"#(\u914d\u7f6e\u8def\u5f84)")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var res = await "#(Furion:Address)/upload".GetAsync();\n')),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "Furion": {\n "Address": "https://www.furion.icu"\n }\n}\n')),(0,s.kt)("h3",{id:"19423-\u91cd\u8bd5\u7b56\u7565"},"19.4.23 \u91cd\u8bd5\u7b56\u7565"),(0,s.kt)("p",null,"\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion v2.18+")," \u7248\u672c\u652f\u6301\u914d\u7f6e\u91cd\u8bd5\u7b56\u7565\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var res = await "https://www.furion.icu".SetRetryPolicy(3, 1000).GetAsync();\n')),(0,s.kt)("p",null,"\u4ee5\u4e0a\u4ee3\u7801\u8868\u793a\u8bf7\u6c42\u5931\u8d25\u91cd\u8bd5 ",(0,s.kt)("inlineCode",{parentName:"p"},"3")," \u6b21\uff0c\u6bcf\u6b21\u5ef6\u8fdf ",(0,s.kt)("inlineCode",{parentName:"p"},"1000ms")," \u3002"),(0,s.kt)("h3",{id:"19424-\u652f\u6301-gzip-\u538b\u7f29"},"19.4.24 \u652f\u6301 ",(0,s.kt)("inlineCode",{parentName:"h3"},"GZip")," \u538b\u7f29"),(0,s.kt)("p",null,"\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion v3.2.0+")," \u7248\u672c\u652f\u6301",(0,s.kt)("inlineCode",{parentName:"p"},"GZip")," \u538b\u7f29\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var res = await "https://www.furion.icu".WithGZip().GetAsync();\n')),(0,s.kt)("h3",{id:"19425-\u8bbe\u7f6e-url-\u8f6c\u7801"},"19.4.25 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Url")," \u8f6c\u7801"),(0,s.kt)("p",null,"\u8fc7\u53bb\u7248\u672c\u4f1a\u5bf9\u6240\u6709\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"Url")," \u8fdb\u884c ",(0,s.kt)("inlineCode",{parentName:"p"},"Uri.EscapeDataString")," \u8f6c\u7801\uff0c\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion v3.8.0+")," \u7248\u672c\u652f\u6301 ",(0,s.kt)("inlineCode",{parentName:"p"},"Url")," \u8f6c\u7801\u8bbe\u7f6e\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var res = await "https://www.furion.icu".WithEncodeUrl(false).GetAsync();\n')),(0,s.kt)("h2",{id:"195-ihttpdispatchproxy-\u4ee3\u7406\u65b9\u5f0f"},"19.5 ",(0,s.kt)("inlineCode",{parentName:"h2"},"IHttpDispatchProxy")," \u4ee3\u7406\u65b9\u5f0f"),(0,s.kt)("h3",{id:"1951-\u652f\u6301\u591a\u79cd\u4ee3\u7406\u65b9\u5f0f"},"19.5.1 \u652f\u6301\u591a\u79cd\u4ee3\u7406\u65b9\u5f0f"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public interface IHttp : IHttpDispatchProxy\n{\n // \u53d1\u9001 Get \u8bf7\u6c42\n [Get("https://www.furion.icu/get")]\n Task GetXXXAsync();\n\n // \u53d1\u9001 Post \u8bf7\u6c42\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync();\n\n // \u53d1\u9001 Put \u8bf7\u6c42\n [Put("https://www.furion.icu/put")]\n Task PutXXXAsync();\n\n // \u53d1\u9001 Delete \u8bf7\u6c42\n [Delete("https://www.furion.icu/delete")]\n Task DeleteXXXAsync();\n\n // \u53d1\u9001 Patch \u8bf7\u6c42\n [Patch("https://www.furion.icu/patch")]\n Task PatchXXXAsync();\n\n // \u53d1\u9001 Head \u8bf7\u6c42\n [Head("https://www.furion.icu/head")]\n Task HeadXXXAsync();\n}\n')),(0,s.kt)("h3",{id:"1952-\u8bbe\u7f6e\u5730\u5740\u6a21\u677f"},"19.5.2 \u8bbe\u7f6e\u5730\u5740\u6a21\u677f"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Get("https://www.furion.icu/get/{id}?name={name}&number={p.PersonDetail.PhonNumber}")]\n Task GetXXXAsync(int id, string name, Person p);\n}\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u6ce8\uff1a\u6a21\u677f\u66ff\u6362\u533a\u5206\u5927\u5c0f\u5199\u3002")),(0,s.kt)("h3",{id:"1953-\u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934"},"19.5.3 \u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u6a21\u5f0f\u63d0\u4f9b\u4e09\u79cd\u65b9\u5f0f\u8bbe\u7f6e\u8bf7\u6c42\u62a5\u6587\u5934\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u652f\u6301\u5728\u63a5\u53e3\u4e2d\u58f0\u660e"),(0,s.kt)("li",{parentName:"ul"},"\u652f\u6301\u5728\u65b9\u6cd5\u4e2d\u58f0\u660e"),(0,s.kt)("li",{parentName:"ul"},"\u652f\u6301\u5728\u53c2\u6570\u4e2d\u58f0\u660e")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-2,5,9,12}",showLineNumbers:!0,"":!0,"{1-2,5,9,12}":!0},'[Headers("key","value")]\n[Headers("key1","value2")] // \u8bbe\u7f6e\u591a\u4e2a\npublic interface IHttp : IHttpDispatchProxy\n{\n [Get("https://www.furion.icu/get/{id}?name={name}"), Headers("key2","value2")]\n Task GetXXXAsync(int id, string name);\n\n [Get("https://www.furion.icu")]\n Task GetXXX2Async(int id, [Headers]string token = default);\n\n [Get("https://www.furion.icu")]\n Task GetXXX2Async(int id, string name, [Headers("\u522b\u540d")]string token = default);\n}\n')),(0,s.kt)("h3",{id:"1954-\u8bbe\u7f6e-url-\u5730\u5740\u53c2\u6570"},"19.5.4 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"URL")," \u5730\u5740\u53c2\u6570"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,7,10,13}",showLineNumbers:!0,"":!0,"{4,7,10,13}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Get("https://www.furion.icu/get/{id}?name={name}")]\n Task GetXXXAsync(int id, string name);\n\n [Get("https://www.furion.icu/get/{p.Id}?name={p.Name}")]\n Task GetXXXAsync(Person p);\n\n [Get("https://www.furion.icu/get")]\n Task GetXXXAsync([QueryString]int id, [QueryString]string name);\n\n [Get("https://www.furion.icu/get")]\n Task GetXXXAsync([QueryString]int id, [QueryString("\u522b\u540d")]string name);\n}\n')),(0,s.kt)("p",null,"\u6700\u7ec8\u8f93\u51fa\u683c\u5f0f\u4e3a\uff1a",(0,s.kt)("inlineCode",{parentName:"p"},"https://www.furion.icu/get?id=1&name=Furion"),"\u3002"),(0,s.kt)("h3",{id:"1955-\u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef"},"19.5.5 \u8bbe\u7f6e\u8bf7\u6c42\u5ba2\u6237\u7aef"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("strong",{parentName:"li"},"\u5168\u5c40\u914d\u7f6e\u65b9\u5f0f"))),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3-4,14}",showLineNumbers:!0,"":!0,"{1,3-4,14}":!0},'services.AddRemoteRequest(options=>\n{\n // \u914d\u7f6e Github \u57fa\u672c\u4fe1\u606f\n options.AddHttpClient("github", c =>\n {\n c.BaseAddress = new Uri("https://api.github.com/");\n c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");\n c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");\n });\n});\n\npublic interface IHttp : IHttpDispatchProxy\n{\n [Get("get"), Client("github")]\n Task GetXXXAsync();\n}\n')),(0,s.kt)("p",null,"\u6700\u7ec8\u751f\u6210\u8bf7\u6c42\u5730\u5740\u4e3a\uff1a",(0,s.kt)("inlineCode",{parentName:"p"},"https://api.github.com/get"),"\u3002"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("strong",{parentName:"li"},"\u5c40\u90e8\u914d\u7f6e\u65b9\u5f0f"))),(0,s.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,s.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion 4.3.8 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,7-11}",showLineNumbers:!0,"{5,7-11}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n // \u5c40\u90e8\u65b9\u5f0f\n [Get("get")]\n Task GetXXXAsync([Interceptor(InterceptorTypes.Initiate)]Func clientProvider);\n\n // \u5168\u5c40\u9759\u6001\u65b9\u5f0f\n [Interceptor(InterceptorTypes.Initiate)]\n static HttpClient CreateHttpClient()\n {\n return new HttpClient(...);\n }\n}\n')),(0,s.kt)("h3",{id:"1956-\u8bbe\u7f6e-body-\u53c2\u6570"},"19.5.6 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Body")," \u53c2\u6570"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,6,9}",showLineNumbers:!0,"":!0,"{3,6,9}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Body]User user);\n\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Body("application/x-www-form-urlencoded")]User user);\n\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Body("application/x-www-form-urlencoded", "UTF-8")]User user);\n}\n')),(0,s.kt)("h3",{id:"1957-\u8bbe\u7f6e-json-\u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f"},"19.5.7 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"JSON")," \u5e8f\u5217\u5316\u63d0\u4f9b\u7a0b\u5e8f"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u9ed8\u8ba4\u60c5\u51b5\u4e0b\u91c7\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"System.Text.Json")," \u8fdb\u884c ",(0,s.kt)("inlineCode",{parentName:"p"},"JSON")," \u5e8f\u5217\u5316\u5904\u7406\uff0c\u5982\u9700\u8bbe\u7f6e\u7b2c\u4e09\u65b9 ",(0,s.kt)("inlineCode",{parentName:"p"},"JSON")," \u63d0\u4f9b\u5668\uff0c\u5219\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,6-7}",showLineNumbers:!0,"":!0,"{3,6-7}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu/post"), JsonSerialization(typeof(NewtonsoftJsonSerializerProvider))]\n Task PostXXXAsync([Body]User user);\n\n [Post("https://www.furion.icu/post"), JsonSerialization(typeof(NewtonsoftJsonSerializerProvider))]\n Task PostXXXAsync([Body]User user, [JsonSerializerOptions]object jsonSerializerOptions = default);\n\n /// \n /// \u7f3a\u7701\u5e8f\u5217\u5316\u914d\u7f6e\n /// \n /// \n [JsonSerializerOptions]\n static object GetJsonSerializerOptions()\n {\n // \u8fd9\u91cc\u4e5f\u53ef\u4ee5\u901a\u8fc7 JSON.GetSerializerOptions() \u83b7\u53d6 Startup.cs \u4e2d\u7684\u914d\u7f6e\n return new JsonSerializerOptions\n {\n\n };\n }\n}\n')),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"[JsonSerializerOptions]")," \u53ef\u4ee5\u6807\u8bb0\u53c2\u6570\u662f\u4e00\u4e2a ",(0,s.kt)("inlineCode",{parentName:"p"},"JSON")," \u5e8f\u5217\u5316\u914d\u7f6e\u53c2\u6570\u3002"),(0,s.kt)("admonition",{type:"important"},(0,s.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u5173\u4e8e ",(0,s.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"JSON")," \u5e8f\u5217\u5316\u63d0\u4f9b\u5668"),(0,s.kt)("p",{parentName:"admonition"},"\u5982\u9700\u4e86\u89e3\u66f4\u591a ",(0,s.kt)("inlineCode",{parentName:"p"},"JSON")," \u5e8f\u5217\u5316\u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,s.kt)("a",{parentName:"p",href:"json-serialization#2351-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BA%8F%E5%88%97%E5%8C%96%E6%8F%90%E4%BE%9B%E5%99%A8"},"23. JSON \u5e8f\u5217\u5316")," \u7ae0\u8282")),(0,s.kt)("h3",{id:"1958-\u53c2\u6570\u9a8c\u8bc1"},"19.5.8 \u53c2\u6570\u9a8c\u8bc1"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,7}",showLineNumbers:!0,"":!0,"{4,7}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Range(1,10)]int id, [Required, MaxLength(10)]string name);\n\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Required]User user); // \u5bf9\u8c61\u7c7b\u578b\u652f\u6301\u5c5e\u6027\u914d\u7f6e\u7279\u6027\u9a8c\u8bc1\n}\n')),(0,s.kt)("h3",{id:"1959-\u8bf7\u6c42\u62e6\u622a"},"19.5.9 \u8bf7\u6c42\u62e6\u622a"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u65b9\u5f0f\u63d0\u4f9b\u4e24\u79cd\u62e6\u622a\u65b9\u5f0f\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u63a5\u53e3\u9759\u6001\u65b9\u6cd5\u62e6\u622a"),(0,s.kt)("li",{parentName:"ul"},"\u53c2\u6570\u6807\u8bb0\u62e6\u622a")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8,18}",showLineNumbers:!0,"":!0,"{5,8,18}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n // \u901a\u8fc7\u53c2\u6570\u62e6\u622a\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Interceptor(InterceptorTypes.Request)] Action action = default);\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Request)]\n static void OnRequesting1(HttpClient client, HttpRequestMessage req)\n {\n // \u8ffd\u52a0\u66f4\u591a\u53c2\u6570\n req.AppendQueries(new Dictionary {\n { "access_token", "xxxx"}\n });\n }\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Request)]\n static void OnRequesting2(HttpClient client, HttpRequestMessage req)\n {\n\n }\n}\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19510-httpclient-\u62e6\u622a"},"19.5.10 ",(0,s.kt)("inlineCode",{parentName:"h3"},"HttpClient")," \u62e6\u622a"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u65b9\u5f0f\u63d0\u4f9b\u4e24\u79cd\u62e6\u622a\u65b9\u5f0f\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u63a5\u53e3\u9759\u6001\u65b9\u6cd5\u62e6\u622a"),(0,s.kt)("li",{parentName:"ul"},"\u53c2\u6570\u6807\u8bb0\u62e6\u622a")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8,15}",showLineNumbers:!0,"":!0,"{5,8,15}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n // \u901a\u8fc7\u53c2\u6570\u62e6\u622a\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Interceptor(InterceptorTypes.Client)] Action action = default);\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Client)]\n static void onClientCreating1(HttpClient client)\n {\n\n }\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Client)]\n static void onClientCreating2(HttpClient client)\n {\n\n }\n}\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19511-\u8bf7\u6c42\u4e4b\u524d\u62e6\u622a"},"19.5.11 \u8bf7\u6c42\u4e4b\u524d\u62e6\u622a"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u65b9\u5f0f\u63d0\u4f9b\u4e24\u79cd\u62e6\u622a\u65b9\u5f0f\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u63a5\u53e3\u9759\u6001\u65b9\u6cd5\u62e6\u622a"),(0,s.kt)("li",{parentName:"ul"},"\u53c2\u6570\u6807\u8bb0\u62e6\u622a")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8,15}",showLineNumbers:!0,"":!0,"{5,8,15}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n // \u901a\u8fc7\u53c2\u6570\u62e6\u622a\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Interceptor(InterceptorTypes.Request)] Action action = default);\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Request)]\n static void OnRequest1(HttpClient client, HttpRequestMessage req)\n {\n\n }\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Request)]\n static void OnRequest2(HttpClient client, HttpRequestMessage req)\n {\n\n }\n}\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19512-\u6210\u529f\u8bf7\u6c42\u62e6\u622a"},"19.5.12 \u6210\u529f\u8bf7\u6c42\u62e6\u622a"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u65b9\u5f0f\u63d0\u4f9b\u4e24\u79cd\u62e6\u622a\u65b9\u5f0f\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u63a5\u53e3\u9759\u6001\u65b9\u6cd5\u62e6\u622a"),(0,s.kt)("li",{parentName:"ul"},"\u53c2\u6570\u6807\u8bb0\u62e6\u622a")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8,15}",showLineNumbers:!0,"":!0,"{5,8,15}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n // \u901a\u8fc7\u53c2\u6570\u62e6\u622a\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Interceptor(InterceptorTypes.Response)] Action action = default);\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Response)]\n static void OnResponsing1(HttpClien client, HttpResponseMessage res)\n {\n\n }\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Response)]\n static void OnResponsing2(HttpClien client, HttpResponseMessage res)\n {\n\n }\n}\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19513-\u8bf7\u6c42\u5f02\u5e38\u62e6\u622a"},"19.5.13 \u8bf7\u6c42\u5f02\u5e38\u62e6\u622a"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fdc\u7a0b\u8bf7\u6c42\u4ee3\u7406\u65b9\u5f0f\u63d0\u4f9b\u4e24\u79cd\u62e6\u622a\u65b9\u5f0f\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u63a5\u53e3\u9759\u6001\u65b9\u6cd5\u62e6\u622a"),(0,s.kt)("li",{parentName:"ul"},"\u53c2\u6570\u6807\u8bb0\u62e6\u622a")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8,15}",showLineNumbers:!0,"":!0,"{5,8,15}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n // \u901a\u8fc7\u53c2\u6570\u62e6\u622a\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync([Interceptor(InterceptorTypes.Exception)] Action action = default);\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Exception)]\n static void OnException1(HttpClient client, HttpResponseMessage res, string errors)\n {\n\n }\n\n // \u5168\u5c40\u62e6\u622a\uff0c\u7c7b\u4e2d\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u4f1a\u89e6\u53d1\n [Interceptor(InterceptorTypes.Exception)]\n static void OnException2(HttpClient client, HttpResponseMessage res, string errors)\n {\n\n }\n}\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u652f\u6301\u591a\u6b21\u62e6\u622a")),(0,s.kt)("h3",{id:"19514-\u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406"},"19.5.14 \u5404\u79cd\u8fd4\u56de\u503c\u5904\u7406"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u8fdc\u7a0b\u8bf7\u6c42\u9ed8\u8ba4\u63d0\u4f9b\u56db\u79cd\u8fd4\u56de\u503c\u7c7b\u578b\uff1a"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"HttpResponseMessage"),"\uff1a\u8bf7\u6c42\u54cd\u5e94\u6d88\u606f\u7c7b\u578b"),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"Stream"),"\uff1a\u6d41\u7c7b\u578b"),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"T"),"\uff1a\u6cdb\u578b ",(0,s.kt)("inlineCode",{parentName:"li"},"T")," \u7c7b\u578b"),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"String"),"\uff1a\u5b57\u7b26\u4e32\u7c7b\u578b\uff0c\u4e5f\u5c31\u662f\u76f4\u63a5\u5c06\u7f51\u7edc\u8bf7\u6c42\u7ed3\u679c\u5185\u5bb9\u5b57\u7b26\u4e32\u5316")),(0,s.kt)("p",null,"\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync();\n\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync();\n\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync();\n\n [Post("https://www.furion.icu/post")]\n Task PostXXXAsync();\n}\n')),(0,s.kt)("h3",{id:"19515-\u8bbe\u7f6e-byte-\u7c7b\u578b\u4e0a\u4f20\u6587\u4ef6"},"19.5.15 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Byte[]")," \u7c7b\u578b/\u4e0a\u4f20\u6587\u4ef6"),(0,s.kt)("admonition",{type:"warning"},(0,s.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,s.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Furion 4.4.0")," \u4ee5\u4e0b\u7248\u672c"),(0,s.kt)("p",{parentName:"admonition"},"\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion 4.4.0+")," \u7248\u672c\u79fb\u9664\u4e86 ",(0,s.kt)("inlineCode",{parentName:"p"},"[BodyBytes]")," \u65b9\u5f0f\uff0c\u539f\u56e0\u662f\u62d3\u5c55\u6027\u592a\u5dee\uff0c",(0,s.kt)("strong",{parentName:"p"},"\u65b0\u7248\u672c\u8bf7\u4f7f\u7528 ",(0,s.kt)("inlineCode",{parentName:"strong"},"HttpFile")," \u65b9\u5f0f"),"\u3002")),(0,s.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u4e0a\u4f20\u6587\u4ef6\uff0c\u9700\u8981\u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"p"},"Content-Type")," \u4e3a ",(0,s.kt)("inlineCode",{parentName:"p"},"multipart/form-data")," \u7c7b\u578b\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,4}",showLineNumbers:!0,"{3,4}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")] // bytes \u53ef\u4ee5\u901a\u8fc7 File.ReadAllBytes(\u6587\u4ef6\u8def\u5f84) \u83b7\u53d6\n Task PostXXXAsync([BodyBytes("\u952e","\u6587\u4ef6\u540d")]Byte[] bytes);\n\n // \u652f\u6301\u591a\u4e2a\u6587\u4ef6\n [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")] // bytes \u53ef\u4ee5\u901a\u8fc7 File.ReadAllBytes(\u6587\u4ef6\u8def\u5f84) \u83b7\u53d6\n Task PostXXXAsync([BodyBytes("\u952e","\u6587\u4ef6\u540d")]Byte[] bytes,[BodyBytes("\u952e","\u6587\u4ef6\u540d")]Byte[] bytes2);\n}\n')),(0,s.kt)("admonition",{type:"tip"},(0,s.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,s.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"Furion 4.4.0+")," \u7248\u672c"),(0,s.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion 4.4.0+")," \u7248\u672c\uff0c\u8bf7\u4f7f\u7528\u4ee5\u4e0b\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"HttpFile")," \u66ff\u4ee3 ",(0,s.kt)("inlineCode",{parentName:"p"},"[BodyBytes]")," \u64cd\u4f5c\u3002")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3-4,7-8,11-12}",showLineNumbers:!0,"{3-4,7-8,11-12}":!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")] \n Task PostXXXAsync(HttpFile file);\n\n // \u652f\u6301\u591a\u4e2a\u6587\u4ef6\n [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")] \n Task PostXXXAsync(HttpFile[] files);\n \n // \u652f\u6301\u591a\u4e2a\u6587\u4ef6\n [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")] \n Task PostXXXAsync(IList files);\n}\n')),(0,s.kt)("h3",{id:"19516-\u8bbe\u7f6e-timeout-\u8d85\u65f6\u65f6\u95f4"},"19.5.16 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Timeout")," \u8d85\u65f6\u65f6\u95f4"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[Timeout(1000)]\npublic interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu/upload"), Timeout(500)] // \u5355\u4f4d\u79d2\n Task PostXXXAsync([Body]User user);\n}\n')),(0,s.kt)("h3",{id:"19517-\u652f\u6301\u6a21\u677f\u914d\u7f6e"},"19.5.17 \u652f\u6301\u6a21\u677f\u914d\u7f6e"),(0,s.kt)("p",null,"\u6a21\u677f\u683c\u5f0f\u4e3a\uff1a",(0,s.kt)("inlineCode",{parentName:"p"},"#(\u914d\u7f6e\u8def\u5f84)")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("#(Furion:Address)/upload")]\n Task PostXXXAsync([Body]User user);\n}\n')),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "Furion": {\n "Address": "https://www.furion.icu"\n }\n}\n')),(0,s.kt)("p",null,"\u65b9\u6cd5\u7684\u4f18\u5148\u7ea7\u9ad8\u4e8e\u63a5\u53e3\u5b9a\u4e49\u7684\u4f18\u5148\u7ea7\u3002"),(0,s.kt)("h3",{id:"19518-\u91cd\u8bd5\u7b56\u7565"},"19.5.18 \u91cd\u8bd5\u7b56\u7565"),(0,s.kt)("p",null,"\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion v2.18+")," \u7248\u672c\u652f\u6301\u914d\u7f6e\u91cd\u8bd5\u7b56\u7565\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[RetryPolicy(3, 1000)] // \u652f\u6301\u5168\u5c40\npublic interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu"), RetryPolicy(3, 1000)] // \u652f\u6301\u5c40\u90e8\n Task PostXXXAsync([Body]User user);\n}\n')),(0,s.kt)("p",null,"\u4ee5\u4e0a\u4ee3\u7801\u8868\u793a\u8bf7\u6c42\u5931\u8d25\u91cd\u8bd5 ",(0,s.kt)("inlineCode",{parentName:"p"},"3")," \u6b21\uff0c\u6bcf\u6b21\u5ef6\u8fdf ",(0,s.kt)("inlineCode",{parentName:"p"},"1000ms")," \u3002"),(0,s.kt)("h3",{id:"19519-\u652f\u6301-gzip"},"19.5.19 \u652f\u6301 ",(0,s.kt)("inlineCode",{parentName:"h3"},"GZip")),(0,s.kt)("p",null,"\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion v3.2.0+")," \u7248\u672c\u652f\u6301 ",(0,s.kt)("inlineCode",{parentName:"p"},"GZip"),"\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu", WithGZip = true)]\n Task PostXXXAsync([Body]User user);\n}\n')),(0,s.kt)("h3",{id:"19520-\u8bbe\u7f6e-url-\u8f6c\u7801"},"19.5.20 \u8bbe\u7f6e ",(0,s.kt)("inlineCode",{parentName:"h3"},"Url")," \u8f6c\u7801"),(0,s.kt)("p",null,"\u8fc7\u53bb\u7248\u672c\u4f1a\u5bf9\u6240\u6709\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"Url")," \u8fdb\u884c ",(0,s.kt)("inlineCode",{parentName:"p"},"Uri.EscapeDataString")," \u8f6c\u7801\uff0c\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion v3.8.0+")," \u7248\u672c\u652f\u6301 ",(0,s.kt)("inlineCode",{parentName:"p"},"Url")," \u8f6c\u7801\u8bbe\u7f6e\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'public interface IHttp : IHttpDispatchProxy\n{\n [Post("https://www.furion.icu", WithEncodeUrl = false)]\n Task PostXXXAsync([Body]User user);\n}\n')),(0,s.kt)("h2",{id:"196-\u8bf7\u6c42\u5ba2\u6237\u7aef\u914d\u7f6e"},"19.6 \u8bf7\u6c42\u5ba2\u6237\u7aef\u914d\u7f6e"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e5f\u63d0\u4f9b\u4e86\u591a\u4e2a\u8bf7\u6c42\u5ba2\u6237\u7aef\u914d\u7f6e\uff0c\u53ef\u4ee5\u4e3a\u591a\u4e2a\u5ba2\u6237\u7aef\u8bf7\u6c42\u914d\u7f6e\u9ed8\u8ba4\u8bf7\u6c42\u4fe1\u606f\uff0c\u76ee\u524d\u652f\u6301\u56db\u79cd\u6a21\u5f0f\u8fdb\u884c\u914d\u7f6e\u3002"),(0,s.kt)("h3",{id:"1961-startupcs-\u7edf\u4e00\u914d\u7f6e"},"19.6.1 ",(0,s.kt)("inlineCode",{parentName:"h3"},"Startup.cs")," \u7edf\u4e00\u914d\u7f6e"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,9}",showLineNumbers:!0,"":!0,"{4,9}":!0},'services.AddRemoteRequest(options=>\n{\n // \u914d\u7f6e\u9ed8\u8ba4 HttpClient\n options.AddHttpClient(string.Empty, c => {\n // \u5176\u4ed6\u914d\u7f6e\n });\n\n // \u914d\u7f6e\u7279\u5b9a\u5ba2\u6237\u7aef\n options.AddHttpClient("github", c =>\n {\n c.BaseAddress = new Uri("https://api.github.com/");\n c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");\n c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");\n });\n})\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"\u914d\u7f6e\u4e86\u547d\u540d\u5ba2\u6237\u7aef\u540e\uff0c\u6bcf\u6b21\u8bf7\u6c42\u90fd\u4f1a\u81ea\u52a8\u52a0\u4e0a\u8fd9\u4e9b\u914d\u7f6e\u3002")),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u5728 ",(0,s.kt)("inlineCode",{parentName:"li"},"\u4ee3\u7406\u8bf7\u6c42")," \u4f7f\u7528")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[Get("api/getdata"), Client("github")]\nTask GetData();\n\n[Put("api/getdata"), Client("facebook")]\nTask GetData();\n')),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u5728 ",(0,s.kt)("inlineCode",{parentName:"li"},"\u5b57\u7b26\u4e32\u62d3\u5c55")," \u4f7f\u7528")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u8bbe\u7f6e\u8bf7\u6c42\u62e6\u622a\nvar response = await "http://47.100.247.61/api/sysdata/categories".SetClient("github").PostAsync();\n')),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"\u5728 ",(0,s.kt)("inlineCode",{parentName:"li"},"IHttpClientFactory")," \u4e2d\u4f7f\u7528")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,13}",showLineNumbers:!0,"{3,13}":!0},'public class ValuesController : Controller\n{\n private readonly IHttpClientFactory _httpClientFactory;\n\n public ValuesController(IHttpClientFactory httpClientFactory)\n {\n _httpClientFactory = httpClientFactory;\n }\n\n [HttpGet]\n public async Task Get()\n {\n var client = _httpClientFactory.CreateClient("github");\n string result = await client.GetStringAsync("/");\n return Ok(result);\n }\n}\n')),(0,s.kt)("h3",{id:"1962-\u81ea\u5b9a\u4e49-client-\u7c7b\u65b9\u5f0f"},"19.6.2 \u81ea\u5b9a\u4e49 ",(0,s.kt)("inlineCode",{parentName:"h3"},"Client")," \u7c7b\u65b9\u5f0f"),(0,s.kt)("p",null,"\u6211\u4eec\u53ef\u4ee5\u6309\u7167\u4e00\u5b9a\u7684\u89c4\u5219\u7f16\u5199\u7279\u5b9a\u670d\u52a1\u7684\u8bf7\u6c42\u5ba2\u6237\u7aef\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,5}",showLineNumbers:!0,"{1,3,5}":!0},'public class GitHubClient\n{\n public HttpClient Client { get; private set; }\n\n public GitHubClient(HttpClient httpClient)\n {\n httpClient.BaseAddress = new Uri("https://api.github.com/");\n httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");\n httpClient.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");\n Client = httpClient;\n }\n}\n')),(0,s.kt)("p",null,"\u7136\u540e\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddHttpClient();\n")),(0,s.kt)("p",null,"\u4f7f\u7528\u5982\u4e0b\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,13}",showLineNumbers:!0,"{3,13}":!0},'public class ValuesController : Controller\n{\n private readonly GitHubClient _gitHubClient;;\n\n public ValuesController(GitHubClient gitHubClient)\n {\n _gitHubClient = gitHubClient;\n }\n\n [HttpGet]\n public async Task Get()\n {\n string result = await _gitHubClient.Client.GetStringAsync("/");\n return Ok(result);\n }\n}\n')),(0,s.kt)("h3",{id:"1963-\u81ea\u5b9a\u4e49-client-\u7c7b--\u63a5\u53e3\u65b9\u5f0f"},"19.6.3 \u81ea\u5b9a\u4e49 ",(0,s.kt)("inlineCode",{parentName:"h3"},"Client")," \u7c7b + \u63a5\u53e3\u65b9\u5f0f"),(0,s.kt)("p",null,"\u6211\u4eec\u4e5f\u53ef\u4ee5\u5b9a\u4e49\u63a5\u53e3\uff0c\u901a\u8fc7\u63a5\u53e3\u7684\u63d0\u4f9b\u5177\u4f53\u7684\u670d\u52a1 ",(0,s.kt)("inlineCode",{parentName:"p"},"API")," \u64cd\u4f5c\uff0c\u65e0\u9700\u624b\u52a8\u914d\u7f6e ",(0,s.kt)("inlineCode",{parentName:"p"},"Url"),"\uff0c\u5982\u4e0a\u9762\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},'GetStringAsync("/")'),"\u3002"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3,6,10,18-21}",showLineNumbers:!0,"{1,3,6,10,18-21}":!0},'public interface IGitHubClient\n{\n Task GetData();\n}\n\npublic class GitHubClient : IGitHubClient\n{\n private readonly HttpClient _client;\n\n public GitHubClient(HttpClient httpClient)\n {\n httpClient.BaseAddress = new Uri("https://api.github.com/");\n httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");\n httpClient.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");\n _client = httpClient;\n }\n\n public async Task GetData()\n {\n return await _client.GetStringAsync("/");\n }\n}\n')),(0,s.kt)("p",null,"\u7136\u540e\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddHttpClient();\n")),(0,s.kt)("p",null,"\u4f7f\u7528\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,13}",showLineNumbers:!0,"{3,13}":!0},"public class ValuesController : Controller\n{\n private readonly IGitHubClient _gitHubClient;;\n\n public ValuesController(IGitHubClient gitHubClient)\n {\n _gitHubClient = gitHubClient;\n }\n\n [HttpGet]\n public async Task Get()\n {\n string result = await _gitHubClient.GetData();\n return Ok(result);\n }\n}\n")),(0,s.kt)("h2",{id:"197-sslhttps-\u8bc1\u4e66\u914d\u7f6e"},"19.7 ",(0,s.kt)("inlineCode",{parentName:"h2"},"SSL/https")," \u8bc1\u4e66\u914d\u7f6e"),(0,s.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u8bf7\u6c42\u8fdc\u7a0b\u63a5\u53e3\u65f6\u4f1a\u9047\u5230 ",(0,s.kt)("inlineCode",{parentName:"p"},"The SSL connection could not be established, see inner exception.")," \u8fd9\u6837\u7684\u9519\u8bef\uff0c\u539f\u56e0\u662f\u8bc1\u4e66\u914d\u7f6e\u4e0d\u6b63\u786e\u95ee\u9898\uff0c\u4e0b\u9762\u6709\u51e0\u79cd\u89e3\u51b3\u65b9\u6cd5\u3002"),(0,s.kt)("h3",{id:"1971-\u5ffd\u7565\u7279\u5b9a\u5ba2\u6237\u7aef-ssl-\u8bc1\u4e66\u68c0\u67e5"},"19.7.1 \u5ffd\u7565\u7279\u5b9a\u5ba2\u6237\u7aef ",(0,s.kt)("inlineCode",{parentName:"h3"},"SSL")," \u8bc1\u4e66\u68c0\u67e5"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,7,12,14}",showLineNumbers:!0,"{5,7,12,14}":!0},'services.AddRemoteRequest(options=>\n{\n // \u9ed8\u8ba4 HttpClient \u5728 Furion \u6846\u67b6\u5185\u90e8\u5df2\u7ecf\u914d\u7f6e\u4e86\u8be5\u64cd\u4f5c\n options.AddHttpClient(string.Empty)\n .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler\n {\n ServerCertificateCustomValidationCallback = (_, _, _, _) => true,\n });\n\n // \u914d\u7f6e\u7279\u5b9a\u5ba2\u6237\u7aef\n options.AddHttpClient("github", c => { /*\u5176\u4ed6\u914d\u7f6e*/ })\n .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler\n {\n ServerCertificateCustomValidationCallback = (_, _, _, _) => true,\n });\n});\n')),(0,s.kt)("admonition",{type:"tip"},(0,s.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u5173\u4e8e ",(0,s.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"HttpClientHandler")," \u548c ",(0,s.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"SocketsHttpHandler")),(0,s.kt)("p",{parentName:"admonition"},"\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},".NET6")," \u4e4b\u540e\u9ed8\u8ba4\u4f7f\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"SocketsHttpHandler ")," \u4f5c\u4e3a\u9ed8\u8ba4\u5e95\u5c42\u7f51\u7edc\u901a\u4fe1\uff0c\u4f46\u6bd4 ",(0,s.kt)("inlineCode",{parentName:"p"},"HttpClientHandler")," \u63d0\u4f9b\u4e86\u66f4\u591a\u5e73\u53f0\u65e0\u5dee\u5f02\u7684\u529f\u80fd\uff0c\u5bf9 ",(0,s.kt)("inlineCode",{parentName:"p"},"HttpClientHandler")," \u7684\u4efb\u4f55\u8bbe\u7f6e\u90fd\u4f1a\u8f6c\u53d1\u5230 ",(0,s.kt)("inlineCode",{parentName:"p"},"SocketsHttpHandler")," \u4e2d\uff0c\u5982\u9700\u4f7f\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"SocketsHttpHandler")," \u914d\u7f6e\u53ef\u53c2\u8003\uff1a"),(0,s.kt)("pre",{parentName:"admonition"},(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3,5-8}",showLineNumbers:!0,"{3,5-8}":!0},"// \u5ffd\u7565 SSL \u4e0d\u5b89\u5168\u68c0\u67e5\uff0c\u6216 https \u4e0d\u5b89\u5168\u6216 https \u8bc1\u4e66\u6709\u8bef\noptions.AddHttpClient(string.Empty)\n .ConfigurePrimaryHttpMessageHandler(u => new SocketsHttpHandler\n {\n SslOptions = new SslClientAuthenticationOptions\n {\n RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true\n }\n });\n"))),(0,s.kt)("h3",{id:"1972-\u624b\u52a8\u6307\u5b9a-ssl-\u8bc1\u4e66"},"19.7.2 \u624b\u52a8\u6307\u5b9a ",(0,s.kt)("inlineCode",{parentName:"h3"},"SSL")," \u8bc1\u4e66"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8-13}",showLineNumbers:!0,"{5,8-13}":!0},'services.AddRemoteRequest(options=>\n{\n // \u914d\u7f6e\u7279\u5b9a\u5ba2\u6237\u7aef\n options.AddHttpClient("github", c => { /*\u5176\u4ed6\u914d\u7f6e*/ })\n .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler\n {\n // \u624b\u52a8\u914d\u7f6e\u8bc1\u4e66\n ClientCertificateOptions = ClientCertificateOption.Manual,\n ClientCertificates = {\n new X509Certificate2("...","..."),\n new X509Certificate2("...","..."),\n new X509Certificate2("...","...")\n }\n });\n});\n')),(0,s.kt)("h3",{id:"1973-\u5ffd\u7565\u6240\u6709\u5ba2\u6237\u7aef\u8bc1\u4e66\u68c0\u67e5"},"19.7.3 \u5ffd\u7565\u6240\u6709\u5ba2\u6237\u7aef\u8bc1\u4e66\u68c0\u67e5"),(0,s.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,s.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,s.kt)("inlineCode",{parentName:"p"},"Furion v3.6.6+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4}",showLineNumbers:!0,"{1,4}":!0},"services.AddRemoteRequest(options=>\n{\n // \u9700\u5728\u6240\u6709\u5ba2\u6237\u7aef\u6ce8\u518c\u4e4b\u524d\u6ce8\u518c\n options.ApproveAllCerts();\n});\n")),(0,s.kt)("h2",{id:"198-\u5173\u4e8e\u8fd4\u56de\u503c\u975e-200-\u65f6\u5ffd\u7565-http\u72b6\u6001"},"19.8 \u5173\u4e8e\u8fd4\u56de\u503c\u975e ",(0,s.kt)("inlineCode",{parentName:"h2"},"200")," \u65f6\u5ffd\u7565 ",(0,s.kt)("inlineCode",{parentName:"h2"},"Http\u72b6\u6001")),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u975e\u5e38\u65b9\u4fbf\u7684\u8bf7\u6c42\u5e76\u4e14\u5e8f\u5217\u5316\u8bf7\u6c42\u7ed3\u679c ",(0,s.kt)("inlineCode",{parentName:"p"},"PostAsAsync"),"\n\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"2.8.8")," \u53ca\u4ee5\u4e0b\u7248\u672c\uff0c\u5f53\u8fd4\u56de\u7ed3\u679c\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"Http")," \u72b6\u6001\u4e3a\u975e ",(0,s.kt)("inlineCode",{parentName:"p"},"200")," \u65f6\uff0c\u4f1a\u76f4\u63a5\u622a\u65ad\u3002\u8003\u8651\u5230\u8bf7\u6c42\u63a5\u53e3\u7684\u591a\u6837\u6027\uff0c\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"2.8.9")," \u53ca\u4ee5\u4e0a\u7248\u672c\u589e\u52a0\u5ffd\u7565\u8fd4\u56de ",(0,s.kt)("inlineCode",{parentName:"p"},"Http")," \u72b6\u6001\uff0c\u76f4\u63a5\u5e8f\u5217\u5316\u7ed3\u679c\u7684\u65b9\u5f0f\u3002"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'//\u8bf7\u6c42\u5e76\u4e14\u5e8f\u5217\u5316\u8bf7\u6c42\u7ed3\u679c\nvar result = await "https://api.facebook.com/"\n //\u5982\u679c\u4e0d\u52a0OnException\uff0c\u5219\u4f1a\u76f4\u63a5\u622a\u65ad\n .OnException((res,errors)=> {\n //\u6fc0\u6d3b\u5f02\u6b65\u62e6\u622a \u6b64\u5904\u53ef\u4ee5\u505a\u8bb0\u5f55\u65e5\u5fd7\u64cd\u4f5c \u4e5f\u53ef\u4fdd\u6301\u73b0\u72b6\n })\n .PostAsAsync();\n')),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"PostAsStringAsync()")," \u4e5f\u4f7f\u7528\u540c\u6837\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"OnException")," \u64cd\u4f5c\u4f7f\u5f97\u5ffd\u7565\u8fd4\u56de ",(0,s.kt)("inlineCode",{parentName:"p"},"Http")," \u72b6\u6001,\u539f\u6837\u8fd4\u56de ",(0,s.kt)("inlineCode",{parentName:"p"},"Http")," \u8bf7\u6c42\u7ed3\u679c"),(0,s.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"important"},(0,s.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4e0d\u52a0 ",(0,s.kt)("inlineCode",{parentName:"p"},"OnException"),"\uff0c\u5219\u4f1a\u76f4\u63a5\u622a\u65ad\u3002\n\u5982\u679c\u9700\u8981\u590d\u6742\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"Http Post")," \u8bf7\u6c42\uff0c\u5efa\u8bae\u76f4\u63a5\u4f7f\u7528 ",(0,s.kt)("inlineCode",{parentName:"p"},"PostAsync"),",\u8fd4\u56de\u503c\u4e3a ",(0,s.kt)("inlineCode",{parentName:"p"},"HttpResponseMessage"),"\uff0c\u53ef\u4ee5\u66f4\u7075\u6d3b\u7684\u63a7\u5236\u7ed3\u679c\u3002")),(0,s.kt)("h2",{id:"199-\u5173\u4e8e\u540c\u6b65\u8bf7\u6c42"},"19.9 \u5173\u4e8e\u540c\u6b65\u8bf7\u6c42"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u5185\u90e8\u9ed8\u8ba4\u4e0d\u63d0\u4f9b\u540c\u6b65\u8bf7\u6c42\u64cd\u4f5c\uff0c\u5efa\u8bae\u603b\u662f\u4f7f\u7528\u5f02\u6b65\u7684\u65b9\u5f0f\u8bf7\u6c42\u3002\u5982\u5728\u4e0d\u80fd\u4f7f\u7528\u5f02\u6b65\u7684\u60c5\u51b5\u4e0b\uff0c\u53ef\u81ea\u884c\u8f6c\u6362\u4e3a\u540c\u6b65\u6267\u884c\u3002"),(0,s.kt)("h2",{id:"1910-\u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df"},"19.10 \u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df"),(0,s.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u6240\u6709\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"\u5b57\u7b26\u4e32")," \u548c ",(0,s.kt)("inlineCode",{parentName:"p"},"\u5b9e\u4f53")," \u62d3\u5c55\u90fd\u6709\u81ea\u5df1\u72ec\u7acb\u7ef4\u62a4\u7684 ",(0,s.kt)("inlineCode",{parentName:"p"},"ServiceProvider")," \u4f5c\u7528\u57df\u3002"),(0,s.kt)("p",null,"\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"Web")," \u8bf7\u6c42\u4e2d\uff0c\u9ed8\u8ba4\u662f ",(0,s.kt)("inlineCode",{parentName:"p"},"HttpContext.RequestServices"),"\uff0c\u4f46\u5728 ",(0,s.kt)("inlineCode",{parentName:"p"},"\u975e Web"),"\uff0c\u5982\u591a\u7ebf\u7a0b\u64cd\u4f5c\uff0c\u540e\u53f0\u4efb\u52a1\uff0c\u4e8b\u4ef6\u603b\u7ebf\u7b49\u573a\u666f\u4e0b\u4f1a\u81ea\u52a8\u521b\u5efa\u65b0\u7684\u4f5c\u7528\u57df\uff0c\u5b9e\u9645\u4e0a\u8fd9\u662f\u975e\u5e38\u4e0d\u5fc5\u8981\u7684\u5185\u5b58\u5f00\u9500\u3002"),(0,s.kt)("p",null,"\u8fd9\u65f6\uff0c\u6211\u4eec\u53ea\u9700\u8981\u901a\u8fc7 ",(0,s.kt)("inlineCode",{parentName:"p"},".SetXXXScoped(service)")," \u5171\u4eab\u5f53\u524d\u670d\u52a1\u63d0\u4f9b\u5668\u4f5c\u7528\u57df\u5373\u53ef\uff0c\u5982\uff1a"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'Scoped.Create(async (fac, scope) => {\n var response = await "https://www.furion.icu".SetRequestScoped(scope.ServiceProvider).PostAsync();\n});\n')),(0,s.kt)("h2",{id:"1911-\u9759\u6001-default-\u65b9\u5f0f\u6784\u5efa"},"19.11 \u9759\u6001 ",(0,s.kt)("inlineCode",{parentName:"h2"},"Default")," \u65b9\u5f0f\u6784\u5efa"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'await HttpRequestPart.Default.SetRequestUrl("https://www.baidu.com").GetAsStringAsync();\n')),(0,s.kt)("h2",{id:"1912-\u53cd\u9988\u4e0e\u5efa\u8bae"},"19.12 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,s.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,s.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,s.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,s.kt)("hr",null),(0,s.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,s.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,s.kt)("inlineCode",{parentName:"p"},"HttpClient")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,s.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/http-requests?view=aspnetcore-5.0"},"ASP.NET Core - HTTP \u8bf7\u6c42")," \u7ae0\u8282")))}w.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/ace43ec3.2e7195f2.js b/handbook/build/assets/js/ace43ec3.2e7195f2.js deleted file mode 100644 index 8e4b6c92c3..0000000000 --- a/handbook/build/assets/js/ace43ec3.2e7195f2.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[2583],{433:function(e,n,t){t.d(n,{Z:function(){return l}});var i=t(7294),a=t(4334),r="tabItem_Ymn6";function l(e){var n=e.children,t=e.hidden,l=e.className;return i.createElement("div",{role:"tabpanel",className:(0,a.Z)(r,l),hidden:t},n)}},5559:function(e,n,t){t.d(n,{Z:function(){return c}});var i=t(3117),a=t(7294),r=t(4334),l=t(5730),o=t(636),p=t(6602),s=t(3735),u="tabList__CuJ",m="tabItem_LNqP";function d(e){var n,t,l=e.lazy,d=e.block,c=e.defaultValue,k=e.values,g=e.groupId,N=e.className,C=a.Children.map(e.children,(function(e){if((0,a.isValidElement)(e)&&"value"in e.props)return e;throw new Error("Docusaurus error: Bad child <"+("string"==typeof e.type?e.type:e.type.name)+'>: all children of the component should be , and every should have a unique "value" prop.')})),h=null!=k?k:C.map((function(e){var n=e.props;return{value:n.value,label:n.label,attributes:n.attributes}})),f=(0,o.l)(h,(function(e,n){return e.value===n.value}));if(f.length>0)throw new Error('Docusaurus error: Duplicate values "'+f.map((function(e){return e.value})).join(", ")+'" found in . Every value needs to be unique.');var b=null===c?c:null!=(n=null!=c?c:null==(t=C.find((function(e){return e.props.default})))?void 0:t.props.value)?n:C[0].props.value;if(null!==b&&!h.some((function(e){return e.value===b})))throw new Error('Docusaurus error: The has a defaultValue "'+b+'" but none of its children has the corresponding value. Available values are: '+h.map((function(e){return e.value})).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");var w=(0,p.U)(),S=w.tabGroupChoices,v=w.setTabGroupChoices,y=(0,a.useState)(b),A=y[0],T=y[1],F=[],I=(0,s.o5)().blockElementScrollPositionUntilNextRender;if(null!=g){var D=S[g];null!=D&&D!==A&&h.some((function(e){return e.value===D}))&&T(D)}var L=function(e){var n=e.currentTarget,t=F.indexOf(n),i=h[t].value;i!==A&&(I(n),T(i),null!=g&&v(g,String(i)))},E=function(e){var n,t=null;switch(e.key){case"ArrowRight":var i,a=F.indexOf(e.currentTarget)+1;t=null!=(i=F[a])?i:F[0];break;case"ArrowLeft":var r,l=F.indexOf(e.currentTarget)-1;t=null!=(r=F[l])?r:F[F.length-1]}null==(n=t)||n.focus()};return a.createElement("div",{className:(0,r.Z)("tabs-container",u)},a.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,r.Z)("tabs",{"tabs--block":d},N)},h.map((function(e){var n=e.value,t=e.label,l=e.attributes;return a.createElement("li",(0,i.Z)({role:"tab",tabIndex:A===n?0:-1,"aria-selected":A===n,key:n,ref:function(e){return F.push(e)},onKeyDown:E,onFocus:L,onClick:L},l,{className:(0,r.Z)("tabs__item",m,null==l?void 0:l.className,{"tabs__item--active":A===n})}),null!=t?t:n)}))),l?(0,a.cloneElement)(C.filter((function(e){return e.props.value===A}))[0],{className:"margin-top--md"}):a.createElement("div",{className:"margin-top--md"},C.map((function(e,n){return(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==A})}))))}function c(e){var n=(0,l.Z)();return a.createElement(d,(0,i.Z)({key:String(n)},e))}},2017:function(e,n,t){t.r(n),t.d(n,{assets:function(){return c},contentTitle:function(){return m},default:function(){return N},frontMatter:function(){return u},metadata:function(){return d},toc:function(){return k}});var i=t(3117),a=t(102),r=(t(7294),t(3905)),l=t(1402),o=t(5559),p=t(433),s=["components"],u={id:"specification-document",title:"6. \u89c4\u8303\u5316\u63a5\u53e3\u6587\u6863",sidebar_label:"6. \u89c4\u8303\u5316\u63a5\u53e3\u6587\u6863 (Swagger)"},m=void 0,d={unversionedId:"specification-document",id:"specification-document",title:"6. \u89c4\u8303\u5316\u63a5\u53e3\u6587\u6863",description:"",source:"@site/docs/specification-document.mdx",sourceDirName:".",slug:"/specification-document",permalink:"/furion/docs/specification-document",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/specification-document.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1661938334,formattedLastUpdatedAt:"Aug 31, 2022",frontMatter:{id:"specification-document",title:"6. \u89c4\u8303\u5316\u63a5\u53e3\u6587\u6863",sidebar_label:"6. \u89c4\u8303\u5316\u63a5\u53e3\u6587\u6863 (Swagger)"},sidebar:"docs",previous:{title:"5.6 Vue/React/Angular \u8bf7\u6c42\u4ee3\u7406",permalink:"/furion/docs/clientapi"},next:{title:"7. \u53cb\u597d\u5f02\u5e38\u5904\u7406",permalink:"/furion/docs/friendly-exception"}},c={},k=[{value:"6.1 \u4ec0\u4e48\u662f\u63a5\u53e3\u6587\u6863",id:"61-\u4ec0\u4e48\u662f\u63a5\u53e3\u6587\u6863",level:2},{value:"6.2 \u4e3a\u4ec0\u4e48\u8981\u5199\u63a5\u53e3\u6587\u6863",id:"62-\u4e3a\u4ec0\u4e48\u8981\u5199\u63a5\u53e3\u6587\u6863",level:2},{value:"6.3 \u4e3a\u4ec0\u4e48\u9700\u8981\u89c4\u8303\u5316\u6587\u6863",id:"63-\u4e3a\u4ec0\u4e48\u9700\u8981\u89c4\u8303\u5316\u6587\u6863",level:2},{value:"6.3.1 \u534f\u8bae\u89c4\u8303",id:"631-\u534f\u8bae\u89c4\u8303",level:3},{value:"6.3.2 \u63a5\u53e3\u8def\u5f84\u89c4\u8303",id:"632-\u63a5\u53e3\u8def\u5f84\u89c4\u8303",level:3},{value:"6.3.3 \u7248\u672c\u63a7\u5236\u89c4\u8303",id:"633-\u7248\u672c\u63a7\u5236\u89c4\u8303",level:3},{value:"6.3.4 \u63a5\u53e3\u547d\u540d\u89c4\u8303",id:"634-\u63a5\u53e3\u547d\u540d\u89c4\u8303",level:3},{value:"6.3.5 \u8bf7\u6c42\u53c2\u6570\u89c4\u8303",id:"635-\u8bf7\u6c42\u53c2\u6570\u89c4\u8303",level:3},{value:"6.3.6 \u8fd4\u56de\u6570\u636e\u89c4\u8303",id:"636-\u8fd4\u56de\u6570\u636e\u89c4\u8303",level:3},{value:"6.4 \u4ec0\u4e48\u662f Swagger",id:"64-\u4ec0\u4e48\u662f-swagger",level:2},{value:"6.5 Swagger \u4f7f\u7528",id:"65-swagger-\u4f7f\u7528",level:2},{value:"6.5.1 \u6ce8\u518c\u670d\u52a1",id:"651-\u6ce8\u518c\u670d\u52a1",level:3},{value:"6.5.2 \u9ed8\u8ba4\u5730\u5740",id:"652-\u9ed8\u8ba4\u5730\u5740",level:3},{value:"6.5.3 \u9ed8\u8ba4\u5206\u7ec4",id:"653-\u9ed8\u8ba4\u5206\u7ec4",level:3},{value:"6.5.4 \u6587\u6863\u6ce8\u91ca",id:"654-\u6587\u6863\u6ce8\u91ca",level:3},{value:"6.5.5 \u591a\u5206\u7ec4\u652f\u6301",id:"655-\u591a\u5206\u7ec4\u652f\u6301",level:3},{value:"6.5.6 \u591a\u5206\u7ec4\u6392\u5e8f",id:"656-\u591a\u5206\u7ec4\u6392\u5e8f",level:3},{value:"6.5.7 \u591a\u5206\u7ec4\u4fe1\u606f\u914d\u7f6e",id:"657-\u591a\u5206\u7ec4\u4fe1\u606f\u914d\u7f6e",level:3},{value:"6.5.8 \u7ec4\u4e2d\u7ec4\uff08\u6807\u7b7e\uff09",id:"658-\u7ec4\u4e2d\u7ec4\u6807\u7b7e",level:3},{value:"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d",id:"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d",level:4},{value:"\u8d34\u6807\u7b7e\u4e4b\u540e",id:"\u8d34\u6807\u7b7e\u4e4b\u540e",level:4},{value:"6.5.9 \u9ed8\u8ba4\u5c55\u5f00\u6240\u6709\u6587\u6863",id:"659-\u9ed8\u8ba4\u5c55\u5f00\u6240\u6709\u6587\u6863",level:3},{value:"6.5.10 \u914d\u7f6e\u6587\u6863\u6807\u9898",id:"6510-\u914d\u7f6e\u6587\u6863\u6807\u9898",level:3},{value:"6.5.11 \u6388\u6743\u63a7\u5236",id:"6511-\u6388\u6743\u63a7\u5236",level:3},{value:"6.5.12 \u5728\u7ebf\u6d4b\u8bd5",id:"6512-\u5728\u7ebf\u6d4b\u8bd5",level:3},{value:"6.5.13 \u6027\u80fd\u76d1\u89c6 MiniProfiler",id:"6513-\u6027\u80fd\u76d1\u89c6-miniprofiler",level:3},{value:"6.5.14 \u5b9a\u4e49\u63a5\u53e3\u8f93\u51fa\u7c7b\u578b",id:"6514-\u5b9a\u4e49\u63a5\u53e3\u8f93\u51fa\u7c7b\u578b",level:3},{value:"6.5.15 \u9690\u85cf\u7279\u5b9a\u5206\u7ec4",id:"6515-\u9690\u85cf\u7279\u5b9a\u5206\u7ec4",level:3},{value:"6.5.16 \u4e2d\u6587\u4e71\u7801\u95ee\u9898",id:"6516-\u4e2d\u6587\u4e71\u7801\u95ee\u9898",level:3},{value:"6.5.17 \u751f\u4ea7\u73af\u5883\u4e2d\u5173\u95ed Swagger",id:"6517-\u751f\u4ea7\u73af\u5883\u4e2d\u5173\u95ed-swagger",level:3},{value:"6.5.18 \u8bbe\u7f6e Example Value \u9ed8\u8ba4\u503c",id:"6518-\u8bbe\u7f6e-example-value-\u9ed8\u8ba4\u503c",level:3},{value:"6.5.19 \u81ea\u5b9a\u4e49 Swagger \u914d\u7f6e",id:"6519-\u81ea\u5b9a\u4e49-swagger-\u914d\u7f6e",level:3},{value:"6.5.20 \u914d\u7f6e Swagger\u7684 Schemes",id:"6520-\u914d\u7f6e-swagger\u7684-schemes",level:3},{value:"6.5.21 \u81ea\u5b9a\u4e49 swagger.json \u8def\u7531\u6a21\u677f",id:"6521-\u81ea\u5b9a\u4e49-swaggerjson-\u8def\u7531\u6a21\u677f",level:3},{value:"6.5.22 \u5173\u4e8e application/x-www-form-urlencoded \u8bf7\u6c42",id:"6522-\u5173\u4e8e-applicationx-www-form-urlencoded-\u8bf7\u6c42",level:3},{value:"6.5.23 Swagger \u51fa\u73b0 CORS \u95ee\u9898\u89e3\u51b3",id:"6523-swagger-\u51fa\u73b0-cors-\u95ee\u9898\u89e3\u51b3",level:3},{value:"6.5.24 Swagger \u51fa\u73b0\u9ed8\u8ba4 xml \u53c2\u6570\u95ee\u9898\u89e3\u51b3",id:"6524-swagger-\u51fa\u73b0\u9ed8\u8ba4-xml-\u53c2\u6570\u95ee\u9898\u89e3\u51b3",level:3},{value:"6.5.25 Swagger \u591a\u8bed\u8a00\u652f\u6301",id:"6525-swagger-\u591a\u8bed\u8a00\u652f\u6301",level:3},{value:"6.5.26 \u81ea\u5b9a\u4e49\u903b\u8f91\u63a7\u5236 Swagger \u6bcf\u4e00\u4e2a api \u53ef\u89c1\u6027",id:"6526-\u81ea\u5b9a\u4e49\u903b\u8f91\u63a7\u5236-swagger-\u6bcf\u4e00\u4e2a-api-\u53ef\u89c1\u6027",level:3},{value:"6.5.27 \u914d\u7f6e MVC \u63a7\u5236\u5668\u652f\u6301\u89c4\u8303\u5316\u5904\u7406",id:"6527-\u914d\u7f6e-mvc-\u63a7\u5236\u5668\u652f\u6301\u89c4\u8303\u5316\u5904\u7406",level:3},{value:"6.5.28 Swagger \u5237\u65b0\u8bb0\u4f4f\u6388\u6743\u72b6\u6001",id:"6528-swagger-\u5237\u65b0\u8bb0\u4f4f\u6388\u6743\u72b6\u6001",level:3},{value:"6.5.29 \u5e26\u767b\u5f55\u7684 Swagger \u6587\u6863",id:"6529-\u5e26\u767b\u5f55\u7684-swagger-\u6587\u6863",level:3},{value:"\u914d\u7f6e\u8bf4\u660e",id:"\u914d\u7f6e\u8bf4\u660e",level:4},{value:"\u914d\u7f6e\u793a\u4f8b",id:"\u914d\u7f6e\u793a\u4f8b",level:4},{value:"6.5.30 inheritdoc \u5b9e\u73b0\u6ce8\u91ca\u7ee7\u627f",id:"6530-inheritdoc-\u5b9e\u73b0\u6ce8\u91ca\u7ee7\u627f",level:2},{value:"6.5.31 \u542f\u7528 All Groups \u5206\u7ec4\u529f\u80fd",id:"6531-\u542f\u7528-all-groups-\u5206\u7ec4\u529f\u80fd",level:3},{value:"6.5.32 \u63a5\u53e3\u8fc7\u65f6\u63a7\u5236",id:"6532-\u63a5\u53e3\u8fc7\u65f6\u63a7\u5236",level:3},{value:"6.5.33 \u5355\u4e00\u63a5\u53e3\u66f4\u591a\u63cf\u8ff0",id:"6533-\u5355\u4e00\u63a5\u53e3\u66f4\u591a\u63cf\u8ff0",level:3},{value:"6.5.34 Swagger \u5f02\u5e38/\u4e0d\u80fd\u663e\u793a/\u9519\u8bef\u5904\u7406",id:"6534-swagger-\u5f02\u5e38\u4e0d\u80fd\u663e\u793a\u9519\u8bef\u5904\u7406",level:3},{value:"6.5.35 \u81ea\u5b9a\u4e49 Swagger \u7684 SchemaId",id:"6535-\u81ea\u5b9a\u4e49-swagger-\u7684-schemaid",level:3},{value:"6.5.36 \u81ea\u5b9a\u4e49 Swagger \u7684 OperationId",id:"6536-\u81ea\u5b9a\u4e49-swagger-\u7684-operationid",level:3},{value:"6.5.37 Swagger \u63a5\u53e3\u6587\u6863\u652f\u6301\u5b8c\u6574\u7684 Markdown",id:"6537-swagger-\u63a5\u53e3\u6587\u6863\u652f\u6301\u5b8c\u6574\u7684-markdown",level:3},{value:"6.6 SpecificationDocumentSettings \u914d\u7f6e",id:"66-specificationdocumentsettings-\u914d\u7f6e",level:2},{value:"6.7 \u7edf\u4e00\u8fd4\u56de\u503c\u6a21\u578b/\u89c4\u8303\u5316\u7ed3\u679c/API \u8fd4\u56de\u503c",id:"67-\u7edf\u4e00\u8fd4\u56de\u503c\u6a21\u578b\u89c4\u8303\u5316\u7ed3\u679capi-\u8fd4\u56de\u503c",level:2},{value:"6.7.1 \u6392\u9664\u89c4\u8303\u5316\u5904\u7406",id:"671-\u6392\u9664\u89c4\u8303\u5316\u5904\u7406",level:3},{value:"6.7.2 \u89c4\u8303\u5316\u7ed3\u679c\u6dfb\u52a0\u989d\u5916\u6570\u636e",id:"672-\u89c4\u8303\u5316\u7ed3\u679c\u6dfb\u52a0\u989d\u5916\u6570\u636e",level:3},{value:"6.7.3 \u81ea\u5b9a\u4e49\u7279\u522b\u63a5\u53e3\u89c4\u8303\u5316\u7ed3\u679c",id:"673-\u81ea\u5b9a\u4e49\u7279\u522b\u63a5\u53e3\u89c4\u8303\u5316\u7ed3\u679c",level:3},{value:"6.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"68-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],g={toc:k};function N(e){var n=e.components,t=(0,a.Z)(e,s);return(0,r.kt)("wrapper",(0,i.Z)({},g,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"61-\u4ec0\u4e48\u662f\u63a5\u53e3\u6587\u6863"},"6.1 \u4ec0\u4e48\u662f\u63a5\u53e3\u6587\u6863"),(0,r.kt)("p",null,"\u5728\u73b0\u5728\u79fb\u52a8\u4e3a\u738b\u3001\u591a\u7aef\u4e92\u8f85\u3001\u524d\u7aef\u767e\u82b1\u9f50\u653e\u7684\u5f00\u653e\u65f6\u4ee3\uff0c\u4e0d\u518d\u662f\u4e00\u4eba\u5305\u63fd\u5f0f\u5f00\u53d1\uff0c\u5927\u5bb6\u5404\u53f8\u5176\u804c\uff0c\u540e\u7aef\u5de5\u7a0b\u5e08\u8d1f\u8d23\u63a5\u53e3\u5f00\u53d1\uff0c\u524d\u7aef\u8d1f\u8d23\u63a5\u53e3\u8054\u8c03\uff0c\u4e5f\u5c31\u662f\u4e92\u8054\u7f51\u73b0\u5728\u6d41\u884c\u7684\u524d\u540e\u7aef\u5206\u79bb\u67b6\u6784\u3002"),(0,r.kt)("p",null,"\u6240\u4ee5\u5c31\u9700\u8981\u7531\u524d\u540e\u7aef\u5de5\u7a0b\u5e08\u5171\u540c\u5b9a\u4e49\u63a5\u53e3\uff0c\u7f16\u5199\u63a5\u53e3\u6587\u6863\uff0c\u4e4b\u540e\u5927\u5bb6\u6309\u7167\u8fd9\u4e2a\u63a5\u53e3\u6587\u6863\u8fdb\u884c\u5f00\u53d1\u3001\u7ef4\u62a4\u53ca\u5f00\u653e\u7ed9\u7b2c\u4e09\u65b9\u3002"),(0,r.kt)("h2",{id:"62-\u4e3a\u4ec0\u4e48\u8981\u5199\u63a5\u53e3\u6587\u6863"},"6.2 \u4e3a\u4ec0\u4e48\u8981\u5199\u63a5\u53e3\u6587\u6863"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u80fd\u591f\u8ba9\u524d\u7aef\u5f00\u53d1\u4e0e\u540e\u53f0\u5f00\u53d1\u4eba\u5458\u66f4\u597d\u7684\u914d\u5408\uff0c\u63d0\u9ad8\u5de5\u4f5c\u6548\u7387"),(0,r.kt)("li",{parentName:"ul"},"\u9879\u76ee\u8fed\u4ee3\u6216\u8005\u9879\u76ee\u4eba\u5458\u66f4\u8fed\u65f6\uff0c\u65b9\u4fbf\u540e\u671f\u4eba\u5458\u67e5\u770b\u548c\u7ef4\u62a4"),(0,r.kt)("li",{parentName:"ul"},"\u65b9\u4fbf\u6d4b\u8bd5\u4eba\u5458\u8fdb\u884c\u63a5\u53e3\u6d4b\u8bd5")),(0,r.kt)("h2",{id:"63-\u4e3a\u4ec0\u4e48\u9700\u8981\u89c4\u8303\u5316\u6587\u6863"},"6.3 \u4e3a\u4ec0\u4e48\u9700\u8981\u89c4\u8303\u5316\u6587\u6863"),(0,r.kt)("p",null,"\u7531\u4e8e\u6bcf\u4e2a\u516c\u53f8\u540e\u7aef\u4eba\u5458\u6280\u672f\u53c2\u5dee\u4e0d\u9f50\uff0c\u6280\u672f\u6587\u6863\u80fd\u529b\u4e5f\u4e0d\u4f8b\u5916\uff0c\u5bfc\u81f4\u63a5\u53e3\u5b9a\u4e49\u53ca\u6587\u6863\u4e94\u82b1\u516b\u95e8\uff0c\u4e0d\u540c\u9879\u76ee\u6216\u4e0d\u540c\u516c\u53f8\u5bf9\u63a5\u6781\u5176\u56f0\u96be\uff0c\u800c\u4e14\u4f53\u9a8c\u7cdf\u7cd5\u3002\u6240\u4ee5\uff0c\u65e0\u89c4\u77e9\u4e0d\u6210\u65b9\u5706\uff0c\u4e3a\u4e86\u5f00\u53d1\u4eba\u5458\u95f4\u66f4\u597d\u7684\u914d\u5408\uff0c\u8feb\u5207\u9700\u8981\u6574\u7406\u51fa\u4e00\u5957\u89c4\u8303\u3002"),(0,r.kt)("p",null,"\u901a\u5e38\u63a5\u53e3\u89c4\u8303\u5206\u4e3a\u516d\u4e2a\u90e8\u5206\uff1a"),(0,r.kt)("h3",{id:"631-\u534f\u8bae\u89c4\u8303"},"6.3.1 \u534f\u8bae\u89c4\u8303"),(0,r.kt)("p",null,"\u4e3a\u4e86\u786e\u4fdd\u4e0d\u540c\u7cfb\u7edf/\u6a21\u5757\u95f4\u7684\u6570\u636e\u4ea4\u4e92\uff0c\u9700\u8981\u4e8b\u5148\u7ea6\u5b9a\u597d\u901a\u8baf\u534f\u8bae\uff0c\u5982\uff1aTCP\u3001HTTP\u3001HTTPS \u534f\u8bae\u3002\u4e3a\u4e86\u786e\u4fdd\u6570\u636e\u4ea4\u4e92\u5b89\u5168\uff0c\u5efa\u8bae\u4f7f\u7528 HTTPS \u534f\u8bae"),(0,r.kt)("h3",{id:"632-\u63a5\u53e3\u8def\u5f84\u89c4\u8303"},"6.3.2 \u63a5\u53e3\u8def\u5f84\u89c4\u8303"),(0,r.kt)("p",null,"\u4f5c\u4e3a\u63a5\u53e3\u8def\u5f84\uff0c\u4e3a\u4e86\u65b9\u4fbf\u6e05\u6670\u7684\u533a\u5206\u6765\u81ea\u4e0d\u540c\u7684\u7cfb\u7edf\uff0c\u53ef\u4ee5\u91c7\u7528\u4e0d\u540c\u7cfb\u7edf/\u6a21\u5757\u540d\u4f5c\u4e3a\u63a5\u53e3\u8def\u5f84\u524d\u7f00\uff0c\u5982\uff1a\u652f\u4ed8\u6a21\u5757\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"/pay/xxx"),"\uff0c\u8ba2\u5355\u6a21\u5757\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"/order/xxx")),(0,r.kt)("h3",{id:"633-\u7248\u672c\u63a7\u5236\u89c4\u8303"},"6.3.3 \u7248\u672c\u63a7\u5236\u89c4\u8303"),(0,r.kt)("p",null,'\u4e3a\u4e86\u4fbf\u4e8e\u540e\u671f\u63a5\u53e3\u7684\u5347\u7ea7\u548c\u7ef4\u62a4\uff0c\u5efa\u8bae\u5728\u63a5\u53e3\u8def\u5f84\u4e2d\u52a0\u5165\u7248\u672c\u53f7\uff0c\u4fbf\u4e8e\u7ba1\u7406\uff0c\u5b9e\u73b0\u63a5\u53e3\u591a\u7248\u672c\u7684\u53ef\u7ef4\u62a4\u6027\u3002\u5982\uff1a\u63a5\u53e3\u8def\u5f84\u4e2d\u6dfb\u52a0\u7c7b\u4f3c"',(0,r.kt)("inlineCode",{parentName:"p"},"v1"),'"\u3001"',(0,r.kt)("inlineCode",{parentName:"p"},"v2"),'"\u7b49\u7248\u672c\u53f7'),(0,r.kt)("h3",{id:"634-\u63a5\u53e3\u547d\u540d\u89c4\u8303"},"6.3.4 \u63a5\u53e3\u547d\u540d\u89c4\u8303"),(0,r.kt)("p",null,'\u548c C# \u547d\u540d\u89c4\u8303\u4e00\u6837\uff0c\u597d\u7684\u3001\u7edf\u4e00\u7684\u63a5\u53e3\u547d\u540d\u89c4\u8303\uff0c\u4e0d\u4ec5\u53ef\u4ee5\u589e\u5f3a\u5176\u53ef\u8bfb\u6027\uff0c\u800c\u4e14\u8fd8\u4f1a\u51cf\u5c11\u5f88\u591a\u4e0d\u5fc5\u8981\u7684\u53e3\u5934/\u4e66\u9762\u4e0a\u7684\u89e3\u91ca\u3002\u53ef\u4f7f\u7528"\u9a7c\u5cf0\u547d\u540d\u6cd5"\u6309\u7167\u5b9e\u73b0\u63a5\u53e3\u7684',(0,r.kt)("strong",{parentName:"p"},"\u4e1a\u52a1\u7c7b\u578b\u3001\u4e1a\u52a1\u573a\u666f"),"\u7b49\u547d\u540d\uff0c\u6709\u5fc5\u8981\u65f6\u53ef\u91c7\u53d6\u591a\u7ea7\u76ee\u5f55\u547d\u540d\uff0c\u4f46\u76ee\u5f55\u4e0d\u5b9c\u8fc7\u957f\uff0c\u4e24\u7ea7\u76ee\u5f55\u8f83\u4e3a\u9002\u5b9c"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u5e38\u89c1\u547d\u540d\u65b9\u5f0f"),":",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u63a5\u53e3\u540d\u79f0\u52a8\u8bcd\u524d/\u540e\u7f00\u5316"),"\uff1a \u63a5\u53e3\u540d\u79f0\u4ee5\u63a5\u53e3\u6570\u636e\u64cd\u4f5c\u7684\u52a8\u8bcd\u4e3a\u524d/\u540e\u7f00\uff0c\u5e38\u89c1\u52a8\u8bcd\u6709\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Add\u3001Delete\u3001Update\u3001Query\u3001Get\u3001Send\u3001Save\u3001Detail\u3001List"),"\u7b49\uff0c\u5982\uff1a\u65b0\u5efa\u7528\u6237 ",(0,r.kt)("inlineCode",{parentName:"li"},"AddUser"),"\u3001\u67e5\u8be2\u8ba2\u5355\u8be6\u60c5 ",(0,r.kt)("inlineCode",{parentName:"li"},"QueryOrderDetail"),"\u3002"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u63a5\u53e3\u540d\u79f0\u52a8\u8bcd + \u8bf7\u6c42\u65b9\u5f0f"),"\uff1a\u63a5\u53e3\u8def\u5f84\u4e2d\u5305\u542b\u5177\u4f53\u63a5\u53e3\u540d\u79f0\u7684\u540d\u8bcd\uff0c\u63a5\u53e3\u6570\u636e\u64cd\u4f5c\u52a8\u4f5c\u4ee5 HTTP \u8bf7\u6c42\u65b9\u5f0f\u6765\u533a\u5206\u3002\u5e38\u7528\u7684 HTTP \u8bf7\u6c42\u65b9\u5f0f\u6709\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"GET"),"\uff1a\u4ece\u670d\u52a1\u5668\u53d6\u51fa\u8d44\u6e90\uff08\u4e00\u9879\u6216\u591a\u9879\uff09"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"POST"),"\uff1a\u5728\u670d\u52a1\u5668\u65b0\u5efa\u4e00\u4e2a\u8d44\u6e90"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"PUT"),"\uff1a\u5728\u670d\u52a1\u5668\u66f4\u65b0\u8d44\u6e90\uff08\u5ba2\u6237\u7aef\u63d0\u4f9b\u6539\u53d8\u540e\u7684\u5b8c\u6574\u8d44\u6e90\uff09"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"PATCH"),"\uff1a\u5728\u670d\u52a1\u5668\u66f4\u65b0\u8d44\u6e90\uff08\u5ba2\u6237\u7aef\u63d0\u4f9b\u6539\u53d8\u7684\u5c5e\u6027\uff09"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DELETE"),"\uff1a\u4ece\u670d\u52a1\u5668\u5220\u9664\u8d44\u6e90")))))),(0,r.kt)("h3",{id:"635-\u8bf7\u6c42\u53c2\u6570\u89c4\u8303"},"6.3.5 \u8bf7\u6c42\u53c2\u6570\u89c4\u8303"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u8bf7\u6c42\u65b9\u5f0f"),"\uff1a\u6309\u7167 ",(0,r.kt)("inlineCode",{parentName:"li"},"GET\u3001POST\u3001PUT")," \u7b49\u542b\u4e49\u5b9a\u4e49\uff0c\u907f\u514d\u51fa\u73b0\u4e0d\u4e00\u81f4\u73b0\u8c61\uff0c\u5bf9\u4eba\u9020\u6210\u8bef\u89e3\u3001\u6b67\u4e49",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u8bf7\u6c42\u5934"),"\uff1a\u8bf7\u6c42\u5934\u6839\u636e\u9879\u76ee\u9700\u6c42\u6dfb\u52a0\u914d\u7f6e\u53c2\u6570\u3002\u5982\uff1a\u8bf7\u6c42\u6570\u636e\u683c\u5f0f\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"accept=application/json")," \u7b49\u3002\u5982\u6709\u9700\u8981\uff0c\u8bf7\u6c42\u5934\u53ef\u6839\u636e\u9879\u76ee\u9700\u6c42\u8981\u6c42\u4f20\u5165\u7528\u6237 token\u3001\u552f\u4e00\u9a8c\u7b7e\u7801\u7b49\u52a0\u5bc6\u6570\u636e"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u8bf7\u6c42\u53c2\u6570/\u8bf7\u6c42\u4f53"),"\uff1a \u8bf7\u6c42\u53c2\u6570\u5b57\u6bb5\uff0c\u5c3d\u53ef\u80fd\u4e0e\u6570\u636e\u5e93\u8868\u5b57\u6bb5\u3001\u5bf9\u8c61\u5c5e\u6027\u540d\u7b49\u4fdd\u6301\u4e00\u81f4\uff0c\u56e0\u4e3a\u4fdd\u6301\u4e00\u81f4\u662f\u6700\u7701\u4e8b\uff0c\u6700\u8212\u670d\u7684\u4e00\u4ef6\u4e8b")))),(0,r.kt)("h3",{id:"636-\u8fd4\u56de\u6570\u636e\u89c4\u8303"},"6.3.6 \u8fd4\u56de\u6570\u636e\u89c4\u8303"),(0,r.kt)("p",null,"\u7edf\u4e00\u89c4\u8303\u8fd4\u56de\u6570\u636e\u7684\u683c\u5f0f\uff0c\u5bf9\u5df1\u5bf9\u5f7c\u90fd\u6709\u597d\u5904\uff0c\u6b64\u5904\u4ee5 json \u683c\u5f0f\u4e3a\u4f8b\u3002\u8fd4\u56de\u6570\u636e\u5e94\u5305\u542b\uff1a",(0,r.kt)("strong",{parentName:"p"},"\u8fd4\u56de\u72b6\u6001\u7801\u3001\u8fd4\u56de\u72b6\u6001\u4fe1\u606f\u3001\u5177\u4f53\u6570\u636e"),"\u3002",(0,r.kt)("strong",{parentName:"p"},"\u8fd4\u56de\u6570\u636e\u4e2d\u7684\u72b6\u6001\u7801\u3001\u72b6\u6001\u4fe1\u606f\uff0c\u5e38\u6307\u5177\u4f53\u7684\u4e1a\u52a1\u72b6\u6001\uff0c\u4e0d\u5efa\u8bae\u548c HTTP \u72b6\u6001\u7801\u6df7\u5728\u4e00\u8d77"),"\u3002HTTP \u72b6\u6001\uff0c\u662f\u7528\u6765\u4f53\u73b0 HTTP \u94fe\u8def\u72b6\u6001\u60c5\u51b5\uff0c\u5982\uff1a404-Not Found\u3002HTTP \u72b6\u6001\u7801\u548c json \u7ed3\u679c\u4e2d\u7684\u72b6\u6001\u7801\uff0c\u5e76\u5b58\u5c1a\u53ef\uff0c\u7528\u4e8e\u4f53\u73b0\u4e0d\u540c\u7ef4\u5ea6\u7684\u72b6\u6001\u3002"),(0,r.kt)("h2",{id:"64-\u4ec0\u4e48\u662f-swagger"},"6.4 \u4ec0\u4e48\u662f Swagger"),(0,r.kt)("p",null,"\u76f8\u4fe1\u65e0\u8bba\u662f\u524d\u7aef\u8fd8\u662f\u540e\u7aef\u5f00\u53d1\uff0c\u90fd\u6216\u591a\u6216\u5c11\u5730\u88ab\u63a5\u53e3\u6587\u6863\u6298\u78e8\u8fc7\u3002\u524d\u7aef\u7ecf\u5e38\u62b1\u6028\u540e\u7aef\u7ed9\u7684\u63a5\u53e3\u6587\u6863\u4e0e\u5b9e\u9645\u60c5\u51b5\u4e0d\u4e00\u81f4\u3002\u540e\u7aef\u53c8\u89c9\u5f97\u7f16\u5199\u53ca\u7ef4\u62a4\u63a5\u53e3\u6587\u6863\u4f1a\u8017\u8d39\u4e0d\u5c11\u7cbe\u529b\uff0c\u7ecf\u5e38\u6765\u4e0d\u53ca\u66f4\u65b0\u3002"),(0,r.kt)("p",null,"\u5176\u5b9e\u65e0\u8bba\u662f\u524d\u7aef\u8c03\u7528\u540e\u7aef\uff0c\u8fd8\u662f\u540e\u7aef\u8c03\u7528\u540e\u7aef\uff0c\u90fd\u671f\u671b\u6709\u4e00\u4e2a\u597d\u7684\u63a5\u53e3\u6587\u6863\u3002\u4f46\u662f\u8fd9\u4e2a\u63a5\u53e3\u6587\u6863\u5bf9\u4e8e\u7a0b\u5e8f\u5458\u6765\u8bf4\uff0c\u5c31\u8ddf\u6ce8\u91ca\u4e00\u6837\uff0c\u7ecf\u5e38\u4f1a\u62b1\u6028\u522b\u4eba\u5199\u7684\u4ee3\u7801\u6ca1\u6709\u5199\u6ce8\u91ca\uff0c\u7136\u800c\u81ea\u5df1\u5199\u8d77\u4ee3\u7801\u8d77\u6765\uff0c\u6700\u8ba8\u538c\u7684\uff0c\u4e5f\u662f\u5199\u6ce8\u91ca\u3002\u6240\u4ee5\u4ec5\u4ec5\u53ea\u901a\u8fc7\u5f3a\u5236\u6765\u89c4\u8303\u5927\u5bb6\u662f\u4e0d\u591f\u7684\uff0c\u968f\u7740\u65f6\u95f4\u63a8\u79fb\uff0c\u7248\u672c\u8fed\u4ee3\uff0c\u63a5\u53e3\u6587\u6863\u5f80\u5f80\u5f88\u5bb9\u6613\u5c31\u8ddf\u4e0d\u4e0a\u4ee3\u7801\u4e86\u3002"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u53d1\u73b0\u4e86\u75db\u70b9\u5c31\u8981\u53bb\u627e\u89e3\u51b3\u65b9\u6848\u3002\u89e3\u51b3\u65b9\u6848\u7528\u7684\u4eba\u591a\u4e86\uff0c\u5c31\u6210\u4e86\u6807\u51c6\u7684\u89c4\u8303\uff0c\u8fd9\u5c31\u662f ",(0,r.kt)("inlineCode",{parentName:"strong"},"Swagger")," \u7684\u7531\u6765"),"\u3002"),(0,r.kt)("p",null,"\u901a\u8fc7\u8fd9\u5957\u89c4\u8303\uff0c\u4f60\u53ea\u9700\u8981\u6309\u7167\u5b83\u7684\u89c4\u8303\u53bb\u5b9a\u4e49\u63a5\u53e3\u53ca\u63a5\u53e3\u76f8\u5173\u7684\u4fe1\u606f\u3002\u518d\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u884d\u751f\u51fa\u6765\u7684\u4e00\u7cfb\u5217\u9879\u76ee\u548c\u5de5\u5177\uff0c\u5c31\u53ef\u4ee5\u505a\u5230\u751f\u6210\u5404\u79cd\u683c\u5f0f\u7684\u63a5\u53e3\u6587\u6863\uff0c\u751f\u6210\u591a\u79cd\u8bed\u8a00\u7684\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u7aef\u7684\u4ee3\u7801\uff0c\u4ee5\u53ca\u5728\u7ebf\u63a5\u53e3\u8c03\u8bd5\u9875\u9762\u7b49\u7b49\u3002"),(0,r.kt)("p",null,"\u8fd9\u6837\uff0c\u5982\u679c\u6309\u7167\u65b0\u7684\u5f00\u53d1\u6a21\u5f0f\uff0c\u5728\u5f00\u53d1\u65b0\u7248\u672c\u6216\u8005\u8fed\u4ee3\u7248\u672c\u7684\u65f6\u5019\uff0c\u53ea\u9700\u8981\u66f4\u65b0 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u63cf\u8ff0\u6587\u4ef6\uff0c\u5c31\u53ef\u4ee5\u81ea\u52a8\u751f\u6210\u63a5\u53e3\u6587\u6863\u548c\u5ba2\u6237\u7aef\u670d\u52a1\u7aef\u4ee3\u7801\uff0c\u505a\u5230\u8c03\u7528\u7aef\u4ee3\u7801\u3001\u670d\u52a1\u7aef\u4ee3\u7801\u4ee5\u53ca\u63a5\u53e3\u6587\u6863\u7684\u4e00\u81f4\u6027\u3002"),(0,r.kt)("p",null,"\u6240\u4ee5\uff0cSwagger \u662f\u4e00\u4e2a\u89c4\u8303\u548c\u5b8c\u6574\u7684\u6846\u67b6\uff0c\u7528\u4e8e\u751f\u6210\u3001\u63cf\u8ff0\u3001\u8c03\u7528\u548c\u53ef\u89c6\u5316",(0,r.kt)("inlineCode",{parentName:"p"},"RESTful")," \u98ce\u683c\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Web")," \u670d\u52a1\u3002"),(0,r.kt)("p",null,"\u603b\u4f53\u76ee\u6807\u662f\u4f7f\u5ba2\u6237\u7aef\u548c\u6587\u4ef6\u7cfb\u7edf\u4f5c\u4e3a\u670d\u52a1\u5668\u4ee5\u540c\u6837\u7684\u901f\u5ea6\u6765\u66f4\u65b0\u3002\u6587\u4ef6\u7684\u65b9\u6cd5\u3001\u53c2\u6570\u548c\u6a21\u578b\u7d27\u5bc6\u96c6\u6210\u5230\u670d\u52a1\u5668\u7aef\u7684\u4ee3\u7801\uff0c\u5141\u8bb8 API \u6765\u59cb\u7ec8\u4fdd\u6301\u540c\u6b65\u3002",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u8ba9\u90e8\u7f72\u7ba1\u7406\u548c\u4f7f\u7528\u529f\u80fd\u5f3a\u5927\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"API")," \u4ece\u672a\u5982\u6b64\u7b80\u5355\u3002"),(0,r.kt)("h2",{id:"65-swagger-\u4f7f\u7528"},"6.5 Swagger \u4f7f\u7528"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u975e\u5e38\u65b9\u4fbf\u4e14\u7075\u6d3b\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u914d\u7f6e\uff0c\u65e0\u9700\u589e\u52a0\u989d\u5916\u5b66\u4e60\u6210\u672c\u3002"),(0,r.kt)("h3",{id:"651-\u6ce8\u518c\u670d\u52a1"},"6.5.1 \u6ce8\u518c\u670d\u52a1"),(0,r.kt)("admonition",{title:"\u5907\u6ce8",type:"important"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},".UseInject()")," \u5df2\u7ecf\u5305\u542b\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},".UseSpecificationDocuments()")," \u6ce8\u518c\uff0c\u65e0\u9700\u518d\u6b21\u6ce8\u518c\u3002")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {11,21} title="Furion.Web.Core\\FurWebCoreStartup.cs"',showLineNumbers:!0,"":!0,"{11,21}":!0,title:'"Furion.Web.Core\\FurWebCoreStartup.cs"'},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Furion.Web.Core\n{\n [AppStartup(800)]\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddSpecificationDocuments();\n services.AddControllers();\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n // Other Codes\n\n app.UseSpecificationDocuments();\n\n app.UseEndpoints(endpoints =>\n {\n endpoints.MapControllers();\n });\n }\n }\n}\n")),(0,r.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"services.AddSpecificationDocuments()")," \u901a\u5e38\u548c ",(0,r.kt)("inlineCode",{parentName:"p"},".AddDynamicApiControllers()")," \u6210\u5bf9\u51fa\u73b0\u3002")),(0,r.kt)("h3",{id:"652-\u9ed8\u8ba4\u5730\u5740"},"6.5.2 \u9ed8\u8ba4\u5730\u5740"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"p"},"\u89c4\u8303\u5316\u6587\u6863")," \u5730\u5740\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"/api")," \u76ee\u5f55\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"),"\u3002"),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger1.png")}),(0,r.kt)("p",null,"\u53ef\u4ee5\u901a\u8fc7\u4e24\u79cd\u65b9\u5f0f\u914d\u7f6e\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},'app.UseInject("\u8def\u7531")')," \u65b9\u5f0f\uff0c\u5982")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'app.UseInject("testapi"); // \u90a3\u4e48 /testapi \u5c31\u662f\u89c4\u8303\u5316\u5730\u5740\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e"),"\uff1a")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},'{\n "SpecificationDocumentSettings": {\n "RoutePrefix": "testapi"\n }\n}\n')),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u914d\u7f6e\u6587\u4ef6\u4f18\u5148\u7ea7\u5927\u4e8e ",(0,r.kt)("inlineCode",{parentName:"strong"},"UseInject()")," \u65b9\u5f0f")),(0,r.kt)("h3",{id:"653-\u9ed8\u8ba4\u5206\u7ec4"},"6.5.3 \u9ed8\u8ba4\u5206\u7ec4"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u9ed8\u8ba4\u5206\u7ec4\u540d\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"Default"),"\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"),"\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},'{\n "SpecificationDocumentSettings": {\n "DefaultGroupName": "MyGroup"\n }\n}\n')),(0,r.kt)("h3",{id:"654-\u6587\u6863\u6ce8\u91ca"},"6.5.4 \u6587\u6863\u6ce8\u91ca"),(0,r.kt)("p",null,"\u89c4\u8303\u5316\u6587\u6863\u9ed8\u8ba4\u626b\u63cf ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Application"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Web.Core"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Web.Entry")," \u4e09\u4e2a\u7a0b\u5e8f\u96c6",(0,r.kt)("inlineCode",{parentName:"p"},".xml")," \u6ce8\u91ca\u6587\u4ef6\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"),"\u3002"),(0,r.kt)("p",null,"\u53ea\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"p"},"///")," \u6807\u8bc6\u7684\u6ce8\u91ca\u8bed\u6cd5\uff0c\u5982\uff1a",(0,r.kt)("strong",{parentName:"p"},"\u7c7b\u3001\u65b9\u6cd5\u3001\u5c5e\u6027\u3001\u53c2\u6570\u3001\u8fd4\u56de\u503c\u3001\u9a8c\u8bc1\u7279\u6027"),"\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5-7,10-13,19-23}",showLineNumbers:!0,"":!0,"{5-7,10-13,19-23}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n /// \n /// \u7c7b\u6ce8\u91ca\n /// \n public class FurionAppService : IDynamicApiController\n {\n /// \n /// \u65b9\u6cd5\u6ce8\u91ca\n /// \n /// \n public string Get()\n {\n return nameof(Furion);\n }\n\n /// \n /// \u5e26 ID \u53c2\u6570\u7684\u65b9\u6cd5\u6ce8\u91ca\n /// \n /// \n /// \n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger2.png")}),(0,r.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u5982\u679c\u6587\u6863\u6ce8\u91ca\u6ca1\u6709\u663e\u793a\uff0c\u8bf7\u68c0\u67e5\u9879\u76ee ",(0,r.kt)("inlineCode",{parentName:"p"},"\u5c5e\u6027->\u751f\u6210->\u8f93\u51fa")," \u4e2d XML \u6587\u6863\u662f\u5426\u914d\u7f6e\u8f93\u51fa\u8def\u5f84\u3002",(0,r.kt)("strong",{parentName:"p"},"\u6ce8\u610f\uff1a\u53ea\u6709\u4e0d\u5e26\u8def\u5f84\u7684 \u3010\u9879\u76ee\u540d\u79f0.xml\u3011 \u624d\u4f1a\u81ea\u52a8\u52a0\u8f7d\u3002"))),(0,r.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"info"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Debug")," \u6a21\u5f0f\u4e0b\u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"Release")," \u6a21\u5f0f\u4e0b\u7684\u6ce8\u91ca\u6587\u4ef6\u662f\u4e0d\u901a\u7528\u7684\uff0c\u6240\u4ee5\u5bfc\u81f4\u5f88\u591a\u5f00\u53d1\u8005\u53d1\u5e03\u5230\u670d\u52a1\u5668\u4e0a\u53d1\u73b0\u6ca1\u6709\u663e\u793a\u6ce8\u91ca\u3002\u6211\u4eec\u53ea\u9700\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u4e2d\u5207\u6362 ",(0,r.kt)("inlineCode",{parentName:"p"},"Debug")," \u6a21\u5f0f\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"Release"),"\uff0c\u7136\u540e\u91cd\u65b0\u914d\u7f6e\u4e00\u6b21\u5373\u53ef\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u8fd9\u6837\u4e0d\u7ba1\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"Debug")," \u8fd8\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"Release")," \u6a21\u5f0f\u90fd\u4f1a\u663e\u793a\u6ce8\u91ca\u4e86\u3002")),(0,r.kt)("h3",{id:"655-\u591a\u5206\u7ec4\u652f\u6301"},"6.5.5 \u591a\u5206\u7ec4\u652f\u6301"),(0,r.kt)("p",null,"\u591a\u5206\u7ec4\u662f\u4e00\u4e2a\u7cfb\u7edf\u4e2d\u5fc5\u5907\u529f\u80fd\uff0c\u6211\u4eec\u53ef\u4ee5\u5c06\u7cfb\u7edf\u5212\u5206\u4e3a\u591a\u4e2a\u6a21\u5757\uff0c\u6bcf\u4e2a\u6a21\u5757\u90fd\u72ec\u7acb\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"api")," \u914d\u7f6e\u3002\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5b9e\u73b0\u591a\u5206\u7ec4\u975e\u5e38\u7b80\u5355\u3002\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,21,32}",showLineNumbers:!0,"":!0,"{5,21,32}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings("Group1")]\n public class FurionAppService : IDynamicApiController\n {\n /// \n /// \u968f\u7236\u7c7b Group1 \u5206\u7ec4\n /// \n /// \n public string Post()\n {\n return nameof(Furion);\n }\n\n /// \n /// \u5728 Group1\u3001Group3 \u90fd\u6709\u6211\n /// \n /// \n [ApiDescriptionSettings("Group1", "Group3")]\n public string Get()\n {\n return nameof(Furion);\n }\n\n /// \n /// \u6211\u53ea\u5728 Group2 \u51fa\u73b0\n /// \n /// \n /// \n [ApiDescriptionSettings("Group2")]\n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger3.gif")}),(0,r.kt)("h3",{id:"656-\u591a\u5206\u7ec4\u6392\u5e8f"},"6.5.6 \u591a\u5206\u7ec4\u6392\u5e8f"),(0,r.kt)(o.Z,{defaultValue:"fz1",values:[{label:"\u65b9\u5f0f\u4e00",value:"fz1"},{label:"\u65b9\u5f0f\u4e8c",value:"fz2"}],mdxType:"Tabs"},(0,r.kt)(p.Z,{value:"fz1",mdxType:"TabItem"},(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u901a\u8fc7\u5206\u7ec4\u540d\u79f0\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"strong"},"@\u6574\u6570")," \u8fdb\u884c\u6392\u5e8f")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,19}",showLineNumbers:!0,"":!0,"{5,19}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings("Group1@1")]\n public class FurionAppService : IDynamicApiController\n {\n public string Post()\n {\n return nameof(Furion);\n }\n\n [ApiDescriptionSettings("Group1", "Group3")]\n public string Get()\n {\n return nameof(Furion);\n }\n\n [ApiDescriptionSettings("Group@2")]\n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,r.kt)("p",null,"\u53ef\u4ee5\u901a\u8fc7\u5728\u5206\u7ec4\u540d\u540e\u9762\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"@\u6574\u6570")," \u8fdb\u884c\u6392\u5e8f\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"\u6574\u6570")," \u8d8a\u5927\u6392\u524d\u9762\u3002\u5982\u679c\u5206\u7ec4\u540d\u79f0\u591a\u6b21\u6307\u5b9a\u4e14\u591a\u6b21\u6307\u5b9a\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"@\u6574\u6570")," \uff0c\u5219\u81ea\u52a8",(0,r.kt)("strong",{parentName:"p"},"\u53d6\u8be5\u5206\u7ec4\u6700\u5927\u7684\u6574\u6570"),"\u8fdb\u884c\u6392\u5e8f\u3002")),(0,r.kt)(p.Z,{value:"fz2",mdxType:"TabItem"},(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u901a\u8fc7\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e\u6392\u5e8f")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers {2-17} title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,"{2-17}":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "SpecificationDocumentSettings": {\n "GroupOpenApiInfos": [\n {\n "Group": "Group1",\n "Order": 1\n },\n {\n "Group": "Group2",\n "Order": 2\n },\n {\n "Group": "Group3",\n "Order": 0\n }\n ]\n }\n}\n')))),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger4.png")}),(0,r.kt)("admonition",{title:"\u6392\u5e8f\u8bf4\u660e",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"\u5206\u7ec4\u9ed8\u8ba4\u6392\u5e8f ",(0,r.kt)("inlineCode",{parentName:"p"},"Order")," \u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"0"),"\u3002\u5982\u679c\u540c\u65f6\u914d\u7f6e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"@\u6574\u6570")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u914d\u7f6e\u6587\u4ef6\uff0c\u90a3\u4e48\u4f18\u5148\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u4e2d\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Order"))),(0,r.kt)("h3",{id:"657-\u591a\u5206\u7ec4\u4fe1\u606f\u914d\u7f6e"},"6.5.7 \u591a\u5206\u7ec4\u4fe1\u606f\u914d\u7f6e"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u53ef\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"appsetting.json")," \u914d\u7f6e\u5206\u7ec4\u4fe1\u606f\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers {3-20} title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,"{3-20}":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "SpecificationDocumentSettings": {\n "GroupOpenApiInfos": [\n {\n "Group": "Group1",\n "Title": "\u5206\u7ec4\u6807\u9898",\n "Description": "\u8fd9\u91cc\u662f\u5206\u7ec4\u63cf\u8ff0",\n "Version": "\u7248\u672c\u53f7",\n "TermsOfService": "https://furion.icu",\n "Contact": {\n "Name": "\u767e\u5c0f\u50e7",\n "Url": "https://gitee.com/monksoul",\n "Email": "monksoul@outlook.com"\n },\n "License": {\n "Name": "MIT",\n "Url": "https://gitee.com/dotnetchina/Furion/blob/alpha/LICENSE"\n }\n }\n ]\n }\n}\n')),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger5.png")}),(0,r.kt)("h3",{id:"658-\u7ec4\u4e2d\u7ec4\u6807\u7b7e"},"6.5.8 \u7ec4\u4e2d\u7ec4\uff08\u6807\u7b7e\uff09"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Tag")," \u914d\u7f6e\u4e3b\u8981\u7528\u4e8e\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u6807\u7b7e\u5206\u7ec4\u4fe1\u606f\u53ca\u5408\u5e76\u6807\u7b7e\u3002\u4e5f\u5c31\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"\u7ec4\u4e2d\u7ec4"),":"),(0,r.kt)(o.Z,{defaultValue:"tag1",values:[{label:"\u6807\u7b7e\u547d\u540d",value:"tag1"},{label:"\u5408\u5e76\u6807\u7b7e",value:"tag2"}],mdxType:"Tabs"},(0,r.kt)(p.Z,{value:"tag1",mdxType:"TabItem"},(0,r.kt)("h4",{id:"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d"},"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n\n public class TestAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n}\n")),(0,r.kt)("h4",{id:"\u8d34\u6807\u7b7e\u4e4b\u540e"},"\u8d34\u6807\u7b7e\u4e4b\u540e"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,19}",showLineNumbers:!0,"":!0,"{5,19}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(Tag = "\u5206\u7ec4\u4e00")]\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n\n [ApiDescriptionSettings(Tag = "\u5206\u7ec4\u4e8c")]\n public class TestAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/tag1.png")})),(0,r.kt)(p.Z,{value:"tag2",mdxType:"TabItem"},(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,19}",showLineNumbers:!0,"":!0,"{5,19}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(Tag = "\u5408\u5e76\u6240\u6709\u6807\u7b7e")]\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n\n [ApiDescriptionSettings(Tag = "\u5408\u5e76\u6240\u6709\u6807\u7b7e")]\n public class TestAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/tag2.png")}))),(0,r.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"\u5982\u679c ",(0,r.kt)("inlineCode",{parentName:"p"},"Tag")," \u540d\u5b57\u4e00\u6837\uff0c\u5219\u4f1a\u81ea\u52a8\u5408\u5e76\uff0c\u5426\u5219\u53ea\u662f\u547d\u540d\u3002")),(0,r.kt)("h3",{id:"659-\u9ed8\u8ba4\u5c55\u5f00\u6240\u6709\u6587\u6863"},"6.5.9 \u9ed8\u8ba4\u5c55\u5f00\u6240\u6709\u6587\u6863"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers {2-4} title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,"{2-4}":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "SpecificationDocumentSettings": {\n "DocExpansionState": "Full"\n }\n}\n')),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger6.gif")}),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"DocExpansionState")," \u914d\u7f6e\u8bf4\u660e\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"List"),"\uff1a\u5217\u8868\u5f0f\uff08\u5c55\u5f00\u5b50\u7c7b\uff09\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u9ed8\u8ba4\u503c")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Full"),"\uff1a\u5b8c\u5168\u5c55\u5f00"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"None"),"\uff1a\u5217\u8868\u5f0f\uff08\u4e0d\u5c55\u5f00\u5b50\u7c7b\uff09")),(0,r.kt)("h3",{id:"6510-\u914d\u7f6e\u6587\u6863\u6807\u9898"},"6.5.10 \u914d\u7f6e\u6587\u6863\u6807\u9898"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers {2-4} title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,"{2-4}":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "SpecificationDocumentSettings": {\n "DocumentTitle": "\u6211\u662f\u81ea\u5b9a\u4e49\u6807\u9898"\n }\n}\n')),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger7.png")}),(0,r.kt)("h3",{id:"6511-\u6388\u6743\u63a7\u5236"},"6.5.11 \u6388\u6743\u63a7\u5236"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7248\u672c ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5df2\u7ecf\u9ed8\u8ba4\u542f\u7528\u4e86 Bearer Token \u6388\u6743\u914d\u7f6e\uff0c\u65e0\u9700\u624b\u52a8\u914d\u7f6e"),"\uff0c\u5982\u9700\u624b\u52a8\u914d\u7f6e\uff0c\u53ef\u624b\u52a8\u6dfb\u52a0\u4ee5\u4e0b\u7c7b\u4f3c\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "SpecificationDocumentSettings": {\n "EnableAuthorized": true,\n\n "SecurityDefinitions": [\n {\n "Id": "Bearer",\n "Type": "Http",\n "Name": "Authorization",\n "Description": "JWT Authorization header using the Bearer scheme.",\n "BearerFormat": "JWT",\n "Scheme": "bearer",\n "In": "Header",\n\n "Requirement": {\n "Scheme": {\n "Reference": {\n "Id": "Bearer",\n "Type": "SecurityScheme"\n },\n "Accesses": []\n }\n }\n }\n ]\n }\n}\n')),(0,r.kt)("h3",{id:"6512-\u5728\u7ebf\u6d4b\u8bd5"},"6.5.12 \u5728\u7ebf\u6d4b\u8bd5"),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger8.gif")}),(0,r.kt)("h3",{id:"6513-\u6027\u80fd\u76d1\u89c6-miniprofiler"},"6.5.13 \u6027\u80fd\u76d1\u89c6 ",(0,r.kt)("inlineCode",{parentName:"h3"},"MiniProfiler")),(0,r.kt)("p",null,"\u89c4\u8303\u5316\u6587\u6863\u9ed8\u8ba4\u96c6\u6210\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"MiniProfiler")," \u7b2c\u4e09\u65b9\u6027\u80fd\u7ec4\u4ef6\uff0c\u901a\u8fc7\u8be5\u7ec4\u4ef6\u53ef\u4ee5\u65b9\u4fbf\u67e5\u770b\u8bf7\u6c42\u6027\u80fd\u3001\u5f02\u5e38\u5806\u6808\u3001\u6570\u636e\u5e93\u64cd\u4f5c\u7b49\u4fe1\u606f\u3002\u9ed8\u8ba4\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u9996\u9875\u5de6\u4e0a\u89d2\u663e\u793a\u3002"),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/mipr.png")}),(0,r.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u4e5f\u53ef\u4ee5\u901a\u8fc7 ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"appsetting.json"))," \u4e2d ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"AppSettings:InjectMiniProfiler"))," \u8bbe\u4e3a ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"false"))," \u5173\u95ed\u3002")),(0,r.kt)("h3",{id:"6514-\u5b9a\u4e49\u63a5\u53e3\u8f93\u51fa\u7c7b\u578b"},"6.5.14 \u5b9a\u4e49\u63a5\u53e3\u8f93\u51fa\u7c7b\u578b"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,8-9}",showLineNumbers:!0,"":!0,"{2,8-9}":!0},"using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n [ProducesResponseType(201, Type = typeof(TestDto))]\n [ProducesResponseType(400)]\n public string Get()\n {\n return nameof(Furion);\n }\n }\n}\n")),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/fhzlx.png")}),(0,r.kt)("h3",{id:"6515-\u9690\u85cf\u7279\u5b9a\u5206\u7ec4"},"6.5.15 \u9690\u85cf\u7279\u5b9a\u5206\u7ec4"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u65b0\u7248\u672c\u63d0\u4f9b\u4e86\u9690\u85cf\u5206\u7ec4\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Visible")," \u914d\u7f6e\uff0c\u8bbe\u7f6e\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"false")," \u4e4b\u540e\u8be5\u5206\u7ec4\u5c06\u4e0d\u663e\u793a\u5728\u89c4\u8303\u5316\u6587\u6863\u4e2d\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers title="appsetting.json"',showLineNumbers:!0,"":!0,title:'"appsetting.json"'},'{\n "SpecificationDocumentSettings": {\n "GroupOpenApiInfos": [\n {\n "Group": "Group1",\n "Visible": false\n }\n ]\n }\n}\n')),(0,r.kt)("h3",{id:"6516-\u4e2d\u6587\u4e71\u7801\u95ee\u9898"},"6.5.16 \u4e2d\u6587\u4e71\u7801\u95ee\u9898"),(0,r.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b,",(0,r.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u5e76\u672a\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"utf-8")," \u7f16\u7801\uff0c\u6240\u4ee5\u5982\u679c\u914d\u7f6e\u4e2d\u6587\u5206\u7ec4\u4fe1\u606f\u5c31\u4f1a\u51fa\u73b0\u4e71\u7801\u60c5\u51b5\uff0c\u8fd9\u65f6\u5019\uff0c\u53ea\u9700\u8981\u4fee\u6539 ",(0,r.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u7f16\u7801\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"utf-8")," \u5373\u53ef\u3002"),(0,r.kt)("h3",{id:"6517-\u751f\u4ea7\u73af\u5883\u4e2d\u5173\u95ed-swagger"},"6.5.17 \u751f\u4ea7\u73af\u5883\u4e2d\u5173\u95ed ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")),(0,r.kt)("p",null,"\u5982\u679c\u4e0d\u9700\u8981\u7ebf\u4e0a\u73af\u5883\u5f00\u542f ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u529f\u80fd\uff0c\u53ea\u9700\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"appsetting.json")," \u914d\u7f6e\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},'{\n "AppSettings": {\n "InjectSpecificationDocument": false\n }\n}\n')),(0,r.kt)("h3",{id:"6518-\u8bbe\u7f6e-example-value-\u9ed8\u8ba4\u503c"},"6.5.18 \u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"h3"},"Example Value")," \u9ed8\u8ba4\u503c"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u4f1a\u81ea\u52a8\u6839\u636e\u5bf9\u8c61\u7c7b\u578b\u8f93\u5165\u53c2\u6570\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"Example Value")," \u9ed8\u8ba4\u503c\uff0c\u4f46\u662f\u8be5\u9ed8\u8ba4\u503c\u901a\u5e38\u662f\u5bf9\u8c61\u5c5e\u6027\u7684\u7c7b\u578b\u5b57\u7b26\u4e32\u6216\u7f3a\u7701\u503c\uff0c\u5982\u679c\u6211\u4eec\u9700\u8981\u81ea\u5b9a\u4e49\u8fd9\u4e9b\u9ed8\u8ba4\u503c\uff0c\u53ea\u9700\u8981\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"/// \u9ed8\u8ba4\u503c")," \u6ce8\u91ca\u5373\u53ef\u3002"),(0,r.kt)("p",null,"\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"/// \n/// \u5e74\u9f84\n/// \n/// 13\n[Required, Range(10, 110)]\npublic int Age { get; set; }\n")),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/sd20.png")}),(0,r.kt)("p",null,"\u66f4\u591a\u7c7b\u578b\u9ed8\u8ba4\u503c\u8bbe\u7f6e\u793a\u4f8b\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"/// true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"/// foobar")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"number")," \u7c7b\u578b\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"/// 123")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"null")," \u7c7b\u578b\uff1a ",(0,r.kt)("inlineCode",{parentName:"li"},"/// null")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"array")," \u7c7b\u578b\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"/// [ 1, 2, 3 ]"))),(0,r.kt)("admonition",{type:"important"},(0,r.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"object")," \u7c7b\u578b\u8f93\u5165\u53c2\u6570"),(0,r.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Example Value")," \u4e0d\u4f1a\u663e\u793a ",(0,r.kt)("inlineCode",{parentName:"p"},"object")," \u7c7b\u578b\u7684\u5bf9\u8c61\u5c5e\u6027\uff0c\u56e0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u8ba4\u4e3a\u8fd9\u662f\u4e0d\u5408\u7406\u7684\u5b9a\u4e49\u3002\u5982\u679c\u9700\u8981\u5f3a\u5236\u663e\u793a\uff0c\u53ea\u9700\u8981\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},'/// "object"')," \u6ce8\u91ca\u5373\u53ef\u3002")),(0,r.kt)("h3",{id:"6519-\u81ea\u5b9a\u4e49-swagger-\u914d\u7f6e"},"6.5.19 \u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u914d\u7f6e"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u9664\u4e86\u5185\u7f6e\u4e86\u4e0d\u5c11\u914d\u7f6e\u4ee5\u5916\uff0c\u8fd8\u63d0\u4f9b\u4e86\u76f4\u63a5\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," Api \u7684\u53c2\u6570\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public void ConfigureServices(IServiceCollection services)\n{\n services.AddInject(options =>\n {\n options.SpecificationDocument = spt =>\n {\n spt.SwaggerGen = gen =>\n {\n // \u914d\u7f6e Swagger Gen\n };\n };\n });\n}\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0}," public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n app.UseInject(configure: options =>\n {\n options.SpecificationDocument = spt =>\n {\n spt.Swagger = swg =>\n {\n // \u914d\u7f6e Swagger Options\n };\n spt.SwaggerUI = ui =>\n {\n // \u914d\u7f6e Swagger UI\n };\n };\n });\n}\n\n")),(0,r.kt)("h3",{id:"6520-\u914d\u7f6e-swagger\u7684-schemes"},"6.5.20 \u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger"),"\u7684 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Schemes")),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u9ed8\u8ba4\u53ea\u663e\u793a\u540d\u79f0\uff0c\u5982\u679c\u9700\u8981\u81ea\u5b9a\u4e49\u663e\u793a\u89c4\u5219\uff0c\u53ea\u9700\u8981\u6dfb\u52a0\u914d\u7f6e\u5373\u53ef\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddControllersWithViews()\n .AddInject(options =>\n {\n options.SpecificationDocument = spt =>\n {\n spt.SwaggerGen = gen =>\n {\n gen.CustomSchemaIds(x => x.FullName);\n };\n };\n });\n")),(0,r.kt)("h3",{id:"6521-\u81ea\u5b9a\u4e49-swaggerjson-\u8def\u7531\u6a21\u677f"},"6.5.21 \u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"h3"},"swagger.json")," \u8def\u7531\u6a21\u677f"),(0,r.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4f1a\u751f\u6210\u7edf\u4e00\u7684\u5206\u7ec4\u6a21\u677f\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"swagger/{documentName}/swagger.json"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"{documentName}")," \u4f1a\u5728\u8fd0\u884c\u65f6\u66ff\u6362\u4e3a\u5206\u7ec4\u540d\uff0c\u5982\u9700\u81ea\u5b9a\u4e49\uff0c\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"RouteTemplate")," \u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers title="appsetting.json"',showLineNumbers:!0,"":!0,title:'"appsetting.json"'},'{\n "SpecificationDocumentSettings": {\n "RouteTemplate": "myapp/{documentName}/xxxx.json"\n }\n}\n')),(0,r.kt)("h3",{id:"6522-\u5173\u4e8e-applicationx-www-form-urlencoded-\u8bf7\u6c42"},"6.5.22 \u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"h3"},"application/x-www-form-urlencoded")," \u8bf7\u6c42"),(0,r.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u5e76\u672a\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"application/x-www-form-urlencoded")," \u652f\u6301\uff0c\u5982\u9700\u542f\u7528\u8be5\u914d\u7f6e\uff0c\u53ea\u9700\u5728\u65b9\u6cd5\u9876\u90e8\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[Consumes]")," \u7279\u6027\u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,2}",showLineNumbers:!0,"":!0,"{1,2}":!0},'[Consumes("application/x-www-form-urlencoded")]\npublic async Task Test([FromForm] TestRequest testRequest)\n{\n // ....\n}\n\npublic class TestRequest\n{\n public string TestValue { get; set; }\n}\n')),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u53c2\u6570\u5fc5\u987b\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[FromForm]")," \u7279\u6027\u3002\u53e6\u5916\u8bf7\u6c42\u65f6\u5c06\u53c2\u6570\u6309 ",(0,r.kt)("inlineCode",{parentName:"p"},"URL")," \u5730\u5740\u62fc\u63a5\u5e76\u653e\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Body")," \u4e2d\u8bf7\u6c42\u3002")),(0,r.kt)("h3",{id:"6523-swagger-\u51fa\u73b0-cors-\u95ee\u9898\u89e3\u51b3"},"6.5.23 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"h3"},"CORS")," \u95ee\u9898\u89e3\u51b3"),(0,r.kt)("p",null,"\u5982\u679c ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u51fa\u73b0\u4ee5\u4e0b\u9519\u8bef\uff0c\u5982\u56fe\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swerror.png")}),(0,r.kt)("p",null,"\u5219\u9700\u8981\u6dfb\u52a0\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2,3}",showLineNumbers:!0,"":!0,"{2,3}":!0},'{\n "SpecificationDocumentSettings": {\n "HideServers": true\n }\n}\n')),(0,r.kt)("h3",{id:"6524-swagger-\u51fa\u73b0\u9ed8\u8ba4-xml-\u53c2\u6570\u95ee\u9898\u89e3\u51b3"},"6.5.24 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u51fa\u73b0\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"h3"},"xml")," \u53c2\u6570\u95ee\u9898\u89e3\u51b3"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u4ea7\u751f\u6b64\u539f\u56e0\u6709\u4e24\u4e2a\u5fc5\u8981\u6761\u4ef6\uff1a")),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"\u4f7f\u7528\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"Microsoft.AspNetCore.Mvc.NewtonsoftJson")," \u5305\u5e76\u6dfb\u52a0\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"AddNewtonsoftJson()")," \u6ce8\u518c\u3002"),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("inlineCode",{parentName:"li"},".AddNewtonsoftJson()")," \u5199\u5728\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},".AddInjectWithUnifyResult()")," \u540e\u9762\u3002")),(0,r.kt)("p",null,"\u6240\u4ee5\u89e3\u51b3\u65b9\u6cd5\u662f\uff0c\u5148\u6ce8\u518c ",(0,r.kt)("inlineCode",{parentName:"p"},".AddNewtonsoftJson()")," \u518d\u6ce8\u518c\u89c4\u8303\u5316\u7ed3\u679c\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},"services.AddControllers()\n .AddNewtonsoftJson()\n .AddInjectWithUnifyResult();\n")),(0,r.kt)("h3",{id:"6525-swagger-\u591a\u8bed\u8a00\u652f\u6301"},"6.5.25 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u591a\u8bed\u8a00\u652f\u6301"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion 2.9.0 + ")," \u7248\u672c\u5df2\u7ecf\u652f\u6301\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u6587\u6863\u5730\u5740 ",(0,r.kt)("inlineCode",{parentName:"p"},"?culture=en-US")," \u53c2\u6570\u591a\u8bed\u8a00\u8f6c\u53d1\u529f\u80fd\u4e86\uff0c\u4e5f\u5c31\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u5730\u5740\u5e26 ",(0,r.kt)("inlineCode",{parentName:"p"},"?culture=")," \u53c2\u6570\u5c06\u81ea\u52a8\u6dfb\u52a0\u5230\u6bcf\u4e00\u4e2a\u8bf7\u6c42\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"api")," \u5730\u5740\u4e2d\u3002"),(0,r.kt)("h3",{id:"6526-\u81ea\u5b9a\u4e49\u903b\u8f91\u63a7\u5236-swagger-\u6bcf\u4e00\u4e2a-api-\u53ef\u89c1\u6027"},"6.5.26 \u81ea\u5b9a\u4e49\u903b\u8f91\u63a7\u5236 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u6bcf\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"h3"},"api")," \u53ef\u89c1\u6027"),(0,r.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u63a5\u53e3\u53ef\u89c1\u6027\uff0c\u6bd4\u5982\u6839\u636e\u6743\u9650\uff0c\u4e0d\u540c\u7528\u6237\u7c7b\u578b\uff0c\u5404\u79cd\u903b\u8f91\u63a7\u5236\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u4e5f\u53ef\u4ee5\u7528 .AddInjectWithUnifyResult\nservices.AddInject(options =>\n{\n options.SpecificationDocument = spt =>\n {\n spt.SwaggerGen = gen =>\n {\n gen.DocInclusionPredicate((currentGroup, apiDescription) =>\n {\n // Furion \u5185\u90e8\u68c0\u67e5\uff0c\u5fc5\u987b\u653e\u7b2c\u4e00\u884c\n var isShow = SpecificationDocumentBuilder.CheckApiDescriptionInCurrentGroup(currentGroup, apiDescription);\n\n // \u83b7\u53d6\u5f53\u524d\u65b9\u6cd5\n _ = apiDescription.TryGetMethodInfo(out var method);\n\n // \u6709\u4e86\u65b9\u6cd5\uff0c\u8fd9\u91cc\u505a\u4f60\u60f3\u505a\u7684\u4e8b\u60c5\uff0cisShow \u8bbe\u7f6e true \u53ef\u89c1\uff0c\u8bbe\u7f6e false \u4e0d\u53ef\u89c1\n\n return isShow;\n });\n };\n };\n});\n")),(0,r.kt)("h3",{id:"6527-\u914d\u7f6e-mvc-\u63a7\u5236\u5668\u652f\u6301\u89c4\u8303\u5316\u5904\u7406"},"6.5.27 \u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"h3"},"MVC")," \u63a7\u5236\u5668\u652f\u6301\u89c4\u8303\u5316\u5904\u7406"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "UnifyResultSettings": {\n "SupportMvcController": true\n }\n}\n')),(0,r.kt)("h3",{id:"6528-swagger-\u5237\u65b0\u8bb0\u4f4f\u6388\u6743\u72b6\u6001"},"6.5.28 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u5237\u65b0\u8bb0\u4f4f\u6388\u6743\u72b6\u6001"),(0,r.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u5237\u65b0\u6d4f\u89c8\u5668\u540e\uff0c\u6388\u6743\u72b6\u6001\u5c06\u88ab\u91cd\u7f6e\uff0c\u4e5f\u5c31\u662f\u9700\u8981\u91cd\u65b0\u767b\u5f55\uff0c\u901a\u8fc7\u4e0b\u9762\u4ee3\u7801\u5728 ",(0,r.kt)("strong",{parentName:"p"},"\u7528\u6237\u767b\u5f55\u6210\u529f\u540e")," \u8c03\u7528\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ....\u9a8c\u8bc1\u7528\u6237\u540d/\u5bc6\u7801....\n\n_httpContextAccessor.HttpContext.SigninToSwagger("\u4f20\u5165 token");\n')),(0,r.kt)("h3",{id:"6529-\u5e26\u767b\u5f55\u7684-swagger-\u6587\u6863"},"6.5.29 \u5e26\u767b\u5f55\u7684 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u6587\u6863"),(0,r.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion v3.3.3+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u662f\u4efb\u4f55\u4eba\u90fd\u53ef\u4ee5\u8bbf\u95ee\u7684\uff0c\u8fd9\u6837\u4e5f\u66b4\u9732\u51fa\u4e00\u4e9b\u5b89\u5168\u95ee\u9898\uff0c\u6240\u4ee5\u5728\u8be5\u7248\u672c\u4e4b\u540e\u6dfb\u52a0\u4e86\u767b\u5f55\u529f\u80fd\uff0c\u53ea\u9700\u8981\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"SpecificationDocumentSettings")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"LoginInfo")," \u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-6}",showLineNumbers:!0,"{2-6}":!0},'{\n "SpecificationDocumentSettings": {\n "LoginInfo": {\n "Enabled": true,\n "CheckUrl": "/Home/CheckUrl",\n "SubmitUrl": "/Home/SubmitUrl",\n "UserName": "admin",\n "Password": "admin"\n }\n }\n}\n')),(0,r.kt)("h4",{id:"\u914d\u7f6e\u8bf4\u660e"},"\u914d\u7f6e\u8bf4\u660e"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"LoginInfo"),"\uff1a\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u662f\u5426\u9700\u8981\u767b\u5f55\u624d\u80fd\u8bbf\u95ee\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationLoginInfo")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"null"),"\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u4ec5\u5728 Furion v3.3.3+` \u6709\u6548"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Enabled"),"\uff1a\u662f\u5426\u542f\u7528\u767b\u5f55\u6388\u6743\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"CheckUrl"),"\uff1a\u68c0\u67e5\u767b\u5f55\u72b6\u6001\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Url")," \u5730\u5740\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u8be5\u5730\u5740\u5fc5\u987b\u662f ",(0,r.kt)("inlineCode",{parentName:"strong"},"POST")," \u8bf7\u6c42"),"\uff0c\u5df2\u6388\u6743\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"200"),"\uff0c\u5426\u5219\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"401"),"\uff0c\u652f\u6301\u76f8\u5bf9\u5730\u5740\uff0c\u4ee5 ",(0,r.kt)("inlineCode",{parentName:"li"},"/")," \u5f00\u5934"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SubmitUrl"),"\uff1a\u63d0\u4ea4\u767b\u5f55\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Url")," \u5730\u5740\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u8be5\u5730\u5740\u5fc5\u987b\u662f ",(0,r.kt)("inlineCode",{parentName:"strong"},"POST")," \u8bf7\u6c42\u4e14\u53ea\u6709\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"strong"},"SpecificationAuth")," \u7c7b\u578b\u53c2\u6570"),"\uff0c\u6210\u529f\u767b\u5f55\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"200"),"\uff0c\u5426\u5219\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"401"),"\uff0c\u652f\u6301\u76f8\u5bf9\u5730\u5740\uff0c\u4ee5 ",(0,r.kt)("inlineCode",{parentName:"li"},"/")," \u5f00\u5934")))),(0,r.kt)("h4",{id:"\u914d\u7f6e\u793a\u4f8b"},"\u914d\u7f6e\u793a\u4f8b"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {10-14,16-31}",showLineNumbers:!0,"{10-14,16-31}":!0},'using Furion.SpecificationDocument;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Furion.Web.Entry.Controllers;\n\npublic class HomeController : Controller\n{\n [HttpPost, AllowAnonymous, NonUnify]\n public int CheckUrl()\n {\n return 401;\n }\n\n [HttpPost, AllowAnonymous, NonUnify]\n public int SubmitUrl([FromForm] SpecificationAuth auth)\n {\n // \u8bfb\u53d6\u914d\u7f6e\u4fe1\u606f\n var userName = App.Configuration["SpecificationDocumentSettings:LoginInfo:UserName"];\n var password = App.Configuration["SpecificationDocumentSettings:LoginInfo:Password"];\n\n if (auth.UserName == userName && auth.Password == password)\n {\n return 200;\n }\n else\n {\n return 401;\n }\n }\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/swgdl.png")}),(0,r.kt)("h2",{id:"6530-inheritdoc-\u5b9e\u73b0\u6ce8\u91ca\u7ee7\u627f"},"6.5.30 ",(0,r.kt)("inlineCode",{parentName:"h2"},"inheritdoc")," \u5b9e\u73b0\u6ce8\u91ca\u7ee7\u627f"),(0,r.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion v3.3.3+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u5728\u8fc7\u53bb\u6211\u4eec\u5728\u63a5\u53e3\u5b9a\u4e49\u7684\u65f6\u5019\u7f16\u5199\u4e86\u5b8c\u6574\u7684\u6210\u5458\u6ce8\u91ca\uff0c\u7136\u540e\u5728\u6d3e\u751f\u6210\u5458\u4e2d\u53c8\u8981\u91cd\u590d\u5199\u4e00\u6b21\uff0c\u5b9e\u9645\u4e0a\u505a\u4e86\u5f88\u5927\u65e0\u7528\u529f\uff0c\u73b0\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u652f\u6301\u4e86\u6ce8\u91ca\u7ee7\u627f\u4e86\uff0c\u540c\u65f6 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u4e2d\u4e5f\u80fd\u6b63\u786e\u663e\u793a\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8,14}",showLineNumbers:!0,"{5,8,14}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n /// \n public class TestInheritdoc : ITestInheritdoc, IDynamicApiController\n {\n /// \n public string GetName()\n {\n return "Furion";\n }\n\n /// \n public string GetVersion()\n {\n return "3.3.3";\n }\n }\n\n /// \n /// \u6d4b\u8bd5\u6ce8\u91ca\u7ee7\u627f\n /// \n public interface ITestInheritdoc\n {\n /// \n /// \u83b7\u53d6\u540d\u79f0\n /// \n /// \n string GetName();\n\n /// \n /// \u83b7\u53d6\u7248\u672c\n /// \n /// \n string GetVersion();\n }\n}\n\n')),(0,r.kt)("p",null,"\u663e\u793a\u6548\u679c\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/cdr22.png")}),(0,r.kt)("admonition",{title:"\u6ce8\u610f\u4e8b\u9879",type:"important"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"")," \u4e0d\u6307\u5b9a ",(0,r.kt)("inlineCode",{parentName:"p"},"cref")," ",(0,r.kt)("strong",{parentName:"p"},"\u4ec5\u9650\u6210\u5458\u53ef\u7528"),"\u4e14\u6240\u5728\u7684\u7c7b\u578b\u5fc5\u987b\u6307\u5b9a ",(0,r.kt)("inlineCode",{parentName:"p"},''),"\uff0c\u8fd9\u6837\u624d\u80fd\u81ea\u52a8\u8bc6\u522b\u3002")),(0,r.kt)("h3",{id:"6531-\u542f\u7528-all-groups-\u5206\u7ec4\u529f\u80fd"},"6.5.31 \u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"h3"},"All Groups")," \u5206\u7ec4\u529f\u80fd"),(0,r.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion v3.3.4+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u4e3a\u4e86\u66f4\u597d\u7684\u5bf9\u63a5\u53e3\u8fdb\u884c\u5f52\u7c7b\uff0c\u914d\u7f6e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u591a\u4e2a\u5206\u7ec4\u7684\u529f\u80fd\uff0c\u4f46\u8fd9\u6837\u4e5f\u5bf9\u751f\u6210\u5ba2\u6237\u7aef\u8bf7\u6c42\u4ee3\u7801\u9020\u6210\u4e86\u56f0\u6270\uff0c\u6240\u4ee5\u6dfb\u52a0\u4e86\u65b0\u7684\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-3}",showLineNumbers:!0,"{2-3}":!0},'{\n "SpecificationDocumentSettings": {\n "EnableAllGroups": true\n }\n}\n')),(0,r.kt)("h3",{id:"6532-\u63a5\u53e3\u8fc7\u65f6\u63a7\u5236"},"6.5.32 \u63a5\u53e3\u8fc7\u65f6\u63a7\u5236"),(0,r.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion v3.3.5+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u67d0\u4e2a\u63a5\u53e3\u5df2\u7ecf\u8fc7\u65f6\uff0c\u63d0\u793a\u5c3d\u65e9\u8c03\u7528\u6700\u65b0\u63a5\u53e3\uff0c\u53ea\u9700\u8981\u5728\u65b9\u6cd5\u4e0a\u9762\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[Obsolete]")," \u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,7}",showLineNumbers:!0,"{1,7}":!0},'[Obsolete("GetName() \u5df2\u7ecf\u8fc7\u65f6\uff0c\u8bf7\u8c03\u7528 GetFrameworkName() \u66ff\u4ee3")]\npublic string GetName()\n{\n return nameof(Furion);\n}\n\n[Obsolete]\npublic string Other()\n{\n // ...\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/swg2.png")}),(0,r.kt)("h3",{id:"6533-\u5355\u4e00\u63a5\u53e3\u66f4\u591a\u63cf\u8ff0"},"6.5.33 \u5355\u4e00\u63a5\u53e3\u66f4\u591a\u63cf\u8ff0"),(0,r.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion v3.3.5+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u5728\u8be5\u7248\u672c\u65b0\u589e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"[ApiDescriptionSettings]")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Description")," \u5c5e\u6027\uff0c\u652f\u6301\u5b9a\u4e49\u66f4\u591a\u63cf\u8ff0\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},'[ApiDescriptionSettings(Description = "\u6211\u662f\u4e00\u6bb5\u63cf\u8ff0\uff0c\u663e\u793a\u66f4\u591a\u5185\u5bb9 ")]\npublic string add()\n{\n //....\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/swg1.png")}),(0,r.kt)("h3",{id:"6534-swagger-\u5f02\u5e38\u4e0d\u80fd\u663e\u793a\u9519\u8bef\u5904\u7406"},"6.5.34 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u5f02\u5e38/\u4e0d\u80fd\u663e\u793a/\u9519\u8bef\u5904\u7406"),(0,r.kt)("p",null,"\u6709\u65f6\u5019\u53ef\u80fd\u56e0\u4e3a\u9519\u8bef\u7684\u914d\u7f6e\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u4e0d\u80fd\u663e\u793a\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u590d\u5236\u63d0\u793a\u7684\u9519\u8bef ",(0,r.kt)("inlineCode",{parentName:"p"},".json")," \u94fe\u63a5\u5730\u5740\u5230\u6d4f\u89c8\u5668\u4e2d\u8bbf\u95ee\u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"https://localhost:\u4f60\u7684\u7aef\u53e3/swagger/Default/swagger.json\n")),(0,r.kt)("p",null,"\u540e\u9762\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"/swagger/Default/swagger.json")," \u5c31\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u9519\u8bef\u63d0\u793a\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},".json")," \u94fe\u63a5\u5730\u5740\u3002"),(0,r.kt)("p",null,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u770b\u5230\u8be6\u7ec6\u7684\u9519\u8bef\u4e86\u3002"),(0,r.kt)("img",{src:(0,l.Z)("img/sperr.png")}),(0,r.kt)("img",{src:(0,l.Z)("img/sperr2.png")}),(0,r.kt)("h3",{id:"6535-\u81ea\u5b9a\u4e49-swagger-\u7684-schemaid"},"6.5.35 \u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"h3"},"SchemaId")),(0,r.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion v3.6.4+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u6709\u65f6\u5019\uff0c\u4e0d\u540c\u7a0b\u5e8f\u96c6\u4f1a\u5b9a\u4e49\u76f8\u540c\u7684\u7c7b\u578b\u540d\u79f0 ",(0,r.kt)("inlineCode",{parentName:"p"},"Name"),"\uff0c\u8fd9\u6837\u5c31\u4f1a\u5bfc\u81f4\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"SchemaId")," \u51fa\u73b0\u51b2\u7a81\uff0c\u8fd9\u65f6\u53ea\u9700\u8981\u5728\u7c7b\u578b\u4e0a\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[SchemaId]")," \u7279\u6027\u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"{3}":!0},'using Furion.SpecificationDocument;\n\n[SchemaId("Other_")]\npublic class PersonDto\n{\n // ...\n}\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SchemaIdAttribute")," \u914d\u7f6e\u9009\u9879\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SchemaId"),"\uff1a\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},"SchemaId"),"\uff0c\u5b57\u7b26\u4e32\u7c7b\u578b\uff0c\u53ea\u80fd\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"\u5b57\u6bcd,\u6570\u5b57\uff0c\u4e0b\u5212\u7ebf")," \u7ec4\u5408"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Replace"),"\uff1a\u662f\u5426\u5b8c\u5168\u66ff\u6362\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false"),"\uff0c\u9ed8\u8ba4\u662f\u4f5c\u4e3a\u524d\u7f00\u62fc\u63a5\uff0c\u5982\u4e0a\u9762\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"PersonDto")," \u4f1a\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"Other_PersonDto"),"\uff0c\u5982\u679c\u8bbe\u7f6e\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"true"),"\uff0c\u5219\u76f4\u63a5\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Test_"))))),(0,r.kt)("h3",{id:"6536-\u81ea\u5b9a\u4e49-swagger-\u7684-operationid"},"6.5.36 \u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"h3"},"OperationId")),(0,r.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion 4.1.7+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u901a\u8fc7\u6211\u4eec\u6839\u636e ",(0,r.kt)("inlineCode",{parentName:"p"},"swagger.json")," \u751f\u6210\u524d\u7aef\u4ee3\u7801\u65f6\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u4f1a\u81ea\u52a8\u6839\u636e\u8def\u7531\u5730\u5740\u751f\u6210\u8c03\u7528\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"api")," \u540d\u79f0\uff0c\u4f46\u8fd9\u6837\u7684\u540d\u79f0\u5f80\u5f80\u4e0d\u6613\u8bfb\uff0c\u8fd9\u65f6\u5019\u53ef\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"p"},"[OperationId]")," \u6765\u914d\u7f6e\u751f\u6210\u7684\u524d\u7aef\u540d\u79f0\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5}",showLineNumbers:!0,"{5}":!0},'using Furion.SpecificationDocument;\n\npublic class PersonDto\n{\n [OperationId("MyClientMethodName")]\n public string TestMethod()\n {\n // ...\n }\n}\n')),(0,r.kt)("h3",{id:"6537-swagger-\u63a5\u53e3\u6587\u6863\u652f\u6301\u5b8c\u6574\u7684-markdown"},"6.5.37 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u63a5\u53e3\u6587\u6863\u652f\u6301\u5b8c\u6574\u7684 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Markdown")),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6700\u65b0\u7248\u4e2d\uff0c\u652f\u6301\u4e86\u5b8c\u6574\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Markdown")," \u6ce8\u518c\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,80}",showLineNumbers:!0,"{4,80}":!0},'/// \n/// \u6d4b\u8bd5 Markdown\n/// \n/// \n/// # \u5148\u77e5 / Furion ([\u63a2\u7d22\u7248](https://gitee.com/dotnetchina/Furion/tree/experimental/))\n///\n/// \u4e00\u4e2a\u5e94\u7528\u7a0b\u5e8f\u6846\u67b6\uff0c\u60a8\u53ef\u4ee5\u5c06\u5b83\u96c6\u6210\u5230\u4efb\u4f55.NET/C# \u5e94\u7528\u7a0b\u5e8f\u4e2d\u3002\n///\n/// An application framework that you can integrate into any.NET/C# application.\n///\n/// ## \u5b89\u88c5 / Installation\n///\n/// - [Package Manager] (https://www.nuget.org/packages/Furion)\n///\n/// ```powershell\n/// Install-Package Furion\n/// ```\n///\n/// - [.NET CLI] (https://www.nuget.org/packages/Furion)\n///\n/// ```powershell\n/// dotnet add package Furion\n/// ```\n///\n/// ## \u4f8b\u5b50 / Examples\n///\n/// \u6211\u4eec\u5728[\u4e3b\u9875](https://dotnetchina.gitee.io/furion)\u4e0a\u6709\u4e0d\u5c11\u4f8b\u5b50\uff0c\u8fd9\u662f\u8ba9\u60a8\u5165\u95e8\u7684\u7b2c\u4e00\u4e2a\uff1a\n///\n/// We have several examples [on the website] (https://dotnetchina.gitee.io/furion). Here is the first one to get you started:\n///\n/// ```cs\n/// Serve.Run();\n///\n/// [DynamicApiController]\n/// public class HelloService\n/// {\n/// public string Say()\n/// {\n/// return "Hello, Furion";\n/// }\n/// }\n/// ```\n///\n/// \u6253\u5f00\u6d4f\u89c8\u5668\u8bbf\u95ee `https://localhost:5001`\u3002\n///\n/// Open browser access `https://localhost:5001`.\n///\n/// ## \u6587\u6863 / Documentation\n///\n/// \u60a8\u53ef\u4ee5\u5728[\u4e3b\u9875] (https://dotnetchina.gitee.io/furion)\u6216[\u5907\u4efd\u4e3b\u9875](https://furion.icu)\u627e\u5230 Furion \u6587\u6863\u3002\n///\n/// You can find the Furion documentation[on the website](https://dotnetchina.gitee.io/furion) or [on the backup website](https://furion.icu).\n///\n/// ## \u8d21\u732e / Contributing\n///\n/// \u8be5\u5b58\u50a8\u5e93\u7684\u4e3b\u8981\u76ee\u7684\u662f\u7ee7\u7eed\u53d1\u5c55 Furion \u6838\u5fc3\uff0c\u4f7f\u5176\u66f4\u5feb\u3001\u66f4\u6613\u4e8e\u4f7f\u7528\u3002 Furion \u7684\u5f00\u53d1\u5728[Gitee](https://gitee.com/dotnetchina/Furion) \u4e0a\u516c\u5f00\u8fdb\u884c\uff0c\u6211\u4eec\u611f\u8c22\u793e\u533a\u8d21\u732e\u9519\u8bef\u4fee\u590d\u548c\u6539\u8fdb\u3002\n///\n/// \u9605\u8bfb[\u8d21\u732e\u6307\u5357] (https://dotnetchina.gitee.io/furion/docs/contribute)\u5185\u5bb9\uff0c\u4e86\u89e3\u5982\u4f55\u53c2\u4e0e\u6539\u8fdb Furion\u3002\n///\n/// The main purpose of this repository is to continue evolving Furion core, making it faster and easier to use.Development of Furion happens in the open on[Gitee] (https://gitee.com/dotnetchina/Furion), and we are grateful to the community for contributing bugfixes and improvements.\n///\n/// Read[contribution documents] (https://dotnetchina.gitee.io/furion/docs/contribute) to learn how you can take part in improving Furion.\n///\n/// ## \u8bb8\u53ef\u8bc1 / License\n///\n/// Furion \u91c7\u7528[MIT](https://gitee.com/dotnetchina/Furion/blob/net6/LICENSE) \u5f00\u6e90\u8bb8\u53ef\u8bc1\u3002\n///\n/// Furion uses the[MIT] (https://gitee.com/dotnetchina/Furion/blob/net6/LICENSE) open source license.\n///\n/// ```\n/// Copyright(c) 2020-2022 \u767e\u5c0f\u50e7, Baiqian Co., Ltd.\n/// Furion is licensed under Mulan PSL v2.\n/// You can use this software according to the terms andconditions of the Mulan PSL v2.\n/// You may obtain a copy of Mulan PSL v2 at:\n/// https://gitee.com/dotnetchina/Furion/blob/net6/LICENSE\n/// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUTWARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.\n/// See the Mulan PSL v2 for more details.\n/// ```\n///\n/// \n/// \npublic string Hello()\n{\n return "Furion";\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/mdx.png")}),(0,r.kt)("h2",{id:"66-specificationdocumentsettings-\u914d\u7f6e"},"6.6 ",(0,r.kt)("inlineCode",{parentName:"h2"},"SpecificationDocumentSettings")," \u914d\u7f6e"),(0,r.kt)("p",null,"\u9664\u4e86\u4e0a\u8ff0\u4f8b\u5b50\u5916\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u4e00\u4e9b\u914d\u7f6e\u9009\u9879\uff0c\u5982\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DocumentTitle"),"\uff1a\u6587\u6863\u6807\u9898\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Specification Api Document")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DefaultGroupName"),"\uff1a\u9ed8\u8ba4\u5206\u7ec4\u540d\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Default")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EnableAuthorized"),"\uff1a\u662f\u5426\u542f\u7528\u6743\u9650\u63a7\u5236\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"FormatAsV2"),"\uff1a\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger 2.0")," \u7248\u672c\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false")," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("a",{parentName:"strong",href:"https://github.com/domaindrivendev/Swashbuckle.WebApi/issues/1393"},"\u5df2\u5f03\u7528"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"RoutePrefix"),"\uff1a\u89c4\u8303\u5316\u6587\u6863\u5730\u5740\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"api"),"\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u5982\u679c\u5e0c\u671b\u5728\u9996\u9875\uff0c\u6539\u4e3a\u7a7a\u5b57\u7b26\u4e32\u5373\u53ef"),"\u3002"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DocExpansionState"),"\uff1a\u6587\u6863\u663e\u793a\u65b9\u5f0f\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"DocExpansion"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"List"),"\uff0c\u53d6\u503c\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"List"),"\uff1a\u5217\u8868\u5f0f\uff08\u5c55\u5f00\u5b50\u7c7b\uff09\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u9ed8\u8ba4\u503c")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Full"),"\uff1a\u5b8c\u5168\u5c55\u5f00"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"None"),"\uff1a\u5217\u8868\u5f0f\uff08\u4e0d\u5c55\u5f00\u5b50\u7c7b\uff09"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"XmlComments"),"\uff1a\u7a0b\u5e8f\u96c6\u6ce8\u91ca\u63cf\u8ff0\u6587\u4ef6\u540d\uff08\u53ef\u5e26 ",(0,r.kt)("inlineCode",{parentName:"li"},".xml"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Application, Furion.Web.Entry, Furion.Web.Core")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"GroupOpenApiInfos"),"\uff1a\u5206\u7ec4\u4fe1\u606f\u914d\u7f6e\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationOpenApiInfo[]"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"{ 'Group': 'Default'}")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SecurityDefinitions"),"\uff1a\u5b89\u5168\u7b56\u7565\u5b9a\u4e49\u914d\u7f6e\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationOpenApiSecurityScheme[]"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"[]")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Servers"),"\uff1a\u914d\u7f6e Server \u4e0b\u62c9\u5217\u8868\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"OpenApiServer[]")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"[]"),"\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},'{Servers:[ { Url:"\u5730\u5740", Description:"\u63cf\u8ff0"} ]}')),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"HideServers"),"\uff1a\u662f\u5426\u9690\u85cf Server \u4e0b\u62c9\u5217\u8868\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"RouteTemplate"),"\uff1a\u914d\u7f6e\u6587\u6863 ",(0,r.kt)("inlineCode",{parentName:"li"},"swagger.json")," \u8def\u7531\u6a21\u677f\uff0c\u9ed8\u8ba4\u6a21\u677f\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"swagger/{documentName}/swagger.json"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"{documentName}")," \u4ee3\u8868\u5206\u7ec4\u540d\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u5fc5\u987b\u4fdd\u7559\u539f\u6837")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"PackagesGroups"),"\uff1a\u914d\u7f6e\u6a21\u5757\u5316\u5185\u7f6e\u5206\u7ec4\u540d\u79f0\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string[]")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"[]")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EnableEnumSchemaFilter"),"\uff1a\u542f\u7528\u679a\u4e3e Schema \u7b5b\u9009\u5668\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EnableTagsOrderDocumentFilter"),"\uff1a\u542f\u7528\u6807\u7b7e\u6392\u5e8f\u7b5b\u9009\u5668\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ServerDir"),"\uff1a\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"IIS")," \u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Application")," \u90e8\u7f72\u540d\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u9ed8\u8ba4\u7a7a\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u4ec5\u5728 Furion v3.2.0+` \u6709\u6548")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"LoginInfo"),"\uff1a\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u662f\u5426\u9700\u8981\u767b\u5f55\u624d\u80fd\u8bbf\u95ee\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationLoginInfo")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"null"),"\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u4ec5\u5728 Furion v3.3.3+` \u6709\u6548"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Enabled"),"\uff1a\u662f\u5426\u542f\u7528\u767b\u5f55\u6388\u6743\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"CheckUrl"),"\uff1a\u68c0\u67e5\u767b\u5f55\u72b6\u6001\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Url")," \u5730\u5740\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u8be5\u5730\u5740\u5fc5\u987b\u662f ",(0,r.kt)("inlineCode",{parentName:"strong"},"POST")," \u8bf7\u6c42"),"\uff0c\u5df2\u6388\u6743\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"200"),"\uff0c\u5426\u5219\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"401")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SubmitUrl"),"\uff1a\u63d0\u4ea4\u767b\u5f55\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Url")," \u5730\u5740\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u8be5\u5730\u5740\u5fc5\u987b\u662f ",(0,r.kt)("inlineCode",{parentName:"strong"},"POST")," \u8bf7\u6c42\u4e14\u53ea\u6709\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"strong"},"SpecificationAuth")," \u7c7b\u578b\u53c2\u6570"),"\uff0c\u6210\u529f\u767b\u5f55\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"200"),"\uff0c\u5426\u5219\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"401"),"\uff0c\u652f\u6301\u76f8\u5bf9\u5730\u5740\uff0c\u4ee5 ",(0,r.kt)("inlineCode",{parentName:"li"},"/")," \u5f00\u5934"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EnableAllGroups"),"\uff1a\u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u603b\u5206\u7ec4\u529f\u80fd\uff0c\u81ea\u52a8\u5c06\u6240\u6709\u5206\u7ec4\u7684\u63a5\u53e3\u5408\u5e76\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"All Groups")," \u4e2d\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false"),"\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u4ec5\u5728 Furion v3.3.4+` \u6709\u6548"))),(0,r.kt)("p",null,"\u53e6\u5916 ",(0,r.kt)("inlineCode",{parentName:"p"},"SpecificationOpenApiInfo")," \u5185\u7f6e\u914d\u7f6e\u5982\u4e0b\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Group"),"\uff1a\u5206\u7ec4\u552f\u4e00\u6807\u8bc6\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u5fc5\u586b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Order"),"\uff1a\u5206\u7ec4\u6392\u5e8f\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"int")," \u7c7b\u578b\uff0c\u6570\u5b57\u8d8a\u5927\u6392\u524d\u9762\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"0")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Visible"),"\uff1a\u914d\u7f6e\u5206\u7ec4\u662f\u5426\u53ef\u89c1\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Title"),"\uff1a\u914d\u7f6e\u5206\u7ec4\u6807\u9898\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Description"),"\uff1a\u914d\u7f6e\u5206\u7ec4\u63cf\u8ff0\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Version"),"\uff1a\u914d\u7f6e\u5206\u7ec4\u7248\u672c\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"1.0")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"TermsOfService"),"\uff1a\u914d\u7f6e\u76f8\u5173\u94fe\u63a5\u5730\u5740\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"Uri")," \u7c7b\u578b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Contact"),"\uff1a\u914d\u7f6e\u8054\u7cfb\u65b9\u5f0f\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"OpenApiContact")," \u7c7b\u578b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"License"),"\uff1a\u914d\u7f6e\u534f\u8bae\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"OpenApiLicense")," \u7c7b\u578b")),(0,r.kt)("p",null,"\u914d\u7f6e\u793a\u4f8b\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "SpecificationDocumentSettings": {\n "GroupOpenApiInfos": [\n {\n "Group": "Group1",\n "Title": "\u5206\u7ec4\u6807\u9898",\n "Description": "\u8fd9\u91cc\u662f\u5206\u7ec4\u63cf\u8ff0",\n "Version": "\u7248\u672c\u53f7",\n "TermsOfService": "https://furion.icu",\n "Contact": {\n "Name": "\u767e\u5c0f\u50e7",\n "Url": "https://gitee.com/monksoul",\n "Email": "monksoul@outlook.com"\n },\n "License": {\n "Name": "MIT",\n "Url": "https://gitee.com/dotnetchina/Furion/blob/alpha/LICENSE"\n }\n }\n ]\n }\n}\n')),(0,r.kt)("h2",{id:"67-\u7edf\u4e00\u8fd4\u56de\u503c\u6a21\u578b\u89c4\u8303\u5316\u7ed3\u679capi-\u8fd4\u56de\u503c"},"6.7 \u7edf\u4e00\u8fd4\u56de\u503c\u6a21\u578b/\u89c4\u8303\u5316\u7ed3\u679c/API \u8fd4\u56de\u503c"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b ",(0,r.kt)("inlineCode",{parentName:"p"},"\u89c4\u8303\u5316\u7ed3\u679c")," \u529f\u80fd\uff0c\u53ef\u4ee5\u901a\u8fc7\u5b9e\u73b0 ",(0,r.kt)("inlineCode",{parentName:"p"},"IUnifyResultProvider")," \u63d0\u4f9b\u5668\u5b9e\u73b0\u7edf\u4e00\u89c4\u8303\u5316\u8fd4\u56de\u503c\u5b9a\u5236\uff0c\u5982\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"\u5b9a\u4e49\u7ed3\u679c\u5305\u88c5\u7c7b\u578b"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-2}",showLineNumbers:!0,"{1-2}":!0},"// \u5fc5\u987b\u662f\u6cdb\u578b\u7c7b\u578b\npublic class YourRESTfulResult\n{\n /// \n /// \u72b6\u6001\u7801\n /// \n public int? StatusCode { get; set; }\n\n /// \n /// \u6570\u636e\n /// \n public T Data { get; set; }\n\n /// \n /// \u6267\u884c\u6210\u529f\n /// \n public bool Succeeded { get; set; }\n\n /// \n /// \u9519\u8bef\u4fe1\u606f\n /// \n public object Errors { get; set; }\n\n /// \n /// \u9644\u52a0\u6570\u636e\n /// \n public object Extras { get; set; }\n\n /// \n /// \u65f6\u95f4\u6233\n /// \n public long Timestamp { get; set; }\n}\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"strong"},"IUnifyResultProvider")," \u5b9e\u73b0\u7c7b\uff0c\u5e76\u8d34\u7279\u6027 ",(0,r.kt)("inlineCode",{parentName:"strong"},"[UnifyModel(typeof(YourRESTfulResult<>))]")))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {15-16,24,35,46,58}",showLineNumbers:!0,"":!0,"{15-16,24,35,46,58}":!0},'using Furion.DataValidation;\nusing Furion.DependencyInjection;\nusing Furion.UnifyResult.Internal;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.Filters;\nusing System;\nusing System.Threading.Tasks;\n\nnamespace YourProject.UnifyResult\n{\n /// \n /// RESTful \u98ce\u683c\u8fd4\u56de\u503c\n /// \n [UnifyModel(typeof(YourRESTfulResult<>))]\n public class YourRESTfulResultProvider : IUnifyResultProvider\n {\n /// \n /// \u5f02\u5e38\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata)\n {\n return new JsonResult(YourRESTfulResult(metadata.StatusCode, errors: metadata.Errors));\n }\n\n /// \n /// \u6210\u529f\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n public IActionResult OnSucceeded(ActionExecutedContext context, object data)\n {\n return new JsonResult(YourRESTfulResult(StatusCodes.Status200OK, true, data));\n }\n\n /// \n /// \u9a8c\u8bc1\u5931\u8d25\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n public IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata)\n {\n return new JsonResult(YourRESTfulResult(metadata.StatusCode ?? StatusCodes.Status400BadRequest, errors: metadata.ValidationResult));\n }\n\n /// \n /// \u7279\u5b9a\u72b6\u6001\u7801\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n /// \n public async Task OnResponseStatusCodes(HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings)\n {\n // \u8bbe\u7f6e\u54cd\u5e94\u72b6\u6001\u7801\n UnifyContext.SetResponseStatusCodes(context, statusCode, unifyResultSettings);\n\n switch (statusCode)\n {\n // \u5904\u7406 401 \u72b6\u6001\u7801\n case StatusCodes.Status401Unauthorized:\n await context.Response.WriteAsJsonAsync(YourRESTfulResult(statusCode, errors: "401 Unauthorized")\n , App.GetOptions()?.JsonSerializerOptions);\n break;\n // \u5904\u7406 403 \u72b6\u6001\u7801\n case StatusCodes.Status403Forbidden:\n await context.Response.WriteAsJsonAsync(YourRESTfulResult(statusCode, errors: "403 Forbidden")\n , App.GetOptions()?.JsonSerializerOptions);\n break;\n default: break;\n }\n }\n\n /// \n /// \u8fd4\u56de RESTful \u98ce\u683c\u7ed3\u679c\u96c6\n /// \n /// \n /// \n /// \n /// \n /// \n private static YourRESTfulResult YourRESTfulResult(int statusCode, bool succeeded = default, object data = default, object errors = default)\n {\n return new YourRESTfulResult\n {\n StatusCode = statusCode,\n Succeeded = succeeded,\n Data = data,\n Errors = errors,\n Extras = UnifyContext.Take(),\n Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()\n };\n }\n }\n}\n')),(0,r.kt)("p",null,"\u4e4b\u540e\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddControllers()\n .AddInjectWithUnifyResult();\n")),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u89c4\u8303\u5316\u7ed3\u679c\u4e0d\u4f1a\u5bf9 ",(0,r.kt)("inlineCode",{parentName:"p"},"401")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"403"),"\u3001",(0,r.kt)("inlineCode",{parentName:"p"},"404")," \u72b6\u6001\u7801\u8fdb\u884c\u89c4\u8303\u5316\u5904\u7406\uff0c\u5982\u9700\u542f\u52a8\u8be5\u72b6\u6001\u7801\u5904\u7406\uff0c\u53ea\u9700\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Configure")," \u4e2d\u542f\u7528\u63a5\u53e3\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n{\n if (env.IsDevelopment())\n {\n app.UseDeveloperExceptionPage();\n }\n // \u6dfb\u52a0\u89c4\u8303\u5316\u7ed3\u679c\u72b6\u6001\u7801\uff0c\u9700\u8981\u5728\u8fd9\u91cc\u6ce8\u518c\n app.UseUnifyResultStatusCodes();\n // \u5176\u4ed6\u6ce8\u518c...\n}\n"))),(0,r.kt)("h3",{id:"671-\u6392\u9664\u89c4\u8303\u5316\u5904\u7406"},"6.7.1 \u6392\u9664\u89c4\u8303\u5316\u5904\u7406"),(0,r.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u67d0\u4e9b\u63a5\u53e3\u4e0d\u9700\u8981\u8fdb\u884c\u89c4\u8303\u5316\u5904\u7406\uff0c\u8fd9\u65f6\uff0c\u6211\u4eec\u53ea\u9700\u8981\u5e16 ",(0,r.kt)("inlineCode",{parentName:"p"},"[NonUnify]")," \u7279\u6027\u5373\u53ef\u3002"),(0,r.kt)("h3",{id:"672-\u89c4\u8303\u5316\u7ed3\u679c\u6dfb\u52a0\u989d\u5916\u6570\u636e"},"6.7.2 \u89c4\u8303\u5316\u7ed3\u679c\u6dfb\u52a0\u989d\u5916\u6570\u636e"),(0,r.kt)("p",null,"\u9ed8\u8ba4\u7684\u89c4\u8303\u5316\u7ed3\u679c\u4e2d\u5305\u542b ",(0,r.kt)("inlineCode",{parentName:"p"},"extras")," \u5c5e\u6027\uff0c\u53ef\u4ee5\u914d\u7f6e\u989d\u5916\u6570\u636e\u8fd4\u56de\u5230\u5ba2\u6237\u7aef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'UnifyContext.Fill(new { Message = "\u64cd\u4f5c\u6210\u529f" });\n')),(0,r.kt)("h3",{id:"673-\u81ea\u5b9a\u4e49\u7279\u522b\u63a5\u53e3\u89c4\u8303\u5316\u7ed3\u679c"},"6.7.3 \u81ea\u5b9a\u4e49\u7279\u522b\u63a5\u53e3\u89c4\u8303\u5316\u7ed3\u679c"),(0,r.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u7279\u5b9a\u63a5\u53e3\u9700\u8fd4\u56de\u7279\u5b9a\u7684\u63a5\u53e3\u7c7b\u578b\uff0c\u65e0\u9700\u89c4\u8303\u5316\u5904\u7406\uff0c\u8fd9\u65f6\u5019\u6211\u4eec\u53ea\u9700\u8981\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[UnifyResult(typeof(\u7ed3\u679c\u7c7b))]")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"[ProducesResponseType(typeof(\u7ed3\u679c\u7c7b),200)]"),"\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"[UnifyResult(typeof(Person))]\npublic Person GetPerson(int id)\n{\n // ...\n}\n")),(0,r.kt)("h2",{id:"68-\u53cd\u9988\u4e0e\u5efa\u8bae"},"6.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,r.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}N.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return u},kt:function(){return c}});var i=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function l(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var p=i.createContext({}),s=function(e){var n=i.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},u=function(e){var n=s(e.components);return i.createElement(p.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},d=i.forwardRef((function(e,n){var t=e.components,a=e.mdxType,r=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),d=s(t),c=a,k=d["".concat(p,".").concat(c)]||d[c]||m[c]||r;return t?i.createElement(k,l(l({ref:n},u),{},{components:t})):i.createElement(k,l({ref:n},u))}));function c(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var r=t.length,l=new Array(r);l[0]=d;var o={};for(var p in n)hasOwnProperty.call(n,p)&&(o[p]=n[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var s=2;s=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var p=i.createContext({}),s=function(e){var n=i.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},u=function(e){var n=s(e.components);return i.createElement(p.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},d=i.forwardRef((function(e,n){var t=e.components,a=e.mdxType,r=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),d=s(t),c=a,k=d["".concat(p,".").concat(c)]||d[c]||m[c]||r;return t?i.createElement(k,l(l({ref:n},u),{},{components:t})):i.createElement(k,l({ref:n},u))}));function c(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var r=t.length,l=new Array(r);l[0]=d;var o={};for(var p in n)hasOwnProperty.call(n,p)&&(o[p]=n[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var s=2;s child <"+("string"==typeof e.type?e.type:e.type.name)+'>: all children of the component should be , and every should have a unique "value" prop.')})),h=null!=k?k:C.map((function(e){var n=e.props;return{value:n.value,label:n.label,attributes:n.attributes}})),f=(0,o.l)(h,(function(e,n){return e.value===n.value}));if(f.length>0)throw new Error('Docusaurus error: Duplicate values "'+f.map((function(e){return e.value})).join(", ")+'" found in . Every value needs to be unique.');var b=null===c?c:null!=(n=null!=c?c:null==(t=C.find((function(e){return e.props.default})))?void 0:t.props.value)?n:C[0].props.value;if(null!==b&&!h.some((function(e){return e.value===b})))throw new Error('Docusaurus error: The has a defaultValue "'+b+'" but none of its children has the corresponding value. Available values are: '+h.map((function(e){return e.value})).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");var w=(0,p.U)(),S=w.tabGroupChoices,v=w.setTabGroupChoices,y=(0,a.useState)(b),A=y[0],T=y[1],F=[],I=(0,s.o5)().blockElementScrollPositionUntilNextRender;if(null!=g){var D=S[g];null!=D&&D!==A&&h.some((function(e){return e.value===D}))&&T(D)}var L=function(e){var n=e.currentTarget,t=F.indexOf(n),i=h[t].value;i!==A&&(I(n),T(i),null!=g&&v(g,String(i)))},E=function(e){var n,t=null;switch(e.key){case"ArrowRight":var i,a=F.indexOf(e.currentTarget)+1;t=null!=(i=F[a])?i:F[0];break;case"ArrowLeft":var r,l=F.indexOf(e.currentTarget)-1;t=null!=(r=F[l])?r:F[F.length-1]}null==(n=t)||n.focus()};return a.createElement("div",{className:(0,r.Z)("tabs-container",u)},a.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,r.Z)("tabs",{"tabs--block":d},N)},h.map((function(e){var n=e.value,t=e.label,l=e.attributes;return a.createElement("li",(0,i.Z)({role:"tab",tabIndex:A===n?0:-1,"aria-selected":A===n,key:n,ref:function(e){return F.push(e)},onKeyDown:E,onFocus:L,onClick:L},l,{className:(0,r.Z)("tabs__item",m,null==l?void 0:l.className,{"tabs__item--active":A===n})}),null!=t?t:n)}))),l?(0,a.cloneElement)(C.filter((function(e){return e.props.value===A}))[0],{className:"margin-top--md"}):a.createElement("div",{className:"margin-top--md"},C.map((function(e,n){return(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==A})}))))}function c(e){var n=(0,l.Z)();return a.createElement(d,(0,i.Z)({key:String(n)},e))}},3113:function(e,n,t){t.r(n),t.d(n,{assets:function(){return c},contentTitle:function(){return m},default:function(){return N},frontMatter:function(){return u},metadata:function(){return d},toc:function(){return k}});var i=t(3117),a=t(102),r=(t(7294),t(3905)),l=t(4996),o=t(5488),p=t(5162),s=["components"],u={id:"specification-document",title:"6. \u89c4\u8303\u5316\u63a5\u53e3\u6587\u6863",sidebar_label:"6. \u89c4\u8303\u5316\u63a5\u53e3\u6587\u6863 (Swagger)"},m=void 0,d={unversionedId:"specification-document",id:"specification-document",title:"6. \u89c4\u8303\u5316\u63a5\u53e3\u6587\u6863",description:"",source:"@site/docs/specification-document.mdx",sourceDirName:".",slug:"/specification-document",permalink:"/furion/docs/specification-document",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/specification-document.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1661938334,formattedLastUpdatedAt:"Aug 31, 2022",frontMatter:{id:"specification-document",title:"6. \u89c4\u8303\u5316\u63a5\u53e3\u6587\u6863",sidebar_label:"6. \u89c4\u8303\u5316\u63a5\u53e3\u6587\u6863 (Swagger)"},sidebar:"docs",previous:{title:"5.6 Vue/React/Angular \u8bf7\u6c42\u4ee3\u7406",permalink:"/furion/docs/clientapi"},next:{title:"7. \u53cb\u597d\u5f02\u5e38\u5904\u7406",permalink:"/furion/docs/friendly-exception"}},c={},k=[{value:"6.1 \u4ec0\u4e48\u662f\u63a5\u53e3\u6587\u6863",id:"61-\u4ec0\u4e48\u662f\u63a5\u53e3\u6587\u6863",level:2},{value:"6.2 \u4e3a\u4ec0\u4e48\u8981\u5199\u63a5\u53e3\u6587\u6863",id:"62-\u4e3a\u4ec0\u4e48\u8981\u5199\u63a5\u53e3\u6587\u6863",level:2},{value:"6.3 \u4e3a\u4ec0\u4e48\u9700\u8981\u89c4\u8303\u5316\u6587\u6863",id:"63-\u4e3a\u4ec0\u4e48\u9700\u8981\u89c4\u8303\u5316\u6587\u6863",level:2},{value:"6.3.1 \u534f\u8bae\u89c4\u8303",id:"631-\u534f\u8bae\u89c4\u8303",level:3},{value:"6.3.2 \u63a5\u53e3\u8def\u5f84\u89c4\u8303",id:"632-\u63a5\u53e3\u8def\u5f84\u89c4\u8303",level:3},{value:"6.3.3 \u7248\u672c\u63a7\u5236\u89c4\u8303",id:"633-\u7248\u672c\u63a7\u5236\u89c4\u8303",level:3},{value:"6.3.4 \u63a5\u53e3\u547d\u540d\u89c4\u8303",id:"634-\u63a5\u53e3\u547d\u540d\u89c4\u8303",level:3},{value:"6.3.5 \u8bf7\u6c42\u53c2\u6570\u89c4\u8303",id:"635-\u8bf7\u6c42\u53c2\u6570\u89c4\u8303",level:3},{value:"6.3.6 \u8fd4\u56de\u6570\u636e\u89c4\u8303",id:"636-\u8fd4\u56de\u6570\u636e\u89c4\u8303",level:3},{value:"6.4 \u4ec0\u4e48\u662f Swagger",id:"64-\u4ec0\u4e48\u662f-swagger",level:2},{value:"6.5 Swagger \u4f7f\u7528",id:"65-swagger-\u4f7f\u7528",level:2},{value:"6.5.1 \u6ce8\u518c\u670d\u52a1",id:"651-\u6ce8\u518c\u670d\u52a1",level:3},{value:"6.5.2 \u9ed8\u8ba4\u5730\u5740",id:"652-\u9ed8\u8ba4\u5730\u5740",level:3},{value:"6.5.3 \u9ed8\u8ba4\u5206\u7ec4",id:"653-\u9ed8\u8ba4\u5206\u7ec4",level:3},{value:"6.5.4 \u6587\u6863\u6ce8\u91ca",id:"654-\u6587\u6863\u6ce8\u91ca",level:3},{value:"6.5.5 \u591a\u5206\u7ec4\u652f\u6301",id:"655-\u591a\u5206\u7ec4\u652f\u6301",level:3},{value:"6.5.6 \u591a\u5206\u7ec4\u6392\u5e8f",id:"656-\u591a\u5206\u7ec4\u6392\u5e8f",level:3},{value:"6.5.7 \u591a\u5206\u7ec4\u4fe1\u606f\u914d\u7f6e",id:"657-\u591a\u5206\u7ec4\u4fe1\u606f\u914d\u7f6e",level:3},{value:"6.5.8 \u7ec4\u4e2d\u7ec4\uff08\u6807\u7b7e\uff09",id:"658-\u7ec4\u4e2d\u7ec4\u6807\u7b7e",level:3},{value:"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d",id:"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d",level:4},{value:"\u8d34\u6807\u7b7e\u4e4b\u540e",id:"\u8d34\u6807\u7b7e\u4e4b\u540e",level:4},{value:"6.5.9 \u9ed8\u8ba4\u5c55\u5f00\u6240\u6709\u6587\u6863",id:"659-\u9ed8\u8ba4\u5c55\u5f00\u6240\u6709\u6587\u6863",level:3},{value:"6.5.10 \u914d\u7f6e\u6587\u6863\u6807\u9898",id:"6510-\u914d\u7f6e\u6587\u6863\u6807\u9898",level:3},{value:"6.5.11 \u6388\u6743\u63a7\u5236",id:"6511-\u6388\u6743\u63a7\u5236",level:3},{value:"6.5.12 \u5728\u7ebf\u6d4b\u8bd5",id:"6512-\u5728\u7ebf\u6d4b\u8bd5",level:3},{value:"6.5.13 \u6027\u80fd\u76d1\u89c6 MiniProfiler",id:"6513-\u6027\u80fd\u76d1\u89c6-miniprofiler",level:3},{value:"6.5.14 \u5b9a\u4e49\u63a5\u53e3\u8f93\u51fa\u7c7b\u578b",id:"6514-\u5b9a\u4e49\u63a5\u53e3\u8f93\u51fa\u7c7b\u578b",level:3},{value:"6.5.15 \u9690\u85cf\u7279\u5b9a\u5206\u7ec4",id:"6515-\u9690\u85cf\u7279\u5b9a\u5206\u7ec4",level:3},{value:"6.5.16 \u4e2d\u6587\u4e71\u7801\u95ee\u9898",id:"6516-\u4e2d\u6587\u4e71\u7801\u95ee\u9898",level:3},{value:"6.5.17 \u751f\u4ea7\u73af\u5883\u4e2d\u5173\u95ed Swagger",id:"6517-\u751f\u4ea7\u73af\u5883\u4e2d\u5173\u95ed-swagger",level:3},{value:"6.5.18 \u8bbe\u7f6e Example Value \u9ed8\u8ba4\u503c",id:"6518-\u8bbe\u7f6e-example-value-\u9ed8\u8ba4\u503c",level:3},{value:"6.5.19 \u81ea\u5b9a\u4e49 Swagger \u914d\u7f6e",id:"6519-\u81ea\u5b9a\u4e49-swagger-\u914d\u7f6e",level:3},{value:"6.5.20 \u914d\u7f6e Swagger\u7684 Schemes",id:"6520-\u914d\u7f6e-swagger\u7684-schemes",level:3},{value:"6.5.21 \u81ea\u5b9a\u4e49 swagger.json \u8def\u7531\u6a21\u677f",id:"6521-\u81ea\u5b9a\u4e49-swaggerjson-\u8def\u7531\u6a21\u677f",level:3},{value:"6.5.22 \u5173\u4e8e application/x-www-form-urlencoded \u8bf7\u6c42",id:"6522-\u5173\u4e8e-applicationx-www-form-urlencoded-\u8bf7\u6c42",level:3},{value:"6.5.23 Swagger \u51fa\u73b0 CORS \u95ee\u9898\u89e3\u51b3",id:"6523-swagger-\u51fa\u73b0-cors-\u95ee\u9898\u89e3\u51b3",level:3},{value:"6.5.24 Swagger \u51fa\u73b0\u9ed8\u8ba4 xml \u53c2\u6570\u95ee\u9898\u89e3\u51b3",id:"6524-swagger-\u51fa\u73b0\u9ed8\u8ba4-xml-\u53c2\u6570\u95ee\u9898\u89e3\u51b3",level:3},{value:"6.5.25 Swagger \u591a\u8bed\u8a00\u652f\u6301",id:"6525-swagger-\u591a\u8bed\u8a00\u652f\u6301",level:3},{value:"6.5.26 \u81ea\u5b9a\u4e49\u903b\u8f91\u63a7\u5236 Swagger \u6bcf\u4e00\u4e2a api \u53ef\u89c1\u6027",id:"6526-\u81ea\u5b9a\u4e49\u903b\u8f91\u63a7\u5236-swagger-\u6bcf\u4e00\u4e2a-api-\u53ef\u89c1\u6027",level:3},{value:"6.5.27 \u914d\u7f6e MVC \u63a7\u5236\u5668\u652f\u6301\u89c4\u8303\u5316\u5904\u7406",id:"6527-\u914d\u7f6e-mvc-\u63a7\u5236\u5668\u652f\u6301\u89c4\u8303\u5316\u5904\u7406",level:3},{value:"6.5.28 Swagger \u5237\u65b0\u8bb0\u4f4f\u6388\u6743\u72b6\u6001",id:"6528-swagger-\u5237\u65b0\u8bb0\u4f4f\u6388\u6743\u72b6\u6001",level:3},{value:"6.5.29 \u5e26\u767b\u5f55\u7684 Swagger \u6587\u6863",id:"6529-\u5e26\u767b\u5f55\u7684-swagger-\u6587\u6863",level:3},{value:"\u914d\u7f6e\u8bf4\u660e",id:"\u914d\u7f6e\u8bf4\u660e",level:4},{value:"\u914d\u7f6e\u793a\u4f8b",id:"\u914d\u7f6e\u793a\u4f8b",level:4},{value:"6.5.30 inheritdoc \u5b9e\u73b0\u6ce8\u91ca\u7ee7\u627f",id:"6530-inheritdoc-\u5b9e\u73b0\u6ce8\u91ca\u7ee7\u627f",level:2},{value:"6.5.31 \u542f\u7528 All Groups \u5206\u7ec4\u529f\u80fd",id:"6531-\u542f\u7528-all-groups-\u5206\u7ec4\u529f\u80fd",level:3},{value:"6.5.32 \u63a5\u53e3\u8fc7\u65f6\u63a7\u5236",id:"6532-\u63a5\u53e3\u8fc7\u65f6\u63a7\u5236",level:3},{value:"6.5.33 \u5355\u4e00\u63a5\u53e3\u66f4\u591a\u63cf\u8ff0",id:"6533-\u5355\u4e00\u63a5\u53e3\u66f4\u591a\u63cf\u8ff0",level:3},{value:"6.5.34 Swagger \u5f02\u5e38/\u4e0d\u80fd\u663e\u793a/\u9519\u8bef\u5904\u7406",id:"6534-swagger-\u5f02\u5e38\u4e0d\u80fd\u663e\u793a\u9519\u8bef\u5904\u7406",level:3},{value:"6.5.35 \u81ea\u5b9a\u4e49 Swagger \u7684 SchemaId",id:"6535-\u81ea\u5b9a\u4e49-swagger-\u7684-schemaid",level:3},{value:"6.5.36 \u81ea\u5b9a\u4e49 Swagger \u7684 OperationId",id:"6536-\u81ea\u5b9a\u4e49-swagger-\u7684-operationid",level:3},{value:"6.5.37 Swagger \u63a5\u53e3\u6587\u6863\u652f\u6301\u5b8c\u6574\u7684 Markdown",id:"6537-swagger-\u63a5\u53e3\u6587\u6863\u652f\u6301\u5b8c\u6574\u7684-markdown",level:3},{value:"6.6 SpecificationDocumentSettings \u914d\u7f6e",id:"66-specificationdocumentsettings-\u914d\u7f6e",level:2},{value:"6.7 \u7edf\u4e00\u8fd4\u56de\u503c\u6a21\u578b/\u89c4\u8303\u5316\u7ed3\u679c/API \u8fd4\u56de\u503c",id:"67-\u7edf\u4e00\u8fd4\u56de\u503c\u6a21\u578b\u89c4\u8303\u5316\u7ed3\u679capi-\u8fd4\u56de\u503c",level:2},{value:"6.7.1 \u6392\u9664\u89c4\u8303\u5316\u5904\u7406",id:"671-\u6392\u9664\u89c4\u8303\u5316\u5904\u7406",level:3},{value:"6.7.2 \u89c4\u8303\u5316\u7ed3\u679c\u6dfb\u52a0\u989d\u5916\u6570\u636e",id:"672-\u89c4\u8303\u5316\u7ed3\u679c\u6dfb\u52a0\u989d\u5916\u6570\u636e",level:3},{value:"6.7.3 \u81ea\u5b9a\u4e49\u7279\u522b\u63a5\u53e3\u89c4\u8303\u5316\u7ed3\u679c",id:"673-\u81ea\u5b9a\u4e49\u7279\u522b\u63a5\u53e3\u89c4\u8303\u5316\u7ed3\u679c",level:3},{value:"6.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"68-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],g={toc:k};function N(e){var n=e.components,t=(0,a.Z)(e,s);return(0,r.kt)("wrapper",(0,i.Z)({},g,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"61-\u4ec0\u4e48\u662f\u63a5\u53e3\u6587\u6863"},"6.1 \u4ec0\u4e48\u662f\u63a5\u53e3\u6587\u6863"),(0,r.kt)("p",null,"\u5728\u73b0\u5728\u79fb\u52a8\u4e3a\u738b\u3001\u591a\u7aef\u4e92\u8f85\u3001\u524d\u7aef\u767e\u82b1\u9f50\u653e\u7684\u5f00\u653e\u65f6\u4ee3\uff0c\u4e0d\u518d\u662f\u4e00\u4eba\u5305\u63fd\u5f0f\u5f00\u53d1\uff0c\u5927\u5bb6\u5404\u53f8\u5176\u804c\uff0c\u540e\u7aef\u5de5\u7a0b\u5e08\u8d1f\u8d23\u63a5\u53e3\u5f00\u53d1\uff0c\u524d\u7aef\u8d1f\u8d23\u63a5\u53e3\u8054\u8c03\uff0c\u4e5f\u5c31\u662f\u4e92\u8054\u7f51\u73b0\u5728\u6d41\u884c\u7684\u524d\u540e\u7aef\u5206\u79bb\u67b6\u6784\u3002"),(0,r.kt)("p",null,"\u6240\u4ee5\u5c31\u9700\u8981\u7531\u524d\u540e\u7aef\u5de5\u7a0b\u5e08\u5171\u540c\u5b9a\u4e49\u63a5\u53e3\uff0c\u7f16\u5199\u63a5\u53e3\u6587\u6863\uff0c\u4e4b\u540e\u5927\u5bb6\u6309\u7167\u8fd9\u4e2a\u63a5\u53e3\u6587\u6863\u8fdb\u884c\u5f00\u53d1\u3001\u7ef4\u62a4\u53ca\u5f00\u653e\u7ed9\u7b2c\u4e09\u65b9\u3002"),(0,r.kt)("h2",{id:"62-\u4e3a\u4ec0\u4e48\u8981\u5199\u63a5\u53e3\u6587\u6863"},"6.2 \u4e3a\u4ec0\u4e48\u8981\u5199\u63a5\u53e3\u6587\u6863"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u80fd\u591f\u8ba9\u524d\u7aef\u5f00\u53d1\u4e0e\u540e\u53f0\u5f00\u53d1\u4eba\u5458\u66f4\u597d\u7684\u914d\u5408\uff0c\u63d0\u9ad8\u5de5\u4f5c\u6548\u7387"),(0,r.kt)("li",{parentName:"ul"},"\u9879\u76ee\u8fed\u4ee3\u6216\u8005\u9879\u76ee\u4eba\u5458\u66f4\u8fed\u65f6\uff0c\u65b9\u4fbf\u540e\u671f\u4eba\u5458\u67e5\u770b\u548c\u7ef4\u62a4"),(0,r.kt)("li",{parentName:"ul"},"\u65b9\u4fbf\u6d4b\u8bd5\u4eba\u5458\u8fdb\u884c\u63a5\u53e3\u6d4b\u8bd5")),(0,r.kt)("h2",{id:"63-\u4e3a\u4ec0\u4e48\u9700\u8981\u89c4\u8303\u5316\u6587\u6863"},"6.3 \u4e3a\u4ec0\u4e48\u9700\u8981\u89c4\u8303\u5316\u6587\u6863"),(0,r.kt)("p",null,"\u7531\u4e8e\u6bcf\u4e2a\u516c\u53f8\u540e\u7aef\u4eba\u5458\u6280\u672f\u53c2\u5dee\u4e0d\u9f50\uff0c\u6280\u672f\u6587\u6863\u80fd\u529b\u4e5f\u4e0d\u4f8b\u5916\uff0c\u5bfc\u81f4\u63a5\u53e3\u5b9a\u4e49\u53ca\u6587\u6863\u4e94\u82b1\u516b\u95e8\uff0c\u4e0d\u540c\u9879\u76ee\u6216\u4e0d\u540c\u516c\u53f8\u5bf9\u63a5\u6781\u5176\u56f0\u96be\uff0c\u800c\u4e14\u4f53\u9a8c\u7cdf\u7cd5\u3002\u6240\u4ee5\uff0c\u65e0\u89c4\u77e9\u4e0d\u6210\u65b9\u5706\uff0c\u4e3a\u4e86\u5f00\u53d1\u4eba\u5458\u95f4\u66f4\u597d\u7684\u914d\u5408\uff0c\u8feb\u5207\u9700\u8981\u6574\u7406\u51fa\u4e00\u5957\u89c4\u8303\u3002"),(0,r.kt)("p",null,"\u901a\u5e38\u63a5\u53e3\u89c4\u8303\u5206\u4e3a\u516d\u4e2a\u90e8\u5206\uff1a"),(0,r.kt)("h3",{id:"631-\u534f\u8bae\u89c4\u8303"},"6.3.1 \u534f\u8bae\u89c4\u8303"),(0,r.kt)("p",null,"\u4e3a\u4e86\u786e\u4fdd\u4e0d\u540c\u7cfb\u7edf/\u6a21\u5757\u95f4\u7684\u6570\u636e\u4ea4\u4e92\uff0c\u9700\u8981\u4e8b\u5148\u7ea6\u5b9a\u597d\u901a\u8baf\u534f\u8bae\uff0c\u5982\uff1aTCP\u3001HTTP\u3001HTTPS \u534f\u8bae\u3002\u4e3a\u4e86\u786e\u4fdd\u6570\u636e\u4ea4\u4e92\u5b89\u5168\uff0c\u5efa\u8bae\u4f7f\u7528 HTTPS \u534f\u8bae"),(0,r.kt)("h3",{id:"632-\u63a5\u53e3\u8def\u5f84\u89c4\u8303"},"6.3.2 \u63a5\u53e3\u8def\u5f84\u89c4\u8303"),(0,r.kt)("p",null,"\u4f5c\u4e3a\u63a5\u53e3\u8def\u5f84\uff0c\u4e3a\u4e86\u65b9\u4fbf\u6e05\u6670\u7684\u533a\u5206\u6765\u81ea\u4e0d\u540c\u7684\u7cfb\u7edf\uff0c\u53ef\u4ee5\u91c7\u7528\u4e0d\u540c\u7cfb\u7edf/\u6a21\u5757\u540d\u4f5c\u4e3a\u63a5\u53e3\u8def\u5f84\u524d\u7f00\uff0c\u5982\uff1a\u652f\u4ed8\u6a21\u5757\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"/pay/xxx"),"\uff0c\u8ba2\u5355\u6a21\u5757\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"/order/xxx")),(0,r.kt)("h3",{id:"633-\u7248\u672c\u63a7\u5236\u89c4\u8303"},"6.3.3 \u7248\u672c\u63a7\u5236\u89c4\u8303"),(0,r.kt)("p",null,'\u4e3a\u4e86\u4fbf\u4e8e\u540e\u671f\u63a5\u53e3\u7684\u5347\u7ea7\u548c\u7ef4\u62a4\uff0c\u5efa\u8bae\u5728\u63a5\u53e3\u8def\u5f84\u4e2d\u52a0\u5165\u7248\u672c\u53f7\uff0c\u4fbf\u4e8e\u7ba1\u7406\uff0c\u5b9e\u73b0\u63a5\u53e3\u591a\u7248\u672c\u7684\u53ef\u7ef4\u62a4\u6027\u3002\u5982\uff1a\u63a5\u53e3\u8def\u5f84\u4e2d\u6dfb\u52a0\u7c7b\u4f3c"',(0,r.kt)("inlineCode",{parentName:"p"},"v1"),'"\u3001"',(0,r.kt)("inlineCode",{parentName:"p"},"v2"),'"\u7b49\u7248\u672c\u53f7'),(0,r.kt)("h3",{id:"634-\u63a5\u53e3\u547d\u540d\u89c4\u8303"},"6.3.4 \u63a5\u53e3\u547d\u540d\u89c4\u8303"),(0,r.kt)("p",null,'\u548c C# \u547d\u540d\u89c4\u8303\u4e00\u6837\uff0c\u597d\u7684\u3001\u7edf\u4e00\u7684\u63a5\u53e3\u547d\u540d\u89c4\u8303\uff0c\u4e0d\u4ec5\u53ef\u4ee5\u589e\u5f3a\u5176\u53ef\u8bfb\u6027\uff0c\u800c\u4e14\u8fd8\u4f1a\u51cf\u5c11\u5f88\u591a\u4e0d\u5fc5\u8981\u7684\u53e3\u5934/\u4e66\u9762\u4e0a\u7684\u89e3\u91ca\u3002\u53ef\u4f7f\u7528"\u9a7c\u5cf0\u547d\u540d\u6cd5"\u6309\u7167\u5b9e\u73b0\u63a5\u53e3\u7684',(0,r.kt)("strong",{parentName:"p"},"\u4e1a\u52a1\u7c7b\u578b\u3001\u4e1a\u52a1\u573a\u666f"),"\u7b49\u547d\u540d\uff0c\u6709\u5fc5\u8981\u65f6\u53ef\u91c7\u53d6\u591a\u7ea7\u76ee\u5f55\u547d\u540d\uff0c\u4f46\u76ee\u5f55\u4e0d\u5b9c\u8fc7\u957f\uff0c\u4e24\u7ea7\u76ee\u5f55\u8f83\u4e3a\u9002\u5b9c"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u5e38\u89c1\u547d\u540d\u65b9\u5f0f"),":",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u63a5\u53e3\u540d\u79f0\u52a8\u8bcd\u524d/\u540e\u7f00\u5316"),"\uff1a \u63a5\u53e3\u540d\u79f0\u4ee5\u63a5\u53e3\u6570\u636e\u64cd\u4f5c\u7684\u52a8\u8bcd\u4e3a\u524d/\u540e\u7f00\uff0c\u5e38\u89c1\u52a8\u8bcd\u6709\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"Add\u3001Delete\u3001Update\u3001Query\u3001Get\u3001Send\u3001Save\u3001Detail\u3001List"),"\u7b49\uff0c\u5982\uff1a\u65b0\u5efa\u7528\u6237 ",(0,r.kt)("inlineCode",{parentName:"li"},"AddUser"),"\u3001\u67e5\u8be2\u8ba2\u5355\u8be6\u60c5 ",(0,r.kt)("inlineCode",{parentName:"li"},"QueryOrderDetail"),"\u3002"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u63a5\u53e3\u540d\u79f0\u52a8\u8bcd + \u8bf7\u6c42\u65b9\u5f0f"),"\uff1a\u63a5\u53e3\u8def\u5f84\u4e2d\u5305\u542b\u5177\u4f53\u63a5\u53e3\u540d\u79f0\u7684\u540d\u8bcd\uff0c\u63a5\u53e3\u6570\u636e\u64cd\u4f5c\u52a8\u4f5c\u4ee5 HTTP \u8bf7\u6c42\u65b9\u5f0f\u6765\u533a\u5206\u3002\u5e38\u7528\u7684 HTTP \u8bf7\u6c42\u65b9\u5f0f\u6709\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"GET"),"\uff1a\u4ece\u670d\u52a1\u5668\u53d6\u51fa\u8d44\u6e90\uff08\u4e00\u9879\u6216\u591a\u9879\uff09"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"POST"),"\uff1a\u5728\u670d\u52a1\u5668\u65b0\u5efa\u4e00\u4e2a\u8d44\u6e90"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"PUT"),"\uff1a\u5728\u670d\u52a1\u5668\u66f4\u65b0\u8d44\u6e90\uff08\u5ba2\u6237\u7aef\u63d0\u4f9b\u6539\u53d8\u540e\u7684\u5b8c\u6574\u8d44\u6e90\uff09"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"PATCH"),"\uff1a\u5728\u670d\u52a1\u5668\u66f4\u65b0\u8d44\u6e90\uff08\u5ba2\u6237\u7aef\u63d0\u4f9b\u6539\u53d8\u7684\u5c5e\u6027\uff09"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DELETE"),"\uff1a\u4ece\u670d\u52a1\u5668\u5220\u9664\u8d44\u6e90")))))),(0,r.kt)("h3",{id:"635-\u8bf7\u6c42\u53c2\u6570\u89c4\u8303"},"6.3.5 \u8bf7\u6c42\u53c2\u6570\u89c4\u8303"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u8bf7\u6c42\u65b9\u5f0f"),"\uff1a\u6309\u7167 ",(0,r.kt)("inlineCode",{parentName:"li"},"GET\u3001POST\u3001PUT")," \u7b49\u542b\u4e49\u5b9a\u4e49\uff0c\u907f\u514d\u51fa\u73b0\u4e0d\u4e00\u81f4\u73b0\u8c61\uff0c\u5bf9\u4eba\u9020\u6210\u8bef\u89e3\u3001\u6b67\u4e49",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u8bf7\u6c42\u5934"),"\uff1a\u8bf7\u6c42\u5934\u6839\u636e\u9879\u76ee\u9700\u6c42\u6dfb\u52a0\u914d\u7f6e\u53c2\u6570\u3002\u5982\uff1a\u8bf7\u6c42\u6570\u636e\u683c\u5f0f\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"accept=application/json")," \u7b49\u3002\u5982\u6709\u9700\u8981\uff0c\u8bf7\u6c42\u5934\u53ef\u6839\u636e\u9879\u76ee\u9700\u6c42\u8981\u6c42\u4f20\u5165\u7528\u6237 token\u3001\u552f\u4e00\u9a8c\u7b7e\u7801\u7b49\u52a0\u5bc6\u6570\u636e"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u8bf7\u6c42\u53c2\u6570/\u8bf7\u6c42\u4f53"),"\uff1a \u8bf7\u6c42\u53c2\u6570\u5b57\u6bb5\uff0c\u5c3d\u53ef\u80fd\u4e0e\u6570\u636e\u5e93\u8868\u5b57\u6bb5\u3001\u5bf9\u8c61\u5c5e\u6027\u540d\u7b49\u4fdd\u6301\u4e00\u81f4\uff0c\u56e0\u4e3a\u4fdd\u6301\u4e00\u81f4\u662f\u6700\u7701\u4e8b\uff0c\u6700\u8212\u670d\u7684\u4e00\u4ef6\u4e8b")))),(0,r.kt)("h3",{id:"636-\u8fd4\u56de\u6570\u636e\u89c4\u8303"},"6.3.6 \u8fd4\u56de\u6570\u636e\u89c4\u8303"),(0,r.kt)("p",null,"\u7edf\u4e00\u89c4\u8303\u8fd4\u56de\u6570\u636e\u7684\u683c\u5f0f\uff0c\u5bf9\u5df1\u5bf9\u5f7c\u90fd\u6709\u597d\u5904\uff0c\u6b64\u5904\u4ee5 json \u683c\u5f0f\u4e3a\u4f8b\u3002\u8fd4\u56de\u6570\u636e\u5e94\u5305\u542b\uff1a",(0,r.kt)("strong",{parentName:"p"},"\u8fd4\u56de\u72b6\u6001\u7801\u3001\u8fd4\u56de\u72b6\u6001\u4fe1\u606f\u3001\u5177\u4f53\u6570\u636e"),"\u3002",(0,r.kt)("strong",{parentName:"p"},"\u8fd4\u56de\u6570\u636e\u4e2d\u7684\u72b6\u6001\u7801\u3001\u72b6\u6001\u4fe1\u606f\uff0c\u5e38\u6307\u5177\u4f53\u7684\u4e1a\u52a1\u72b6\u6001\uff0c\u4e0d\u5efa\u8bae\u548c HTTP \u72b6\u6001\u7801\u6df7\u5728\u4e00\u8d77"),"\u3002HTTP \u72b6\u6001\uff0c\u662f\u7528\u6765\u4f53\u73b0 HTTP \u94fe\u8def\u72b6\u6001\u60c5\u51b5\uff0c\u5982\uff1a404-Not Found\u3002HTTP \u72b6\u6001\u7801\u548c json \u7ed3\u679c\u4e2d\u7684\u72b6\u6001\u7801\uff0c\u5e76\u5b58\u5c1a\u53ef\uff0c\u7528\u4e8e\u4f53\u73b0\u4e0d\u540c\u7ef4\u5ea6\u7684\u72b6\u6001\u3002"),(0,r.kt)("h2",{id:"64-\u4ec0\u4e48\u662f-swagger"},"6.4 \u4ec0\u4e48\u662f Swagger"),(0,r.kt)("p",null,"\u76f8\u4fe1\u65e0\u8bba\u662f\u524d\u7aef\u8fd8\u662f\u540e\u7aef\u5f00\u53d1\uff0c\u90fd\u6216\u591a\u6216\u5c11\u5730\u88ab\u63a5\u53e3\u6587\u6863\u6298\u78e8\u8fc7\u3002\u524d\u7aef\u7ecf\u5e38\u62b1\u6028\u540e\u7aef\u7ed9\u7684\u63a5\u53e3\u6587\u6863\u4e0e\u5b9e\u9645\u60c5\u51b5\u4e0d\u4e00\u81f4\u3002\u540e\u7aef\u53c8\u89c9\u5f97\u7f16\u5199\u53ca\u7ef4\u62a4\u63a5\u53e3\u6587\u6863\u4f1a\u8017\u8d39\u4e0d\u5c11\u7cbe\u529b\uff0c\u7ecf\u5e38\u6765\u4e0d\u53ca\u66f4\u65b0\u3002"),(0,r.kt)("p",null,"\u5176\u5b9e\u65e0\u8bba\u662f\u524d\u7aef\u8c03\u7528\u540e\u7aef\uff0c\u8fd8\u662f\u540e\u7aef\u8c03\u7528\u540e\u7aef\uff0c\u90fd\u671f\u671b\u6709\u4e00\u4e2a\u597d\u7684\u63a5\u53e3\u6587\u6863\u3002\u4f46\u662f\u8fd9\u4e2a\u63a5\u53e3\u6587\u6863\u5bf9\u4e8e\u7a0b\u5e8f\u5458\u6765\u8bf4\uff0c\u5c31\u8ddf\u6ce8\u91ca\u4e00\u6837\uff0c\u7ecf\u5e38\u4f1a\u62b1\u6028\u522b\u4eba\u5199\u7684\u4ee3\u7801\u6ca1\u6709\u5199\u6ce8\u91ca\uff0c\u7136\u800c\u81ea\u5df1\u5199\u8d77\u4ee3\u7801\u8d77\u6765\uff0c\u6700\u8ba8\u538c\u7684\uff0c\u4e5f\u662f\u5199\u6ce8\u91ca\u3002\u6240\u4ee5\u4ec5\u4ec5\u53ea\u901a\u8fc7\u5f3a\u5236\u6765\u89c4\u8303\u5927\u5bb6\u662f\u4e0d\u591f\u7684\uff0c\u968f\u7740\u65f6\u95f4\u63a8\u79fb\uff0c\u7248\u672c\u8fed\u4ee3\uff0c\u63a5\u53e3\u6587\u6863\u5f80\u5f80\u5f88\u5bb9\u6613\u5c31\u8ddf\u4e0d\u4e0a\u4ee3\u7801\u4e86\u3002"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u53d1\u73b0\u4e86\u75db\u70b9\u5c31\u8981\u53bb\u627e\u89e3\u51b3\u65b9\u6848\u3002\u89e3\u51b3\u65b9\u6848\u7528\u7684\u4eba\u591a\u4e86\uff0c\u5c31\u6210\u4e86\u6807\u51c6\u7684\u89c4\u8303\uff0c\u8fd9\u5c31\u662f ",(0,r.kt)("inlineCode",{parentName:"strong"},"Swagger")," \u7684\u7531\u6765"),"\u3002"),(0,r.kt)("p",null,"\u901a\u8fc7\u8fd9\u5957\u89c4\u8303\uff0c\u4f60\u53ea\u9700\u8981\u6309\u7167\u5b83\u7684\u89c4\u8303\u53bb\u5b9a\u4e49\u63a5\u53e3\u53ca\u63a5\u53e3\u76f8\u5173\u7684\u4fe1\u606f\u3002\u518d\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u884d\u751f\u51fa\u6765\u7684\u4e00\u7cfb\u5217\u9879\u76ee\u548c\u5de5\u5177\uff0c\u5c31\u53ef\u4ee5\u505a\u5230\u751f\u6210\u5404\u79cd\u683c\u5f0f\u7684\u63a5\u53e3\u6587\u6863\uff0c\u751f\u6210\u591a\u79cd\u8bed\u8a00\u7684\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u7aef\u7684\u4ee3\u7801\uff0c\u4ee5\u53ca\u5728\u7ebf\u63a5\u53e3\u8c03\u8bd5\u9875\u9762\u7b49\u7b49\u3002"),(0,r.kt)("p",null,"\u8fd9\u6837\uff0c\u5982\u679c\u6309\u7167\u65b0\u7684\u5f00\u53d1\u6a21\u5f0f\uff0c\u5728\u5f00\u53d1\u65b0\u7248\u672c\u6216\u8005\u8fed\u4ee3\u7248\u672c\u7684\u65f6\u5019\uff0c\u53ea\u9700\u8981\u66f4\u65b0 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u63cf\u8ff0\u6587\u4ef6\uff0c\u5c31\u53ef\u4ee5\u81ea\u52a8\u751f\u6210\u63a5\u53e3\u6587\u6863\u548c\u5ba2\u6237\u7aef\u670d\u52a1\u7aef\u4ee3\u7801\uff0c\u505a\u5230\u8c03\u7528\u7aef\u4ee3\u7801\u3001\u670d\u52a1\u7aef\u4ee3\u7801\u4ee5\u53ca\u63a5\u53e3\u6587\u6863\u7684\u4e00\u81f4\u6027\u3002"),(0,r.kt)("p",null,"\u6240\u4ee5\uff0cSwagger \u662f\u4e00\u4e2a\u89c4\u8303\u548c\u5b8c\u6574\u7684\u6846\u67b6\uff0c\u7528\u4e8e\u751f\u6210\u3001\u63cf\u8ff0\u3001\u8c03\u7528\u548c\u53ef\u89c6\u5316",(0,r.kt)("inlineCode",{parentName:"p"},"RESTful")," \u98ce\u683c\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Web")," \u670d\u52a1\u3002"),(0,r.kt)("p",null,"\u603b\u4f53\u76ee\u6807\u662f\u4f7f\u5ba2\u6237\u7aef\u548c\u6587\u4ef6\u7cfb\u7edf\u4f5c\u4e3a\u670d\u52a1\u5668\u4ee5\u540c\u6837\u7684\u901f\u5ea6\u6765\u66f4\u65b0\u3002\u6587\u4ef6\u7684\u65b9\u6cd5\u3001\u53c2\u6570\u548c\u6a21\u578b\u7d27\u5bc6\u96c6\u6210\u5230\u670d\u52a1\u5668\u7aef\u7684\u4ee3\u7801\uff0c\u5141\u8bb8 API \u6765\u59cb\u7ec8\u4fdd\u6301\u540c\u6b65\u3002",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u8ba9\u90e8\u7f72\u7ba1\u7406\u548c\u4f7f\u7528\u529f\u80fd\u5f3a\u5927\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"API")," \u4ece\u672a\u5982\u6b64\u7b80\u5355\u3002"),(0,r.kt)("h2",{id:"65-swagger-\u4f7f\u7528"},"6.5 Swagger \u4f7f\u7528"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u975e\u5e38\u65b9\u4fbf\u4e14\u7075\u6d3b\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u914d\u7f6e\uff0c\u65e0\u9700\u589e\u52a0\u989d\u5916\u5b66\u4e60\u6210\u672c\u3002"),(0,r.kt)("h3",{id:"651-\u6ce8\u518c\u670d\u52a1"},"6.5.1 \u6ce8\u518c\u670d\u52a1"),(0,r.kt)("admonition",{title:"\u5907\u6ce8",type:"important"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},".UseInject()")," \u5df2\u7ecf\u5305\u542b\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},".UseSpecificationDocuments()")," \u6ce8\u518c\uff0c\u65e0\u9700\u518d\u6b21\u6ce8\u518c\u3002")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:'showLineNumbers {11,21} title="Furion.Web.Core\\FurWebCoreStartup.cs"',showLineNumbers:!0,"":!0,"{11,21}":!0,title:'"Furion.Web.Core\\FurWebCoreStartup.cs"'},"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Furion.Web.Core\n{\n [AppStartup(800)]\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddSpecificationDocuments();\n services.AddControllers();\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n // Other Codes\n\n app.UseSpecificationDocuments();\n\n app.UseEndpoints(endpoints =>\n {\n endpoints.MapControllers();\n });\n }\n }\n}\n")),(0,r.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"services.AddSpecificationDocuments()")," \u901a\u5e38\u548c ",(0,r.kt)("inlineCode",{parentName:"p"},".AddDynamicApiControllers()")," \u6210\u5bf9\u51fa\u73b0\u3002")),(0,r.kt)("h3",{id:"652-\u9ed8\u8ba4\u5730\u5740"},"6.5.2 \u9ed8\u8ba4\u5730\u5740"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"p"},"\u89c4\u8303\u5316\u6587\u6863")," \u5730\u5740\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"/api")," \u76ee\u5f55\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"),"\u3002"),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger1.png")}),(0,r.kt)("p",null,"\u53ef\u4ee5\u901a\u8fc7\u4e24\u79cd\u65b9\u5f0f\u914d\u7f6e\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},'app.UseInject("\u8def\u7531")')," \u65b9\u5f0f\uff0c\u5982")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'app.UseInject("testapi"); // \u90a3\u4e48 /testapi \u5c31\u662f\u89c4\u8303\u5316\u5730\u5740\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e"),"\uff1a")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},'{\n "SpecificationDocumentSettings": {\n "RoutePrefix": "testapi"\n }\n}\n')),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u914d\u7f6e\u6587\u4ef6\u4f18\u5148\u7ea7\u5927\u4e8e ",(0,r.kt)("inlineCode",{parentName:"strong"},"UseInject()")," \u65b9\u5f0f")),(0,r.kt)("h3",{id:"653-\u9ed8\u8ba4\u5206\u7ec4"},"6.5.3 \u9ed8\u8ba4\u5206\u7ec4"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\u9ed8\u8ba4\u5206\u7ec4\u540d\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"Default"),"\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"),"\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},'{\n "SpecificationDocumentSettings": {\n "DefaultGroupName": "MyGroup"\n }\n}\n')),(0,r.kt)("h3",{id:"654-\u6587\u6863\u6ce8\u91ca"},"6.5.4 \u6587\u6863\u6ce8\u91ca"),(0,r.kt)("p",null,"\u89c4\u8303\u5316\u6587\u6863\u9ed8\u8ba4\u626b\u63cf ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Application"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Web.Core"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Web.Entry")," \u4e09\u4e2a\u7a0b\u5e8f\u96c6",(0,r.kt)("inlineCode",{parentName:"p"},".xml")," \u6ce8\u91ca\u6587\u4ef6\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e"),"\u3002"),(0,r.kt)("p",null,"\u53ea\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"p"},"///")," \u6807\u8bc6\u7684\u6ce8\u91ca\u8bed\u6cd5\uff0c\u5982\uff1a",(0,r.kt)("strong",{parentName:"p"},"\u7c7b\u3001\u65b9\u6cd5\u3001\u5c5e\u6027\u3001\u53c2\u6570\u3001\u8fd4\u56de\u503c\u3001\u9a8c\u8bc1\u7279\u6027"),"\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5-7,10-13,19-23}",showLineNumbers:!0,"":!0,"{5-7,10-13,19-23}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n /// \n /// \u7c7b\u6ce8\u91ca\n /// \n public class FurionAppService : IDynamicApiController\n {\n /// \n /// \u65b9\u6cd5\u6ce8\u91ca\n /// \n /// \n public string Get()\n {\n return nameof(Furion);\n }\n\n /// \n /// \u5e26 ID \u53c2\u6570\u7684\u65b9\u6cd5\u6ce8\u91ca\n /// \n /// \n /// \n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger2.png")}),(0,r.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u5982\u679c\u6587\u6863\u6ce8\u91ca\u6ca1\u6709\u663e\u793a\uff0c\u8bf7\u68c0\u67e5\u9879\u76ee ",(0,r.kt)("inlineCode",{parentName:"p"},"\u5c5e\u6027->\u751f\u6210->\u8f93\u51fa")," \u4e2d XML \u6587\u6863\u662f\u5426\u914d\u7f6e\u8f93\u51fa\u8def\u5f84\u3002",(0,r.kt)("strong",{parentName:"p"},"\u6ce8\u610f\uff1a\u53ea\u6709\u4e0d\u5e26\u8def\u5f84\u7684 \u3010\u9879\u76ee\u540d\u79f0.xml\u3011 \u624d\u4f1a\u81ea\u52a8\u52a0\u8f7d\u3002"))),(0,r.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"info"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Debug")," \u6a21\u5f0f\u4e0b\u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"Release")," \u6a21\u5f0f\u4e0b\u7684\u6ce8\u91ca\u6587\u4ef6\u662f\u4e0d\u901a\u7528\u7684\uff0c\u6240\u4ee5\u5bfc\u81f4\u5f88\u591a\u5f00\u53d1\u8005\u53d1\u5e03\u5230\u670d\u52a1\u5668\u4e0a\u53d1\u73b0\u6ca1\u6709\u663e\u793a\u6ce8\u91ca\u3002\u6211\u4eec\u53ea\u9700\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Visual Studio")," \u4e2d\u5207\u6362 ",(0,r.kt)("inlineCode",{parentName:"p"},"Debug")," \u6a21\u5f0f\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"Release"),"\uff0c\u7136\u540e\u91cd\u65b0\u914d\u7f6e\u4e00\u6b21\u5373\u53ef\u3002"),(0,r.kt)("p",{parentName:"admonition"},"\u8fd9\u6837\u4e0d\u7ba1\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"Debug")," \u8fd8\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"Release")," \u6a21\u5f0f\u90fd\u4f1a\u663e\u793a\u6ce8\u91ca\u4e86\u3002")),(0,r.kt)("h3",{id:"655-\u591a\u5206\u7ec4\u652f\u6301"},"6.5.5 \u591a\u5206\u7ec4\u652f\u6301"),(0,r.kt)("p",null,"\u591a\u5206\u7ec4\u662f\u4e00\u4e2a\u7cfb\u7edf\u4e2d\u5fc5\u5907\u529f\u80fd\uff0c\u6211\u4eec\u53ef\u4ee5\u5c06\u7cfb\u7edf\u5212\u5206\u4e3a\u591a\u4e2a\u6a21\u5757\uff0c\u6bcf\u4e2a\u6a21\u5757\u90fd\u72ec\u7acb\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"api")," \u914d\u7f6e\u3002\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u5b9e\u73b0\u591a\u5206\u7ec4\u975e\u5e38\u7b80\u5355\u3002\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,21,32}",showLineNumbers:!0,"":!0,"{5,21,32}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings("Group1")]\n public class FurionAppService : IDynamicApiController\n {\n /// \n /// \u968f\u7236\u7c7b Group1 \u5206\u7ec4\n /// \n /// \n public string Post()\n {\n return nameof(Furion);\n }\n\n /// \n /// \u5728 Group1\u3001Group3 \u90fd\u6709\u6211\n /// \n /// \n [ApiDescriptionSettings("Group1", "Group3")]\n public string Get()\n {\n return nameof(Furion);\n }\n\n /// \n /// \u6211\u53ea\u5728 Group2 \u51fa\u73b0\n /// \n /// \n /// \n [ApiDescriptionSettings("Group2")]\n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger3.gif")}),(0,r.kt)("h3",{id:"656-\u591a\u5206\u7ec4\u6392\u5e8f"},"6.5.6 \u591a\u5206\u7ec4\u6392\u5e8f"),(0,r.kt)(o.Z,{defaultValue:"fz1",values:[{label:"\u65b9\u5f0f\u4e00",value:"fz1"},{label:"\u65b9\u5f0f\u4e8c",value:"fz2"}],mdxType:"Tabs"},(0,r.kt)(p.Z,{value:"fz1",mdxType:"TabItem"},(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u901a\u8fc7\u5206\u7ec4\u540d\u79f0\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"strong"},"@\u6574\u6570")," \u8fdb\u884c\u6392\u5e8f")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,19}",showLineNumbers:!0,"":!0,"{5,19}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings("Group1@1")]\n public class FurionAppService : IDynamicApiController\n {\n public string Post()\n {\n return nameof(Furion);\n }\n\n [ApiDescriptionSettings("Group1", "Group3")]\n public string Get()\n {\n return nameof(Furion);\n }\n\n [ApiDescriptionSettings("Group@2")]\n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,r.kt)("p",null,"\u53ef\u4ee5\u901a\u8fc7\u5728\u5206\u7ec4\u540d\u540e\u9762\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"@\u6574\u6570")," \u8fdb\u884c\u6392\u5e8f\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"\u6574\u6570")," \u8d8a\u5927\u6392\u524d\u9762\u3002\u5982\u679c\u5206\u7ec4\u540d\u79f0\u591a\u6b21\u6307\u5b9a\u4e14\u591a\u6b21\u6307\u5b9a\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"@\u6574\u6570")," \uff0c\u5219\u81ea\u52a8",(0,r.kt)("strong",{parentName:"p"},"\u53d6\u8be5\u5206\u7ec4\u6700\u5927\u7684\u6574\u6570"),"\u8fdb\u884c\u6392\u5e8f\u3002")),(0,r.kt)(p.Z,{value:"fz2",mdxType:"TabItem"},(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u901a\u8fc7\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e\u6392\u5e8f")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers {2-17} title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,"{2-17}":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "SpecificationDocumentSettings": {\n "GroupOpenApiInfos": [\n {\n "Group": "Group1",\n "Order": 1\n },\n {\n "Group": "Group2",\n "Order": 2\n },\n {\n "Group": "Group3",\n "Order": 0\n }\n ]\n }\n}\n')))),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger4.png")}),(0,r.kt)("admonition",{title:"\u6392\u5e8f\u8bf4\u660e",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"\u5206\u7ec4\u9ed8\u8ba4\u6392\u5e8f ",(0,r.kt)("inlineCode",{parentName:"p"},"Order")," \u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"0"),"\u3002\u5982\u679c\u540c\u65f6\u914d\u7f6e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"@\u6574\u6570")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u914d\u7f6e\u6587\u4ef6\uff0c\u90a3\u4e48\u4f18\u5148\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"appsettings.json")," \u4e2d\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Order"))),(0,r.kt)("h3",{id:"657-\u591a\u5206\u7ec4\u4fe1\u606f\u914d\u7f6e"},"6.5.7 \u591a\u5206\u7ec4\u4fe1\u606f\u914d\u7f6e"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u53ef\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"appsetting.json")," \u914d\u7f6e\u5206\u7ec4\u4fe1\u606f\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers {3-20} title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,"{3-20}":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "SpecificationDocumentSettings": {\n "GroupOpenApiInfos": [\n {\n "Group": "Group1",\n "Title": "\u5206\u7ec4\u6807\u9898",\n "Description": "\u8fd9\u91cc\u662f\u5206\u7ec4\u63cf\u8ff0",\n "Version": "\u7248\u672c\u53f7",\n "TermsOfService": "https://furion.icu",\n "Contact": {\n "Name": "\u767e\u5c0f\u50e7",\n "Url": "https://gitee.com/monksoul",\n "Email": "monksoul@outlook.com"\n },\n "License": {\n "Name": "MIT",\n "Url": "https://gitee.com/dotnetchina/Furion/blob/alpha/LICENSE"\n }\n }\n ]\n }\n}\n')),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger5.png")}),(0,r.kt)("h3",{id:"658-\u7ec4\u4e2d\u7ec4\u6807\u7b7e"},"6.5.8 \u7ec4\u4e2d\u7ec4\uff08\u6807\u7b7e\uff09"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Tag")," \u914d\u7f6e\u4e3b\u8981\u7528\u4e8e\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u6807\u7b7e\u5206\u7ec4\u4fe1\u606f\u53ca\u5408\u5e76\u6807\u7b7e\u3002\u4e5f\u5c31\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"\u7ec4\u4e2d\u7ec4"),":"),(0,r.kt)(o.Z,{defaultValue:"tag1",values:[{label:"\u6807\u7b7e\u547d\u540d",value:"tag1"},{label:"\u5408\u5e76\u6807\u7b7e",value:"tag2"}],mdxType:"Tabs"},(0,r.kt)(p.Z,{value:"tag1",mdxType:"TabItem"},(0,r.kt)("h4",{id:"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d"},"\u672a\u8d34\u6807\u7b7e\u4e4b\u524d"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n\n public class TestAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n}\n")),(0,r.kt)("h4",{id:"\u8d34\u6807\u7b7e\u4e4b\u540e"},"\u8d34\u6807\u7b7e\u4e4b\u540e"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,19}",showLineNumbers:!0,"":!0,"{5,19}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(Tag = "\u5206\u7ec4\u4e00")]\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n\n [ApiDescriptionSettings(Tag = "\u5206\u7ec4\u4e8c")]\n public class TestAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/tag1.png")})),(0,r.kt)(p.Z,{value:"tag2",mdxType:"TabItem"},(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,19}",showLineNumbers:!0,"":!0,"{5,19}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n [ApiDescriptionSettings(Tag = "\u5408\u5e76\u6240\u6709\u6807\u7b7e")]\n public class FurionAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n\n [ApiDescriptionSettings(Tag = "\u5408\u5e76\u6240\u6709\u6807\u7b7e")]\n public class TestAppService : IDynamicApiController\n {\n public string Get()\n {\n return nameof(Furion);\n }\n\n public int Get(int id)\n {\n return id;\n }\n }\n}\n')),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/tag2.png")}))),(0,r.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"\u5982\u679c ",(0,r.kt)("inlineCode",{parentName:"p"},"Tag")," \u540d\u5b57\u4e00\u6837\uff0c\u5219\u4f1a\u81ea\u52a8\u5408\u5e76\uff0c\u5426\u5219\u53ea\u662f\u547d\u540d\u3002")),(0,r.kt)("h3",{id:"659-\u9ed8\u8ba4\u5c55\u5f00\u6240\u6709\u6587\u6863"},"6.5.9 \u9ed8\u8ba4\u5c55\u5f00\u6240\u6709\u6587\u6863"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers {2-4} title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,"{2-4}":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "SpecificationDocumentSettings": {\n "DocExpansionState": "Full"\n }\n}\n')),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger6.gif")}),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"DocExpansionState")," \u914d\u7f6e\u8bf4\u660e\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"List"),"\uff1a\u5217\u8868\u5f0f\uff08\u5c55\u5f00\u5b50\u7c7b\uff09\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u9ed8\u8ba4\u503c")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Full"),"\uff1a\u5b8c\u5168\u5c55\u5f00"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"None"),"\uff1a\u5217\u8868\u5f0f\uff08\u4e0d\u5c55\u5f00\u5b50\u7c7b\uff09")),(0,r.kt)("h3",{id:"6510-\u914d\u7f6e\u6587\u6863\u6807\u9898"},"6.5.10 \u914d\u7f6e\u6587\u6863\u6807\u9898"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers {2-4} title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,"{2-4}":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "SpecificationDocumentSettings": {\n "DocumentTitle": "\u6211\u662f\u81ea\u5b9a\u4e49\u6807\u9898"\n }\n}\n')),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger7.png")}),(0,r.kt)("h3",{id:"6511-\u6388\u6743\u63a7\u5236"},"6.5.11 \u6388\u6743\u63a7\u5236"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u65b0\u7248\u672c ",(0,r.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5df2\u7ecf\u9ed8\u8ba4\u542f\u7528\u4e86 Bearer Token \u6388\u6743\u914d\u7f6e\uff0c\u65e0\u9700\u624b\u52a8\u914d\u7f6e"),"\uff0c\u5982\u9700\u624b\u52a8\u914d\u7f6e\uff0c\u53ef\u624b\u52a8\u6dfb\u52a0\u4ee5\u4e0b\u7c7b\u4f3c\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers title="Furion.Web.Entry/appsettings.json"',showLineNumbers:!0,"":!0,title:'"Furion.Web.Entry/appsettings.json"'},'{\n "SpecificationDocumentSettings": {\n "EnableAuthorized": true,\n\n "SecurityDefinitions": [\n {\n "Id": "Bearer",\n "Type": "Http",\n "Name": "Authorization",\n "Description": "JWT Authorization header using the Bearer scheme.",\n "BearerFormat": "JWT",\n "Scheme": "bearer",\n "In": "Header",\n\n "Requirement": {\n "Scheme": {\n "Reference": {\n "Id": "Bearer",\n "Type": "SecurityScheme"\n },\n "Accesses": []\n }\n }\n }\n ]\n }\n}\n')),(0,r.kt)("h3",{id:"6512-\u5728\u7ebf\u6d4b\u8bd5"},"6.5.12 \u5728\u7ebf\u6d4b\u8bd5"),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swagger8.gif")}),(0,r.kt)("h3",{id:"6513-\u6027\u80fd\u76d1\u89c6-miniprofiler"},"6.5.13 \u6027\u80fd\u76d1\u89c6 ",(0,r.kt)("inlineCode",{parentName:"h3"},"MiniProfiler")),(0,r.kt)("p",null,"\u89c4\u8303\u5316\u6587\u6863\u9ed8\u8ba4\u96c6\u6210\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"MiniProfiler")," \u7b2c\u4e09\u65b9\u6027\u80fd\u7ec4\u4ef6\uff0c\u901a\u8fc7\u8be5\u7ec4\u4ef6\u53ef\u4ee5\u65b9\u4fbf\u67e5\u770b\u8bf7\u6c42\u6027\u80fd\u3001\u5f02\u5e38\u5806\u6808\u3001\u6570\u636e\u5e93\u64cd\u4f5c\u7b49\u4fe1\u606f\u3002\u9ed8\u8ba4\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u9996\u9875\u5de6\u4e0a\u89d2\u663e\u793a\u3002"),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/mipr.png")}),(0,r.kt)("admonition",{title:"\u5c0f\u63d0\u793a",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u4e5f\u53ef\u4ee5\u901a\u8fc7 ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"appsetting.json"))," \u4e2d ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"AppSettings:InjectMiniProfiler"))," \u8bbe\u4e3a ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"false"))," \u5173\u95ed\u3002")),(0,r.kt)("h3",{id:"6514-\u5b9a\u4e49\u63a5\u53e3\u8f93\u51fa\u7c7b\u578b"},"6.5.14 \u5b9a\u4e49\u63a5\u53e3\u8f93\u51fa\u7c7b\u578b"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2,8-9}",showLineNumbers:!0,"":!0,"{2,8-9}":!0},"using Furion.DynamicApiController;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace Furion.Application\n{\n public class FurionAppService : IDynamicApiController\n {\n [ProducesResponseType(201, Type = typeof(TestDto))]\n [ProducesResponseType(400)]\n public string Get()\n {\n return nameof(Furion);\n }\n }\n}\n")),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/fhzlx.png")}),(0,r.kt)("h3",{id:"6515-\u9690\u85cf\u7279\u5b9a\u5206\u7ec4"},"6.5.15 \u9690\u85cf\u7279\u5b9a\u5206\u7ec4"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u65b0\u7248\u672c\u63d0\u4f9b\u4e86\u9690\u85cf\u5206\u7ec4\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Visible")," \u914d\u7f6e\uff0c\u8bbe\u7f6e\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"false")," \u4e4b\u540e\u8be5\u5206\u7ec4\u5c06\u4e0d\u663e\u793a\u5728\u89c4\u8303\u5316\u6587\u6863\u4e2d\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers title="appsetting.json"',showLineNumbers:!0,"":!0,title:'"appsetting.json"'},'{\n "SpecificationDocumentSettings": {\n "GroupOpenApiInfos": [\n {\n "Group": "Group1",\n "Visible": false\n }\n ]\n }\n}\n')),(0,r.kt)("h3",{id:"6516-\u4e2d\u6587\u4e71\u7801\u95ee\u9898"},"6.5.16 \u4e2d\u6587\u4e71\u7801\u95ee\u9898"),(0,r.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b,",(0,r.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u5e76\u672a\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"utf-8")," \u7f16\u7801\uff0c\u6240\u4ee5\u5982\u679c\u914d\u7f6e\u4e2d\u6587\u5206\u7ec4\u4fe1\u606f\u5c31\u4f1a\u51fa\u73b0\u4e71\u7801\u60c5\u51b5\uff0c\u8fd9\u65f6\u5019\uff0c\u53ea\u9700\u8981\u4fee\u6539 ",(0,r.kt)("inlineCode",{parentName:"p"},".json")," \u6587\u4ef6\u7f16\u7801\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"utf-8")," \u5373\u53ef\u3002"),(0,r.kt)("h3",{id:"6517-\u751f\u4ea7\u73af\u5883\u4e2d\u5173\u95ed-swagger"},"6.5.17 \u751f\u4ea7\u73af\u5883\u4e2d\u5173\u95ed ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")),(0,r.kt)("p",null,"\u5982\u679c\u4e0d\u9700\u8981\u7ebf\u4e0a\u73af\u5883\u5f00\u542f ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u529f\u80fd\uff0c\u53ea\u9700\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"appsetting.json")," \u914d\u7f6e\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},'{\n "AppSettings": {\n "InjectSpecificationDocument": false\n }\n}\n')),(0,r.kt)("h3",{id:"6518-\u8bbe\u7f6e-example-value-\u9ed8\u8ba4\u503c"},"6.5.18 \u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"h3"},"Example Value")," \u9ed8\u8ba4\u503c"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u4f1a\u81ea\u52a8\u6839\u636e\u5bf9\u8c61\u7c7b\u578b\u8f93\u5165\u53c2\u6570\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"Example Value")," \u9ed8\u8ba4\u503c\uff0c\u4f46\u662f\u8be5\u9ed8\u8ba4\u503c\u901a\u5e38\u662f\u5bf9\u8c61\u5c5e\u6027\u7684\u7c7b\u578b\u5b57\u7b26\u4e32\u6216\u7f3a\u7701\u503c\uff0c\u5982\u679c\u6211\u4eec\u9700\u8981\u81ea\u5b9a\u4e49\u8fd9\u4e9b\u9ed8\u8ba4\u503c\uff0c\u53ea\u9700\u8981\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"/// \u9ed8\u8ba4\u503c")," \u6ce8\u91ca\u5373\u53ef\u3002"),(0,r.kt)("p",null,"\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"/// \n/// \u5e74\u9f84\n/// \n/// 13\n[Required, Range(10, 110)]\npublic int Age { get; set; }\n")),(0,r.kt)("p",null,"\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/sd20.png")}),(0,r.kt)("p",null,"\u66f4\u591a\u7c7b\u578b\u9ed8\u8ba4\u503c\u8bbe\u7f6e\u793a\u4f8b\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"/// true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"/// foobar")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"number")," \u7c7b\u578b\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"/// 123")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"null")," \u7c7b\u578b\uff1a ",(0,r.kt)("inlineCode",{parentName:"li"},"/// null")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"array")," \u7c7b\u578b\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"/// [ 1, 2, 3 ]"))),(0,r.kt)("admonition",{type:"important"},(0,r.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"object")," \u7c7b\u578b\u8f93\u5165\u53c2\u6570"),(0,r.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Example Value")," \u4e0d\u4f1a\u663e\u793a ",(0,r.kt)("inlineCode",{parentName:"p"},"object")," \u7c7b\u578b\u7684\u5bf9\u8c61\u5c5e\u6027\uff0c\u56e0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u8ba4\u4e3a\u8fd9\u662f\u4e0d\u5408\u7406\u7684\u5b9a\u4e49\u3002\u5982\u679c\u9700\u8981\u5f3a\u5236\u663e\u793a\uff0c\u53ea\u9700\u8981\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},'/// "object"')," \u6ce8\u91ca\u5373\u53ef\u3002")),(0,r.kt)("h3",{id:"6519-\u81ea\u5b9a\u4e49-swagger-\u914d\u7f6e"},"6.5.19 \u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u914d\u7f6e"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u9664\u4e86\u5185\u7f6e\u4e86\u4e0d\u5c11\u914d\u7f6e\u4ee5\u5916\uff0c\u8fd8\u63d0\u4f9b\u4e86\u76f4\u63a5\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," Api \u7684\u53c2\u6570\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public void ConfigureServices(IServiceCollection services)\n{\n services.AddInject(options =>\n {\n options.SpecificationDocument = spt =>\n {\n spt.SwaggerGen = gen =>\n {\n // \u914d\u7f6e Swagger Gen\n };\n };\n });\n}\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0}," public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n app.UseInject(configure: options =>\n {\n options.SpecificationDocument = spt =>\n {\n spt.Swagger = swg =>\n {\n // \u914d\u7f6e Swagger Options\n };\n spt.SwaggerUI = ui =>\n {\n // \u914d\u7f6e Swagger UI\n };\n };\n });\n}\n\n")),(0,r.kt)("h3",{id:"6520-\u914d\u7f6e-swagger\u7684-schemes"},"6.5.20 \u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger"),"\u7684 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Schemes")),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u9ed8\u8ba4\u53ea\u663e\u793a\u540d\u79f0\uff0c\u5982\u679c\u9700\u8981\u81ea\u5b9a\u4e49\u663e\u793a\u89c4\u5219\uff0c\u53ea\u9700\u8981\u6dfb\u52a0\u914d\u7f6e\u5373\u53ef\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddControllersWithViews()\n .AddInject(options =>\n {\n options.SpecificationDocument = spt =>\n {\n spt.SwaggerGen = gen =>\n {\n gen.CustomSchemaIds(x => x.FullName);\n };\n };\n });\n")),(0,r.kt)("h3",{id:"6521-\u81ea\u5b9a\u4e49-swaggerjson-\u8def\u7531\u6a21\u677f"},"6.5.21 \u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"h3"},"swagger.json")," \u8def\u7531\u6a21\u677f"),(0,r.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4f1a\u751f\u6210\u7edf\u4e00\u7684\u5206\u7ec4\u6a21\u677f\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"swagger/{documentName}/swagger.json"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"{documentName}")," \u4f1a\u5728\u8fd0\u884c\u65f6\u66ff\u6362\u4e3a\u5206\u7ec4\u540d\uff0c\u5982\u9700\u81ea\u5b9a\u4e49\uff0c\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"RouteTemplate")," \u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'showLineNumbers title="appsetting.json"',showLineNumbers:!0,"":!0,title:'"appsetting.json"'},'{\n "SpecificationDocumentSettings": {\n "RouteTemplate": "myapp/{documentName}/xxxx.json"\n }\n}\n')),(0,r.kt)("h3",{id:"6522-\u5173\u4e8e-applicationx-www-form-urlencoded-\u8bf7\u6c42"},"6.5.22 \u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"h3"},"application/x-www-form-urlencoded")," \u8bf7\u6c42"),(0,r.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u5e76\u672a\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"application/x-www-form-urlencoded")," \u652f\u6301\uff0c\u5982\u9700\u542f\u7528\u8be5\u914d\u7f6e\uff0c\u53ea\u9700\u5728\u65b9\u6cd5\u9876\u90e8\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[Consumes]")," \u7279\u6027\u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,2}",showLineNumbers:!0,"":!0,"{1,2}":!0},'[Consumes("application/x-www-form-urlencoded")]\npublic async Task Test([FromForm] TestRequest testRequest)\n{\n // ....\n}\n\npublic class TestRequest\n{\n public string TestValue { get; set; }\n}\n')),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u53c2\u6570\u5fc5\u987b\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[FromForm]")," \u7279\u6027\u3002\u53e6\u5916\u8bf7\u6c42\u65f6\u5c06\u53c2\u6570\u6309 ",(0,r.kt)("inlineCode",{parentName:"p"},"URL")," \u5730\u5740\u62fc\u63a5\u5e76\u653e\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Body")," \u4e2d\u8bf7\u6c42\u3002")),(0,r.kt)("h3",{id:"6523-swagger-\u51fa\u73b0-cors-\u95ee\u9898\u89e3\u51b3"},"6.5.23 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u51fa\u73b0 ",(0,r.kt)("inlineCode",{parentName:"h3"},"CORS")," \u95ee\u9898\u89e3\u51b3"),(0,r.kt)("p",null,"\u5982\u679c ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u51fa\u73b0\u4ee5\u4e0b\u9519\u8bef\uff0c\u5982\u56fe\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/swerror.png")}),(0,r.kt)("p",null,"\u5219\u9700\u8981\u6dfb\u52a0\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2,3}",showLineNumbers:!0,"":!0,"{2,3}":!0},'{\n "SpecificationDocumentSettings": {\n "HideServers": true\n }\n}\n')),(0,r.kt)("h3",{id:"6524-swagger-\u51fa\u73b0\u9ed8\u8ba4-xml-\u53c2\u6570\u95ee\u9898\u89e3\u51b3"},"6.5.24 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u51fa\u73b0\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"h3"},"xml")," \u53c2\u6570\u95ee\u9898\u89e3\u51b3"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u4ea7\u751f\u6b64\u539f\u56e0\u6709\u4e24\u4e2a\u5fc5\u8981\u6761\u4ef6\uff1a")),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"\u4f7f\u7528\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"Microsoft.AspNetCore.Mvc.NewtonsoftJson")," \u5305\u5e76\u6dfb\u52a0\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},"AddNewtonsoftJson()")," \u6ce8\u518c\u3002"),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("inlineCode",{parentName:"li"},".AddNewtonsoftJson()")," \u5199\u5728\u4e86 ",(0,r.kt)("inlineCode",{parentName:"li"},".AddInjectWithUnifyResult()")," \u540e\u9762\u3002")),(0,r.kt)("p",null,"\u6240\u4ee5\u89e3\u51b3\u65b9\u6cd5\u662f\uff0c\u5148\u6ce8\u518c ",(0,r.kt)("inlineCode",{parentName:"p"},".AddNewtonsoftJson()")," \u518d\u6ce8\u518c\u89c4\u8303\u5316\u7ed3\u679c\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"":!0,"{2}":!0},"services.AddControllers()\n .AddNewtonsoftJson()\n .AddInjectWithUnifyResult();\n")),(0,r.kt)("h3",{id:"6525-swagger-\u591a\u8bed\u8a00\u652f\u6301"},"6.5.25 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u591a\u8bed\u8a00\u652f\u6301"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion 2.9.0 + ")," \u7248\u672c\u5df2\u7ecf\u652f\u6301\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u6587\u6863\u5730\u5740 ",(0,r.kt)("inlineCode",{parentName:"p"},"?culture=en-US")," \u53c2\u6570\u591a\u8bed\u8a00\u8f6c\u53d1\u529f\u80fd\u4e86\uff0c\u4e5f\u5c31\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u5730\u5740\u5e26 ",(0,r.kt)("inlineCode",{parentName:"p"},"?culture=")," \u53c2\u6570\u5c06\u81ea\u52a8\u6dfb\u52a0\u5230\u6bcf\u4e00\u4e2a\u8bf7\u6c42\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"api")," \u5730\u5740\u4e2d\u3002"),(0,r.kt)("h3",{id:"6526-\u81ea\u5b9a\u4e49\u903b\u8f91\u63a7\u5236-swagger-\u6bcf\u4e00\u4e2a-api-\u53ef\u89c1\u6027"},"6.5.26 \u81ea\u5b9a\u4e49\u903b\u8f91\u63a7\u5236 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u6bcf\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"h3"},"api")," \u53ef\u89c1\u6027"),(0,r.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u63a5\u53e3\u53ef\u89c1\u6027\uff0c\u6bd4\u5982\u6839\u636e\u6743\u9650\uff0c\u4e0d\u540c\u7528\u6237\u7c7b\u578b\uff0c\u5404\u79cd\u903b\u8f91\u63a7\u5236\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u4e5f\u53ef\u4ee5\u7528 .AddInjectWithUnifyResult\nservices.AddInject(options =>\n{\n options.SpecificationDocument = spt =>\n {\n spt.SwaggerGen = gen =>\n {\n gen.DocInclusionPredicate((currentGroup, apiDescription) =>\n {\n // Furion \u5185\u90e8\u68c0\u67e5\uff0c\u5fc5\u987b\u653e\u7b2c\u4e00\u884c\n var isShow = SpecificationDocumentBuilder.CheckApiDescriptionInCurrentGroup(currentGroup, apiDescription);\n\n // \u83b7\u53d6\u5f53\u524d\u65b9\u6cd5\n _ = apiDescription.TryGetMethodInfo(out var method);\n\n // \u6709\u4e86\u65b9\u6cd5\uff0c\u8fd9\u91cc\u505a\u4f60\u60f3\u505a\u7684\u4e8b\u60c5\uff0cisShow \u8bbe\u7f6e true \u53ef\u89c1\uff0c\u8bbe\u7f6e false \u4e0d\u53ef\u89c1\n\n return isShow;\n });\n };\n };\n});\n")),(0,r.kt)("h3",{id:"6527-\u914d\u7f6e-mvc-\u63a7\u5236\u5668\u652f\u6301\u89c4\u8303\u5316\u5904\u7406"},"6.5.27 \u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"h3"},"MVC")," \u63a7\u5236\u5668\u652f\u6301\u89c4\u8303\u5316\u5904\u7406"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "UnifyResultSettings": {\n "SupportMvcController": true\n }\n}\n')),(0,r.kt)("h3",{id:"6528-swagger-\u5237\u65b0\u8bb0\u4f4f\u6388\u6743\u72b6\u6001"},"6.5.28 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u5237\u65b0\u8bb0\u4f4f\u6388\u6743\u72b6\u6001"),(0,r.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u5237\u65b0\u6d4f\u89c8\u5668\u540e\uff0c\u6388\u6743\u72b6\u6001\u5c06\u88ab\u91cd\u7f6e\uff0c\u4e5f\u5c31\u662f\u9700\u8981\u91cd\u65b0\u767b\u5f55\uff0c\u901a\u8fc7\u4e0b\u9762\u4ee3\u7801\u5728 ",(0,r.kt)("strong",{parentName:"p"},"\u7528\u6237\u767b\u5f55\u6210\u529f\u540e")," \u8c03\u7528\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ....\u9a8c\u8bc1\u7528\u6237\u540d/\u5bc6\u7801....\n\n_httpContextAccessor.HttpContext.SigninToSwagger("\u4f20\u5165 token");\n')),(0,r.kt)("h3",{id:"6529-\u5e26\u767b\u5f55\u7684-swagger-\u6587\u6863"},"6.5.29 \u5e26\u767b\u5f55\u7684 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u6587\u6863"),(0,r.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion v3.3.3+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u662f\u4efb\u4f55\u4eba\u90fd\u53ef\u4ee5\u8bbf\u95ee\u7684\uff0c\u8fd9\u6837\u4e5f\u66b4\u9732\u51fa\u4e00\u4e9b\u5b89\u5168\u95ee\u9898\uff0c\u6240\u4ee5\u5728\u8be5\u7248\u672c\u4e4b\u540e\u6dfb\u52a0\u4e86\u767b\u5f55\u529f\u80fd\uff0c\u53ea\u9700\u8981\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"p"},"SpecificationDocumentSettings")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"LoginInfo")," \u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-6}",showLineNumbers:!0,"{2-6}":!0},'{\n "SpecificationDocumentSettings": {\n "LoginInfo": {\n "Enabled": true,\n "CheckUrl": "/Home/CheckUrl",\n "SubmitUrl": "/Home/SubmitUrl",\n "UserName": "admin",\n "Password": "admin"\n }\n }\n}\n')),(0,r.kt)("h4",{id:"\u914d\u7f6e\u8bf4\u660e"},"\u914d\u7f6e\u8bf4\u660e"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"LoginInfo"),"\uff1a\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u662f\u5426\u9700\u8981\u767b\u5f55\u624d\u80fd\u8bbf\u95ee\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationLoginInfo")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"null"),"\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u4ec5\u5728 Furion v3.3.3+` \u6709\u6548"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Enabled"),"\uff1a\u662f\u5426\u542f\u7528\u767b\u5f55\u6388\u6743\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"CheckUrl"),"\uff1a\u68c0\u67e5\u767b\u5f55\u72b6\u6001\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Url")," \u5730\u5740\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u8be5\u5730\u5740\u5fc5\u987b\u662f ",(0,r.kt)("inlineCode",{parentName:"strong"},"POST")," \u8bf7\u6c42"),"\uff0c\u5df2\u6388\u6743\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"200"),"\uff0c\u5426\u5219\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"401"),"\uff0c\u652f\u6301\u76f8\u5bf9\u5730\u5740\uff0c\u4ee5 ",(0,r.kt)("inlineCode",{parentName:"li"},"/")," \u5f00\u5934"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SubmitUrl"),"\uff1a\u63d0\u4ea4\u767b\u5f55\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Url")," \u5730\u5740\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u8be5\u5730\u5740\u5fc5\u987b\u662f ",(0,r.kt)("inlineCode",{parentName:"strong"},"POST")," \u8bf7\u6c42\u4e14\u53ea\u6709\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"strong"},"SpecificationAuth")," \u7c7b\u578b\u53c2\u6570"),"\uff0c\u6210\u529f\u767b\u5f55\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"200"),"\uff0c\u5426\u5219\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"401"),"\uff0c\u652f\u6301\u76f8\u5bf9\u5730\u5740\uff0c\u4ee5 ",(0,r.kt)("inlineCode",{parentName:"li"},"/")," \u5f00\u5934")))),(0,r.kt)("h4",{id:"\u914d\u7f6e\u793a\u4f8b"},"\u914d\u7f6e\u793a\u4f8b"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {10-14,16-31}",showLineNumbers:!0,"{10-14,16-31}":!0},'using Furion.SpecificationDocument;\nusing Microsoft.AspNetCore.Authorization;\nusing Microsoft.AspNetCore.Mvc;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Furion.Web.Entry.Controllers;\n\npublic class HomeController : Controller\n{\n [HttpPost, AllowAnonymous, NonUnify]\n public int CheckUrl()\n {\n return 401;\n }\n\n [HttpPost, AllowAnonymous, NonUnify]\n public int SubmitUrl([FromForm] SpecificationAuth auth)\n {\n // \u8bfb\u53d6\u914d\u7f6e\u4fe1\u606f\n var userName = App.Configuration["SpecificationDocumentSettings:LoginInfo:UserName"];\n var password = App.Configuration["SpecificationDocumentSettings:LoginInfo:Password"];\n\n if (auth.UserName == userName && auth.Password == password)\n {\n return 200;\n }\n else\n {\n return 401;\n }\n }\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/swgdl.png")}),(0,r.kt)("h2",{id:"6530-inheritdoc-\u5b9e\u73b0\u6ce8\u91ca\u7ee7\u627f"},"6.5.30 ",(0,r.kt)("inlineCode",{parentName:"h2"},"inheritdoc")," \u5b9e\u73b0\u6ce8\u91ca\u7ee7\u627f"),(0,r.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion v3.3.3+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u5728\u8fc7\u53bb\u6211\u4eec\u5728\u63a5\u53e3\u5b9a\u4e49\u7684\u65f6\u5019\u7f16\u5199\u4e86\u5b8c\u6574\u7684\u6210\u5458\u6ce8\u91ca\uff0c\u7136\u540e\u5728\u6d3e\u751f\u6210\u5458\u4e2d\u53c8\u8981\u91cd\u590d\u5199\u4e00\u6b21\uff0c\u5b9e\u9645\u4e0a\u505a\u4e86\u5f88\u5927\u65e0\u7528\u529f\uff0c\u73b0\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u652f\u6301\u4e86\u6ce8\u91ca\u7ee7\u627f\u4e86\uff0c\u540c\u65f6 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u4e2d\u4e5f\u80fd\u6b63\u786e\u663e\u793a\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5,8,14}",showLineNumbers:!0,"{5,8,14}":!0},'using Furion.DynamicApiController;\n\nnamespace Furion.Application\n{\n /// \n public class TestInheritdoc : ITestInheritdoc, IDynamicApiController\n {\n /// \n public string GetName()\n {\n return "Furion";\n }\n\n /// \n public string GetVersion()\n {\n return "3.3.3";\n }\n }\n\n /// \n /// \u6d4b\u8bd5\u6ce8\u91ca\u7ee7\u627f\n /// \n public interface ITestInheritdoc\n {\n /// \n /// \u83b7\u53d6\u540d\u79f0\n /// \n /// \n string GetName();\n\n /// \n /// \u83b7\u53d6\u7248\u672c\n /// \n /// \n string GetVersion();\n }\n}\n\n')),(0,r.kt)("p",null,"\u663e\u793a\u6548\u679c\uff1a"),(0,r.kt)("img",{src:(0,l.Z)("img/cdr22.png")}),(0,r.kt)("admonition",{title:"\u6ce8\u610f\u4e8b\u9879",type:"important"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"")," \u4e0d\u6307\u5b9a ",(0,r.kt)("inlineCode",{parentName:"p"},"cref")," ",(0,r.kt)("strong",{parentName:"p"},"\u4ec5\u9650\u6210\u5458\u53ef\u7528"),"\u4e14\u6240\u5728\u7684\u7c7b\u578b\u5fc5\u987b\u6307\u5b9a ",(0,r.kt)("inlineCode",{parentName:"p"},''),"\uff0c\u8fd9\u6837\u624d\u80fd\u81ea\u52a8\u8bc6\u522b\u3002")),(0,r.kt)("h3",{id:"6531-\u542f\u7528-all-groups-\u5206\u7ec4\u529f\u80fd"},"6.5.31 \u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"h3"},"All Groups")," \u5206\u7ec4\u529f\u80fd"),(0,r.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion v3.3.4+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u4e3a\u4e86\u66f4\u597d\u7684\u5bf9\u63a5\u53e3\u8fdb\u884c\u5f52\u7c7b\uff0c\u914d\u7f6e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u591a\u4e2a\u5206\u7ec4\u7684\u529f\u80fd\uff0c\u4f46\u8fd9\u6837\u4e5f\u5bf9\u751f\u6210\u5ba2\u6237\u7aef\u8bf7\u6c42\u4ee3\u7801\u9020\u6210\u4e86\u56f0\u6270\uff0c\u6240\u4ee5\u6dfb\u52a0\u4e86\u65b0\u7684\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {2-3}",showLineNumbers:!0,"{2-3}":!0},'{\n "SpecificationDocumentSettings": {\n "EnableAllGroups": true\n }\n}\n')),(0,r.kt)("h3",{id:"6532-\u63a5\u53e3\u8fc7\u65f6\u63a7\u5236"},"6.5.32 \u63a5\u53e3\u8fc7\u65f6\u63a7\u5236"),(0,r.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion v3.3.5+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u67d0\u4e2a\u63a5\u53e3\u5df2\u7ecf\u8fc7\u65f6\uff0c\u63d0\u793a\u5c3d\u65e9\u8c03\u7528\u6700\u65b0\u63a5\u53e3\uff0c\u53ea\u9700\u8981\u5728\u65b9\u6cd5\u4e0a\u9762\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[Obsolete]")," \u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,7}",showLineNumbers:!0,"{1,7}":!0},'[Obsolete("GetName() \u5df2\u7ecf\u8fc7\u65f6\uff0c\u8bf7\u8c03\u7528 GetFrameworkName() \u66ff\u4ee3")]\npublic string GetName()\n{\n return nameof(Furion);\n}\n\n[Obsolete]\npublic string Other()\n{\n // ...\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/swg2.png")}),(0,r.kt)("h3",{id:"6533-\u5355\u4e00\u63a5\u53e3\u66f4\u591a\u63cf\u8ff0"},"6.5.33 \u5355\u4e00\u63a5\u53e3\u66f4\u591a\u63cf\u8ff0"),(0,r.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion v3.3.5+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u5728\u8be5\u7248\u672c\u65b0\u589e\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"[ApiDescriptionSettings]")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Description")," \u5c5e\u6027\uff0c\u652f\u6301\u5b9a\u4e49\u66f4\u591a\u63cf\u8ff0\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"{1}":!0},'[ApiDescriptionSettings(Description = "\u6211\u662f\u4e00\u6bb5\u63cf\u8ff0\uff0c\u663e\u793a\u66f4\u591a\u5185\u5bb9 ")]\npublic string add()\n{\n //....\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/swg1.png")}),(0,r.kt)("h3",{id:"6534-swagger-\u5f02\u5e38\u4e0d\u80fd\u663e\u793a\u9519\u8bef\u5904\u7406"},"6.5.34 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u5f02\u5e38/\u4e0d\u80fd\u663e\u793a/\u9519\u8bef\u5904\u7406"),(0,r.kt)("p",null,"\u6709\u65f6\u5019\u53ef\u80fd\u56e0\u4e3a\u9519\u8bef\u7684\u914d\u7f6e\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u4e0d\u80fd\u663e\u793a\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u590d\u5236\u63d0\u793a\u7684\u9519\u8bef ",(0,r.kt)("inlineCode",{parentName:"p"},".json")," \u94fe\u63a5\u5730\u5740\u5230\u6d4f\u89c8\u5668\u4e2d\u8bbf\u95ee\u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"https://localhost:\u4f60\u7684\u7aef\u53e3/swagger/Default/swagger.json\n")),(0,r.kt)("p",null,"\u540e\u9762\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"/swagger/Default/swagger.json")," \u5c31\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u9519\u8bef\u63d0\u793a\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},".json")," \u94fe\u63a5\u5730\u5740\u3002"),(0,r.kt)("p",null,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u770b\u5230\u8be6\u7ec6\u7684\u9519\u8bef\u4e86\u3002"),(0,r.kt)("img",{src:(0,l.Z)("img/sperr.png")}),(0,r.kt)("img",{src:(0,l.Z)("img/sperr2.png")}),(0,r.kt)("h3",{id:"6535-\u81ea\u5b9a\u4e49-swagger-\u7684-schemaid"},"6.5.35 \u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"h3"},"SchemaId")),(0,r.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion v3.6.4+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u6709\u65f6\u5019\uff0c\u4e0d\u540c\u7a0b\u5e8f\u96c6\u4f1a\u5b9a\u4e49\u76f8\u540c\u7684\u7c7b\u578b\u540d\u79f0 ",(0,r.kt)("inlineCode",{parentName:"p"},"Name"),"\uff0c\u8fd9\u6837\u5c31\u4f1a\u5bfc\u81f4\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"SchemaId")," \u51fa\u73b0\u51b2\u7a81\uff0c\u8fd9\u65f6\u53ea\u9700\u8981\u5728\u7c7b\u578b\u4e0a\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[SchemaId]")," \u7279\u6027\u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"{3}":!0},'using Furion.SpecificationDocument;\n\n[SchemaId("Other_")]\npublic class PersonDto\n{\n // ...\n}\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SchemaIdAttribute")," \u914d\u7f6e\u9009\u9879\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SchemaId"),"\uff1a\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"li"},"SchemaId"),"\uff0c\u5b57\u7b26\u4e32\u7c7b\u578b\uff0c\u53ea\u80fd\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"\u5b57\u6bcd,\u6570\u5b57\uff0c\u4e0b\u5212\u7ebf")," \u7ec4\u5408"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Replace"),"\uff1a\u662f\u5426\u5b8c\u5168\u66ff\u6362\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false"),"\uff0c\u9ed8\u8ba4\u662f\u4f5c\u4e3a\u524d\u7f00\u62fc\u63a5\uff0c\u5982\u4e0a\u9762\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"PersonDto")," \u4f1a\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},"Other_PersonDto"),"\uff0c\u5982\u679c\u8bbe\u7f6e\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"true"),"\uff0c\u5219\u76f4\u63a5\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Test_"))))),(0,r.kt)("h3",{id:"6536-\u81ea\u5b9a\u4e49-swagger-\u7684-operationid"},"6.5.36 \u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"h3"},"OperationId")),(0,r.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion 4.1.7+")," \u7248\u672c\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u901a\u8fc7\u6211\u4eec\u6839\u636e ",(0,r.kt)("inlineCode",{parentName:"p"},"swagger.json")," \u751f\u6210\u524d\u7aef\u4ee3\u7801\u65f6\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Swagger")," \u4f1a\u81ea\u52a8\u6839\u636e\u8def\u7531\u5730\u5740\u751f\u6210\u8c03\u7528\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"api")," \u540d\u79f0\uff0c\u4f46\u8fd9\u6837\u7684\u540d\u79f0\u5f80\u5f80\u4e0d\u6613\u8bfb\uff0c\u8fd9\u65f6\u5019\u53ef\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"p"},"[OperationId]")," \u6765\u914d\u7f6e\u751f\u6210\u7684\u524d\u7aef\u540d\u79f0\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {5}",showLineNumbers:!0,"{5}":!0},'using Furion.SpecificationDocument;\n\npublic class PersonDto\n{\n [OperationId("MyClientMethodName")]\n public string TestMethod()\n {\n // ...\n }\n}\n')),(0,r.kt)("h3",{id:"6537-swagger-\u63a5\u53e3\u6587\u6863\u652f\u6301\u5b8c\u6574\u7684-markdown"},"6.5.37 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Swagger")," \u63a5\u53e3\u6587\u6863\u652f\u6301\u5b8c\u6574\u7684 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Markdown")),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6700\u65b0\u7248\u4e2d\uff0c\u652f\u6301\u4e86\u5b8c\u6574\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Markdown")," \u6ce8\u518c\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,80}",showLineNumbers:!0,"{4,80}":!0},'/// \n/// \u6d4b\u8bd5 Markdown\n/// \n/// \n/// # \u5148\u77e5 / Furion ([\u63a2\u7d22\u7248](https://gitee.com/dotnetchina/Furion/tree/experimental/))\n///\n/// \u4e00\u4e2a\u5e94\u7528\u7a0b\u5e8f\u6846\u67b6\uff0c\u60a8\u53ef\u4ee5\u5c06\u5b83\u96c6\u6210\u5230\u4efb\u4f55.NET/C# \u5e94\u7528\u7a0b\u5e8f\u4e2d\u3002\n///\n/// An application framework that you can integrate into any.NET/C# application.\n///\n/// ## \u5b89\u88c5 / Installation\n///\n/// - [Package Manager] (https://www.nuget.org/packages/Furion)\n///\n/// ```powershell\n/// Install-Package Furion\n/// ```\n///\n/// - [.NET CLI] (https://www.nuget.org/packages/Furion)\n///\n/// ```powershell\n/// dotnet add package Furion\n/// ```\n///\n/// ## \u4f8b\u5b50 / Examples\n///\n/// \u6211\u4eec\u5728[\u4e3b\u9875](https://dotnetchina.gitee.io/furion)\u4e0a\u6709\u4e0d\u5c11\u4f8b\u5b50\uff0c\u8fd9\u662f\u8ba9\u60a8\u5165\u95e8\u7684\u7b2c\u4e00\u4e2a\uff1a\n///\n/// We have several examples [on the website] (https://dotnetchina.gitee.io/furion). Here is the first one to get you started:\n///\n/// ```cs\n/// Serve.Run();\n///\n/// [DynamicApiController]\n/// public class HelloService\n/// {\n/// public string Say()\n/// {\n/// return "Hello, Furion";\n/// }\n/// }\n/// ```\n///\n/// \u6253\u5f00\u6d4f\u89c8\u5668\u8bbf\u95ee `https://localhost:5001`\u3002\n///\n/// Open browser access `https://localhost:5001`.\n///\n/// ## \u6587\u6863 / Documentation\n///\n/// \u60a8\u53ef\u4ee5\u5728[\u4e3b\u9875] (https://dotnetchina.gitee.io/furion)\u6216[\u5907\u4efd\u4e3b\u9875](https://furion.icu)\u627e\u5230 Furion \u6587\u6863\u3002\n///\n/// You can find the Furion documentation[on the website](https://dotnetchina.gitee.io/furion) or [on the backup website](https://furion.icu).\n///\n/// ## \u8d21\u732e / Contributing\n///\n/// \u8be5\u5b58\u50a8\u5e93\u7684\u4e3b\u8981\u76ee\u7684\u662f\u7ee7\u7eed\u53d1\u5c55 Furion \u6838\u5fc3\uff0c\u4f7f\u5176\u66f4\u5feb\u3001\u66f4\u6613\u4e8e\u4f7f\u7528\u3002 Furion \u7684\u5f00\u53d1\u5728[Gitee](https://gitee.com/dotnetchina/Furion) \u4e0a\u516c\u5f00\u8fdb\u884c\uff0c\u6211\u4eec\u611f\u8c22\u793e\u533a\u8d21\u732e\u9519\u8bef\u4fee\u590d\u548c\u6539\u8fdb\u3002\n///\n/// \u9605\u8bfb[\u8d21\u732e\u6307\u5357] (https://dotnetchina.gitee.io/furion/docs/contribute)\u5185\u5bb9\uff0c\u4e86\u89e3\u5982\u4f55\u53c2\u4e0e\u6539\u8fdb Furion\u3002\n///\n/// The main purpose of this repository is to continue evolving Furion core, making it faster and easier to use.Development of Furion happens in the open on[Gitee] (https://gitee.com/dotnetchina/Furion), and we are grateful to the community for contributing bugfixes and improvements.\n///\n/// Read[contribution documents] (https://dotnetchina.gitee.io/furion/docs/contribute) to learn how you can take part in improving Furion.\n///\n/// ## \u8bb8\u53ef\u8bc1 / License\n///\n/// Furion \u91c7\u7528[MIT](https://gitee.com/dotnetchina/Furion/blob/net6/LICENSE) \u5f00\u6e90\u8bb8\u53ef\u8bc1\u3002\n///\n/// Furion uses the[MIT] (https://gitee.com/dotnetchina/Furion/blob/net6/LICENSE) open source license.\n///\n/// ```\n/// Copyright(c) 2020-2022 \u767e\u5c0f\u50e7, Baiqian Co., Ltd.\n/// Furion is licensed under Mulan PSL v2.\n/// You can use this software according to the terms andconditions of the Mulan PSL v2.\n/// You may obtain a copy of Mulan PSL v2 at:\n/// https://gitee.com/dotnetchina/Furion/blob/net6/LICENSE\n/// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUTWARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.\n/// See the Mulan PSL v2 for more details.\n/// ```\n///\n/// \n/// \npublic string Hello()\n{\n return "Furion";\n}\n')),(0,r.kt)("img",{src:(0,l.Z)("img/mdx.png")}),(0,r.kt)("h2",{id:"66-specificationdocumentsettings-\u914d\u7f6e"},"6.6 ",(0,r.kt)("inlineCode",{parentName:"h2"},"SpecificationDocumentSettings")," \u914d\u7f6e"),(0,r.kt)("p",null,"\u9664\u4e86\u4e0a\u8ff0\u4f8b\u5b50\u5916\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u4e00\u4e9b\u914d\u7f6e\u9009\u9879\uff0c\u5982\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DocumentTitle"),"\uff1a\u6587\u6863\u6807\u9898\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Specification Api Document")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DefaultGroupName"),"\uff1a\u9ed8\u8ba4\u5206\u7ec4\u540d\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Default")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EnableAuthorized"),"\uff1a\u662f\u5426\u542f\u7528\u6743\u9650\u63a7\u5236\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"FormatAsV2"),"\uff1a\u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger 2.0")," \u7248\u672c\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false")," ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("a",{parentName:"strong",href:"https://github.com/domaindrivendev/Swashbuckle.WebApi/issues/1393"},"\u5df2\u5f03\u7528"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"RoutePrefix"),"\uff1a\u89c4\u8303\u5316\u6587\u6863\u5730\u5740\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"api"),"\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u5982\u679c\u5e0c\u671b\u5728\u9996\u9875\uff0c\u6539\u4e3a\u7a7a\u5b57\u7b26\u4e32\u5373\u53ef"),"\u3002"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"DocExpansionState"),"\uff1a\u6587\u6863\u663e\u793a\u65b9\u5f0f\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"DocExpansion"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"List"),"\uff0c\u53d6\u503c\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"List"),"\uff1a\u5217\u8868\u5f0f\uff08\u5c55\u5f00\u5b50\u7c7b\uff09\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u9ed8\u8ba4\u503c")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Full"),"\uff1a\u5b8c\u5168\u5c55\u5f00"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"None"),"\uff1a\u5217\u8868\u5f0f\uff08\u4e0d\u5c55\u5f00\u5b50\u7c7b\uff09"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"XmlComments"),"\uff1a\u7a0b\u5e8f\u96c6\u6ce8\u91ca\u63cf\u8ff0\u6587\u4ef6\u540d\uff08\u53ef\u5e26 ",(0,r.kt)("inlineCode",{parentName:"li"},".xml"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"Furion.Application, Furion.Web.Entry, Furion.Web.Core")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"GroupOpenApiInfos"),"\uff1a\u5206\u7ec4\u4fe1\u606f\u914d\u7f6e\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationOpenApiInfo[]"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"{ 'Group': 'Default'}")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SecurityDefinitions"),"\uff1a\u5b89\u5168\u7b56\u7565\u5b9a\u4e49\u914d\u7f6e\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationOpenApiSecurityScheme[]"),"\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"[]")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Servers"),"\uff1a\u914d\u7f6e Server \u4e0b\u62c9\u5217\u8868\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"OpenApiServer[]")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"[]"),"\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},'{Servers:[ { Url:"\u5730\u5740", Description:"\u63cf\u8ff0"} ]}')),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"HideServers"),"\uff1a\u662f\u5426\u9690\u85cf Server \u4e0b\u62c9\u5217\u8868\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"RouteTemplate"),"\uff1a\u914d\u7f6e\u6587\u6863 ",(0,r.kt)("inlineCode",{parentName:"li"},"swagger.json")," \u8def\u7531\u6a21\u677f\uff0c\u9ed8\u8ba4\u6a21\u677f\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"swagger/{documentName}/swagger.json"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"{documentName}")," \u4ee3\u8868\u5206\u7ec4\u540d\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u5fc5\u987b\u4fdd\u7559\u539f\u6837")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"PackagesGroups"),"\uff1a\u914d\u7f6e\u6a21\u5757\u5316\u5185\u7f6e\u5206\u7ec4\u540d\u79f0\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string[]")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"[]")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EnableEnumSchemaFilter"),"\uff1a\u542f\u7528\u679a\u4e3e Schema \u7b5b\u9009\u5668\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EnableTagsOrderDocumentFilter"),"\uff1a\u542f\u7528\u6807\u7b7e\u6392\u5e8f\u7b5b\u9009\u5668\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ServerDir"),"\uff1a\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"IIS")," \u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Application")," \u90e8\u7f72\u540d\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u9ed8\u8ba4\u7a7a\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u4ec5\u5728 Furion v3.2.0+` \u6709\u6548")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"LoginInfo"),"\uff1a\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u662f\u5426\u9700\u8981\u767b\u5f55\u624d\u80fd\u8bbf\u95ee\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"SpecificationLoginInfo")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"null"),"\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u4ec5\u5728 Furion v3.3.3+` \u6709\u6548"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Enabled"),"\uff1a\u662f\u5426\u542f\u7528\u767b\u5f55\u6388\u6743\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"CheckUrl"),"\uff1a\u68c0\u67e5\u767b\u5f55\u72b6\u6001\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Url")," \u5730\u5740\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u8be5\u5730\u5740\u5fc5\u987b\u662f ",(0,r.kt)("inlineCode",{parentName:"strong"},"POST")," \u8bf7\u6c42"),"\uff0c\u5df2\u6388\u6743\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"200"),"\uff0c\u5426\u5219\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"401")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SubmitUrl"),"\uff1a\u63d0\u4ea4\u767b\u5f55\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Url")," \u5730\u5740\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u8be5\u5730\u5740\u5fc5\u987b\u662f ",(0,r.kt)("inlineCode",{parentName:"strong"},"POST")," \u8bf7\u6c42\u4e14\u53ea\u6709\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"strong"},"SpecificationAuth")," \u7c7b\u578b\u53c2\u6570"),"\uff0c\u6210\u529f\u767b\u5f55\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"200"),"\uff0c\u5426\u5219\u8fd4\u56de ",(0,r.kt)("inlineCode",{parentName:"li"},"401"),"\uff0c\u652f\u6301\u76f8\u5bf9\u5730\u5740\uff0c\u4ee5 ",(0,r.kt)("inlineCode",{parentName:"li"},"/")," \u5f00\u5934"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"EnableAllGroups"),"\uff1a\u542f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"Swagger")," \u603b\u5206\u7ec4\u529f\u80fd\uff0c\u81ea\u52a8\u5c06\u6240\u6709\u5206\u7ec4\u7684\u63a5\u53e3\u5408\u5e76\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"All Groups")," \u4e2d\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"false"),"\uff0c",(0,r.kt)("strong",{parentName:"li"},"\u4ec5\u5728 Furion v3.3.4+` \u6709\u6548"))),(0,r.kt)("p",null,"\u53e6\u5916 ",(0,r.kt)("inlineCode",{parentName:"p"},"SpecificationOpenApiInfo")," \u5185\u7f6e\u914d\u7f6e\u5982\u4e0b\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Group"),"\uff1a\u5206\u7ec4\u552f\u4e00\u6807\u8bc6\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b\uff0c\u5fc5\u586b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Order"),"\uff1a\u5206\u7ec4\u6392\u5e8f\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"int")," \u7c7b\u578b\uff0c\u6570\u5b57\u8d8a\u5927\u6392\u524d\u9762\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"0")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Visible"),"\uff1a\u914d\u7f6e\u5206\u7ec4\u662f\u5426\u53ef\u89c1\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"bool")," \u7c7b\u578b\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Title"),"\uff1a\u914d\u7f6e\u5206\u7ec4\u6807\u9898\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Description"),"\uff1a\u914d\u7f6e\u5206\u7ec4\u63cf\u8ff0\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"string")," \u7c7b\u578b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Version"),"\uff1a\u914d\u7f6e\u5206\u7ec4\u7248\u672c\uff0c\u9ed8\u8ba4 ",(0,r.kt)("inlineCode",{parentName:"li"},"1.0")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"TermsOfService"),"\uff1a\u914d\u7f6e\u76f8\u5173\u94fe\u63a5\u5730\u5740\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"Uri")," \u7c7b\u578b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Contact"),"\uff1a\u914d\u7f6e\u8054\u7cfb\u65b9\u5f0f\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"OpenApiContact")," \u7c7b\u578b"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"License"),"\uff1a\u914d\u7f6e\u534f\u8bae\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"OpenApiLicense")," \u7c7b\u578b")),(0,r.kt)("p",null,"\u914d\u7f6e\u793a\u4f8b\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "SpecificationDocumentSettings": {\n "GroupOpenApiInfos": [\n {\n "Group": "Group1",\n "Title": "\u5206\u7ec4\u6807\u9898",\n "Description": "\u8fd9\u91cc\u662f\u5206\u7ec4\u63cf\u8ff0",\n "Version": "\u7248\u672c\u53f7",\n "TermsOfService": "https://furion.icu",\n "Contact": {\n "Name": "\u767e\u5c0f\u50e7",\n "Url": "https://gitee.com/monksoul",\n "Email": "monksoul@outlook.com"\n },\n "License": {\n "Name": "MIT",\n "Url": "https://gitee.com/dotnetchina/Furion/blob/alpha/LICENSE"\n }\n }\n ]\n }\n}\n')),(0,r.kt)("h2",{id:"67-\u7edf\u4e00\u8fd4\u56de\u503c\u6a21\u578b\u89c4\u8303\u5316\u7ed3\u679capi-\u8fd4\u56de\u503c"},"6.7 \u7edf\u4e00\u8fd4\u56de\u503c\u6a21\u578b/\u89c4\u8303\u5316\u7ed3\u679c/API \u8fd4\u56de\u503c"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b ",(0,r.kt)("inlineCode",{parentName:"p"},"\u89c4\u8303\u5316\u7ed3\u679c")," \u529f\u80fd\uff0c\u53ef\u4ee5\u901a\u8fc7\u5b9e\u73b0 ",(0,r.kt)("inlineCode",{parentName:"p"},"IUnifyResultProvider")," \u63d0\u4f9b\u5668\u5b9e\u73b0\u7edf\u4e00\u89c4\u8303\u5316\u8fd4\u56de\u503c\u5b9a\u5236\uff0c\u5982\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"\u5b9a\u4e49\u7ed3\u679c\u5305\u88c5\u7c7b\u578b"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1-2}",showLineNumbers:!0,"{1-2}":!0},"// \u5fc5\u987b\u662f\u6cdb\u578b\u7c7b\u578b\npublic class YourRESTfulResult\n{\n /// \n /// \u72b6\u6001\u7801\n /// \n public int? StatusCode { get; set; }\n\n /// \n /// \u6570\u636e\n /// \n public T Data { get; set; }\n\n /// \n /// \u6267\u884c\u6210\u529f\n /// \n public bool Succeeded { get; set; }\n\n /// \n /// \u9519\u8bef\u4fe1\u606f\n /// \n public object Errors { get; set; }\n\n /// \n /// \u9644\u52a0\u6570\u636e\n /// \n public object Extras { get; set; }\n\n /// \n /// \u65f6\u95f4\u6233\n /// \n public long Timestamp { get; set; }\n}\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"strong"},"IUnifyResultProvider")," \u5b9e\u73b0\u7c7b\uff0c\u5e76\u8d34\u7279\u6027 ",(0,r.kt)("inlineCode",{parentName:"strong"},"[UnifyModel(typeof(YourRESTfulResult<>))]")))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {15-16,24,35,46,58}",showLineNumbers:!0,"":!0,"{15-16,24,35,46,58}":!0},'using Furion.DataValidation;\nusing Furion.DependencyInjection;\nusing Furion.UnifyResult.Internal;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Mvc;\nusing Microsoft.AspNetCore.Mvc.Filters;\nusing System;\nusing System.Threading.Tasks;\n\nnamespace YourProject.UnifyResult\n{\n /// \n /// RESTful \u98ce\u683c\u8fd4\u56de\u503c\n /// \n [UnifyModel(typeof(YourRESTfulResult<>))]\n public class YourRESTfulResultProvider : IUnifyResultProvider\n {\n /// \n /// \u5f02\u5e38\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata)\n {\n return new JsonResult(YourRESTfulResult(metadata.StatusCode, errors: metadata.Errors));\n }\n\n /// \n /// \u6210\u529f\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n public IActionResult OnSucceeded(ActionExecutedContext context, object data)\n {\n return new JsonResult(YourRESTfulResult(StatusCodes.Status200OK, true, data));\n }\n\n /// \n /// \u9a8c\u8bc1\u5931\u8d25\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n public IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata)\n {\n return new JsonResult(YourRESTfulResult(metadata.StatusCode ?? StatusCodes.Status400BadRequest, errors: metadata.ValidationResult));\n }\n\n /// \n /// \u7279\u5b9a\u72b6\u6001\u7801\u8fd4\u56de\u503c\n /// \n /// \n /// \n /// \n /// \n public async Task OnResponseStatusCodes(HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings)\n {\n // \u8bbe\u7f6e\u54cd\u5e94\u72b6\u6001\u7801\n UnifyContext.SetResponseStatusCodes(context, statusCode, unifyResultSettings);\n\n switch (statusCode)\n {\n // \u5904\u7406 401 \u72b6\u6001\u7801\n case StatusCodes.Status401Unauthorized:\n await context.Response.WriteAsJsonAsync(YourRESTfulResult(statusCode, errors: "401 Unauthorized")\n , App.GetOptions()?.JsonSerializerOptions);\n break;\n // \u5904\u7406 403 \u72b6\u6001\u7801\n case StatusCodes.Status403Forbidden:\n await context.Response.WriteAsJsonAsync(YourRESTfulResult(statusCode, errors: "403 Forbidden")\n , App.GetOptions()?.JsonSerializerOptions);\n break;\n default: break;\n }\n }\n\n /// \n /// \u8fd4\u56de RESTful \u98ce\u683c\u7ed3\u679c\u96c6\n /// \n /// \n /// \n /// \n /// \n /// \n private static YourRESTfulResult YourRESTfulResult(int statusCode, bool succeeded = default, object data = default, object errors = default)\n {\n return new YourRESTfulResult\n {\n StatusCode = statusCode,\n Succeeded = succeeded,\n Data = data,\n Errors = errors,\n Extras = UnifyContext.Take(),\n Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()\n };\n }\n }\n}\n')),(0,r.kt)("p",null,"\u4e4b\u540e\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddControllers()\n .AddInjectWithUnifyResult();\n")),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u89c4\u8303\u5316\u7ed3\u679c\u4e0d\u4f1a\u5bf9 ",(0,r.kt)("inlineCode",{parentName:"p"},"401")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"403"),"\u3001",(0,r.kt)("inlineCode",{parentName:"p"},"404")," \u72b6\u6001\u7801\u8fdb\u884c\u89c4\u8303\u5316\u5904\u7406\uff0c\u5982\u9700\u542f\u52a8\u8be5\u72b6\u6001\u7801\u5904\u7406\uff0c\u53ea\u9700\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Configure")," \u4e2d\u542f\u7528\u63a5\u53e3\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n{\n if (env.IsDevelopment())\n {\n app.UseDeveloperExceptionPage();\n }\n // \u6dfb\u52a0\u89c4\u8303\u5316\u7ed3\u679c\u72b6\u6001\u7801\uff0c\u9700\u8981\u5728\u8fd9\u91cc\u6ce8\u518c\n app.UseUnifyResultStatusCodes();\n // \u5176\u4ed6\u6ce8\u518c...\n}\n"))),(0,r.kt)("h3",{id:"671-\u6392\u9664\u89c4\u8303\u5316\u5904\u7406"},"6.7.1 \u6392\u9664\u89c4\u8303\u5316\u5904\u7406"),(0,r.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u67d0\u4e9b\u63a5\u53e3\u4e0d\u9700\u8981\u8fdb\u884c\u89c4\u8303\u5316\u5904\u7406\uff0c\u8fd9\u65f6\uff0c\u6211\u4eec\u53ea\u9700\u8981\u5e16 ",(0,r.kt)("inlineCode",{parentName:"p"},"[NonUnify]")," \u7279\u6027\u5373\u53ef\u3002"),(0,r.kt)("h3",{id:"672-\u89c4\u8303\u5316\u7ed3\u679c\u6dfb\u52a0\u989d\u5916\u6570\u636e"},"6.7.2 \u89c4\u8303\u5316\u7ed3\u679c\u6dfb\u52a0\u989d\u5916\u6570\u636e"),(0,r.kt)("p",null,"\u9ed8\u8ba4\u7684\u89c4\u8303\u5316\u7ed3\u679c\u4e2d\u5305\u542b ",(0,r.kt)("inlineCode",{parentName:"p"},"extras")," \u5c5e\u6027\uff0c\u53ef\u4ee5\u914d\u7f6e\u989d\u5916\u6570\u636e\u8fd4\u56de\u5230\u5ba2\u6237\u7aef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'UnifyContext.Fill(new { Message = "\u64cd\u4f5c\u6210\u529f" });\n')),(0,r.kt)("h3",{id:"673-\u81ea\u5b9a\u4e49\u7279\u522b\u63a5\u53e3\u89c4\u8303\u5316\u7ed3\u679c"},"6.7.3 \u81ea\u5b9a\u4e49\u7279\u522b\u63a5\u53e3\u89c4\u8303\u5316\u7ed3\u679c"),(0,r.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u7279\u5b9a\u63a5\u53e3\u9700\u8fd4\u56de\u7279\u5b9a\u7684\u63a5\u53e3\u7c7b\u578b\uff0c\u65e0\u9700\u89c4\u8303\u5316\u5904\u7406\uff0c\u8fd9\u65f6\u5019\u6211\u4eec\u53ea\u9700\u8981\u8d34 ",(0,r.kt)("inlineCode",{parentName:"p"},"[UnifyResult(typeof(\u7ed3\u679c\u7c7b))]")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"[ProducesResponseType(typeof(\u7ed3\u679c\u7c7b),200)]"),"\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"[UnifyResult(typeof(Person))]\npublic Person GetPerson(int id)\n{\n // ...\n}\n")),(0,r.kt)("h2",{id:"68-\u53cd\u9988\u4e0e\u5efa\u8bae"},"6.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,r.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}N.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/adf0697d.8c4636c6.js b/handbook/build/assets/js/adf0697d.8c4636c6.js deleted file mode 100644 index 9437dae06d..0000000000 --- a/handbook/build/assets/js/adf0697d.8c4636c6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[7400],{6991:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return m},default:function(){return N},frontMatter:function(){return p},metadata:function(){return s},toc:function(){return d}});var a=n(3117),l=n(102),r=(n(7294),n(3905)),o=n(1402),i=["components"],p={id:"dotnet-tools",title:"37. \u7f16\u5199\u5305\u7ba1\u7406\u5de5\u5177",sidebar_label:"37. \u7f16\u5199\u5305\u7ba1\u7406\u5de5\u5177 (Tools)"},m=void 0,s={unversionedId:"dotnet-tools",id:"dotnet-tools",title:"37. \u7f16\u5199\u5305\u7ba1\u7406\u5de5\u5177",description:"",source:"@site/docs/dotnet-tools.mdx",sourceDirName:".",slug:"/dotnet-tools",permalink:"/furion/docs/dotnet-tools",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dotnet-tools.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1661482799,formattedLastUpdatedAt:"Aug 26, 2022",frontMatter:{id:"dotnet-tools",title:"37. \u7f16\u5199\u5305\u7ba1\u7406\u5de5\u5177",sidebar_label:"37. \u7f16\u5199\u5305\u7ba1\u7406\u5de5\u5177 (Tools)"},sidebar:"docs",previous:{title:"36.4 \u5e76\u53d1\u6d4b\u8bd5",permalink:"/furion/docs/bingfa"},next:{title:"38. \u8d21\u732e\u6307\u5357",permalink:"/furion/docs/contribute"}},u={},d=[{value:"37.1 \u5173\u4e8e\u5305\u7ba1\u7406\u5de5\u5177",id:"371-\u5173\u4e8e\u5305\u7ba1\u7406\u5de5\u5177",level:2},{value:"37.1.2 dotnet tools \u5305\u7ba1\u7406\u597d\u5904",id:"3712-dotnet-tools-\u5305\u7ba1\u7406\u597d\u5904",level:3},{value:"37.2 \u4e86\u89e3\u5305\u547d\u4ee4\u8bed\u6cd5",id:"372-\u4e86\u89e3\u5305\u547d\u4ee4\u8bed\u6cd5",level:2},{value:"37.2.1 \u77ed\u53c2\u6570\u4f8b\u5b50",id:"3721-\u77ed\u53c2\u6570\u4f8b\u5b50",level:3},{value:"37.2.2 \u957f\u53c2\u6570\u4f8b\u5b50",id:"3722-\u957f\u53c2\u6570\u4f8b\u5b50",level:3},{value:"37.2.3 \u6df7\u5408\u53c2\u6570\u4f8b\u5b50",id:"3723-\u6df7\u5408\u53c2\u6570\u4f8b\u5b50",level:3},{value:"37.2.4 \u591a\u4e2a\u503c\u53c2\u6570",id:"3724-\u591a\u4e2a\u503c\u53c2\u6570",level:3},{value:"37.2.5 \u64cd\u4f5c\u7b26",id:"3725-\u64cd\u4f5c\u7b26",level:3},{value:"37.3 \u7f16\u5199\u7b2c\u4e00\u4e2a\u5305",id:"373-\u7f16\u5199\u7b2c\u4e00\u4e2a\u5305",level:2},{value:"37.3.1 \u521b\u5efa HelloTools \u63a7\u5236\u53f0\u5e94\u7528",id:"3731-\u521b\u5efa-hellotools-\u63a7\u5236\u53f0\u5e94\u7528",level:3},{value:"37.3.2 \u7f16\u8f91 HelloTools.csproj",id:"3732-\u7f16\u8f91-hellotoolscsproj",level:3},{value:"\u914d\u7f6e\u5173\u952e\u8282\u70b9\u8bf4\u660e",id:"\u914d\u7f6e\u5173\u952e\u8282\u70b9\u8bf4\u660e",level:4},{value:"37.3.3 \u5b89\u88c5 Furion.Tools.CommandLine \u5305",id:"3733-\u5b89\u88c5-furiontoolscommandline-\u5305",level:3},{value:"37.3.4 \u7f16\u5199\u903b\u8f91\u4ee3\u7801",id:"3734-\u7f16\u5199\u903b\u8f91\u4ee3\u7801",level:3},{value:"37.3.5 \u5982\u4f55\u8c03\u8bd5\u5305\u5de5\u5177 \ud83d\udc4f",id:"3735-\u5982\u4f55\u8c03\u8bd5\u5305\u5de5\u5177-",level:3},{value:"37.3.6 \u6d4b\u8bd5\u5404\u4e2a\u53c2\u6570\u60c5\u51b5",id:"3736-\u6d4b\u8bd5\u5404\u4e2a\u53c2\u6570\u60c5\u51b5",level:3},{value:"37.4 \u6253\u5305\uff08\u672c\u673a\uff09\u6d4b\u8bd5",id:"374-\u6253\u5305\u672c\u673a\u6d4b\u8bd5",level:2},{value:"37.4.1 \u5168\u5c40\u6253\u5305\u5b89\u88c5",id:"3741-\u5168\u5c40\u6253\u5305\u5b89\u88c5",level:3},{value:"\u2714 \u5b89\u88c5\u5168\u5c40\u5305",id:"-\u5b89\u88c5\u5168\u5c40\u5305",level:4},{value:"\u2714 \u6d4b\u8bd5\u5168\u5c40\u5305",id:"-\u6d4b\u8bd5\u5168\u5c40\u5305",level:4},{value:"\u2714 \u66f4\u65b0\u5168\u5c40\u5305",id:"-\u66f4\u65b0\u5168\u5c40\u5305",level:4},{value:"\u2714 \u5378\u8f7d\u5168\u5c40\u5305",id:"-\u5378\u8f7d\u5168\u5c40\u5305",level:4},{value:"37.4.2 \u672c\u5730\u6253\u5305\u5b89\u88c5",id:"3742-\u672c\u5730\u6253\u5305\u5b89\u88c5",level:3},{value:"\u2714 \u521b\u5efa\u672c\u5730\u6e05\u5355\u6587\u4ef6",id:"-\u521b\u5efa\u672c\u5730\u6e05\u5355\u6587\u4ef6",level:4},{value:"\u2714 \u5b89\u88c5\u672c\u5730\u5305",id:"-\u5b89\u88c5\u672c\u5730\u5305",level:4},{value:"\u2714 \u6d4b\u8bd5\u672c\u5730\u5305",id:"-\u6d4b\u8bd5\u672c\u5730\u5305",level:4},{value:"\u2714 \u66f4\u65b0\u672c\u5730\u5305",id:"-\u66f4\u65b0\u672c\u5730\u5305",level:4},{value:"\u2714 \u5378\u8f7d\u672c\u5730\u5305",id:"-\u5378\u8f7d\u672c\u5730\u5305",level:4},{value:"37.5 \u53d1\u5e03\u5230 Nuget \u5e73\u53f0 \ud83d\udc4f",id:"375-\u53d1\u5e03\u5230-nuget-\u5e73\u53f0-",level:2},{value:"\u2714 \u5b89\u88c5 Nuget \u5305\u5230\u672c\u5730",id:"-\u5b89\u88c5-nuget-\u5305\u5230\u672c\u5730",level:4},{value:"37.6 Cli \u9759\u6001\u7c7b\u8bf4\u660e",id:"376-cli-\u9759\u6001\u7c7b\u8bf4\u660e",level:2},{value:"37.6.1 \u6d88\u606f\u7c7b",id:"3761-\u6d88\u606f\u7c7b",level:3},{value:"37.6.2 \u5de5\u5177\u7c7b",id:"3762-\u5de5\u5177\u7c7b",level:3},{value:"37.6.2 \u4fe1\u606f\u7c7b",id:"3762-\u4fe1\u606f\u7c7b",level:3},{value:"37.6.3 \u5176\u4ed6\u7c7b",id:"3763-\u5176\u4ed6\u7c7b",level:3},{value:"37.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"377-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],k={toc:d};function N(e){var t=e.components,n=(0,l.Z)(e,i);return(0,r.kt)("wrapper",(0,a.Z)({},k,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"371-\u5173\u4e8e\u5305\u7ba1\u7406\u5de5\u5177"},"37.1 \u5173\u4e8e\u5305\u7ba1\u7406\u5de5\u5177"),(0,r.kt)("p",null,"\u4f7f\u7528\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"NodeJs")," \u7684\u670b\u53cb\u4e00\u5b9a\u5bf9 ",(0,r.kt)("inlineCode",{parentName:"p"},"npm")," \u547d\u4ee4\u4e0d\u4f1a\u964c\u751f\uff0c\u53ef\u4ee5\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"npm")," \u5b89\u88c5\u9879\u76ee\u9700\u8981\u7684\u5305\u6216\u73af\u5883\u9700\u8981\u7684\u5de5\u5177\uff0c\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET Core 2.1+")," \u4e4b\u540e\uff0c\u5fae\u8f6f\u4e5f\u63a8\u51fa\u4e86\u65b0\u7684\u7279\u6027\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Global/Local Tools"),"\uff0c\u8be5\u7279\u6027\u529f\u80fd\u4e5f\u6b63\u662f\u53d7\u5230 ",(0,r.kt)("inlineCode",{parentName:"p"},"npm")," \u542f\u53d1\u4e0b\u8bde\u751f\u7684\u3002"),(0,r.kt)("p",null,"\u4e0d\u540c\u7684\u662f\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"npm")," \u4e2d\u7684\u5305\u91c7\u7528\u7684\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"Javascript")," \u7f16\u5199\u5e76\u53d1\u5e03\u5230 ",(0,r.kt)("a",{parentName:"p",href:"https://www.npmjs.com/"},"https://www.npmjs.com/")," \u5e73\u53f0\uff0c\u800c ",(0,r.kt)("inlineCode",{parentName:"p"},"dotnet tools")," \u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"C#")," \u7f16\u5199\u5e76\u53d1\u5e03\u5230 ",(0,r.kt)("inlineCode",{parentName:"p"},"https://www.nuget.org/")," \u5e73\u53f0\u4f9b\u5b89\u88c5\u4f7f\u7528\u3002"),(0,r.kt)("h3",{id:"3712-dotnet-tools-\u5305\u7ba1\u7406\u597d\u5904"},"37.1.2 ",(0,r.kt)("inlineCode",{parentName:"h3"},"dotnet tools")," \u5305\u7ba1\u7406\u597d\u5904"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u8de8\u5e73\u53f0\uff0c\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Linux/Mac/Windows")," \u5e73\u53f0\u4f9b\u5b89\u88c5\u4f7f\u7528"),(0,r.kt)("li",{parentName:"ul"},"\u5b8c\u6574\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"C#")," \u751f\u6001\u652f\u6301"),(0,r.kt)("li",{parentName:"ul"},"\u4e3a\u6240\u6b32\u4e3a~~~\uff08\u62e5\u6709\u64cd\u4f5c\u7cfb\u7edf\u7684\u6743\u9650\uff09")),(0,r.kt)("h2",{id:"372-\u4e86\u89e3\u5305\u547d\u4ee4\u8bed\u6cd5"},"37.2 \u4e86\u89e3\u5305\u547d\u4ee4\u8bed\u6cd5"),(0,r.kt)("p",null,"\u901a\u5e38\u5305\u547d\u4ee4\u8bed\u6cd5\u90fd\u9075\u5faa\u4ee5\u4e0b\u89c4\u5219\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"<-|--|/>argument-name<=|:| >[\"|']value['|\"] [--] [operand] ... [operand]\n")),(0,r.kt)("p",null,"\u5728\u8fd9\u91cc\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u5c06\u7b80\u5355\u4ecb\u7ecd\u547d\u4ee4\u5e38\u7528\u7684\u77e5\u8bc6\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u5de5\u5177\u7b26"),"\uff1a\u901a\u5e38\u6307\u7684\u662f\u4f60\u5de5\u5177\u7684\u552f\u4e00\u540d\u79f0\uff0c\u4e5f\u5c31\u662f\u5173\u952e\u5b57\uff0c\u800c\u4e14\u603b\u662f\u5728\u6700\u5f00\u5934\u7f16\u5199\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"dotnet"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"npm"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"node")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u77ed\u53c2\u6570"),"\uff1a\u77ed\u53c2\u6570\u6307\u7684\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"\u5355\u4e2a\u5b57\u7b26")," \u7684\u5b57\u7b26\u4e32\uff0c\u6211\u4eec\u901a\u5e38\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"-")," \u4e00\u4e2a\u6a2a\u6746\u6307\u5b9a\u53c2\u6570\u53ca\u503c\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"-v")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"li"},"-v 0.0.1")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u957f\u53c2\u6570"),"\uff1a\u957f\u53c2\u6570\u6307\u7684\u662f\u4e00\u4e2a\u6216\u591a\u4e2a\u5355\u8bcd\u8fde\u63a5\u7684\u5b57\u7b26\u4e32\uff0c\u8be5\u53c2\u6570\u901a\u5e38\u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"\u77ed\u53c2\u6570")," \u540c\u65f6\u5b58\u5728\uff0c\u901a\u5e38\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"--")," \u6307\u5b9a\u53c2\u6570\u53ca\u503c\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"--version")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"li"},"--version 0.0.1")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u64cd\u4f5c\u7b26"),"\uff1a\u5b57\u7b26\u4e32\u4e2d\u4e0e\u53c2\u6570\u503c\u683c\u5f0f\u4e0d\u5339\u914d\u7684\u4efb\u4f55\u6587\u672c\u90fd\u88ab\u89c6\u4e3a\u64cd\u4f5c\u6570\uff0c\u4efb\u4f55\u51fa\u73b0\u5728\u53cc\u8fde\u5b57\u7b26 ",(0,r.kt)("inlineCode",{parentName:"li"},"--")," \u4e4b\u540e\u4e14\u672a\u5305\u542b\u5728\u5355\u5f15\u53f7\u6216\u53cc\u5f15\u53f7\u4e2d\u4e14\u4e24\u4fa7\u6709\u7a7a\u683c\u7684\u6587\u672c\u90fd\u88ab\u89c6\u4e3a\u64cd\u4f5c\u6570\uff0c\u65e0\u8bba\u5b83\u662f\u5426\u4e0e\u53c2\u6570\u503c\u683c\u5f0f\u5339\u914d\uff0c\u901a\u5e38\u7528\u4e8e\u5f52\u7c7b/\u5206\u7c7b\u4f5c\u7528\u3002")),(0,r.kt)("h3",{id:"3721-\u77ed\u53c2\u6570\u4f8b\u5b50"},"37.2.1 \u77ed\u53c2\u6570\u4f8b\u5b50"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"-a foo"))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u77ed\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"a"),(0,r.kt)("td",{parentName:"tr",align:null},"foo")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"-ab"))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u77ed\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"a"),(0,r.kt)("td",{parentName:"tr",align:null})),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"b"),(0,r.kt)("td",{parentName:"tr",align:null})))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"-abc bar"))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u77ed\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"a"),(0,r.kt)("td",{parentName:"tr",align:null})),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"b"),(0,r.kt)("td",{parentName:"tr",align:null})),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"c"),(0,r.kt)("td",{parentName:"tr",align:null},"bar")))),(0,r.kt)("h3",{id:"3722-\u957f\u53c2\u6570\u4f8b\u5b50"},"37.2.2 \u957f\u53c2\u6570\u4f8b\u5b50"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"--foo bar"))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u957f\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"foo"),(0,r.kt)("td",{parentName:"tr",align:null},"bar")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"--foo --bar"))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u957f\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"foo"),(0,r.kt)("td",{parentName:"tr",align:null})),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"bar"),(0,r.kt)("td",{parentName:"tr",align:null})))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"--foo bar --hello world"))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u957f\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"foo"),(0,r.kt)("td",{parentName:"tr",align:null},"bar")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"hello"),(0,r.kt)("td",{parentName:"tr",align:null},"world")))),(0,r.kt)("h3",{id:"3723-\u6df7\u5408\u53c2\u6570\u4f8b\u5b50"},"37.2.3 \u6df7\u5408\u53c2\u6570\u4f8b\u5b50"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},'-abc foo --hello world /new="slashes are ok too"'))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u77ed/\u957f\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"a"),(0,r.kt)("td",{parentName:"tr",align:null})),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"b"),(0,r.kt)("td",{parentName:"tr",align:null})),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"c"),(0,r.kt)("td",{parentName:"tr",align:null},"foo")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"hello"),(0,r.kt)("td",{parentName:"tr",align:null},"world")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"new"),(0,r.kt)("td",{parentName:"tr",align:null},"slashes are ok too")))),(0,r.kt)("h3",{id:"3724-\u591a\u4e2a\u503c\u53c2\u6570"},"37.2.4 \u591a\u4e2a\u503c\u53c2\u6570"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"--list 1 --list 2 --list 3"))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u957f\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"list"),(0,r.kt)("td",{parentName:"tr",align:null},"1,2,3")))),(0,r.kt)("h3",{id:"3725-\u64cd\u4f5c\u7b26"},"37.2.5 \u64cd\u4f5c\u7b26"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},'-a foo bar "hello world" -b -- -explicit operand'))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u77ed\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"a"),(0,r.kt)("td",{parentName:"tr",align:null},"foo")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"b"),(0,r.kt)("td",{parentName:"tr",align:null})))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u64cd\u4f5c\u7b26"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"bar")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},'"hello world"')),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"-explicit")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"operand")))),(0,r.kt)("p",null,"\u4e86\u89e3\u66f4\u591a\u5173\u4e8e\u5305\u547d\u4ee4\u8bed\u6cd5\u7684\u5b98\u65b9\u77e5\u8bc6\uff1a",(0,r.kt)("a",{parentName:"p",href:"https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html"},"https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html")),(0,r.kt)("h2",{id:"373-\u7f16\u5199\u7b2c\u4e00\u4e2a\u5305"},"37.3 \u7f16\u5199\u7b2c\u4e00\u4e2a\u5305"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"dotnet tools")," \u5de5\u5177\u5b9e\u9645\u4e0a\u662f\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"p"},"\u63a7\u5236\u53f0")," \u5e94\u7528\u7a0b\u5e8f\uff0c\u4e0d\u540c\u7684\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},".csproj")," \u9879\u76ee\u6587\u4ef6\u9700\u8981\u6dfb\u52a0\u7279\u5b9a\u914d\u7f6e\u3002\u4e0b\u9762\u5c06\u7ed9\u5927\u5bb6\u7f16\u5199\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"p"},"HelloTools")," \u5305\u7ba1\u7406\u5de5\u5177\u3002"),(0,r.kt)("h3",{id:"3731-\u521b\u5efa-hellotools-\u63a7\u5236\u53f0\u5e94\u7528"},"37.3.1 \u521b\u5efa ",(0,r.kt)("inlineCode",{parentName:"h3"},"HelloTools")," \u63a7\u5236\u53f0\u5e94\u7528"),(0,r.kt)("img",{src:(0,o.Z)("img/ts1.png")}),(0,r.kt)("h3",{id:"3732-\u7f16\u8f91-hellotoolscsproj"},"37.3.2 \u7f16\u8f91 ",(0,r.kt)("inlineCode",{parentName:"h3"},"HelloTools.csproj")),(0,r.kt)("p",null,"\u5c06\u63a7\u5236\u53f0\u9879\u76ee\u6807\u8bb0\u6210 ",(0,r.kt)("inlineCode",{parentName:"p"},"dotnet tools")," \u9700\u8981\u914d\u7f6e\u4ee5\u4e0b\u8282\u70b9\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-xml",metastring:"showLineNumbers {6-11}",showLineNumbers:!0,"":!0,"{6-11}":!0},'\n\n \n Exe\n net5.0\n 0.0.1\n \u7b2c\u4e00\u4e2a dotnet tools \u5de5\u5177\n hello-tools\n true\n true\n ./nupkg\n \n\n\n')),(0,r.kt)("h4",{id:"\u914d\u7f6e\u5173\u952e\u8282\u70b9\u8bf4\u660e"},"\u914d\u7f6e\u5173\u952e\u8282\u70b9\u8bf4\u660e"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Version"),"\uff1a\u5305\u5de5\u5177\u7248\u672c\u53f7"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Description"),"\uff1a\u5305\u5de5\u5177\u4ecb\u7ecd"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ToolCommandName"),"\uff1a\u5305\u5de5\u5177\u5173\u952e\u5b57\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"li"},"dotnet"),"\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"npm"),"\uff0c\u540e\u7eed\u4f7f\u7528\u90fd\u662f\u901a\u8fc7\u8be5\u5173\u952e\u5b57\u4f7f\u7528"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"PackAsTool"),"\uff1a\u662f\u5426\u58f0\u660e\u4e3a\u5305\u7ba1\u7406\u5de5\u5177\uff0c\u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"GeneratePackageOnBuild"),"\uff1a\u662f\u5426\u7f16\u8bd1\u65f6\u81ea\u52a8\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},".nupkg")," \u5305\uff0c\u65b9\u4fbf\u540e\u7eed\u4e0a\u4f20\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"Nuget")," \u5e73\u53f0"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"PackageOutputPath"),"\uff1a\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},".nupkg")," \u5305\u5b58\u50a8\u76ee\u5f55\uff0c\u63a8\u8350\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"./nupkg"))),(0,r.kt)("h3",{id:"3733-\u5b89\u88c5-furiontoolscommandline-\u5305"},"37.3.3 \u5b89\u88c5 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Furion.Tools.CommandLine")," \u5305"),(0,r.kt)("p",null,"\u4e3a\u4e86\u65b9\u4fbf\u7ba1\u7406\u5de5\u5177\u5305\u5f00\u53d1\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u5b98\u65b9\u7279\u610f\u5f00\u53d1\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Tools.CommandLine")," \u5305\uff0c\u5e2e\u52a9\u5927\u5bb6\u5feb\u901f\u5f00\u53d1\u7ba1\u7406\u5de5\u5177\u5305\u3002"),(0,r.kt)("img",{src:(0,o.Z)("img/ts2.png")}),(0,r.kt)("h3",{id:"3734-\u7f16\u5199\u903b\u8f91\u4ee3\u7801"},"37.3.4 \u7f16\u5199\u903b\u8f91\u4ee3\u7801"),(0,r.kt)("p",null,"\u6211\u4eec\u5148\u5b9a\u4e49\u51e0\u4e2a\u9700\u6c42\uff0c\u7136\u540e\u7f16\u5199\u903b\u8f91\u4ee3\u7801\uff1a"),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u4e00\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"hello-tools")," \u6253\u5370\u4ecb\u7ecd\u4fe1\u606f"),(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u4e8c\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"-n")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"--name")," \u8f93\u51fa ",(0,r.kt)("inlineCode",{parentName:"p"},"Hello \u540d\u5b57")),(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u4e09\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"-v")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"--version")," \u8f93\u51fa\u5f53\u524d\u7248\u672c"),(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u56db\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"-h")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"--help")," \u8f93\u51fa\u5e2e\u52a9\u6587\u6863")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u751f\u6210\u63a7\u5236\u53f0 ",(0,r.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"LOGO")),(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},"\u4e0d\u652f\u6301\u4e2d\u6587\uff1a",(0,r.kt)("a",{parentName:"li",href:"http://patorjk.com/software/taag/#p=display&f=Big&t=Furion%20Tools"},"http://patorjk.com/software/taag/#p=display&f=Big&t=Furion%20Tools")),(0,r.kt)("li",{parentName:"ul"},"\u652f\u6301\u6240\u6709\u5b57\u7b26\uff1a",(0,r.kt)("a",{parentName:"li",href:"https://www.qqxiuzi.cn/zh/dianzhenzi-zifu/"},"https://www.qqxiuzi.cn/zh/dianzhenzi-zifu/")))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,10,15-18,26-29,37-40,45}",showLineNumbers:!0,"":!0,"{1,10,15-18,26-29,37-40,45}":!0},'using Furion.Tools.CommandLine;\nusing System;\nusing System.Collections.Generic;\n\nnamespace HelloTools\n{\n class Program\n {\n // \u901a\u8fc7 Cli.Inject() \u5b8c\u6210\u51c6\u5907\u5de5\u4f5c\n static void Main(string[] args) => Cli.Inject();\n\n /// \n /// \u8f93\u51fa Hello \u540d\u5b57\n /// \n [Argument(\'n\', "name", "\u60a8\u7684\u540d\u5b57")]\n static string Name { get; set; }\n // \u5b9a\u4e49\u53c2\u6570\u5904\u7406\u7a0b\u5e8f\uff0c\u5fc5\u987b [\u5c5e\u6027\u540d]+Handler\n static void NameHandler(ArgumentMetadata argument)\n {\n Console.WriteLine($"Hello {Name}");\n }\n\n /// \n /// \u67e5\u770b\u7248\u672c\n /// \n [Argument(\'v\', "version", "\u5de5\u5177\u7248\u672c\u53f7")]\n static bool Version { get; set; }\n // \u5b9a\u4e49\u53c2\u6570\u5904\u7406\u7a0b\u5e8f\uff0c\u5fc5\u987b [\u5c5e\u6027\u540d]+Handler\n static void VersionHandler(ArgumentMetadata argument)\n {\n Console.WriteLine(Cli.GetVersion());\n }\n\n /// \n /// \u67e5\u770b\u5e2e\u52a9\u6587\u6863\n /// \n [Argument(\'h\', "help", "\u67e5\u770b\u5e2e\u52a9\u6587\u6863")]\n static bool Help { get; set; }\n // \u5b9a\u4e49\u53c2\u6570\u5904\u7406\u7a0b\u5e8f\uff0c\u5fc5\u987b [\u5c5e\u6027\u540d]+Handler\n static void HelpHandler(ArgumentMetadata argument)\n {\n Cli.GetHelpText("hello-tools");\n }\n\n // \u6240\u6709\u672a\u5339\u914d\u7684\u53c2\u6570/\u64cd\u4f5c\u7b26\u5904\u7406\u7a0b\u5e8f\uff0c\u56fa\u5b9a NoMatchesHandler \u65b9\u6cd5\u540d\n static void NoMatchesHandler(bool isEmpty, string[] operands, Dictionary noMatches)\n {\n if (isEmpty)\n {\n Console.WriteLine(@"\n _ _ _ _ _______ _\n | | | | | | | |__ __| | |\n | |__| | ___| | | ___ | | ___ ___ | |___\n | __ |/ _ \\ | |/ _ \\ | |/ _ \\ / _ \\| / __|\n | | | | __/ | | (_) | | | (_) | (_) | \\__ \\\n |_| |_|\\___|_|_|\\___/ |_|\\___/ \\___/|_|___/\n\n\n");\n Console.WriteLine($"\u6b22\u8fce\u4f7f\u7528{Cli.GetDescription()}");\n }\n }\n }\n}\n')),(0,r.kt)("admonition",{title:"\u4ee3\u7801\u8bf4\u660e",type:"tip"},(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u5de5\u5177\u5305\u63d0\u4f9b\u4e86\u975e\u5e38\u65b9\u4fbf\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Cli.Inject()")," \u65b9\u6cd5\uff0c\u53ef\u4ee5\u5b9e\u73b0\u4e00\u6b21\u6027\u5b8c\u6210\u6240\u6709\u521d\u59cb\u5316\u5de5\u4f5c\uff0c\u53ea\u9700\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Main")," \u65b9\u6cd5\u8c03\u7528\u5373\u53ef"),(0,r.kt)("li",{parentName:"ul"},"\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"[Argument(\u77ed\u53c2\u6570\uff0c\u957f\u53c2\u6570\uff0c\u63d0\u793a\u6587\u6863)]")," \u5b9a\u4e49\u6bcf\u4e00\u4e2a\u53c2\u6570\u5c5e\u6027\uff0c\u53c2\u6570\u5fc5\u987b\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"static")," \u9759\u6001"),(0,r.kt)("li",{parentName:"ul"},"\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"[\u5c5e\u6027\u540d]Handler")," \u5b9a\u4e49\u6bcf\u4e2a\u53c2\u6570\u5339\u914d\u540e\u7684\u5904\u7406\u7a0b\u5e8f\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"VersionHandler"),"\uff0c\u683c\u5f0f\u4e3a\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"static void \u5c5e\u6027\u540dHandler(ArgumentMetadata argument)")),(0,r.kt)("li",{parentName:"ul"},"\u901a\u8fc7\u56fa\u5b9a\u65b9\u6cd5\u540d ",(0,r.kt)("inlineCode",{parentName:"li"},"NoMatchesHandler")," \u5b9a\u4e49\u672a\u5339\u914d\u7684\u53c2\u6570\u53ca\u64cd\u4f5c\u7b26\uff0c\u8be5\u65b9\u6cd5\u6709\u4e09\u4e2a\u53c2\u6570\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"isEmpty"),"\uff1a\u5224\u65ad\u662f\u5426\u6ca1\u6709\u4f20\u9012\u4efb\u4f55\u53c2\u6570\uff0c\u901a\u5e38\u7528\u4e8e\u8f93\u51fa\u4ecb\u7ecd"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"operands"),"\uff1a\u83b7\u53d6\u6240\u6709\u64cd\u4f5c\u7b26\u5217\u8868"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"noMatches"),"\uff1a\u83b7\u53d6\u6240\u6709\u672a\u5339\u914d\u7684\u53c2\u6570\u5b57\u5178"))))),(0,r.kt)("h3",{id:"3735-\u5982\u4f55\u8c03\u8bd5\u5305\u5de5\u5177-"},"37.3.5 \u5982\u4f55\u8c03\u8bd5\u5305\u5de5\u5177 \ud83d\udc4f"),(0,r.kt)("p",null,"\u5305\u7ba1\u7406\u5de5\u5177\u8c03\u8bd5\u6709\u522b\u4e8e\u666e\u901a\u7684\u63a7\u5236\u53f0\uff0c\u4e3b\u8981\u533a\u522b\u662f\u6d4b\u8bd5\u5404\u4e2a\u53c2\u6570\u7684\u4f7f\u7528\uff0c\u4e5f\u5c31\u662f\u5982\u4f55\u4f20\u9012 ",(0,r.kt)("inlineCode",{parentName:"p"},"Main")," \u65b9\u6cd5\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"args")," \u53c2\u6570\u3002\u53ea\u9700\u8981\u4ee5\u4e0b\u4e24\u4e2a\u6b65\u9aa4\u5373\u53ef\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u5728\u9879\u76ee\u6839\u76ee\u5f55\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Properties")," \u76ee\u5f55"),(0,r.kt)("li",{parentName:"ul"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Properties")," \u76ee\u5f55\u4e2d\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"launchSettings.json")," \u6587\u4ef6\uff0c\u5e76\u9075\u5faa\u4ee5\u4e0b\u89c4\u5219\uff1a")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {3,5}",showLineNumbers:!0,"":!0,"{3,5}":!0},'{\n "profiles": {\n "\u9879\u76ee\u540d\u79f0": {\n "commandName": "Project",\n "commandLineArgs": "\u4f60\u7684\u547d\u4ee4"\n }\n }\n}\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u9879\u76ee\u540d\u79f0"),"\uff1a\u5199\u4f60\u7684\u9879\u76ee\u5b9e\u9645\u540d\u79f0\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"HelloTools")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"commandName"),"\uff1a\u56fa\u5b9a\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Project")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"commandLineArgs"),"\uff1a\u7f16\u5199\u6d4b\u8bd5\u547d\u4ee4\uff0c\u53ea\u9700\u8981\u5199\u53c2\u6570/\u64cd\u4f5c\u7b26\u90e8\u5206\u5373\u53ef\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"-v"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"-v -h --Name Furion"))),(0,r.kt)("p",null,"\u5982\uff0c\u6211\u4eec\u9700\u8981\u6d4b\u8bd5 ",(0,r.kt)("inlineCode",{parentName:"p"},"HelloTools")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"-n")," \u53c2\u6570"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {3,5}",showLineNumbers:!0,"":!0,"{3,5}":!0},'{\n "profiles": {\n "HelloTools": {\n "commandName": "Project",\n "commandLineArgs": "-n Furion"\n }\n }\n}\n')),(0,r.kt)("img",{src:(0,o.Z)("img/ts3.png")}),(0,r.kt)("p",null,"\u70b9\u51fb ",(0,r.kt)("inlineCode",{parentName:"p"},"\u8fd0\u884c/\u8c03\u8bd5/F5")," \u542f\u52a8\u8c03\u8bd5"),(0,r.kt)("img",{src:(0,o.Z)("img/ts4.png")}),(0,r.kt)("h3",{id:"3736-\u6d4b\u8bd5\u5404\u4e2a\u53c2\u6570\u60c5\u51b5"},"37.3.6 \u6d4b\u8bd5\u5404\u4e2a\u53c2\u6570\u60c5\u51b5"),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u4e00\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"hello-tools")," \u6253\u5370\u4ecb\u7ecd\u4fe1\u606f")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},'{\n "profiles": {\n "HelloTools": {\n "commandName": "Project",\n "commandLineArgs": ""\n }\n }\n}\n')),(0,r.kt)("img",{src:(0,o.Z)("img/ts5.png")}),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u4e8c\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"-n")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"--name")," \u8f93\u51fa ",(0,r.kt)("inlineCode",{parentName:"p"},"Hello \u540d\u5b57"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},'{\n "profiles": {\n "HelloTools": {\n "commandName": "Project",\n "commandLineArgs": "-n Furion"\n }\n }\n}\n')),(0,r.kt)("img",{src:(0,o.Z)("img/ts6.png")}),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u4e09\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"-v")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"--version")," \u8f93\u51fa\u5f53\u524d\u7248\u672c")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},'{\n "profiles": {\n "HelloTools": {\n "commandName": "Project",\n "commandLineArgs": "--version"\n }\n }\n}\n')),(0,r.kt)("img",{src:(0,o.Z)("img/ts7.png")}),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u56db\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"-h")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"--help")," \u8f93\u51fa\u5e2e\u52a9\u6587\u6863")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},'{\n "profiles": {\n "HelloTools": {\n "commandName": "Project",\n "commandLineArgs": "-h"\n }\n }\n}\n')),(0,r.kt)("img",{src:(0,o.Z)("img/ts8.png")}),(0,r.kt)("h2",{id:"374-\u6253\u5305\u672c\u673a\u6d4b\u8bd5"},"37.4 \u6253\u5305\uff08\u672c\u673a\uff09\u6d4b\u8bd5"),(0,r.kt)("p",null,"\u521a\u521a\u6211\u4eec\u5df2\u7ecf\u5b66\u4f1a\u8c03\u8bd5\u5305\u5de5\u5177\u4e86\uff0c\u4f46\u662f\u8fd8\u672a\u505a\u5230\u7c7b\u4f3c ",(0,r.kt)("inlineCode",{parentName:"p"},"npm")," \u5305\u4e00\u6837\uff0c\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"cmd/powershell")," \u4e2d\u5b89\u88c5\u4e4b\u540e\u53ef\u5728\u547d\u4ee4\u884c\u5168\u5c40\u6d4b\u8bd5\uff0c\u4e0b\u9762\u5c06\u6559\u5927\u5bb6\u5982\u4f55\u5b9e\u73b0 ",(0,r.kt)("inlineCode",{parentName:"p"},"\u5168\u5c40\u5b89\u88c5")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"\u672c\u5730\u5b89\u88c5"),"\u3002"),(0,r.kt)("h3",{id:"3741-\u5168\u5c40\u6253\u5305\u5b89\u88c5"},"37.4.1 \u5168\u5c40\u6253\u5305\u5b89\u88c5"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u5168\u5c40\u6253\u5305\u5b89\u88c5\u5c31\u662f\u914d\u7f6e\u5728\u7cfb\u7edf\u73af\u5883\u53d8\u91cf\u4e2d\uff0c\u5728\u4efb\u4f55\u5730\u65b9\u90fd\u53ef\u4ee5\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"HelloTools")," \u9879\u76ee\u6839\u76ee\u5f55\u4e0b\u6253\u5f00 ",(0,r.kt)("inlineCode",{parentName:"p"},"cmd/powershell"),"\uff08",(0,r.kt)("strong",{parentName:"p"},"\u5c3d\u91cf\u4f7f\u7528\u7ba1\u7406\u5458\u5de5\u5177"),"\uff09\u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,r.kt)("h4",{id:"-\u5b89\u88c5\u5168\u5c40\u5305"},"\u2714 \u5b89\u88c5\u5168\u5c40\u5305"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool install --global --add-source ./nupkg HelloTools\n")),(0,r.kt)("p",null,"\u5176\u4e2d ",(0,r.kt)("inlineCode",{parentName:"p"},"HelloTools")," \u5c31\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"\u9879\u76ee\u540d\u79f0"),"\u3002"),(0,r.kt)("img",{src:(0,o.Z)("img/ts9.png")}),(0,r.kt)("p",null,"\u4e4b\u540e\u6211\u4eec\u5c31\u53ef\u4ee5\u901a\u8fc7\u4e4b\u524d ",(0,r.kt)("inlineCode",{parentName:"p"},"HelloTools.csproj")," \u4e2d\u914d\u7f6e\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"hello-tools")," \u4f7f\u7528\u4e86\u3002"),(0,r.kt)("h4",{id:"-\u6d4b\u8bd5\u5168\u5c40\u5305"},"\u2714 \u6d4b\u8bd5\u5168\u5c40\u5305"),(0,r.kt)("img",{src:(0,o.Z)("img/ts10.png")}),(0,r.kt)("h4",{id:"-\u66f4\u65b0\u5168\u5c40\u5305"},"\u2714 \u66f4\u65b0\u5168\u5c40\u5305"),(0,r.kt)("p",null,"\u5982\u679c\u6e90\u7801\u53d1\u751f\u6539\u53d8\uff0c\u53ea\u9700\u8981\u7f16\u8bd1\u9879\u76ee\u540e\u91cd\u65b0\u66f4\u65b0\u5305\u5de5\u5177\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool update --global --add-source ./nupkg HelloTools\n")),(0,r.kt)("h4",{id:"-\u5378\u8f7d\u5168\u5c40\u5305"},"\u2714 \u5378\u8f7d\u5168\u5c40\u5305"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool uninstall --global HelloTools\n")),(0,r.kt)("p",null,"\u60f3\u4e86\u89e3\u66f4\u591a\u5168\u5c40\u6253\u5305\u5b89\u88c5\u77e5\u8bc6\u67e5\u9605\u5b98\u65b9\u6587\u6863\u5373\u53ef\uff1a",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/dotnet/core/tools/global-tools-how-to-use"},"https://docs.microsoft.com/zh-cn/dotnet/core/tools/global-tools-how-to-use")),(0,r.kt)("h3",{id:"3742-\u672c\u5730\u6253\u5305\u5b89\u88c5"},"37.4.2 \u672c\u5730\u6253\u5305\u5b89\u88c5"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u672c\u5730\u6253\u5305\u5b89\u88c5\u5c31\u662f\u53ea\u6709\u5728\u9879\u76ee\u6240\u5728\u76ee\u5f55\u53ca\u5b50\u5b59\u76ee\u5f55\u65b9\u53ef\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"HelloTools")," \u9879\u76ee\u6839\u76ee\u5f55\u4e0b\u6253\u5f00 ",(0,r.kt)("inlineCode",{parentName:"p"},"cmd/powershell")," \u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,r.kt)("h4",{id:"-\u521b\u5efa\u672c\u5730\u6e05\u5355\u6587\u4ef6"},"\u2714 \u521b\u5efa\u672c\u5730\u6e05\u5355\u6587\u4ef6"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new tool-manifest\n")),(0,r.kt)("p",null,"\u6267\u884c\u8be5\u547d\u4ee4\u540e\u4f1a\u81ea\u52a8\u521b\u5efa ",(0,r.kt)("inlineCode",{parentName:"p"},".config")," \u6587\u4ef6\u5939\u5e76\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"dotnet-tools.json")," \u6587\u4ef6\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "version": 1,\n "isRoot": true,\n "tools": {}\n}\n')),(0,r.kt)("admonition",{title:"\u6ce8\u610f\u4e8b\u9879",type:"warning"},(0,r.kt)("p",{parentName:"admonition"},"\u901a\u5e38\u8be5\u6587\u4ef6\u5185\u5bb9\u4e0d\u9700\u8981\u624b\u52a8\u66f4\u6539\u3002")),(0,r.kt)("h4",{id:"-\u5b89\u88c5\u672c\u5730\u5305"},"\u2714 \u5b89\u88c5\u672c\u5730\u5305"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool install --add-source ./nupkg HelloTools\n")),(0,r.kt)("img",{src:(0,o.Z)("img/ts11.png")}),(0,r.kt)("h4",{id:"-\u6d4b\u8bd5\u672c\u5730\u5305"},"\u2714 \u6d4b\u8bd5\u672c\u5730\u5305"),(0,r.kt)("p",null,"\u672c\u5730\u5305\u6d4b\u8bd5\u548c\u5168\u5c40\u5305\u4e0d\u4e00\u6837\u7684\u662f\u672c\u5730\u5305\u662f\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"dotnet \u5173\u952e\u5b57 \u53c2\u6570")," \u6d4b\u8bd5\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet hello-tools -n Furion\n")),(0,r.kt)("img",{src:(0,o.Z)("img/ts12.png")}),(0,r.kt)("h4",{id:"-\u66f4\u65b0\u672c\u5730\u5305"},"\u2714 \u66f4\u65b0\u672c\u5730\u5305"),(0,r.kt)("p",null,"\u5982\u679c\u6e90\u7801\u53d1\u751f\u6539\u53d8\uff0c\u53ea\u9700\u8981\u7f16\u8bd1\u9879\u76ee\u540e\u91cd\u65b0\u66f4\u65b0\u5305\u5de5\u5177\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool update --add-source ./nupkg HelloTools\n")),(0,r.kt)("h4",{id:"-\u5378\u8f7d\u672c\u5730\u5305"},"\u2714 \u5378\u8f7d\u672c\u5730\u5305"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool uninstall HelloTools\n")),(0,r.kt)("p",null,"\u60f3\u4e86\u89e3\u66f4\u591a\u672c\u5730\u6253\u5305\u5b89\u88c5\u77e5\u8bc6\u67e5\u9605\u5b98\u65b9\u6587\u6863\u5373\u53ef\uff1a",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/dotnet/core/tools/local-tools-how-to-use"},"https://docs.microsoft.com/zh-cn/dotnet/core/tools/local-tools-how-to-use")),(0,r.kt)("h2",{id:"375-\u53d1\u5e03\u5230-nuget-\u5e73\u53f0-"},"37.5 \u53d1\u5e03\u5230 ",(0,r.kt)("inlineCode",{parentName:"h2"},"Nuget")," \u5e73\u53f0 \ud83d\udc4f"),(0,r.kt)("p",null,"\u53d1\u5e03\u5230 ",(0,r.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5e73\u53f0\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700\u8981\u4e24\u4e2a\u6b65\u9aa4\u5373\u53ef\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u5207\u6362\u9879\u76ee ",(0,r.kt)("inlineCode",{parentName:"li"},"Debug")," \u6a21\u5f0f\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"Release")," \u5e76\u91cd\u65b0\u7f16\u8bd1\u9879\u76ee"),(0,r.kt)("li",{parentName:"ul"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Nuget")," \u5e73\u53f0\u4e0a\u4f20 ",(0,r.kt)("inlineCode",{parentName:"li"},"nupkg")," \u6587\u4ef6\u5939\u5bf9\u5e94 ",(0,r.kt)("inlineCode",{parentName:"li"},"\u9879\u76ee\u540d\u79f0.\u7248\u672c\u53f7.nupkg")," \u6587\u4ef6\u5373\u53ef\uff1a",(0,r.kt)("a",{parentName:"li",href:"https://www.nuget.org/packages/manage/upload"},"https://www.nuget.org/packages/manage/upload"))),(0,r.kt)("admonition",{title:"\u4e0a\u4f20 Nuget \u5e73\u53f0\u8865\u9f50\u4fe1\u606f",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"\u5efa\u8bae\u4e0a\u4f20\u5230 ",(0,r.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5e73\u53f0\u7f16\u8f91 ",(0,r.kt)("inlineCode",{parentName:"p"},".csproj")," \u6587\u4ef6\u8865\u9f50\u4ee5\u4e0b\u4fe1\u606f\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13-21}",showLineNumbers:!0,"":!0,"{13-21}":!0},'\n\n \n Exe\n net5.0\n 0.0.1\n \u7b2c\u4e00\u4e2a dotnet tools \u5de5\u5177\n hello-tools\n true\n true\n ./nupkg\n\n \u767e\u5c0f\u50e7\n Baiqian Co.,Ltd.\n Furion\n \xa9 2020-2021 \u767e\u5c0f\u50e7, Baiqian Co.,Ltd.\n https://gitee.com/dotnetchina/Furion\n Gitee\n true\n MIT\n https://furion.icu\n \n\n \n \n \n\n\n'))),(0,r.kt)("img",{src:(0,o.Z)("img/ts13.png")}),(0,r.kt)("img",{src:(0,o.Z)("img/ts14.png")}),(0,r.kt)("p",null,"\u53d1\u5e03\u5230 ",(0,r.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5e73\u53f0\u540e\uff0c\u522b\u4eba\u5c31\u53ef\u4ee5\u901a\u8fc7\uff1a"),(0,r.kt)("h4",{id:"-\u5b89\u88c5-nuget-\u5305\u5230\u672c\u5730"},"\u2714 \u5b89\u88c5 Nuget \u5305\u5230\u672c\u5730"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool install --global \u9879\u76ee\u540d --version \u7248\u672c\u53f7\n")),(0,r.kt)("h2",{id:"376-cli-\u9759\u6001\u7c7b\u8bf4\u660e"},"37.6 ",(0,r.kt)("inlineCode",{parentName:"h2"},"Cli")," \u9759\u6001\u7c7b\u8bf4\u660e"),(0,r.kt)("p",null,"\u4e3a\u4e86\u7b80\u5316\u5305\u5de5\u5177\u7684\u5f00\u53d1\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Tools.CommandLine")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Cli")," \u9759\u6001\u7c7b\u63d0\u4f9b\u4e86\u5f88\u591a\u65b9\u4fbf\u7684\u9759\u6001\u65b9\u6cd5\uff1a"),(0,r.kt)("h3",{id:"3761-\u6d88\u606f\u7c7b"},"37.6.1 \u6d88\u606f\u7c7b"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u8f93\u51fa\u7a7a\u884c\nCli.EmptyLine();\n\n// \u8f93\u51fa\u4e00\u884c\nCli.WriteLine("\u6d88\u606f");\nCli.WriteLine("\u6d88\u606f", ConsoleColor.Blue); // \u5b57\u4f53\u989c\u8272\nCli.WriteLine("\u6d88\u606f", ConsoleColor.Blue, ConsoleColor.White); // \u80cc\u666f\u989c\u8272\nCli.WriteLine("\u6d88\u606f", ConsoleColor.Blue, ConsoleColor.White, fillLine: true); // \u586b\u5145\u6574\u884c\n\n// \u8f93\u51fa\uff08\u4e0d\u6362\u884c\uff09\nCli.Write("\u6d88\u606f");\nCli.Write("\u6d88\u606f", ConsoleColor.Blue); // \u5b57\u4f53\u989c\u8272\nCli.Write("\u6d88\u606f", ConsoleColor.Blue, ConsoleColor.White); // \u80cc\u666f\u989c\u8272\nCli.Write("\u6d88\u606f", ConsoleColor.Blue, ConsoleColor.White, fillLine: true); // \u586b\u5145\u6574\u884c\n\n// \u8f93\u51fa\u63d0\u793a\u6d88\u606f\nCli.Success("\u6210\u529f");\nCli.Warn("\u8b66\u544a");\nCli.Error("\u9519\u8bef");\nCli.Tip("\u63d0\u793a");\n\n// \u6536\u96c6\u7528\u6237\u8f93\u5165\uff08\u652f\u6301\u591a\u884c\uff09\nvar inputs = Cli.ReadInput(); // \u8f93\u5165 exit \u9000\u51fa\u8f93\u5165\n\n// \u9009\u62e9\u6d88\u606f\nvar selectId = Cli.ReadOptions("\u8bf7\u9009\u62e9\u559c\u6b22\u7684\u6c34\u679c\uff1a", new []{ "\u897f\u74dc", "\u82f9\u679c", "\u51e4\u68a8"}); // selectId \u4ece 1 \u5f00\u59cb\n')),(0,r.kt)("h3",{id:"3762-\u5de5\u5177\u7c7b"},"37.6.2 \u5de5\u5177\u7c7b"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u5b8c\u6210\u53c2\u6570\u586b\u5145\u5c5e\u6027\u521d\u59cb\u5316\u64cd\u4f5c\nCli.Inject();\n\n// \u83b7\u53d6\u53c2\u6570\u6240\u6709\u4fe1\u606f\nvar arguments = Cli.ArgumentMetadatas;\n\n// \u624b\u52a8\u68c0\u67e5\u53c2\u6570\u662f\u5426\u5339\u914d\nCli.Check(nameof(\u5c5e\u6027\u540d), argument => {\n // \u5982\u679c\u7528\u6237\u8f93\u5165\u8be5\u53c2\u6570\n if(argument?.IsTransmission == true){\n Cli.WriteLine(argument.Value);\n }\n else {\n Cli.Error("\u7528\u6237\u6ca1\u6709\u8f93\u5165");\n }\n});\n\n// \u53ea\u6709\u53c2\u6570\u5339\u914d\u624d\u8fdb\u5165\nCli.CheckMatch(nameof(\u5c5e\u6027\u540d), argument => {\n Cli.WriteLine(argument.Value);\n})\n\n// \u65e0\u5c5e\u6027\u68c0\u67e5\nCli.Check(new[] {"v", "version"}, (isMatch, value) => {\n // \u5982\u679c\u7528\u6237\u8f93\u5165\u8be5\u53c2\u6570\n if(isMatch){\n Cli.WriteLine(value);\n }\n else {\n Cli.Error("\u7528\u6237\u6ca1\u6709\u8f93\u5165");\n }\n});\n\n// \u65e0\u5c5e\u6027\u5339\u914d\nCli.CheckMatch(new[] {"v", "version"}, value => {\n Cli.WriteLine(value);\n});\n\n// \u6240\u6709\u672a\u5339\u914d\u7684\u53c2\u6570\u3001\u64cd\u4f5c\u7b26\nCli.CheckNoMatches((isEmpty, operands, noMatches) => {\n if (isEmpty) Cli.WriteLine($"\u6b22\u8fce\u4f7f\u7528 {Cli.GetDescription()}");\n if (operands.Length > 0) Cli.Error($"\u672a\u627e\u5230\u8be5\u64cd\u4f5c\u7b26\uff1a{string.Join(",", operands)}");\n if (noMatches.Count > 0) Cli.Error($"\u672a\u627e\u5230\u8be5\u53c2\u6570\uff1a{string.Join(",", noMatches.Keys)}");\n});\n\n// \u89e3\u6790 Main \u65b9\u6cd5\u53c2\u6570\u4fe1\u606f\nvar argumentModel = Cli.Parse();\n\n// \u624b\u52a8\u89e3\u6790\u547d\u4ee4\u5b57\u7b26\u4e32\nvar argumentModel = Cli.Parse("-abc foo --hello world");\n\n// \u7ec8\u6b62\u8f93\u51fa/\u7ed3\u675f\u8f93\u51fa\nCli.Exit();\n')),(0,r.kt)("h3",{id:"3762-\u4fe1\u606f\u7c7b"},"37.6.2 \u4fe1\u606f\u7c7b"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u83b7\u53d6\u5f53\u524d\u5de5\u5177\u5305\u7248\u672c\u53f7\nvar version = Cli.GetVersion();\n\n// \u83b7\u53d6\u5f53\u524d\u5de5\u5177\u5305\u63cf\u8ff0\nvar description = Cli.GetDescription();\n")),(0,r.kt)("h3",{id:"3763-\u5176\u4ed6\u7c7b"},"37.6.3 \u5176\u4ed6\u7c7b"),(0,r.kt)("p",null,"\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"Environment")," \u83b7\u53d6\u5f53\u524d\u73af\u5883\u66f4\u591a\u4fe1\u606f\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u5f53\u524d\u6267\u884c\u547d\u4ee4\u76ee\u5f55\nvar currentDirectory = Environment.CurrentDirectory;\n\n// \u83b7\u53d6\u673a\u5668\u540d\u79f0\nvar machineName = Environment.MachineName;\n\n// \u7b49\u7b49\u3002\u3002\u3002\u3002\u3002\n")),(0,r.kt)("h2",{id:"377-\u53cd\u9988\u4e0e\u5efa\u8bae"},"37.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,r.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}N.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return k}});var a=n(7294);function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}var p=a.createContext({}),m=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},s=function(e){var t=m(e.components);return a.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,l=e.mdxType,r=e.originalType,p=e.parentName,s=i(e,["components","mdxType","originalType","parentName"]),d=m(n),k=l,N=d["".concat(p,".").concat(k)]||d[k]||u[k]||r;return n?a.createElement(N,o(o({ref:t},s),{},{components:n})):a.createElement(N,o({ref:t},s))}));function k(e,t){var n=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var r=n.length,o=new Array(r);o[0]=d;var i={};for(var p in t)hasOwnProperty.call(t,p)&&(i[p]=t[p]);i.originalType=e,i.mdxType="string"==typeof e?e:l,o[1]=i;for(var m=2;m=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}var p=a.createContext({}),m=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},s=function(e){var t=m(e.components);return a.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,l=e.mdxType,r=e.originalType,p=e.parentName,s=i(e,["components","mdxType","originalType","parentName"]),d=m(n),k=l,N=d["".concat(p,".").concat(k)]||d[k]||u[k]||r;return n?a.createElement(N,o(o({ref:t},s),{},{components:n})):a.createElement(N,o({ref:t},s))}));function k(e,t){var n=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var r=n.length,o=new Array(r);o[0]=d;var i={};for(var p in t)hasOwnProperty.call(t,p)&&(i[p]=t[p]);i.originalType=e,i.mdxType="string"==typeof e?e:l,o[1]=i;for(var m=2;mdotnet tools \u5305\u7ba1\u7406\u597d\u5904",id:"3712-dotnet-tools-\u5305\u7ba1\u7406\u597d\u5904",level:3},{value:"37.2 \u4e86\u89e3\u5305\u547d\u4ee4\u8bed\u6cd5",id:"372-\u4e86\u89e3\u5305\u547d\u4ee4\u8bed\u6cd5",level:2},{value:"37.2.1 \u77ed\u53c2\u6570\u4f8b\u5b50",id:"3721-\u77ed\u53c2\u6570\u4f8b\u5b50",level:3},{value:"37.2.2 \u957f\u53c2\u6570\u4f8b\u5b50",id:"3722-\u957f\u53c2\u6570\u4f8b\u5b50",level:3},{value:"37.2.3 \u6df7\u5408\u53c2\u6570\u4f8b\u5b50",id:"3723-\u6df7\u5408\u53c2\u6570\u4f8b\u5b50",level:3},{value:"37.2.4 \u591a\u4e2a\u503c\u53c2\u6570",id:"3724-\u591a\u4e2a\u503c\u53c2\u6570",level:3},{value:"37.2.5 \u64cd\u4f5c\u7b26",id:"3725-\u64cd\u4f5c\u7b26",level:3},{value:"37.3 \u7f16\u5199\u7b2c\u4e00\u4e2a\u5305",id:"373-\u7f16\u5199\u7b2c\u4e00\u4e2a\u5305",level:2},{value:"37.3.1 \u521b\u5efa HelloTools \u63a7\u5236\u53f0\u5e94\u7528",id:"3731-\u521b\u5efa-hellotools-\u63a7\u5236\u53f0\u5e94\u7528",level:3},{value:"37.3.2 \u7f16\u8f91 HelloTools.csproj",id:"3732-\u7f16\u8f91-hellotoolscsproj",level:3},{value:"\u914d\u7f6e\u5173\u952e\u8282\u70b9\u8bf4\u660e",id:"\u914d\u7f6e\u5173\u952e\u8282\u70b9\u8bf4\u660e",level:4},{value:"37.3.3 \u5b89\u88c5 Furion.Tools.CommandLine \u5305",id:"3733-\u5b89\u88c5-furiontoolscommandline-\u5305",level:3},{value:"37.3.4 \u7f16\u5199\u903b\u8f91\u4ee3\u7801",id:"3734-\u7f16\u5199\u903b\u8f91\u4ee3\u7801",level:3},{value:"37.3.5 \u5982\u4f55\u8c03\u8bd5\u5305\u5de5\u5177 \ud83d\udc4f",id:"3735-\u5982\u4f55\u8c03\u8bd5\u5305\u5de5\u5177-",level:3},{value:"37.3.6 \u6d4b\u8bd5\u5404\u4e2a\u53c2\u6570\u60c5\u51b5",id:"3736-\u6d4b\u8bd5\u5404\u4e2a\u53c2\u6570\u60c5\u51b5",level:3},{value:"37.4 \u6253\u5305\uff08\u672c\u673a\uff09\u6d4b\u8bd5",id:"374-\u6253\u5305\u672c\u673a\u6d4b\u8bd5",level:2},{value:"37.4.1 \u5168\u5c40\u6253\u5305\u5b89\u88c5",id:"3741-\u5168\u5c40\u6253\u5305\u5b89\u88c5",level:3},{value:"\u2714 \u5b89\u88c5\u5168\u5c40\u5305",id:"-\u5b89\u88c5\u5168\u5c40\u5305",level:4},{value:"\u2714 \u6d4b\u8bd5\u5168\u5c40\u5305",id:"-\u6d4b\u8bd5\u5168\u5c40\u5305",level:4},{value:"\u2714 \u66f4\u65b0\u5168\u5c40\u5305",id:"-\u66f4\u65b0\u5168\u5c40\u5305",level:4},{value:"\u2714 \u5378\u8f7d\u5168\u5c40\u5305",id:"-\u5378\u8f7d\u5168\u5c40\u5305",level:4},{value:"37.4.2 \u672c\u5730\u6253\u5305\u5b89\u88c5",id:"3742-\u672c\u5730\u6253\u5305\u5b89\u88c5",level:3},{value:"\u2714 \u521b\u5efa\u672c\u5730\u6e05\u5355\u6587\u4ef6",id:"-\u521b\u5efa\u672c\u5730\u6e05\u5355\u6587\u4ef6",level:4},{value:"\u2714 \u5b89\u88c5\u672c\u5730\u5305",id:"-\u5b89\u88c5\u672c\u5730\u5305",level:4},{value:"\u2714 \u6d4b\u8bd5\u672c\u5730\u5305",id:"-\u6d4b\u8bd5\u672c\u5730\u5305",level:4},{value:"\u2714 \u66f4\u65b0\u672c\u5730\u5305",id:"-\u66f4\u65b0\u672c\u5730\u5305",level:4},{value:"\u2714 \u5378\u8f7d\u672c\u5730\u5305",id:"-\u5378\u8f7d\u672c\u5730\u5305",level:4},{value:"37.5 \u53d1\u5e03\u5230 Nuget \u5e73\u53f0 \ud83d\udc4f",id:"375-\u53d1\u5e03\u5230-nuget-\u5e73\u53f0-",level:2},{value:"\u2714 \u5b89\u88c5 Nuget \u5305\u5230\u672c\u5730",id:"-\u5b89\u88c5-nuget-\u5305\u5230\u672c\u5730",level:4},{value:"37.6 Cli \u9759\u6001\u7c7b\u8bf4\u660e",id:"376-cli-\u9759\u6001\u7c7b\u8bf4\u660e",level:2},{value:"37.6.1 \u6d88\u606f\u7c7b",id:"3761-\u6d88\u606f\u7c7b",level:3},{value:"37.6.2 \u5de5\u5177\u7c7b",id:"3762-\u5de5\u5177\u7c7b",level:3},{value:"37.6.2 \u4fe1\u606f\u7c7b",id:"3762-\u4fe1\u606f\u7c7b",level:3},{value:"37.6.3 \u5176\u4ed6\u7c7b",id:"3763-\u5176\u4ed6\u7c7b",level:3},{value:"37.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"377-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],k={toc:d};function N(e){var t=e.components,n=(0,l.Z)(e,i);return(0,r.kt)("wrapper",(0,a.Z)({},k,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"371-\u5173\u4e8e\u5305\u7ba1\u7406\u5de5\u5177"},"37.1 \u5173\u4e8e\u5305\u7ba1\u7406\u5de5\u5177"),(0,r.kt)("p",null,"\u4f7f\u7528\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"NodeJs")," \u7684\u670b\u53cb\u4e00\u5b9a\u5bf9 ",(0,r.kt)("inlineCode",{parentName:"p"},"npm")," \u547d\u4ee4\u4e0d\u4f1a\u964c\u751f\uff0c\u53ef\u4ee5\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"npm")," \u5b89\u88c5\u9879\u76ee\u9700\u8981\u7684\u5305\u6216\u73af\u5883\u9700\u8981\u7684\u5de5\u5177\uff0c\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET Core 2.1+")," \u4e4b\u540e\uff0c\u5fae\u8f6f\u4e5f\u63a8\u51fa\u4e86\u65b0\u7684\u7279\u6027\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Global/Local Tools"),"\uff0c\u8be5\u7279\u6027\u529f\u80fd\u4e5f\u6b63\u662f\u53d7\u5230 ",(0,r.kt)("inlineCode",{parentName:"p"},"npm")," \u542f\u53d1\u4e0b\u8bde\u751f\u7684\u3002"),(0,r.kt)("p",null,"\u4e0d\u540c\u7684\u662f\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"npm")," \u4e2d\u7684\u5305\u91c7\u7528\u7684\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"Javascript")," \u7f16\u5199\u5e76\u53d1\u5e03\u5230 ",(0,r.kt)("a",{parentName:"p",href:"https://www.npmjs.com/"},"https://www.npmjs.com/")," \u5e73\u53f0\uff0c\u800c ",(0,r.kt)("inlineCode",{parentName:"p"},"dotnet tools")," \u91c7\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"C#")," \u7f16\u5199\u5e76\u53d1\u5e03\u5230 ",(0,r.kt)("inlineCode",{parentName:"p"},"https://www.nuget.org/")," \u5e73\u53f0\u4f9b\u5b89\u88c5\u4f7f\u7528\u3002"),(0,r.kt)("h3",{id:"3712-dotnet-tools-\u5305\u7ba1\u7406\u597d\u5904"},"37.1.2 ",(0,r.kt)("inlineCode",{parentName:"h3"},"dotnet tools")," \u5305\u7ba1\u7406\u597d\u5904"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u8de8\u5e73\u53f0\uff0c\u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"li"},"Linux/Mac/Windows")," \u5e73\u53f0\u4f9b\u5b89\u88c5\u4f7f\u7528"),(0,r.kt)("li",{parentName:"ul"},"\u5b8c\u6574\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"C#")," \u751f\u6001\u652f\u6301"),(0,r.kt)("li",{parentName:"ul"},"\u4e3a\u6240\u6b32\u4e3a~~~\uff08\u62e5\u6709\u64cd\u4f5c\u7cfb\u7edf\u7684\u6743\u9650\uff09")),(0,r.kt)("h2",{id:"372-\u4e86\u89e3\u5305\u547d\u4ee4\u8bed\u6cd5"},"37.2 \u4e86\u89e3\u5305\u547d\u4ee4\u8bed\u6cd5"),(0,r.kt)("p",null,"\u901a\u5e38\u5305\u547d\u4ee4\u8bed\u6cd5\u90fd\u9075\u5faa\u4ee5\u4e0b\u89c4\u5219\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"<-|--|/>argument-name<=|:| >[\"|']value['|\"] [--] [operand] ... [operand]\n")),(0,r.kt)("p",null,"\u5728\u8fd9\u91cc\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u5c06\u7b80\u5355\u4ecb\u7ecd\u547d\u4ee4\u5e38\u7528\u7684\u77e5\u8bc6\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u5de5\u5177\u7b26"),"\uff1a\u901a\u5e38\u6307\u7684\u662f\u4f60\u5de5\u5177\u7684\u552f\u4e00\u540d\u79f0\uff0c\u4e5f\u5c31\u662f\u5173\u952e\u5b57\uff0c\u800c\u4e14\u603b\u662f\u5728\u6700\u5f00\u5934\u7f16\u5199\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"dotnet"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"npm"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"node")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u77ed\u53c2\u6570"),"\uff1a\u77ed\u53c2\u6570\u6307\u7684\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"\u5355\u4e2a\u5b57\u7b26")," \u7684\u5b57\u7b26\u4e32\uff0c\u6211\u4eec\u901a\u5e38\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"-")," \u4e00\u4e2a\u6a2a\u6746\u6307\u5b9a\u53c2\u6570\u53ca\u503c\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"-v")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"li"},"-v 0.0.1")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u957f\u53c2\u6570"),"\uff1a\u957f\u53c2\u6570\u6307\u7684\u662f\u4e00\u4e2a\u6216\u591a\u4e2a\u5355\u8bcd\u8fde\u63a5\u7684\u5b57\u7b26\u4e32\uff0c\u8be5\u53c2\u6570\u901a\u5e38\u548c ",(0,r.kt)("inlineCode",{parentName:"li"},"\u77ed\u53c2\u6570")," \u540c\u65f6\u5b58\u5728\uff0c\u901a\u5e38\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"--")," \u6307\u5b9a\u53c2\u6570\u53ca\u503c\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"--version")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"li"},"--version 0.0.1")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u64cd\u4f5c\u7b26"),"\uff1a\u5b57\u7b26\u4e32\u4e2d\u4e0e\u53c2\u6570\u503c\u683c\u5f0f\u4e0d\u5339\u914d\u7684\u4efb\u4f55\u6587\u672c\u90fd\u88ab\u89c6\u4e3a\u64cd\u4f5c\u6570\uff0c\u4efb\u4f55\u51fa\u73b0\u5728\u53cc\u8fde\u5b57\u7b26 ",(0,r.kt)("inlineCode",{parentName:"li"},"--")," \u4e4b\u540e\u4e14\u672a\u5305\u542b\u5728\u5355\u5f15\u53f7\u6216\u53cc\u5f15\u53f7\u4e2d\u4e14\u4e24\u4fa7\u6709\u7a7a\u683c\u7684\u6587\u672c\u90fd\u88ab\u89c6\u4e3a\u64cd\u4f5c\u6570\uff0c\u65e0\u8bba\u5b83\u662f\u5426\u4e0e\u53c2\u6570\u503c\u683c\u5f0f\u5339\u914d\uff0c\u901a\u5e38\u7528\u4e8e\u5f52\u7c7b/\u5206\u7c7b\u4f5c\u7528\u3002")),(0,r.kt)("h3",{id:"3721-\u77ed\u53c2\u6570\u4f8b\u5b50"},"37.2.1 \u77ed\u53c2\u6570\u4f8b\u5b50"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"-a foo"))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u77ed\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"a"),(0,r.kt)("td",{parentName:"tr",align:null},"foo")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"-ab"))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u77ed\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"a"),(0,r.kt)("td",{parentName:"tr",align:null})),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"b"),(0,r.kt)("td",{parentName:"tr",align:null})))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"-abc bar"))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u77ed\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"a"),(0,r.kt)("td",{parentName:"tr",align:null})),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"b"),(0,r.kt)("td",{parentName:"tr",align:null})),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"c"),(0,r.kt)("td",{parentName:"tr",align:null},"bar")))),(0,r.kt)("h3",{id:"3722-\u957f\u53c2\u6570\u4f8b\u5b50"},"37.2.2 \u957f\u53c2\u6570\u4f8b\u5b50"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"--foo bar"))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u957f\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"foo"),(0,r.kt)("td",{parentName:"tr",align:null},"bar")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"--foo --bar"))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u957f\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"foo"),(0,r.kt)("td",{parentName:"tr",align:null})),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"bar"),(0,r.kt)("td",{parentName:"tr",align:null})))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"--foo bar --hello world"))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u957f\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"foo"),(0,r.kt)("td",{parentName:"tr",align:null},"bar")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"hello"),(0,r.kt)("td",{parentName:"tr",align:null},"world")))),(0,r.kt)("h3",{id:"3723-\u6df7\u5408\u53c2\u6570\u4f8b\u5b50"},"37.2.3 \u6df7\u5408\u53c2\u6570\u4f8b\u5b50"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},'-abc foo --hello world /new="slashes are ok too"'))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u77ed/\u957f\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"a"),(0,r.kt)("td",{parentName:"tr",align:null})),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"b"),(0,r.kt)("td",{parentName:"tr",align:null})),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"c"),(0,r.kt)("td",{parentName:"tr",align:null},"foo")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"hello"),(0,r.kt)("td",{parentName:"tr",align:null},"world")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"new"),(0,r.kt)("td",{parentName:"tr",align:null},"slashes are ok too")))),(0,r.kt)("h3",{id:"3724-\u591a\u4e2a\u503c\u53c2\u6570"},"37.2.4 \u591a\u4e2a\u503c\u53c2\u6570"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"--list 1 --list 2 --list 3"))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u957f\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"list"),(0,r.kt)("td",{parentName:"tr",align:null},"1,2,3")))),(0,r.kt)("h3",{id:"3725-\u64cd\u4f5c\u7b26"},"37.2.5 \u64cd\u4f5c\u7b26"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},'-a foo bar "hello world" -b -- -explicit operand'))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u77ed\u53c2\u6570"),(0,r.kt)("th",{parentName:"tr",align:null},"\u53c2\u6570\u503c"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"a"),(0,r.kt)("td",{parentName:"tr",align:null},"foo")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"b"),(0,r.kt)("td",{parentName:"tr",align:null})))),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"\u64cd\u4f5c\u7b26"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"bar")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},'"hello world"')),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"-explicit")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"operand")))),(0,r.kt)("p",null,"\u4e86\u89e3\u66f4\u591a\u5173\u4e8e\u5305\u547d\u4ee4\u8bed\u6cd5\u7684\u5b98\u65b9\u77e5\u8bc6\uff1a",(0,r.kt)("a",{parentName:"p",href:"https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html"},"https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html")),(0,r.kt)("h2",{id:"373-\u7f16\u5199\u7b2c\u4e00\u4e2a\u5305"},"37.3 \u7f16\u5199\u7b2c\u4e00\u4e2a\u5305"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"dotnet tools")," \u5de5\u5177\u5b9e\u9645\u4e0a\u662f\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"p"},"\u63a7\u5236\u53f0")," \u5e94\u7528\u7a0b\u5e8f\uff0c\u4e0d\u540c\u7684\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},".csproj")," \u9879\u76ee\u6587\u4ef6\u9700\u8981\u6dfb\u52a0\u7279\u5b9a\u914d\u7f6e\u3002\u4e0b\u9762\u5c06\u7ed9\u5927\u5bb6\u7f16\u5199\u4e00\u4e2a ",(0,r.kt)("inlineCode",{parentName:"p"},"HelloTools")," \u5305\u7ba1\u7406\u5de5\u5177\u3002"),(0,r.kt)("h3",{id:"3731-\u521b\u5efa-hellotools-\u63a7\u5236\u53f0\u5e94\u7528"},"37.3.1 \u521b\u5efa ",(0,r.kt)("inlineCode",{parentName:"h3"},"HelloTools")," \u63a7\u5236\u53f0\u5e94\u7528"),(0,r.kt)("img",{src:(0,o.Z)("img/ts1.png")}),(0,r.kt)("h3",{id:"3732-\u7f16\u8f91-hellotoolscsproj"},"37.3.2 \u7f16\u8f91 ",(0,r.kt)("inlineCode",{parentName:"h3"},"HelloTools.csproj")),(0,r.kt)("p",null,"\u5c06\u63a7\u5236\u53f0\u9879\u76ee\u6807\u8bb0\u6210 ",(0,r.kt)("inlineCode",{parentName:"p"},"dotnet tools")," \u9700\u8981\u914d\u7f6e\u4ee5\u4e0b\u8282\u70b9\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-xml",metastring:"showLineNumbers {6-11}",showLineNumbers:!0,"":!0,"{6-11}":!0},'\n\n \n Exe\n net5.0\n 0.0.1\n \u7b2c\u4e00\u4e2a dotnet tools \u5de5\u5177\n hello-tools\n true\n true\n ./nupkg\n \n\n\n')),(0,r.kt)("h4",{id:"\u914d\u7f6e\u5173\u952e\u8282\u70b9\u8bf4\u660e"},"\u914d\u7f6e\u5173\u952e\u8282\u70b9\u8bf4\u660e"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Version"),"\uff1a\u5305\u5de5\u5177\u7248\u672c\u53f7"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Description"),"\uff1a\u5305\u5de5\u5177\u4ecb\u7ecd"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ToolCommandName"),"\uff1a\u5305\u5de5\u5177\u5173\u952e\u5b57\uff0c\u5982 ",(0,r.kt)("inlineCode",{parentName:"li"},"dotnet"),"\u3001",(0,r.kt)("inlineCode",{parentName:"li"},"npm"),"\uff0c\u540e\u7eed\u4f7f\u7528\u90fd\u662f\u901a\u8fc7\u8be5\u5173\u952e\u5b57\u4f7f\u7528"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"PackAsTool"),"\uff1a\u662f\u5426\u58f0\u660e\u4e3a\u5305\u7ba1\u7406\u5de5\u5177\uff0c\u8bbe\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},"true")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"GeneratePackageOnBuild"),"\uff1a\u662f\u5426\u7f16\u8bd1\u65f6\u81ea\u52a8\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"li"},".nupkg")," \u5305\uff0c\u65b9\u4fbf\u540e\u7eed\u4e0a\u4f20\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"Nuget")," \u5e73\u53f0"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"PackageOutputPath"),"\uff1a\u914d\u7f6e ",(0,r.kt)("inlineCode",{parentName:"li"},".nupkg")," \u5305\u5b58\u50a8\u76ee\u5f55\uff0c\u63a8\u8350\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"li"},"./nupkg"))),(0,r.kt)("h3",{id:"3733-\u5b89\u88c5-furiontoolscommandline-\u5305"},"37.3.3 \u5b89\u88c5 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Furion.Tools.CommandLine")," \u5305"),(0,r.kt)("p",null,"\u4e3a\u4e86\u65b9\u4fbf\u7ba1\u7406\u5de5\u5177\u5305\u5f00\u53d1\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u5b98\u65b9\u7279\u610f\u5f00\u53d1\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Tools.CommandLine")," \u5305\uff0c\u5e2e\u52a9\u5927\u5bb6\u5feb\u901f\u5f00\u53d1\u7ba1\u7406\u5de5\u5177\u5305\u3002"),(0,r.kt)("img",{src:(0,o.Z)("img/ts2.png")}),(0,r.kt)("h3",{id:"3734-\u7f16\u5199\u903b\u8f91\u4ee3\u7801"},"37.3.4 \u7f16\u5199\u903b\u8f91\u4ee3\u7801"),(0,r.kt)("p",null,"\u6211\u4eec\u5148\u5b9a\u4e49\u51e0\u4e2a\u9700\u6c42\uff0c\u7136\u540e\u7f16\u5199\u903b\u8f91\u4ee3\u7801\uff1a"),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u4e00\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"hello-tools")," \u6253\u5370\u4ecb\u7ecd\u4fe1\u606f"),(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u4e8c\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"-n")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"--name")," \u8f93\u51fa ",(0,r.kt)("inlineCode",{parentName:"p"},"Hello \u540d\u5b57")),(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u4e09\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"-v")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"--version")," \u8f93\u51fa\u5f53\u524d\u7248\u672c"),(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u56db\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"-h")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"--help")," \u8f93\u51fa\u5e2e\u52a9\u6587\u6863")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("mdxAdmonitionTitle",{parentName:"admonition"},"\u751f\u6210\u63a7\u5236\u53f0 ",(0,r.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"LOGO")),(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},"\u4e0d\u652f\u6301\u4e2d\u6587\uff1a",(0,r.kt)("a",{parentName:"li",href:"http://patorjk.com/software/taag/#p=display&f=Big&t=Furion%20Tools"},"http://patorjk.com/software/taag/#p=display&f=Big&t=Furion%20Tools")),(0,r.kt)("li",{parentName:"ul"},"\u652f\u6301\u6240\u6709\u5b57\u7b26\uff1a",(0,r.kt)("a",{parentName:"li",href:"https://www.qqxiuzi.cn/zh/dianzhenzi-zifu/"},"https://www.qqxiuzi.cn/zh/dianzhenzi-zifu/")))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,10,15-18,26-29,37-40,45}",showLineNumbers:!0,"":!0,"{1,10,15-18,26-29,37-40,45}":!0},'using Furion.Tools.CommandLine;\nusing System;\nusing System.Collections.Generic;\n\nnamespace HelloTools\n{\n class Program\n {\n // \u901a\u8fc7 Cli.Inject() \u5b8c\u6210\u51c6\u5907\u5de5\u4f5c\n static void Main(string[] args) => Cli.Inject();\n\n /// \n /// \u8f93\u51fa Hello \u540d\u5b57\n /// \n [Argument(\'n\', "name", "\u60a8\u7684\u540d\u5b57")]\n static string Name { get; set; }\n // \u5b9a\u4e49\u53c2\u6570\u5904\u7406\u7a0b\u5e8f\uff0c\u5fc5\u987b [\u5c5e\u6027\u540d]+Handler\n static void NameHandler(ArgumentMetadata argument)\n {\n Console.WriteLine($"Hello {Name}");\n }\n\n /// \n /// \u67e5\u770b\u7248\u672c\n /// \n [Argument(\'v\', "version", "\u5de5\u5177\u7248\u672c\u53f7")]\n static bool Version { get; set; }\n // \u5b9a\u4e49\u53c2\u6570\u5904\u7406\u7a0b\u5e8f\uff0c\u5fc5\u987b [\u5c5e\u6027\u540d]+Handler\n static void VersionHandler(ArgumentMetadata argument)\n {\n Console.WriteLine(Cli.GetVersion());\n }\n\n /// \n /// \u67e5\u770b\u5e2e\u52a9\u6587\u6863\n /// \n [Argument(\'h\', "help", "\u67e5\u770b\u5e2e\u52a9\u6587\u6863")]\n static bool Help { get; set; }\n // \u5b9a\u4e49\u53c2\u6570\u5904\u7406\u7a0b\u5e8f\uff0c\u5fc5\u987b [\u5c5e\u6027\u540d]+Handler\n static void HelpHandler(ArgumentMetadata argument)\n {\n Cli.GetHelpText("hello-tools");\n }\n\n // \u6240\u6709\u672a\u5339\u914d\u7684\u53c2\u6570/\u64cd\u4f5c\u7b26\u5904\u7406\u7a0b\u5e8f\uff0c\u56fa\u5b9a NoMatchesHandler \u65b9\u6cd5\u540d\n static void NoMatchesHandler(bool isEmpty, string[] operands, Dictionary noMatches)\n {\n if (isEmpty)\n {\n Console.WriteLine(@"\n _ _ _ _ _______ _\n | | | | | | | |__ __| | |\n | |__| | ___| | | ___ | | ___ ___ | |___\n | __ |/ _ \\ | |/ _ \\ | |/ _ \\ / _ \\| / __|\n | | | | __/ | | (_) | | | (_) | (_) | \\__ \\\n |_| |_|\\___|_|_|\\___/ |_|\\___/ \\___/|_|___/\n\n\n");\n Console.WriteLine($"\u6b22\u8fce\u4f7f\u7528{Cli.GetDescription()}");\n }\n }\n }\n}\n')),(0,r.kt)("admonition",{title:"\u4ee3\u7801\u8bf4\u660e",type:"tip"},(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Furion")," \u5de5\u5177\u5305\u63d0\u4f9b\u4e86\u975e\u5e38\u65b9\u4fbf\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"Cli.Inject()")," \u65b9\u6cd5\uff0c\u53ef\u4ee5\u5b9e\u73b0\u4e00\u6b21\u6027\u5b8c\u6210\u6240\u6709\u521d\u59cb\u5316\u5de5\u4f5c\uff0c\u53ea\u9700\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Main")," \u65b9\u6cd5\u8c03\u7528\u5373\u53ef"),(0,r.kt)("li",{parentName:"ul"},"\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"[Argument(\u77ed\u53c2\u6570\uff0c\u957f\u53c2\u6570\uff0c\u63d0\u793a\u6587\u6863)]")," \u5b9a\u4e49\u6bcf\u4e00\u4e2a\u53c2\u6570\u5c5e\u6027\uff0c\u53c2\u6570\u5fc5\u987b\u662f ",(0,r.kt)("inlineCode",{parentName:"li"},"static")," \u9759\u6001"),(0,r.kt)("li",{parentName:"ul"},"\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"li"},"[\u5c5e\u6027\u540d]Handler")," \u5b9a\u4e49\u6bcf\u4e2a\u53c2\u6570\u5339\u914d\u540e\u7684\u5904\u7406\u7a0b\u5e8f\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"VersionHandler"),"\uff0c\u683c\u5f0f\u4e3a\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"static void \u5c5e\u6027\u540dHandler(ArgumentMetadata argument)")),(0,r.kt)("li",{parentName:"ul"},"\u901a\u8fc7\u56fa\u5b9a\u65b9\u6cd5\u540d ",(0,r.kt)("inlineCode",{parentName:"li"},"NoMatchesHandler")," \u5b9a\u4e49\u672a\u5339\u914d\u7684\u53c2\u6570\u53ca\u64cd\u4f5c\u7b26\uff0c\u8be5\u65b9\u6cd5\u6709\u4e09\u4e2a\u53c2\u6570\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"isEmpty"),"\uff1a\u5224\u65ad\u662f\u5426\u6ca1\u6709\u4f20\u9012\u4efb\u4f55\u53c2\u6570\uff0c\u901a\u5e38\u7528\u4e8e\u8f93\u51fa\u4ecb\u7ecd"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"operands"),"\uff1a\u83b7\u53d6\u6240\u6709\u64cd\u4f5c\u7b26\u5217\u8868"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"noMatches"),"\uff1a\u83b7\u53d6\u6240\u6709\u672a\u5339\u914d\u7684\u53c2\u6570\u5b57\u5178"))))),(0,r.kt)("h3",{id:"3735-\u5982\u4f55\u8c03\u8bd5\u5305\u5de5\u5177-"},"37.3.5 \u5982\u4f55\u8c03\u8bd5\u5305\u5de5\u5177 \ud83d\udc4f"),(0,r.kt)("p",null,"\u5305\u7ba1\u7406\u5de5\u5177\u8c03\u8bd5\u6709\u522b\u4e8e\u666e\u901a\u7684\u63a7\u5236\u53f0\uff0c\u4e3b\u8981\u533a\u522b\u662f\u6d4b\u8bd5\u5404\u4e2a\u53c2\u6570\u7684\u4f7f\u7528\uff0c\u4e5f\u5c31\u662f\u5982\u4f55\u4f20\u9012 ",(0,r.kt)("inlineCode",{parentName:"p"},"Main")," \u65b9\u6cd5\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"args")," \u53c2\u6570\u3002\u53ea\u9700\u8981\u4ee5\u4e0b\u4e24\u4e2a\u6b65\u9aa4\u5373\u53ef\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u5728\u9879\u76ee\u6839\u76ee\u5f55\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"Properties")," \u76ee\u5f55"),(0,r.kt)("li",{parentName:"ul"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Properties")," \u76ee\u5f55\u4e2d\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"li"},"launchSettings.json")," \u6587\u4ef6\uff0c\u5e76\u9075\u5faa\u4ee5\u4e0b\u89c4\u5219\uff1a")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {3,5}",showLineNumbers:!0,"":!0,"{3,5}":!0},'{\n "profiles": {\n "\u9879\u76ee\u540d\u79f0": {\n "commandName": "Project",\n "commandLineArgs": "\u4f60\u7684\u547d\u4ee4"\n }\n }\n}\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"\u9879\u76ee\u540d\u79f0"),"\uff1a\u5199\u4f60\u7684\u9879\u76ee\u5b9e\u9645\u540d\u79f0\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"HelloTools")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"commandName"),"\uff1a\u56fa\u5b9a\u4e3a ",(0,r.kt)("inlineCode",{parentName:"li"},"Project")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"commandLineArgs"),"\uff1a\u7f16\u5199\u6d4b\u8bd5\u547d\u4ee4\uff0c\u53ea\u9700\u8981\u5199\u53c2\u6570/\u64cd\u4f5c\u7b26\u90e8\u5206\u5373\u53ef\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"li"},"-v"),"\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"-v -h --Name Furion"))),(0,r.kt)("p",null,"\u5982\uff0c\u6211\u4eec\u9700\u8981\u6d4b\u8bd5 ",(0,r.kt)("inlineCode",{parentName:"p"},"HelloTools")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"-n")," \u53c2\u6570"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {3,5}",showLineNumbers:!0,"":!0,"{3,5}":!0},'{\n "profiles": {\n "HelloTools": {\n "commandName": "Project",\n "commandLineArgs": "-n Furion"\n }\n }\n}\n')),(0,r.kt)("img",{src:(0,o.Z)("img/ts3.png")}),(0,r.kt)("p",null,"\u70b9\u51fb ",(0,r.kt)("inlineCode",{parentName:"p"},"\u8fd0\u884c/\u8c03\u8bd5/F5")," \u542f\u52a8\u8c03\u8bd5"),(0,r.kt)("img",{src:(0,o.Z)("img/ts4.png")}),(0,r.kt)("h3",{id:"3736-\u6d4b\u8bd5\u5404\u4e2a\u53c2\u6570\u60c5\u51b5"},"37.3.6 \u6d4b\u8bd5\u5404\u4e2a\u53c2\u6570\u60c5\u51b5"),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u4e00\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"hello-tools")," \u6253\u5370\u4ecb\u7ecd\u4fe1\u606f")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},'{\n "profiles": {\n "HelloTools": {\n "commandName": "Project",\n "commandLineArgs": ""\n }\n }\n}\n')),(0,r.kt)("img",{src:(0,o.Z)("img/ts5.png")}),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u4e8c\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"-n")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"--name")," \u8f93\u51fa ",(0,r.kt)("inlineCode",{parentName:"p"},"Hello \u540d\u5b57"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},'{\n "profiles": {\n "HelloTools": {\n "commandName": "Project",\n "commandLineArgs": "-n Furion"\n }\n }\n}\n')),(0,r.kt)("img",{src:(0,o.Z)("img/ts6.png")}),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u4e09\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"-v")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"--version")," \u8f93\u51fa\u5f53\u524d\u7248\u672c")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},'{\n "profiles": {\n "HelloTools": {\n "commandName": "Project",\n "commandLineArgs": "--version"\n }\n }\n}\n')),(0,r.kt)("img",{src:(0,o.Z)("img/ts7.png")}),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u9700\u6c42\u56db\uff1a\u8f93\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"-h")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"--help")," \u8f93\u51fa\u5e2e\u52a9\u6587\u6863")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers {5}",showLineNumbers:!0,"":!0,"{5}":!0},'{\n "profiles": {\n "HelloTools": {\n "commandName": "Project",\n "commandLineArgs": "-h"\n }\n }\n}\n')),(0,r.kt)("img",{src:(0,o.Z)("img/ts8.png")}),(0,r.kt)("h2",{id:"374-\u6253\u5305\u672c\u673a\u6d4b\u8bd5"},"37.4 \u6253\u5305\uff08\u672c\u673a\uff09\u6d4b\u8bd5"),(0,r.kt)("p",null,"\u521a\u521a\u6211\u4eec\u5df2\u7ecf\u5b66\u4f1a\u8c03\u8bd5\u5305\u5de5\u5177\u4e86\uff0c\u4f46\u662f\u8fd8\u672a\u505a\u5230\u7c7b\u4f3c ",(0,r.kt)("inlineCode",{parentName:"p"},"npm")," \u5305\u4e00\u6837\uff0c\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"cmd/powershell")," \u4e2d\u5b89\u88c5\u4e4b\u540e\u53ef\u5728\u547d\u4ee4\u884c\u5168\u5c40\u6d4b\u8bd5\uff0c\u4e0b\u9762\u5c06\u6559\u5927\u5bb6\u5982\u4f55\u5b9e\u73b0 ",(0,r.kt)("inlineCode",{parentName:"p"},"\u5168\u5c40\u5b89\u88c5")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"\u672c\u5730\u5b89\u88c5"),"\u3002"),(0,r.kt)("h3",{id:"3741-\u5168\u5c40\u6253\u5305\u5b89\u88c5"},"37.4.1 \u5168\u5c40\u6253\u5305\u5b89\u88c5"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u5168\u5c40\u6253\u5305\u5b89\u88c5\u5c31\u662f\u914d\u7f6e\u5728\u7cfb\u7edf\u73af\u5883\u53d8\u91cf\u4e2d\uff0c\u5728\u4efb\u4f55\u5730\u65b9\u90fd\u53ef\u4ee5\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"HelloTools")," \u9879\u76ee\u6839\u76ee\u5f55\u4e0b\u6253\u5f00 ",(0,r.kt)("inlineCode",{parentName:"p"},"cmd/powershell"),"\uff08",(0,r.kt)("strong",{parentName:"p"},"\u5c3d\u91cf\u4f7f\u7528\u7ba1\u7406\u5458\u5de5\u5177"),"\uff09\u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,r.kt)("h4",{id:"-\u5b89\u88c5\u5168\u5c40\u5305"},"\u2714 \u5b89\u88c5\u5168\u5c40\u5305"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool install --global --add-source ./nupkg HelloTools\n")),(0,r.kt)("p",null,"\u5176\u4e2d ",(0,r.kt)("inlineCode",{parentName:"p"},"HelloTools")," \u5c31\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"\u9879\u76ee\u540d\u79f0"),"\u3002"),(0,r.kt)("img",{src:(0,o.Z)("img/ts9.png")}),(0,r.kt)("p",null,"\u4e4b\u540e\u6211\u4eec\u5c31\u53ef\u4ee5\u901a\u8fc7\u4e4b\u524d ",(0,r.kt)("inlineCode",{parentName:"p"},"HelloTools.csproj")," \u4e2d\u914d\u7f6e\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"hello-tools")," \u4f7f\u7528\u4e86\u3002"),(0,r.kt)("h4",{id:"-\u6d4b\u8bd5\u5168\u5c40\u5305"},"\u2714 \u6d4b\u8bd5\u5168\u5c40\u5305"),(0,r.kt)("img",{src:(0,o.Z)("img/ts10.png")}),(0,r.kt)("h4",{id:"-\u66f4\u65b0\u5168\u5c40\u5305"},"\u2714 \u66f4\u65b0\u5168\u5c40\u5305"),(0,r.kt)("p",null,"\u5982\u679c\u6e90\u7801\u53d1\u751f\u6539\u53d8\uff0c\u53ea\u9700\u8981\u7f16\u8bd1\u9879\u76ee\u540e\u91cd\u65b0\u66f4\u65b0\u5305\u5de5\u5177\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool update --global --add-source ./nupkg HelloTools\n")),(0,r.kt)("h4",{id:"-\u5378\u8f7d\u5168\u5c40\u5305"},"\u2714 \u5378\u8f7d\u5168\u5c40\u5305"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool uninstall --global HelloTools\n")),(0,r.kt)("p",null,"\u60f3\u4e86\u89e3\u66f4\u591a\u5168\u5c40\u6253\u5305\u5b89\u88c5\u77e5\u8bc6\u67e5\u9605\u5b98\u65b9\u6587\u6863\u5373\u53ef\uff1a",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/dotnet/core/tools/global-tools-how-to-use"},"https://docs.microsoft.com/zh-cn/dotnet/core/tools/global-tools-how-to-use")),(0,r.kt)("h3",{id:"3742-\u672c\u5730\u6253\u5305\u5b89\u88c5"},"37.4.2 \u672c\u5730\u6253\u5305\u5b89\u88c5"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u672c\u5730\u6253\u5305\u5b89\u88c5\u5c31\u662f\u53ea\u6709\u5728\u9879\u76ee\u6240\u5728\u76ee\u5f55\u53ca\u5b50\u5b59\u76ee\u5f55\u65b9\u53ef\u4f7f\u7528\u3002")),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"HelloTools")," \u9879\u76ee\u6839\u76ee\u5f55\u4e0b\u6253\u5f00 ",(0,r.kt)("inlineCode",{parentName:"p"},"cmd/powershell")," \u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,r.kt)("h4",{id:"-\u521b\u5efa\u672c\u5730\u6e05\u5355\u6587\u4ef6"},"\u2714 \u521b\u5efa\u672c\u5730\u6e05\u5355\u6587\u4ef6"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new tool-manifest\n")),(0,r.kt)("p",null,"\u6267\u884c\u8be5\u547d\u4ee4\u540e\u4f1a\u81ea\u52a8\u521b\u5efa ",(0,r.kt)("inlineCode",{parentName:"p"},".config")," \u6587\u4ef6\u5939\u5e76\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"dotnet-tools.json")," \u6587\u4ef6\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:"showLineNumbers",showLineNumbers:!0},'{\n "version": 1,\n "isRoot": true,\n "tools": {}\n}\n')),(0,r.kt)("admonition",{title:"\u6ce8\u610f\u4e8b\u9879",type:"warning"},(0,r.kt)("p",{parentName:"admonition"},"\u901a\u5e38\u8be5\u6587\u4ef6\u5185\u5bb9\u4e0d\u9700\u8981\u624b\u52a8\u66f4\u6539\u3002")),(0,r.kt)("h4",{id:"-\u5b89\u88c5\u672c\u5730\u5305"},"\u2714 \u5b89\u88c5\u672c\u5730\u5305"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool install --add-source ./nupkg HelloTools\n")),(0,r.kt)("img",{src:(0,o.Z)("img/ts11.png")}),(0,r.kt)("h4",{id:"-\u6d4b\u8bd5\u672c\u5730\u5305"},"\u2714 \u6d4b\u8bd5\u672c\u5730\u5305"),(0,r.kt)("p",null,"\u672c\u5730\u5305\u6d4b\u8bd5\u548c\u5168\u5c40\u5305\u4e0d\u4e00\u6837\u7684\u662f\u672c\u5730\u5305\u662f\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"dotnet \u5173\u952e\u5b57 \u53c2\u6570")," \u6d4b\u8bd5\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet hello-tools -n Furion\n")),(0,r.kt)("img",{src:(0,o.Z)("img/ts12.png")}),(0,r.kt)("h4",{id:"-\u66f4\u65b0\u672c\u5730\u5305"},"\u2714 \u66f4\u65b0\u672c\u5730\u5305"),(0,r.kt)("p",null,"\u5982\u679c\u6e90\u7801\u53d1\u751f\u6539\u53d8\uff0c\u53ea\u9700\u8981\u7f16\u8bd1\u9879\u76ee\u540e\u91cd\u65b0\u66f4\u65b0\u5305\u5de5\u5177\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool update --add-source ./nupkg HelloTools\n")),(0,r.kt)("h4",{id:"-\u5378\u8f7d\u672c\u5730\u5305"},"\u2714 \u5378\u8f7d\u672c\u5730\u5305"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool uninstall HelloTools\n")),(0,r.kt)("p",null,"\u60f3\u4e86\u89e3\u66f4\u591a\u672c\u5730\u6253\u5305\u5b89\u88c5\u77e5\u8bc6\u67e5\u9605\u5b98\u65b9\u6587\u6863\u5373\u53ef\uff1a",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/dotnet/core/tools/local-tools-how-to-use"},"https://docs.microsoft.com/zh-cn/dotnet/core/tools/local-tools-how-to-use")),(0,r.kt)("h2",{id:"375-\u53d1\u5e03\u5230-nuget-\u5e73\u53f0-"},"37.5 \u53d1\u5e03\u5230 ",(0,r.kt)("inlineCode",{parentName:"h2"},"Nuget")," \u5e73\u53f0 \ud83d\udc4f"),(0,r.kt)("p",null,"\u53d1\u5e03\u5230 ",(0,r.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5e73\u53f0\u975e\u5e38\u7b80\u5355\uff0c\u53ea\u9700\u8981\u4e24\u4e2a\u6b65\u9aa4\u5373\u53ef\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u5207\u6362\u9879\u76ee ",(0,r.kt)("inlineCode",{parentName:"li"},"Debug")," \u6a21\u5f0f\u5230 ",(0,r.kt)("inlineCode",{parentName:"li"},"Release")," \u5e76\u91cd\u65b0\u7f16\u8bd1\u9879\u76ee"),(0,r.kt)("li",{parentName:"ul"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"li"},"Nuget")," \u5e73\u53f0\u4e0a\u4f20 ",(0,r.kt)("inlineCode",{parentName:"li"},"nupkg")," \u6587\u4ef6\u5939\u5bf9\u5e94 ",(0,r.kt)("inlineCode",{parentName:"li"},"\u9879\u76ee\u540d\u79f0.\u7248\u672c\u53f7.nupkg")," \u6587\u4ef6\u5373\u53ef\uff1a",(0,r.kt)("a",{parentName:"li",href:"https://www.nuget.org/packages/manage/upload"},"https://www.nuget.org/packages/manage/upload"))),(0,r.kt)("admonition",{title:"\u4e0a\u4f20 Nuget \u5e73\u53f0\u8865\u9f50\u4fe1\u606f",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"\u5efa\u8bae\u4e0a\u4f20\u5230 ",(0,r.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5e73\u53f0\u7f16\u8f91 ",(0,r.kt)("inlineCode",{parentName:"p"},".csproj")," \u6587\u4ef6\u8865\u9f50\u4ee5\u4e0b\u4fe1\u606f\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {13-21}",showLineNumbers:!0,"":!0,"{13-21}":!0},'\n\n \n Exe\n net5.0\n 0.0.1\n \u7b2c\u4e00\u4e2a dotnet tools \u5de5\u5177\n hello-tools\n true\n true\n ./nupkg\n\n \u767e\u5c0f\u50e7\n Baiqian Co.,Ltd.\n Furion\n \xa9 2020-2021 \u767e\u5c0f\u50e7, Baiqian Co.,Ltd.\n https://gitee.com/dotnetchina/Furion\n Gitee\n true\n MIT\n https://furion.icu\n \n\n \n \n \n\n\n'))),(0,r.kt)("img",{src:(0,o.Z)("img/ts13.png")}),(0,r.kt)("img",{src:(0,o.Z)("img/ts14.png")}),(0,r.kt)("p",null,"\u53d1\u5e03\u5230 ",(0,r.kt)("inlineCode",{parentName:"p"},"Nuget")," \u5e73\u53f0\u540e\uff0c\u522b\u4eba\u5c31\u53ef\u4ee5\u901a\u8fc7\uff1a"),(0,r.kt)("h4",{id:"-\u5b89\u88c5-nuget-\u5305\u5230\u672c\u5730"},"\u2714 \u5b89\u88c5 Nuget \u5305\u5230\u672c\u5730"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool install --global \u9879\u76ee\u540d --version \u7248\u672c\u53f7\n")),(0,r.kt)("h2",{id:"376-cli-\u9759\u6001\u7c7b\u8bf4\u660e"},"37.6 ",(0,r.kt)("inlineCode",{parentName:"h2"},"Cli")," \u9759\u6001\u7c7b\u8bf4\u660e"),(0,r.kt)("p",null,"\u4e3a\u4e86\u7b80\u5316\u5305\u5de5\u5177\u7684\u5f00\u53d1\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Tools.CommandLine")," \u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Cli")," \u9759\u6001\u7c7b\u63d0\u4f9b\u4e86\u5f88\u591a\u65b9\u4fbf\u7684\u9759\u6001\u65b9\u6cd5\uff1a"),(0,r.kt)("h3",{id:"3761-\u6d88\u606f\u7c7b"},"37.6.1 \u6d88\u606f\u7c7b"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u8f93\u51fa\u7a7a\u884c\nCli.EmptyLine();\n\n// \u8f93\u51fa\u4e00\u884c\nCli.WriteLine("\u6d88\u606f");\nCli.WriteLine("\u6d88\u606f", ConsoleColor.Blue); // \u5b57\u4f53\u989c\u8272\nCli.WriteLine("\u6d88\u606f", ConsoleColor.Blue, ConsoleColor.White); // \u80cc\u666f\u989c\u8272\nCli.WriteLine("\u6d88\u606f", ConsoleColor.Blue, ConsoleColor.White, fillLine: true); // \u586b\u5145\u6574\u884c\n\n// \u8f93\u51fa\uff08\u4e0d\u6362\u884c\uff09\nCli.Write("\u6d88\u606f");\nCli.Write("\u6d88\u606f", ConsoleColor.Blue); // \u5b57\u4f53\u989c\u8272\nCli.Write("\u6d88\u606f", ConsoleColor.Blue, ConsoleColor.White); // \u80cc\u666f\u989c\u8272\nCli.Write("\u6d88\u606f", ConsoleColor.Blue, ConsoleColor.White, fillLine: true); // \u586b\u5145\u6574\u884c\n\n// \u8f93\u51fa\u63d0\u793a\u6d88\u606f\nCli.Success("\u6210\u529f");\nCli.Warn("\u8b66\u544a");\nCli.Error("\u9519\u8bef");\nCli.Tip("\u63d0\u793a");\n\n// \u6536\u96c6\u7528\u6237\u8f93\u5165\uff08\u652f\u6301\u591a\u884c\uff09\nvar inputs = Cli.ReadInput(); // \u8f93\u5165 exit \u9000\u51fa\u8f93\u5165\n\n// \u9009\u62e9\u6d88\u606f\nvar selectId = Cli.ReadOptions("\u8bf7\u9009\u62e9\u559c\u6b22\u7684\u6c34\u679c\uff1a", new []{ "\u897f\u74dc", "\u82f9\u679c", "\u51e4\u68a8"}); // selectId \u4ece 1 \u5f00\u59cb\n')),(0,r.kt)("h3",{id:"3762-\u5de5\u5177\u7c7b"},"37.6.2 \u5de5\u5177\u7c7b"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u5b8c\u6210\u53c2\u6570\u586b\u5145\u5c5e\u6027\u521d\u59cb\u5316\u64cd\u4f5c\nCli.Inject();\n\n// \u83b7\u53d6\u53c2\u6570\u6240\u6709\u4fe1\u606f\nvar arguments = Cli.ArgumentMetadatas;\n\n// \u624b\u52a8\u68c0\u67e5\u53c2\u6570\u662f\u5426\u5339\u914d\nCli.Check(nameof(\u5c5e\u6027\u540d), argument => {\n // \u5982\u679c\u7528\u6237\u8f93\u5165\u8be5\u53c2\u6570\n if(argument?.IsTransmission == true){\n Cli.WriteLine(argument.Value);\n }\n else {\n Cli.Error("\u7528\u6237\u6ca1\u6709\u8f93\u5165");\n }\n});\n\n// \u53ea\u6709\u53c2\u6570\u5339\u914d\u624d\u8fdb\u5165\nCli.CheckMatch(nameof(\u5c5e\u6027\u540d), argument => {\n Cli.WriteLine(argument.Value);\n})\n\n// \u65e0\u5c5e\u6027\u68c0\u67e5\nCli.Check(new[] {"v", "version"}, (isMatch, value) => {\n // \u5982\u679c\u7528\u6237\u8f93\u5165\u8be5\u53c2\u6570\n if(isMatch){\n Cli.WriteLine(value);\n }\n else {\n Cli.Error("\u7528\u6237\u6ca1\u6709\u8f93\u5165");\n }\n});\n\n// \u65e0\u5c5e\u6027\u5339\u914d\nCli.CheckMatch(new[] {"v", "version"}, value => {\n Cli.WriteLine(value);\n});\n\n// \u6240\u6709\u672a\u5339\u914d\u7684\u53c2\u6570\u3001\u64cd\u4f5c\u7b26\nCli.CheckNoMatches((isEmpty, operands, noMatches) => {\n if (isEmpty) Cli.WriteLine($"\u6b22\u8fce\u4f7f\u7528 {Cli.GetDescription()}");\n if (operands.Length > 0) Cli.Error($"\u672a\u627e\u5230\u8be5\u64cd\u4f5c\u7b26\uff1a{string.Join(",", operands)}");\n if (noMatches.Count > 0) Cli.Error($"\u672a\u627e\u5230\u8be5\u53c2\u6570\uff1a{string.Join(",", noMatches.Keys)}");\n});\n\n// \u89e3\u6790 Main \u65b9\u6cd5\u53c2\u6570\u4fe1\u606f\nvar argumentModel = Cli.Parse();\n\n// \u624b\u52a8\u89e3\u6790\u547d\u4ee4\u5b57\u7b26\u4e32\nvar argumentModel = Cli.Parse("-abc foo --hello world");\n\n// \u7ec8\u6b62\u8f93\u51fa/\u7ed3\u675f\u8f93\u51fa\nCli.Exit();\n')),(0,r.kt)("h3",{id:"3762-\u4fe1\u606f\u7c7b"},"37.6.2 \u4fe1\u606f\u7c7b"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u83b7\u53d6\u5f53\u524d\u5de5\u5177\u5305\u7248\u672c\u53f7\nvar version = Cli.GetVersion();\n\n// \u83b7\u53d6\u5f53\u524d\u5de5\u5177\u5305\u63cf\u8ff0\nvar description = Cli.GetDescription();\n")),(0,r.kt)("h3",{id:"3763-\u5176\u4ed6\u7c7b"},"37.6.3 \u5176\u4ed6\u7c7b"),(0,r.kt)("p",null,"\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"Environment")," \u83b7\u53d6\u5f53\u524d\u73af\u5883\u66f4\u591a\u4fe1\u606f\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// \u5f53\u524d\u6267\u884c\u547d\u4ee4\u76ee\u5f55\nvar currentDirectory = Environment.CurrentDirectory;\n\n// \u83b7\u53d6\u673a\u5668\u540d\u79f0\nvar machineName = Environment.MachineName;\n\n// \u7b49\u7b49\u3002\u3002\u3002\u3002\u3002\n")),(0,r.kt)("h2",{id:"377-\u53cd\u9988\u4e0e\u5efa\u8bae"},"37.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,r.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}N.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/afaad682.373f32f8.js b/handbook/build/assets/js/afaad682.373f32f8.js deleted file mode 100644 index 71600103a3..0000000000 --- a/handbook/build/assets/js/afaad682.373f32f8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[7194],{9124:function(e,n,t){t.r(n),t.d(n,{assets:function(){return s},contentTitle:function(){return u},default:function(){return m},frontMatter:function(){return l},metadata:function(){return c},toc:function(){return p}});var r=t(3117),o=t(102),i=(t(7294),t(3905)),a=(t(1402),["components"]),l={slug:"console",title:"5. \u5728\u63a7\u5236\u53f0\u4e2d\u4f7f\u7528",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5",".net6"]},u=void 0,c={permalink:"/furion/blog/console",editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/blog/2021-07-24-console.mdx",source:"@site/blog/2021-07-24-console.mdx",title:"5. \u5728\u63a7\u5236\u53f0\u4e2d\u4f7f\u7528",description:"",date:"2021-07-24T00:00:00.000Z",formattedDate:"July 24, 2021",tags:[{label:"furion",permalink:"/furion/blog/tags/furion"},{label:"furos",permalink:"/furion/blog/tags/furos"},{label:".net",permalink:"/furion/blog/tags/net"},{label:".netcore",permalink:"/furion/blog/tags/netcore"},{label:".net5",permalink:"/furion/blog/tags/net-5"},{label:".net6",permalink:"/furion/blog/tags/net-6"}],readingTime:.84,hasTruncateMarker:!1,authors:[{name:"dotNET China",title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",url:"https://www.chinadot.net",imageURL:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png"}],frontMatter:{slug:"console",title:"5. \u5728\u63a7\u5236\u53f0\u4e2d\u4f7f\u7528",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5",".net6"]},prevItem:{title:"6. .NET 6 Preview 7 \u5c1d\u9c9c",permalink:"/furion/blog/net6-preview7"},nextItem:{title:"4. .NET 6 Preview 6 \u5c1d\u9c9c",permalink:"/furion/blog/net6-preview6"}},s={authorsImageUrls:[void 0]},p=[],f={toc:p};function m(e){var n=e.components,t=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},f,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u4ece ",(0,i.kt)("inlineCode",{parentName:"p"},"v2.15.3+")," \u7248\u672c\u5f00\u59cb\uff0c\u652f\u6301\u5168\u5e73\u53f0\u5e94\u7528\u7a0b\u5e8f\u5f00\u53d1\uff0c\u5305\u62ec ",(0,i.kt)("inlineCode",{parentName:"p"},"Web"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"\u63a7\u5236\u53f0"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"WinForm"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"WPF"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Xamarin/MAUI")," \u7b49\u3002"),(0,i.kt)("p",null,"\u5728\u63a7\u5236\u53f0\u4e2d\u4f7f\u7528\u793a\u4f8b\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'using Furion;\nusing Furion.DependencyInjection;\nusing Furion.RemoteRequest.Extensions;\nusing Microsoft.Extensions.DependencyInjection;\nusing System;\n\nnamespace ConsoleApp1\n{\n class Program\n {\n static void Main(string[] args)\n {\n // \u521b\u5efa\u4e00\u4e2a\u670d\u52a1\u5bb9\u5668\n var services = Inject.Create();\n // \u6ce8\u518c\u670d\u52a1\n services.AddRemoteRequest();\n // \u6240\u6709\u670d\u52a1\u6ce8\u518c\u5b8c\u6bd5\u540e\u8c03\u7528 Build() \u6784\u5efa\n services.Build();\n\n // \u4f7f\u7528\n var helloService = App.GetService();\n Console.WriteLine(helloService.SayHello());\n\n Console.WriteLine("=============");\n\n var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();\n Console.WriteLine(baidu);\n }\n }\n\n public interface IHelloService\n {\n string SayHello();\n }\n public class HelloService : IHelloService, ITransient\n {\n public string SayHello()\n {\n return "Hello Furion.";\n }\n }\n}\n')),(0,i.kt)("p",null,"\u4ee5\u4e0a\u4ee3\u7801\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"var services = Inject.Create();")," \u521b\u5efa\u4e00\u4e2a\u670d\u52a1\u96c6\u5408\uff0c\u6700\u540e\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"services.Build()")," \u5373\u53ef\u5b8c\u6210\u521d\u59cb\u5316\u3002"))}m.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return s},kt:function(){return m}});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function a(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var u=r.createContext({}),c=function(e){var n=r.useContext(u),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},s=function(e){var n=c(e.components);return r.createElement(u.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},f=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),f=c(t),m=o,g=f["".concat(u,".").concat(m)]||f[m]||p[m]||i;return t?r.createElement(g,a(a({ref:n},s),{},{components:t})):r.createElement(g,a({ref:n},s))}));function m(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=f;var l={};for(var u in n)hasOwnProperty.call(n,u)&&(l[u]=n[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var c=2;c=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var u=r.createContext({}),c=function(e){var n=r.useContext(u),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},s=function(e){var n=c(e.components);return r.createElement(u.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},f=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),f=c(t),m=o,g=f["".concat(u,".").concat(m)]||f[m]||p[m]||i;return t?r.createElement(g,a(a({ref:n},s),{},{components:t})):r.createElement(g,a({ref:n},s))}));function m(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=f;var l={};for(var u in n)hasOwnProperty.call(n,u)&&(l[u]=n[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var c=2;c();\n Console.WriteLine(helloService.SayHello());\n\n Console.WriteLine("=============");\n\n var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();\n Console.WriteLine(baidu);\n }\n }\n\n public interface IHelloService\n {\n string SayHello();\n }\n public class HelloService : IHelloService, ITransient\n {\n public string SayHello()\n {\n return "Hello Furion.";\n }\n }\n}\n')),(0,i.kt)("p",null,"\u4ee5\u4e0a\u4ee3\u7801\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"var services = Inject.Create();")," \u521b\u5efa\u4e00\u4e2a\u670d\u52a1\u96c6\u5408\uff0c\u6700\u540e\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"services.Build()")," \u5373\u53ef\u5b8c\u6210\u521d\u59cb\u5316\u3002"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/b0352e4c.7b695c42.js b/handbook/build/assets/js/b0352e4c.7b695c42.js new file mode 100644 index 0000000000..916c1d4806 --- /dev/null +++ b/handbook/build/assets/js/b0352e4c.7b695c42.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[1912],{3905:function(e,n,t){t.d(n,{Zo:function(){return u},kt:function(){return f}});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function c(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var p=r.createContext({}),l=function(e){var n=r.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},u=function(e){var n=l(e.components);return r.createElement(p.Provider,{value:n},e.children)},s={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,p=e.parentName,u=a(e,["components","mdxType","originalType","parentName"]),d=l(t),f=o,y=d["".concat(p,".").concat(f)]||d[f]||s[f]||i;return t?r.createElement(y,c(c({ref:n},u),{},{components:t})):r.createElement(y,c({ref:n},u))}));function f(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,c=new Array(i);c[0]=d;var a={};for(var p in n)hasOwnProperty.call(n,p)&&(a[p]=n[p]);a.originalType=e,a.mdxType="string"==typeof e?e:o,c[1]=a;for(var l=2;l=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var p=r.createContext({}),l=function(e){var n=r.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},u=function(e){var n=l(e.components);return r.createElement(p.Provider,{value:n},e.children)},s={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,p=e.parentName,u=a(e,["components","mdxType","originalType","parentName"]),d=l(t),f=o,y=d["".concat(p,".").concat(f)]||d[f]||s[f]||i;return t?r.createElement(y,c(c({ref:n},u),{},{components:t})):r.createElement(y,c({ref:n},u))}));function f(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,c=new Array(i);c[0]=d;var a={};for(var p in n)hasOwnProperty.call(n,p)&&(a[p]=n[p]);a.originalType=e,a.mdxType="string"==typeof e?e:o,c[1]=a;for(var l=2;l\n var configConnection=new ConnectionConfig()\n {\n DbType = SqlSugar.DbType.MySql,\n ConnectionString = configuration.GetConnectionString(dbName),\n IsAutoCloseConnection = true,\n };\n \n SqlSugarScope sqlSugar = new SqlSugarScope(configConnection,\n db =>\n {\n //\u5355\u4f8b\u53c2\u6570\u914d\u7f6e\uff0c\u6240\u6709\u4e0a\u4e0b\u6587\u751f\u6548\n db.Aop.OnLogExecuting = (sql, pars) =>\n {\n //Console.WriteLine(sql);//\u8f93\u51fasql\n };\n });\n\n services.AddSingleton(sqlSugar);//\u8fd9\u8fb9\u662fSqlSugarScope\u7528AddSingleton\n }\n}\n')),(0,i.kt)("p",null,"\u4f7f\u7528\u6ce8\u5165"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"//1.\u6784\u9020\u51fd\u6570\u6ce8\u5165\nSqlSugar.ISqlSugarClient db;\npublic WeatherForecastController(ISqlSugarClient db) \n{\n\n this.db = db;\n}\n\n//2.\u624b\u52a8\u83b7\u53d6\nApp.GetService();\n")),(0,i.kt)("ol",{start:2},(0,i.kt)("li",{parentName:"ol"},"\u5728 ",(0,i.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u4e2d\u6ce8\u518c\uff1a")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddSqlsugarSetup(App.Configuration);\n")),(0,i.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u9700\u8981\u591a\u5e93\u914d\u7f6e\uff0c\u53ef\u67e5\u770b ",(0,i.kt)("a",{parentName:"p",href:"https://www.donet5.com/home/Doc?typeId=2246"},"https://www.donet5.com/home/Doc?typeId=2246"))),(0,i.kt)("h2",{id:"1015-\u7279\u8272\u529f\u80fd"},"10.1.5 \u7279\u8272\u529f\u80fd"),(0,i.kt)("h3",{id:"10151-\u8054\u8868\u67e5\u8be2"},"10.1.5.1 \u8054\u8868\u67e5\u8be2"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Linq/Lambda"),"\uff1a")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var query5 = db.Queryable()\n .LeftJoin ((o, cus) => o.CustomId == cus.Id)\n .LeftJoin ((o, cus, oritem ) => o.Id == oritem.OrderId)\n .Where(o => o.Id == 1) \n .Select((o, cus) => new ViewOrder { Id = o.Id, CustomName = cus.Name })\n .ToList(); \n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u751f\u6210 ",(0,i.kt)("inlineCode",{parentName:"li"},"SQL"),"\uff1a")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sql",metastring:"showLineNumbers",showLineNumbers:!0},"SELECT\n [o].[Id] AS [Id],\n [cus].[Name] AS [CustomName]\nFROM\n [Order] o\n Left JOIN [Custom] cus ON ([o].[CustomId] = [cus].[Id])\n Left JOIN [OrderDetail] oritem ON ([o].[Id] = [oritem].[OrderId])\nWHERE\n ([o].[Id] = @Id0)\n")),(0,i.kt)("h3",{id:"10152-\u5206\u9875\u67e5\u8be2"},"10.1.5.2 \u5206\u9875\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"int pageIndex = 1; \nint pageSize = 20;\nint totalCount=0;\nvar page = db.Queryable().ToPageList(pageIndex, pageSize, ref totalCount);\n")),(0,i.kt)("h3",{id:"10153-\u52a8\u6001\u8868\u8fbe\u5f0f"},"10.1.5.3 \u52a8\u6001\u8868\u8fbe\u5f0f"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Linq/Lambda"),"\uff1a")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var names= new string [] { "a","b"};\nExpressionable exp = new Expressionable();\n\nforeach (var item in names)\n{\n exp.Or(it => it.Name.Contains(item.ToString()));\n}\n\nvar list= db.Queryable().Where(exp.ToExpression()).ToList();\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u751f\u6210 ",(0,i.kt)("inlineCode",{parentName:"li"},"SQL"),"\uff1a")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sql",metastring:"showLineNumbers",showLineNumbers:!0},"SELECT [Id],[Name],[Price],[CreateTime],[CustomId]\n FROM [Order] WHERE (\n ([Name] like '%'+ CAST(@MethodConst0 AS NVARCHAR(MAX))+'%') OR \n ([Name] like '%'+ CAST(@MethodConst1 AS NVARCHAR(MAX))+'%')\n )\n")),(0,i.kt)("h3",{id:"10154-\u4ed3\u50a8\u65b9\u6cd5"},"10.1.5.4 \u4ed3\u50a8\u65b9\u6cd5"),(0,i.kt)("p",null,"\u65b0\u5efa\u4e00\u4e2a\u4ed3\u50a8\u7c7b\uff0c\u5982\u679c\u60f3\u6269\u5c55\u65b9\u6cd5\u5199\u5230\u4ed3\u50a8\u7c7b\u4e2d"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public class Repository : SimpleClient where T : class, new()\n{\n public Repository(ISqlSugarClient context = null) : base(context)//\u9ed8\u8ba4\u503c\u7b49\u4e8enull\u4e0d\u80fd\u5c11\n {\n base.Context = App.GetService();//\u7528\u624b\u52a8\u83b7\u53d6\u65b9\u5f0f\u652f\u6301\u5207\u6362\u4ed3\u50a8\n }\n}\n")),(0,i.kt)("p",null,"\u7ee7\u627f\u4ed3\u50a8\u7c7b\u5c31\u53ef\u4ee5\u4f7f\u7528\u4ed3\u50a8API\u4e86"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'//\u67e5\u8be2\nvar data1 = base.GetById(1);//\u6839\u636eid\u67e5\u8be2\nvar data4 = base.GetSingle(it => it.Id == 1);//\u67e5\u8be2\u5355\u6761\u8bb0\u5f55\uff0c\u7ed3\u679c\u96c6\u4e0d\u80fd\u8d85\u8fc71\uff0c\u4e0d\u7136\u4f1a\u63d0\u793a\u9519\u8bef\nvar data = base.GetFirst(it => it.Id == 1);//\u67e5\u8be2\u7b2c\u4e00\u6761\u8bb0\u5f55\n\nvar data2 = base.GetList();//\u67e5\u8be2\u6240\u6709\nvar data3 = base.GetList(it => it.Id == 1); //\u6839\u636e\u6761\u4ef6\u67e5\u8be2\n\nvar p = new PageModel() { PageIndex = 1, PageSize = 2 };\nvar data5 = base.GetPageList(it => it.Name == "xx", p);\nConsole.Write(p.PageCount);\n\nvar data6 = base.GetPageList(it => it.Name == "xx", p, it => it.Name, OrderByType.Asc);\nConsole.Write(p.PageCount);\n\nList conModels = new List();\nconModels.Add(new ConditionalModel(){FieldName="id",ConditionalType=ConditionalType.Equal,FieldValue="1"});//id=1\nvar data7 = base.GetPageList(conModels, p, it => it.Name, OrderByType.Asc);\nbase.AsQueryable().Where(x => x.Id == 1).ToList();\n \n//\u63d2\u5165\nbase.Insert(insertObj);\nbase.InsertRange(InsertObjs);\nvar id = base.InsertReturnIdentity(insertObj);\nbase.AsInsertable(insertObj).ExecuteCommand();\n \n//\u5220\u9664\nbase.Delete(insertObj);\nbase.DeleteById(1);\nbase.DeleteByIds(new object [] { 1, 2 }); //\u6570\u7ec4\u5e26\u662f ids\u65b9\u6cd5 \uff0c\u5c01\u88c5\u4f20 object [] \u7c7b\u578b\nbase.Delete(it => it.Id == 1);\nbase.AsDeleteable().Where(it => it.Id == 1).ExecuteCommand();\n \n//\u66f4\u65b0\nbase.Update(insertObj); \nbase.UpdateRange(InsertObjs); \nbase.Update(it => new Order() { Name = "a", }, it => it.Id == 1);\nbase.AsUpdateable(insertObj).UpdateColumns(it=>new { it.Name }).ExecuteCommand();\n \n//\u9ad8\u7ea7\u64cd\u4f5c\nbase.AsSugarClient // \u83b7\u53d6\u5b8c\u6574\u7684db\u5bf9\u8c61\nbase.AsTenant // \u83b7\u53d6\u591a\u5e93\u76f8\u5173\u64cd\u4f5c\n \n//\u5207\u6362\u4ed3\u50a8\nbase.ChangeRepository>() //\u652f\u6301\u591a\u79df\u6237\u548c\u6269\u5c55\u65b9\u6cd5\uff0c\u4f7f\u7528SqlSugarScope\u5355\u4f8b\uff08\u6216\u8005SqlSugarClient Scope\u6ce8\u5165\uff09\nbase.Change()//\u53ea\u652f\u6301\u81ea\u5e26\u65b9\u6cd5\u548c\u5355\u5e93\n')),(0,i.kt)("h3",{id:"10155-\u591a\u5e93\u4e8b\u52a1"},"10.1.5.5 \u591a\u5e93\u4e8b\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SqlSugarClient db = new SqlSugarClient(new List()\n{\n new ConnectionConfig(){ ConfigId="0", DbType=DbType.SqlServer, ConnectionString=Config.ConnectionString, IsAutoCloseConnection=true },\n new ConnectionConfig(){ ConfigId="1", DbType=DbType.MySql, ConnectionString=Config.ConnectionString4 ,IsAutoCloseConnection=true}\n});\n\nvar mysqldb = db.GetConnection("1"); // mysql db\nvar sqlServerdb = db.GetConnection("0"); // sqlserver db\n \ndb.BeginTran();\n\nmysqldb.Insertable(new Order()\n{\n CreateTime = DateTime.Now,\n CustomId = 1,\n Name = "a",\n Price = 1\n}).ExecuteCommand();\nmysqldb.Queryable().ToList();\nsqlServerdb.Queryable().ToList();\n\ndb.CommitTran();\n')),(0,i.kt)("h3",{id:"10156-\u5355\u4f8b\u6a21\u5f0f"},"10.1.5.6 \u5355\u4f8b\u6a21\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public static SqlSugarScope Db = new SqlSugarScope(new ConnectionConfig()\n {\n DbType = SqlSugar.DbType.SqlServer,\n ConnectionString = Config.ConnectionString,\n IsAutoCloseConnection = true \n },\n db=> {\n db.Aop.OnLogExecuting = (s, p) =>\n {\n Console.WriteLine(s);\n };\n });\n \nusing (var tran = Db.UseTran())\n{\n new Test2().Insert(XX);\n new Test1().Insert(XX);\n ..... \n \n tran.CommitTran(); \n}\n")),(0,i.kt)("h3",{id:"10157-\u5168\u5c40\u8fc7\u6ee4\u5668"},"10.1.5.7 \u5168\u5c40\u8fc7\u6ee4\u5668"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"db.QueryFilter.Add(new TableFilterItem(it => it.Name.Contains(\"a\"))); \n \ndb.Queryable().ToList();\n// SELECT [Id],[Name],[Price],[CreateTime],[CustomId] FROM [Order] WHERE ([Name] like '%'+@MethodConst0+'%') \n\ndb.Queryable((i, o) => i.OrderId == o.Id)\n .Where(i => i.OrderId != 0)\n .Select(\"i.*\").ToList();\n// SELECT i.* FROM [OrderDetail] i ,[Order] o WHERE ( [i].[OrderId] = [o].[Id] ) AND \n// ( [i].[OrderId] <> @OrderId0 ) AND ([o].[Name] like '%'+@MethodConst1+'%')\n")),(0,i.kt)("h3",{id:"10158-\u6dfb\u52a0\u6216\u8005\u66f4\u65b0"},"10.1.5.8 \u6dfb\u52a0\u6216\u8005\u66f4\u65b0"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var x = Db.Storageable(list2).ToStorage(); \nx.AsInsertable.ExecuteCommand(); \nx.AsUpdateable.ExecuteCommand(); \n")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var x = Db.Storageable(list).SplitInsert(it => !it.Any()).ToStorage()\nx.AsInsertable.ExecuteCommand(); \n")),(0,i.kt)("h3",{id:"10159-\u81ea\u52a8\u5206\u8868"},"10.1.5.9 \u81ea\u52a8\u5206\u8868"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[SplitTable(SplitType.Year)] // Table by year (the table supports year, quarter, month, week and day)\n[SugarTable("SplitTestTable_{year}{month}{day}")] \npublic class SplitTestTable\n{\n [SugarColumn(IsPrimaryKey =true)]\n public long Id { get; set; }\n\n public string Name { get; set; }\n \n //When the sub-table field is inserted, which table will be inserted according to this field. \n //When it is updated and deleted, it can also be convenient to use this field to \n //find out the related table \n [SplitField] \n public DateTime CreateTime { get; set; }\n}\n')),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var lis2t = db.Queryable()\n.SplitTable(DateTime.Now.Date.AddYears(-1), DateTime.Now)\n.ToPageList(1,2);\u3000\n")),(0,i.kt)("h3",{id:"101510-\u5927\u6570\u636e\u63d2\u5165\u66f4\u65b0\u63d2\u5165\u6216\u8005\u66f4\u65b0"},"10.1.5.10 \u5927\u6570\u636e\u63d2\u5165\uff0c\u66f4\u65b0\uff0c\u63d2\u5165\u6216\u8005\u66f4\u65b0"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'//Insert A million only takes a few seconds\ndb.Fastest().BulkCopy(GetList());\n \n//update A million only takes a few seconds\ndb.Fastest().BulkUpdate(GetList());//A million only takes a few seconds\u5b8c\ndb.Fastest().BulkUpdate(GetList(),new string[]{"id"},new string[]{"name","time"})//no primary key\n \n//if exists update, else insert\n var x= db.Storageable(data).ToStorage();\n x.BulkCopy();\n x.BulkUpdate(); \n \n//set table name\ndb.Fastest().AS("tableName").BulkCopy(GetList())\n \n//set page \ndb.Fastest().PageSize(300000).BulkCopy(insertObjs);\n')),(0,i.kt)("h3",{id:"101511-\u66f4\u591a\u529f\u80fd"},"10.1.5.11 \u66f4\u591a\u529f\u80fd"),(0,i.kt)("p",null,"\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://www.donet5.com/Home/Doc"},"SqlSugar \u5b98\u7f51"),"\u3002"),(0,i.kt)("h2",{id:"1016-\u53cd\u9988\u4e0e\u5efa\u8bae"},"10.1.6 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,i.kt)("hr",null),(0,i.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"p"},"SqlSugar")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://www.donet5.com/Home/Doc"},"SqlSugar \u5b98\u7f51"),"\u3002")))}c.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return d},kt:function(){return c}});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function l(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),u=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},d=function(e){var n=u(e.components);return a.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,s=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),m=u(t),c=r,g=m["".concat(s,".").concat(c)]||m[c]||p[c]||i;return t?a.createElement(g,l(l({ref:n},d),{},{components:t})):a.createElement(g,l({ref:n},d))}));function c(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,l=new Array(i);l[0]=m;var o={};for(var s in n)hasOwnProperty.call(n,s)&&(o[s]=n[s]);o.originalType=e,o.mdxType="string"==typeof e?e:r,l[1]=o;for(var u=2;u=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),u=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},d=function(e){var n=u(e.components);return a.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,s=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),m=u(t),c=r,g=m["".concat(s,".").concat(c)]||m[c]||p[c]||i;return t?a.createElement(g,l(l({ref:n},d),{},{components:t})):a.createElement(g,l({ref:n},d))}));function c(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,l=new Array(i);l[0]=m;var o={};for(var s in n)hasOwnProperty.call(n,s)&&(o[s]=n[s]);o.originalType=e,o.mdxType="string"==typeof e?e:r,l[1]=o;for(var u=2;u\n var configConnection=new ConnectionConfig()\n {\n DbType = SqlSugar.DbType.MySql,\n ConnectionString = configuration.GetConnectionString(dbName),\n IsAutoCloseConnection = true,\n };\n \n SqlSugarScope sqlSugar = new SqlSugarScope(configConnection,\n db =>\n {\n //\u5355\u4f8b\u53c2\u6570\u914d\u7f6e\uff0c\u6240\u6709\u4e0a\u4e0b\u6587\u751f\u6548\n db.Aop.OnLogExecuting = (sql, pars) =>\n {\n //Console.WriteLine(sql);//\u8f93\u51fasql\n };\n });\n\n services.AddSingleton(sqlSugar);//\u8fd9\u8fb9\u662fSqlSugarScope\u7528AddSingleton\n }\n}\n')),(0,i.kt)("p",null,"\u4f7f\u7528\u6ce8\u5165"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"//1.\u6784\u9020\u51fd\u6570\u6ce8\u5165\nSqlSugar.ISqlSugarClient db;\npublic WeatherForecastController(ISqlSugarClient db) \n{\n\n this.db = db;\n}\n\n//2.\u624b\u52a8\u83b7\u53d6\nApp.GetService();\n")),(0,i.kt)("ol",{start:2},(0,i.kt)("li",{parentName:"ol"},"\u5728 ",(0,i.kt)("inlineCode",{parentName:"li"},"Startup.cs")," \u4e2d\u6ce8\u518c\uff1a")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddSqlsugarSetup(App.Configuration);\n")),(0,i.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u9700\u8981\u591a\u5e93\u914d\u7f6e\uff0c\u53ef\u67e5\u770b ",(0,i.kt)("a",{parentName:"p",href:"https://www.donet5.com/home/Doc?typeId=2246"},"https://www.donet5.com/home/Doc?typeId=2246"))),(0,i.kt)("h2",{id:"1015-\u7279\u8272\u529f\u80fd"},"10.1.5 \u7279\u8272\u529f\u80fd"),(0,i.kt)("h3",{id:"10151-\u8054\u8868\u67e5\u8be2"},"10.1.5.1 \u8054\u8868\u67e5\u8be2"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Linq/Lambda"),"\uff1a")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var query5 = db.Queryable()\n .LeftJoin ((o, cus) => o.CustomId == cus.Id)\n .LeftJoin ((o, cus, oritem ) => o.Id == oritem.OrderId)\n .Where(o => o.Id == 1) \n .Select((o, cus) => new ViewOrder { Id = o.Id, CustomName = cus.Name })\n .ToList(); \n")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u751f\u6210 ",(0,i.kt)("inlineCode",{parentName:"li"},"SQL"),"\uff1a")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sql",metastring:"showLineNumbers",showLineNumbers:!0},"SELECT\n [o].[Id] AS [Id],\n [cus].[Name] AS [CustomName]\nFROM\n [Order] o\n Left JOIN [Custom] cus ON ([o].[CustomId] = [cus].[Id])\n Left JOIN [OrderDetail] oritem ON ([o].[Id] = [oritem].[OrderId])\nWHERE\n ([o].[Id] = @Id0)\n")),(0,i.kt)("h3",{id:"10152-\u5206\u9875\u67e5\u8be2"},"10.1.5.2 \u5206\u9875\u67e5\u8be2"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"int pageIndex = 1; \nint pageSize = 20;\nint totalCount=0;\nvar page = db.Queryable().ToPageList(pageIndex, pageSize, ref totalCount);\n")),(0,i.kt)("h3",{id:"10153-\u52a8\u6001\u8868\u8fbe\u5f0f"},"10.1.5.3 \u52a8\u6001\u8868\u8fbe\u5f0f"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Linq/Lambda"),"\uff1a")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var names= new string [] { "a","b"};\nExpressionable exp = new Expressionable();\n\nforeach (var item in names)\n{\n exp.Or(it => it.Name.Contains(item.ToString()));\n}\n\nvar list= db.Queryable().Where(exp.ToExpression()).ToList();\n')),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u751f\u6210 ",(0,i.kt)("inlineCode",{parentName:"li"},"SQL"),"\uff1a")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sql",metastring:"showLineNumbers",showLineNumbers:!0},"SELECT [Id],[Name],[Price],[CreateTime],[CustomId]\n FROM [Order] WHERE (\n ([Name] like '%'+ CAST(@MethodConst0 AS NVARCHAR(MAX))+'%') OR \n ([Name] like '%'+ CAST(@MethodConst1 AS NVARCHAR(MAX))+'%')\n )\n")),(0,i.kt)("h3",{id:"10154-\u4ed3\u50a8\u65b9\u6cd5"},"10.1.5.4 \u4ed3\u50a8\u65b9\u6cd5"),(0,i.kt)("p",null,"\u65b0\u5efa\u4e00\u4e2a\u4ed3\u50a8\u7c7b\uff0c\u5982\u679c\u60f3\u6269\u5c55\u65b9\u6cd5\u5199\u5230\u4ed3\u50a8\u7c7b\u4e2d"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public class Repository : SimpleClient where T : class, new()\n{\n public Repository(ISqlSugarClient context = null) : base(context)//\u9ed8\u8ba4\u503c\u7b49\u4e8enull\u4e0d\u80fd\u5c11\n {\n base.Context = App.GetService();//\u7528\u624b\u52a8\u83b7\u53d6\u65b9\u5f0f\u652f\u6301\u5207\u6362\u4ed3\u50a8\n }\n}\n")),(0,i.kt)("p",null,"\u7ee7\u627f\u4ed3\u50a8\u7c7b\u5c31\u53ef\u4ee5\u4f7f\u7528\u4ed3\u50a8API\u4e86"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'//\u67e5\u8be2\nvar data1 = base.GetById(1);//\u6839\u636eid\u67e5\u8be2\nvar data4 = base.GetSingle(it => it.Id == 1);//\u67e5\u8be2\u5355\u6761\u8bb0\u5f55\uff0c\u7ed3\u679c\u96c6\u4e0d\u80fd\u8d85\u8fc71\uff0c\u4e0d\u7136\u4f1a\u63d0\u793a\u9519\u8bef\nvar data = base.GetFirst(it => it.Id == 1);//\u67e5\u8be2\u7b2c\u4e00\u6761\u8bb0\u5f55\n\nvar data2 = base.GetList();//\u67e5\u8be2\u6240\u6709\nvar data3 = base.GetList(it => it.Id == 1); //\u6839\u636e\u6761\u4ef6\u67e5\u8be2\n\nvar p = new PageModel() { PageIndex = 1, PageSize = 2 };\nvar data5 = base.GetPageList(it => it.Name == "xx", p);\nConsole.Write(p.PageCount);\n\nvar data6 = base.GetPageList(it => it.Name == "xx", p, it => it.Name, OrderByType.Asc);\nConsole.Write(p.PageCount);\n\nList conModels = new List();\nconModels.Add(new ConditionalModel(){FieldName="id",ConditionalType=ConditionalType.Equal,FieldValue="1"});//id=1\nvar data7 = base.GetPageList(conModels, p, it => it.Name, OrderByType.Asc);\nbase.AsQueryable().Where(x => x.Id == 1).ToList();\n \n//\u63d2\u5165\nbase.Insert(insertObj);\nbase.InsertRange(InsertObjs);\nvar id = base.InsertReturnIdentity(insertObj);\nbase.AsInsertable(insertObj).ExecuteCommand();\n \n//\u5220\u9664\nbase.Delete(insertObj);\nbase.DeleteById(1);\nbase.DeleteByIds(new object [] { 1, 2 }); //\u6570\u7ec4\u5e26\u662f ids\u65b9\u6cd5 \uff0c\u5c01\u88c5\u4f20 object [] \u7c7b\u578b\nbase.Delete(it => it.Id == 1);\nbase.AsDeleteable().Where(it => it.Id == 1).ExecuteCommand();\n \n//\u66f4\u65b0\nbase.Update(insertObj); \nbase.UpdateRange(InsertObjs); \nbase.Update(it => new Order() { Name = "a", }, it => it.Id == 1);\nbase.AsUpdateable(insertObj).UpdateColumns(it=>new { it.Name }).ExecuteCommand();\n \n//\u9ad8\u7ea7\u64cd\u4f5c\nbase.AsSugarClient // \u83b7\u53d6\u5b8c\u6574\u7684db\u5bf9\u8c61\nbase.AsTenant // \u83b7\u53d6\u591a\u5e93\u76f8\u5173\u64cd\u4f5c\n \n//\u5207\u6362\u4ed3\u50a8\nbase.ChangeRepository>() //\u652f\u6301\u591a\u79df\u6237\u548c\u6269\u5c55\u65b9\u6cd5\uff0c\u4f7f\u7528SqlSugarScope\u5355\u4f8b\uff08\u6216\u8005SqlSugarClient Scope\u6ce8\u5165\uff09\nbase.Change()//\u53ea\u652f\u6301\u81ea\u5e26\u65b9\u6cd5\u548c\u5355\u5e93\n')),(0,i.kt)("h3",{id:"10155-\u591a\u5e93\u4e8b\u52a1"},"10.1.5.5 \u591a\u5e93\u4e8b\u52a1"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SqlSugarClient db = new SqlSugarClient(new List()\n{\n new ConnectionConfig(){ ConfigId="0", DbType=DbType.SqlServer, ConnectionString=Config.ConnectionString, IsAutoCloseConnection=true },\n new ConnectionConfig(){ ConfigId="1", DbType=DbType.MySql, ConnectionString=Config.ConnectionString4 ,IsAutoCloseConnection=true}\n});\n\nvar mysqldb = db.GetConnection("1"); // mysql db\nvar sqlServerdb = db.GetConnection("0"); // sqlserver db\n \ndb.BeginTran();\n\nmysqldb.Insertable(new Order()\n{\n CreateTime = DateTime.Now,\n CustomId = 1,\n Name = "a",\n Price = 1\n}).ExecuteCommand();\nmysqldb.Queryable().ToList();\nsqlServerdb.Queryable().ToList();\n\ndb.CommitTran();\n')),(0,i.kt)("h3",{id:"10156-\u5355\u4f8b\u6a21\u5f0f"},"10.1.5.6 \u5355\u4f8b\u6a21\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public static SqlSugarScope Db = new SqlSugarScope(new ConnectionConfig()\n {\n DbType = SqlSugar.DbType.SqlServer,\n ConnectionString = Config.ConnectionString,\n IsAutoCloseConnection = true \n },\n db=> {\n db.Aop.OnLogExecuting = (s, p) =>\n {\n Console.WriteLine(s);\n };\n });\n \nusing (var tran = Db.UseTran())\n{\n new Test2().Insert(XX);\n new Test1().Insert(XX);\n ..... \n \n tran.CommitTran(); \n}\n")),(0,i.kt)("h3",{id:"10157-\u5168\u5c40\u8fc7\u6ee4\u5668"},"10.1.5.7 \u5168\u5c40\u8fc7\u6ee4\u5668"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"db.QueryFilter.Add(new TableFilterItem(it => it.Name.Contains(\"a\"))); \n \ndb.Queryable().ToList();\n// SELECT [Id],[Name],[Price],[CreateTime],[CustomId] FROM [Order] WHERE ([Name] like '%'+@MethodConst0+'%') \n\ndb.Queryable((i, o) => i.OrderId == o.Id)\n .Where(i => i.OrderId != 0)\n .Select(\"i.*\").ToList();\n// SELECT i.* FROM [OrderDetail] i ,[Order] o WHERE ( [i].[OrderId] = [o].[Id] ) AND \n// ( [i].[OrderId] <> @OrderId0 ) AND ([o].[Name] like '%'+@MethodConst1+'%')\n")),(0,i.kt)("h3",{id:"10158-\u6dfb\u52a0\u6216\u8005\u66f4\u65b0"},"10.1.5.8 \u6dfb\u52a0\u6216\u8005\u66f4\u65b0"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var x = Db.Storageable(list2).ToStorage(); \nx.AsInsertable.ExecuteCommand(); \nx.AsUpdateable.ExecuteCommand(); \n")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var x = Db.Storageable(list).SplitInsert(it => !it.Any()).ToStorage()\nx.AsInsertable.ExecuteCommand(); \n")),(0,i.kt)("h3",{id:"10159-\u81ea\u52a8\u5206\u8868"},"10.1.5.9 \u81ea\u52a8\u5206\u8868"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'[SplitTable(SplitType.Year)] // Table by year (the table supports year, quarter, month, week and day)\n[SugarTable("SplitTestTable_{year}{month}{day}")] \npublic class SplitTestTable\n{\n [SugarColumn(IsPrimaryKey =true)]\n public long Id { get; set; }\n\n public string Name { get; set; }\n \n //When the sub-table field is inserted, which table will be inserted according to this field. \n //When it is updated and deleted, it can also be convenient to use this field to \n //find out the related table \n [SplitField] \n public DateTime CreateTime { get; set; }\n}\n')),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var lis2t = db.Queryable()\n.SplitTable(DateTime.Now.Date.AddYears(-1), DateTime.Now)\n.ToPageList(1,2);\u3000\n")),(0,i.kt)("h3",{id:"101510-\u5927\u6570\u636e\u63d2\u5165\u66f4\u65b0\u63d2\u5165\u6216\u8005\u66f4\u65b0"},"10.1.5.10 \u5927\u6570\u636e\u63d2\u5165\uff0c\u66f4\u65b0\uff0c\u63d2\u5165\u6216\u8005\u66f4\u65b0"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'//Insert A million only takes a few seconds\ndb.Fastest().BulkCopy(GetList());\n \n//update A million only takes a few seconds\ndb.Fastest().BulkUpdate(GetList());//A million only takes a few seconds\u5b8c\ndb.Fastest().BulkUpdate(GetList(),new string[]{"id"},new string[]{"name","time"})//no primary key\n \n//if exists update, else insert\n var x= db.Storageable(data).ToStorage();\n x.BulkCopy();\n x.BulkUpdate(); \n \n//set table name\ndb.Fastest().AS("tableName").BulkCopy(GetList())\n \n//set page \ndb.Fastest().PageSize(300000).BulkCopy(insertObjs);\n')),(0,i.kt)("h3",{id:"101511-\u66f4\u591a\u529f\u80fd"},"10.1.5.11 \u66f4\u591a\u529f\u80fd"),(0,i.kt)("p",null,"\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://www.donet5.com/Home/Doc"},"SqlSugar \u5b98\u7f51"),"\u3002"),(0,i.kt)("h2",{id:"1016-\u53cd\u9988\u4e0e\u5efa\u8bae"},"10.1.6 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,i.kt)("hr",null),(0,i.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,i.kt)("inlineCode",{parentName:"p"},"SqlSugar")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,i.kt)("a",{parentName:"p",href:"https://www.donet5.com/Home/Doc"},"SqlSugar \u5b98\u7f51"),"\u3002")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/b4685f05.0886951d.js b/handbook/build/assets/js/b4685f05.0886951d.js deleted file mode 100644 index c90cc06371..0000000000 --- a/handbook/build/assets/js/b4685f05.0886951d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[9138],{4476:function(e,n,t){t.r(n),t.d(n,{assets:function(){return c},contentTitle:function(){return p},default:function(){return v},frontMatter:function(){return l},metadata:function(){return u},toc:function(){return m}});var i=t(3117),r=t(102),a=(t(7294),t(3905)),o=t(1402),s=["components"],l={id:"sensitive-detection",title:"30. \u8131\u654f\u5904\u7406",sidebar_label:"30. \u8131\u654f\u5904\u7406"},p=void 0,u={unversionedId:"sensitive-detection",id:"sensitive-detection",title:"30. \u8131\u654f\u5904\u7406",description:"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 Furion 2.4.4 + \u7248\u672c\u4f7f\u7528\u3002",source:"@site/docs/sensitive-detection.mdx",sourceDirName:".",slug:"/sensitive-detection",permalink:"/furion/docs/sensitive-detection",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/sensitive-detection.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1658474111,formattedLastUpdatedAt:"Jul 22, 2022",frontMatter:{id:"sensitive-detection",title:"30. \u8131\u654f\u5904\u7406",sidebar_label:"30. \u8131\u654f\u5904\u7406"},sidebar:"docs",previous:{title:"29. \u7c98\u571f\u5bf9\u8c61",permalink:"/furion/docs/clayobj"},next:{title:"31. \u865a\u62df\u6587\u4ef6\u7cfb\u7edf\uff08\u4e0a\u4f20\u4e0b\u8f7d\uff09",permalink:"/furion/docs/file-provider"}},c={},m=[{value:"30.1 \u5173\u4e8e\u8131\u654f",id:"301-\u5173\u4e8e\u8131\u654f",level:2},{value:"30.2 \u5982\u4f55\u4f7f\u7528",id:"302-\u5982\u4f55\u4f7f\u7528",level:2},{value:"30.2.1 \u6ce8\u518c \u8131\u654f\u8bcd\u6c47\u68c0\u6d4b \u670d\u52a1",id:"3021-\u6ce8\u518c-\u8131\u654f\u8bcd\u6c47\u68c0\u6d4b-\u670d\u52a1",level:3},{value:"30.2.2 \u521b\u5efa sensitive-words.txt \u6587\u4ef6",id:"3022-\u521b\u5efa-sensitive-wordstxt-\u6587\u4ef6",level:3},{value:"30.2.3 \u4f7f\u7528\u8131\u654f\u68c0\u6d4b",id:"3023-\u4f7f\u7528\u8131\u654f\u68c0\u6d4b",level:3},{value:"30.2.3 \u8131\u654f\u8bcd\u6c47\u66ff\u6362",id:"3023-\u8131\u654f\u8bcd\u6c47\u66ff\u6362",level:3},{value:"30.3 \u81ea\u5b9a\u4e49\u8131\u654f\u8bcd\u6c47\u5904\u7406",id:"303-\u81ea\u5b9a\u4e49\u8131\u654f\u8bcd\u6c47\u5904\u7406",level:2},{value:"30.3.1 \u81ea\u5b9a\u4e49 ISensitiveDetectionProvider \u7a0b\u5e8f\uff0c\u5982\uff1a",id:"3031-\u81ea\u5b9a\u4e49-isensitivedetectionprovider-\u7a0b\u5e8f\u5982",level:3},{value:"30.3.2 \u6ce8\u518c\u81ea\u5b9a\u4e49\u8131\u654f\u63d0\u4f9b\u5668",id:"3032-\u6ce8\u518c\u81ea\u5b9a\u4e49\u8131\u654f\u63d0\u4f9b\u5668",level:3},{value:"30.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"304-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:m};function v(e){var n=e.components,t=(0,r.Z)(e,s);return(0,a.kt)("wrapper",(0,i.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 2.4.4 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,a.kt)("h2",{id:"301-\u5173\u4e8e\u8131\u654f"},"30.1 \u5173\u4e8e\u8131\u654f"),(0,a.kt)("p",null,"\u5f15\u7528\u767e\u5ea6\u767e\u79d1\uff1a"),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},"\u6570\u636e\u8131\u654f\u662f\u6307\u5bf9\u67d0\u4e9b\u654f\u611f\u4fe1\u606f\u901a\u8fc7\u8131\u654f\u89c4\u5219\u8fdb\u884c\u6570\u636e\u7684\u53d8\u5f62\uff0c\u5b9e\u73b0\u654f\u611f\u9690\u79c1\u6570\u636e\u7684\u53ef\u9760\u4fdd\u62a4\u3002\u5728\u6d89\u53ca\u5ba2\u6237\u5b89\u5168\u6570\u636e\u6216\u8005\u4e00\u4e9b\u5546\u4e1a\u6027\u654f\u611f\u6570\u636e\u7684\u60c5\u51b5\u4e0b\uff0c\u5728\u4e0d\u8fdd\u53cd\u7cfb\u7edf\u89c4\u5219\u6761\u4ef6\u4e0b\uff0c\u5bf9\u771f\u5b9e\u6570\u636e\u8fdb\u884c\u6539\u9020\u5e76\u63d0\u4f9b\u6d4b\u8bd5\u4f7f\u7528\uff0c\u5982\u8eab\u4efd\u8bc1\u53f7\u3001\u624b\u673a\u53f7\u3001\u5361\u53f7\u3001\u5ba2\u6237\u53f7\u7b49\u4e2a\u4eba\u4fe1\u606f\u90fd\u9700\u8981\u8fdb\u884c\u6570\u636e\u8131\u654f\u3002\u6570\u636e\u5b89\u5168\u6280\u672f\u4e4b\u4e00\uff0c\u6570\u636e\u5e93\u5b89\u5168\u6280\u672f\u4e3b\u8981\u5305\u62ec\uff1a\u6570\u636e\u5e93\u6f0f\u626b\u3001\u6570\u636e\u5e93\u52a0\u5bc6\u3001\u6570\u636e\u5e93\u9632\u706b\u5899\u3001\u6570\u636e\u8131\u654f\u3001\u6570\u636e\u5e93\u5b89\u5168\u5ba1\u8ba1\u7cfb\u7edf\u3002")),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u7cfb\u7edf\u4e2d\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"\u8131\u654f\u5904\u7406")," \u6307\u7684\u662f\u5bf9\u4e0d\u7b26\u5408\u7cfb\u7edf\u5408\u6cd5\u8bcd\u6c47\u68c0\u6d4b\u9a8c\u8bc1\u3002"),(0,a.kt)("h2",{id:"302-\u5982\u4f55\u4f7f\u7528"},"30.2 \u5982\u4f55\u4f7f\u7528"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u5185\u7f6e\u4e86\u4e00\u5957\u9ed8\u8ba4\u7684\u8131\u654f\u8bcd\u6c47\u8131\u654f\u5904\u7406\u673a\u5236\uff0c\u5e76\u4e14\u63d0\u4f9b\u81ea\u5b9a\u4e49\u64cd\u4f5c\u3002"),(0,a.kt)("h3",{id:"3021-\u6ce8\u518c-\u8131\u654f\u8bcd\u6c47\u68c0\u6d4b-\u670d\u52a1"},"30.2.1 \u6ce8\u518c ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u8131\u654f\u8bcd\u6c47\u68c0\u6d4b")," \u670d\u52a1"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public void ConfigureServices(IServiceCollection services)\n{\n services.AddSensitiveDetection();\n}\n")),(0,a.kt)("h3",{id:"3022-\u521b\u5efa-sensitive-wordstxt-\u6587\u4ef6"},"30.2.2 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h3"},"sensitive-words.txt")," \u6587\u4ef6"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u542f\u52a8\u5c42\u9879\u76ee\u4e2d\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"sensitive-words.txt")," \u6587\u4ef6\uff0c",(0,a.kt)("strong",{parentName:"p"},"\u786e\u4fdd\u91c7\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"UTF-8")," \u7f16\u7801\u683c\u5f0f\u4e14\u4e0d\u80fd\u5e26 ",(0,a.kt)("inlineCode",{parentName:"strong"},"BOM \u7b7e\u540d")," \u4e14\u8bbe\u7f6e\u4e3a\u5d4c\u5165\u5f0f\u8d44\u6e90\uff01"),"\ud83c\udf83"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"sensitive-words.txt")," \u5185\u5bb9\u683c\u5f0f\u4e3a\u6bcf\u4e00\u884c\u6807\u8bc6\u4e00\u4e2a\u8131\u654f\u8bcd\u6c47\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-showLineNumbers"},"\u574f\u4eba\n\u65e0\u8bed\n\u6eda\u5f00\n\u516b\u560e\n")),(0,a.kt)("admonition",{title:"3.8.9+ \u7248\u672c",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 3.8.9+")," \u7248\u672c\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"p"},"|")," \u5206\u9694\u7b26\u8fdb\u884c\u5206\u5272\uff0c\u4e5f\u540c\u65f6\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6362\u884c")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"|")," \u6df7\u7528\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-showLineNumbers"},"\u574f\u4eba|\u65e0\u8bed|\u6eda\u5f00\n\u516b\u560e\n")),(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("strong",{parentName:"p"},"\u63a8\u8350\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"|")," \u65b9\u5f0f\uff0c\u53ef\u4ee5\u8282\u7701\u8bcd\u5e93\u5360\u7528\u5b58\u50a8\u7a7a\u95f4\u3002"))),(0,a.kt)("p",null,"\u63a5\u4e0b\u6765\u8bbe\u7f6e\u4e3a\u5d4c\u5165\u5f0f\u8d44\u6e90\uff1a"),(0,a.kt)("img",{src:(0,o.Z)("img/tm.png")}),(0,a.kt)("h3",{id:"3023-\u4f7f\u7528\u8131\u654f\u68c0\u6d4b"},"30.2.3 \u4f7f\u7528\u8131\u654f\u68c0\u6d4b"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5b9e\u73b0\u6570\u636e\u9a8c\u8bc1\u8131\u654f\u68c0\u6d4b ",(0,a.kt)("inlineCode",{parentName:"strong"},"[SensitiveDetection]")))),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"[SensitiveDetection]")," \u9a8c\u8bc1\u7279\u6027\uff0c\u53ef\u4ee5\u5bf9\u53c2\u6570\u3001\u5c5e\u6027\u8fdb\u884c\u8131\u654f\u9a8c\u8bc1\uff0c\u7528\u6cd5\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"[DataValidation]")," \u4e00\u81f4\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,9}",showLineNumbers:!0,"":!0,"{4,9}":!0},"// \u5728\u5c5e\u6027\u4e2d\u4f7f\u7528\npublic class Content\n{\n [SensitiveDetection]\n public string Text { get; set; }\n}\n\n// \u5728 \u52a8\u6001API/Controller \u4e2d\u4f7f\u7528\npublic void Test([SensitiveDetection] string text)\n{\n\n}\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"strong"},"ISensitiveDetectionProvider")," \u670d\u52a1\u4f7f\u7528"))),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e5f\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"ISensitiveDetectionProvider")," \u670d\u52a1\u8fdb\u884c\u624b\u52a8\u8131\u654f\u9a8c\u8bc1\u5904\u7406\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,15,25,35}",showLineNumbers:!0,"":!0,"{4,15,25,35}":!0},'public class FurionService\n{\n private readonly ISensitiveDetectionProvider _sensitiveDetectionProvider;\n public FurionService(ISensitiveDetectionProvider sensitiveDetectionProvider)\n {\n _sensitiveDetectionProvider = sensitiveDetectionProvider;\n }\n\n /// \n /// \u83b7\u53d6\u6240\u6709\u8131\u654f\u8bcd\u6c47\n /// \n /// \n public async Task> GetWordsAsync()\n {\n return await _sensitiveDetectionProvider.GetWordsAsync();\n }\n\n /// \n /// \u5224\u65ad\u662f\u5426\u662f\u6b63\u5e38\u7684\u8bcd\u6c47\n /// \n /// \n /// \n public async Task VaildedAsync(string text)\n {\n return await _sensitiveDetectionProvider.VaildedAsync(text);\n }\n\n /// \n /// \u66ff\u6362\u975e\u6b63\u5e38\u8bcd\u6c47\n /// \n /// \n /// \n public async Task ReplaceAsync(string text)\n {\n return await _sensitiveDetectionProvider.ReplaceAsync(text, \'*\');\n }\n}\n')),(0,a.kt)("h3",{id:"3023-\u8131\u654f\u8bcd\u6c47\u66ff\u6362"},"30.2.3 \u8131\u654f\u8bcd\u6c47\u66ff\u6362"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e5f\u63d0\u4f9b\u4e86\u66ff\u6362\u8131\u654f\u8bcd\u6c47\u7684\u7279\u6027\u652f\u6301\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"// \u5728\u5c5e\u6027\u4e2d\u4f7f\u7528\npublic class Content\n{\n [SensitiveDetection('*')]\n public string Text { get; set; }\n}\n")),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 3.8.8+")," \u7248\u672c\u540e\u652f\u6301\u65b9\u6cd5\u7279\u6027\u76f4\u63a5\u66ff\u6362"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"public void Test([SensitiveDetection('*')] string text)\n{\n}\n"))),(0,a.kt)("h2",{id:"303-\u81ea\u5b9a\u4e49\u8131\u654f\u8bcd\u6c47\u5904\u7406"},"30.3 \u81ea\u5b9a\u4e49\u8131\u654f\u8bcd\u6c47\u5904\u7406"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u9664\u4e86\u5185\u7f6e\u4e86\u4e00\u5957\u9ed8\u8ba4\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u8131\u654f\u5904\u7406")," \u7a0b\u5e8f\uff0c\u4e5f\u652f\u6301\u81ea\u5b9a\u4e49\u8131\u654f\u5904\u7406\u7a0b\u5e8f\u3002"),(0,a.kt)("h3",{id:"3031-\u81ea\u5b9a\u4e49-isensitivedetectionprovider-\u7a0b\u5e8f\u5982"},"30.3.1 \u81ea\u5b9a\u4e49 ",(0,a.kt)("inlineCode",{parentName:"h3"},"ISensitiveDetectionProvider")," \u7a0b\u5e8f\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,15,25,36}",showLineNumbers:!0,"":!0,"{4,15,25,36}":!0},'/// \n/// \u81ea\u5b9a\u4e49\u8131\u654f\u8bcd\u6c47\u68c0\u6d4b\u5668\n/// \npublic class YourSensitiveDetectionProvider : ISensitiveDetectionProvider\n{\n // \u652f\u6301\u6784\u9020\u51fd\u6570\u6ce8\u5165\n public YourSensitiveDetectionProvider()\n {\n }\n\n /// \n /// \u8fd4\u56de\u6240\u6709\u8131\u654f\u8bcd\u6c47\n /// \n /// \n public async Task> GetWordsAsync()\n {\n // \u8fd9\u91cc\u5199\u4f60\u8131\u654f\u8bcd\u6c47\u6570\u636e\u7684\u6765\u6e90\uff08\u5982\u4ece\u6570\u636e\u5e93\u8bfb\u53d6\uff09\uff0c\u5efa\u8bae\u505a\u597d\u7f13\u5b58\u64cd\u4f5c\n }\n\n /// \n /// \u5224\u65ad\u8131\u654f\u8bcd\u6c47\u662f\u5426\u6709\u6548\n /// \n /// \n /// \n public async Task VaildedAsync(string text)\n {\n // \u8fd9\u91cc\u5199\u4f60\u5982\u4f55\u5224\u65ad\u662f\u6b63\u5e38\u7684\u5b57\u7b26\uff0c\u8fd4\u56de true \u6b63\u5e38\uff0c\u8fd4\u56de false \u8868\u793a\u662f\u4e2a\u8131\u654f\u8bcd\u6c47\n }\n\n /// \n /// \u66ff\u6362\u8131\u654f\u8bcd\u6c47\n /// \n /// \n /// \n /// \n public async Task ReplaceAsync(string text, char transfer = \'*\')\n {\n // \u8fd9\u91cc\u5199\u4f60\u66ff\u6362\u975e\u6b63\u5e38\u5b57\u7b26\u4e3a\u6307\u5b9a\u5b57\u7b26\n }\n}\n')),(0,a.kt)("h3",{id:"3032-\u6ce8\u518c\u81ea\u5b9a\u4e49\u8131\u654f\u63d0\u4f9b\u5668"},"30.3.2 \u6ce8\u518c\u81ea\u5b9a\u4e49\u8131\u654f\u63d0\u4f9b\u5668"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public void ConfigureServices(IServiceCollection services)\n{\n services.AddSensitiveDetection();\n}\n")),(0,a.kt)("p",null,"\u4e4b\u540e\u7cfb\u7edf\u5c06\u81ea\u52a8\u91c7\u7528\u81ea\u5b9a\u4e49\u7684\u65b9\u5f0f\u8fdb\u884c\u8131\u654f\u5904\u7406\u3002"),(0,a.kt)("h2",{id:"304-\u53cd\u9988\u4e0e\u5efa\u8bae"},"30.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,a.kt)("hr",null))}v.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return u},kt:function(){return d}});var i=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function o(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=i.createContext({}),p=function(e){var n=i.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},u=function(e){var n=p(e.components);return i.createElement(l.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},m=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),m=p(t),d=r,v=m["".concat(l,".").concat(d)]||m[d]||c[d]||a;return t?i.createElement(v,o(o({ref:n},u),{},{components:t})):i.createElement(v,o({ref:n},u))}));function d(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,o=new Array(a);o[0]=m;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:r,o[1]=s;for(var p=2;p=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=i.createContext({}),p=function(e){var n=i.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},u=function(e){var n=p(e.components);return i.createElement(l.Provider,{value:n},e.children)},c={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},m=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),m=p(t),d=r,v=m["".concat(l,".").concat(d)]||m[d]||c[d]||a;return t?i.createElement(v,o(o({ref:n},u),{},{components:t})):i.createElement(v,o({ref:n},u))}));function d(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,o=new Array(a);o[0]=m;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:r,o[1]=s;for(var p=2;p\u8131\u654f\u8bcd\u6c47\u68c0\u6d4b \u670d\u52a1",id:"3021-\u6ce8\u518c-\u8131\u654f\u8bcd\u6c47\u68c0\u6d4b-\u670d\u52a1",level:3},{value:"30.2.2 \u521b\u5efa sensitive-words.txt \u6587\u4ef6",id:"3022-\u521b\u5efa-sensitive-wordstxt-\u6587\u4ef6",level:3},{value:"30.2.3 \u4f7f\u7528\u8131\u654f\u68c0\u6d4b",id:"3023-\u4f7f\u7528\u8131\u654f\u68c0\u6d4b",level:3},{value:"30.2.3 \u8131\u654f\u8bcd\u6c47\u66ff\u6362",id:"3023-\u8131\u654f\u8bcd\u6c47\u66ff\u6362",level:3},{value:"30.3 \u81ea\u5b9a\u4e49\u8131\u654f\u8bcd\u6c47\u5904\u7406",id:"303-\u81ea\u5b9a\u4e49\u8131\u654f\u8bcd\u6c47\u5904\u7406",level:2},{value:"30.3.1 \u81ea\u5b9a\u4e49 ISensitiveDetectionProvider \u7a0b\u5e8f\uff0c\u5982\uff1a",id:"3031-\u81ea\u5b9a\u4e49-isensitivedetectionprovider-\u7a0b\u5e8f\u5982",level:3},{value:"30.3.2 \u6ce8\u518c\u81ea\u5b9a\u4e49\u8131\u654f\u63d0\u4f9b\u5668",id:"3032-\u6ce8\u518c\u81ea\u5b9a\u4e49\u8131\u654f\u63d0\u4f9b\u5668",level:3},{value:"30.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"304-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:m};function v(e){var n=e.components,t=(0,r.Z)(e,s);return(0,a.kt)("wrapper",(0,i.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 2.4.4 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,a.kt)("h2",{id:"301-\u5173\u4e8e\u8131\u654f"},"30.1 \u5173\u4e8e\u8131\u654f"),(0,a.kt)("p",null,"\u5f15\u7528\u767e\u5ea6\u767e\u79d1\uff1a"),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},"\u6570\u636e\u8131\u654f\u662f\u6307\u5bf9\u67d0\u4e9b\u654f\u611f\u4fe1\u606f\u901a\u8fc7\u8131\u654f\u89c4\u5219\u8fdb\u884c\u6570\u636e\u7684\u53d8\u5f62\uff0c\u5b9e\u73b0\u654f\u611f\u9690\u79c1\u6570\u636e\u7684\u53ef\u9760\u4fdd\u62a4\u3002\u5728\u6d89\u53ca\u5ba2\u6237\u5b89\u5168\u6570\u636e\u6216\u8005\u4e00\u4e9b\u5546\u4e1a\u6027\u654f\u611f\u6570\u636e\u7684\u60c5\u51b5\u4e0b\uff0c\u5728\u4e0d\u8fdd\u53cd\u7cfb\u7edf\u89c4\u5219\u6761\u4ef6\u4e0b\uff0c\u5bf9\u771f\u5b9e\u6570\u636e\u8fdb\u884c\u6539\u9020\u5e76\u63d0\u4f9b\u6d4b\u8bd5\u4f7f\u7528\uff0c\u5982\u8eab\u4efd\u8bc1\u53f7\u3001\u624b\u673a\u53f7\u3001\u5361\u53f7\u3001\u5ba2\u6237\u53f7\u7b49\u4e2a\u4eba\u4fe1\u606f\u90fd\u9700\u8981\u8fdb\u884c\u6570\u636e\u8131\u654f\u3002\u6570\u636e\u5b89\u5168\u6280\u672f\u4e4b\u4e00\uff0c\u6570\u636e\u5e93\u5b89\u5168\u6280\u672f\u4e3b\u8981\u5305\u62ec\uff1a\u6570\u636e\u5e93\u6f0f\u626b\u3001\u6570\u636e\u5e93\u52a0\u5bc6\u3001\u6570\u636e\u5e93\u9632\u706b\u5899\u3001\u6570\u636e\u8131\u654f\u3001\u6570\u636e\u5e93\u5b89\u5168\u5ba1\u8ba1\u7cfb\u7edf\u3002")),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u7cfb\u7edf\u4e2d\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"\u8131\u654f\u5904\u7406")," \u6307\u7684\u662f\u5bf9\u4e0d\u7b26\u5408\u7cfb\u7edf\u5408\u6cd5\u8bcd\u6c47\u68c0\u6d4b\u9a8c\u8bc1\u3002"),(0,a.kt)("h2",{id:"302-\u5982\u4f55\u4f7f\u7528"},"30.2 \u5982\u4f55\u4f7f\u7528"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u5185\u7f6e\u4e86\u4e00\u5957\u9ed8\u8ba4\u7684\u8131\u654f\u8bcd\u6c47\u8131\u654f\u5904\u7406\u673a\u5236\uff0c\u5e76\u4e14\u63d0\u4f9b\u81ea\u5b9a\u4e49\u64cd\u4f5c\u3002"),(0,a.kt)("h3",{id:"3021-\u6ce8\u518c-\u8131\u654f\u8bcd\u6c47\u68c0\u6d4b-\u670d\u52a1"},"30.2.1 \u6ce8\u518c ",(0,a.kt)("inlineCode",{parentName:"h3"},"\u8131\u654f\u8bcd\u6c47\u68c0\u6d4b")," \u670d\u52a1"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public void ConfigureServices(IServiceCollection services)\n{\n services.AddSensitiveDetection();\n}\n")),(0,a.kt)("h3",{id:"3022-\u521b\u5efa-sensitive-wordstxt-\u6587\u4ef6"},"30.2.2 \u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"h3"},"sensitive-words.txt")," \u6587\u4ef6"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u542f\u52a8\u5c42\u9879\u76ee\u4e2d\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"sensitive-words.txt")," \u6587\u4ef6\uff0c",(0,a.kt)("strong",{parentName:"p"},"\u786e\u4fdd\u91c7\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"UTF-8")," \u7f16\u7801\u683c\u5f0f\u4e14\u4e0d\u80fd\u5e26 ",(0,a.kt)("inlineCode",{parentName:"strong"},"BOM \u7b7e\u540d")," \u4e14\u8bbe\u7f6e\u4e3a\u5d4c\u5165\u5f0f\u8d44\u6e90\uff01"),"\ud83c\udf83"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"sensitive-words.txt")," \u5185\u5bb9\u683c\u5f0f\u4e3a\u6bcf\u4e00\u884c\u6807\u8bc6\u4e00\u4e2a\u8131\u654f\u8bcd\u6c47\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-showLineNumbers"},"\u574f\u4eba\n\u65e0\u8bed\n\u6eda\u5f00\n\u516b\u560e\n")),(0,a.kt)("admonition",{title:"3.8.9+ \u7248\u672c",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 3.8.9+")," \u7248\u672c\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"p"},"|")," \u5206\u9694\u7b26\u8fdb\u884c\u5206\u5272\uff0c\u4e5f\u540c\u65f6\u652f\u6301 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6362\u884c")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"|")," \u6df7\u7528\uff0c\u5982\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-showLineNumbers"},"\u574f\u4eba|\u65e0\u8bed|\u6eda\u5f00\n\u516b\u560e\n")),(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("strong",{parentName:"p"},"\u63a8\u8350\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"strong"},"|")," \u65b9\u5f0f\uff0c\u53ef\u4ee5\u8282\u7701\u8bcd\u5e93\u5360\u7528\u5b58\u50a8\u7a7a\u95f4\u3002"))),(0,a.kt)("p",null,"\u63a5\u4e0b\u6765\u8bbe\u7f6e\u4e3a\u5d4c\u5165\u5f0f\u8d44\u6e90\uff1a"),(0,a.kt)("img",{src:(0,o.Z)("img/tm.png")}),(0,a.kt)("h3",{id:"3023-\u4f7f\u7528\u8131\u654f\u68c0\u6d4b"},"30.2.3 \u4f7f\u7528\u8131\u654f\u68c0\u6d4b"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5b9e\u73b0\u6570\u636e\u9a8c\u8bc1\u8131\u654f\u68c0\u6d4b ",(0,a.kt)("inlineCode",{parentName:"strong"},"[SensitiveDetection]")))),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"[SensitiveDetection]")," \u9a8c\u8bc1\u7279\u6027\uff0c\u53ef\u4ee5\u5bf9\u53c2\u6570\u3001\u5c5e\u6027\u8fdb\u884c\u8131\u654f\u9a8c\u8bc1\uff0c\u7528\u6cd5\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"[DataValidation]")," \u4e00\u81f4\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,9}",showLineNumbers:!0,"":!0,"{4,9}":!0},"// \u5728\u5c5e\u6027\u4e2d\u4f7f\u7528\npublic class Content\n{\n [SensitiveDetection]\n public string Text { get; set; }\n}\n\n// \u5728 \u52a8\u6001API/Controller \u4e2d\u4f7f\u7528\npublic void Test([SensitiveDetection] string text)\n{\n\n}\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"strong"},"ISensitiveDetectionProvider")," \u670d\u52a1\u4f7f\u7528"))),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e5f\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"ISensitiveDetectionProvider")," \u670d\u52a1\u8fdb\u884c\u624b\u52a8\u8131\u654f\u9a8c\u8bc1\u5904\u7406\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,15,25,35}",showLineNumbers:!0,"":!0,"{4,15,25,35}":!0},'public class FurionService\n{\n private readonly ISensitiveDetectionProvider _sensitiveDetectionProvider;\n public FurionService(ISensitiveDetectionProvider sensitiveDetectionProvider)\n {\n _sensitiveDetectionProvider = sensitiveDetectionProvider;\n }\n\n /// \n /// \u83b7\u53d6\u6240\u6709\u8131\u654f\u8bcd\u6c47\n /// \n /// \n public async Task> GetWordsAsync()\n {\n return await _sensitiveDetectionProvider.GetWordsAsync();\n }\n\n /// \n /// \u5224\u65ad\u662f\u5426\u662f\u6b63\u5e38\u7684\u8bcd\u6c47\n /// \n /// \n /// \n public async Task VaildedAsync(string text)\n {\n return await _sensitiveDetectionProvider.VaildedAsync(text);\n }\n\n /// \n /// \u66ff\u6362\u975e\u6b63\u5e38\u8bcd\u6c47\n /// \n /// \n /// \n public async Task ReplaceAsync(string text)\n {\n return await _sensitiveDetectionProvider.ReplaceAsync(text, \'*\');\n }\n}\n')),(0,a.kt)("h3",{id:"3023-\u8131\u654f\u8bcd\u6c47\u66ff\u6362"},"30.2.3 \u8131\u654f\u8bcd\u6c47\u66ff\u6362"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e5f\u63d0\u4f9b\u4e86\u66ff\u6362\u8131\u654f\u8bcd\u6c47\u7684\u7279\u6027\u652f\u6301\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"// \u5728\u5c5e\u6027\u4e2d\u4f7f\u7528\npublic class Content\n{\n [SensitiveDetection('*')]\n public string Text { get; set; }\n}\n")),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 3.8.8+")," \u7248\u672c\u540e\u652f\u6301\u65b9\u6cd5\u7279\u6027\u76f4\u63a5\u66ff\u6362"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"public void Test([SensitiveDetection('*')] string text)\n{\n}\n"))),(0,a.kt)("h2",{id:"303-\u81ea\u5b9a\u4e49\u8131\u654f\u8bcd\u6c47\u5904\u7406"},"30.3 \u81ea\u5b9a\u4e49\u8131\u654f\u8bcd\u6c47\u5904\u7406"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u9664\u4e86\u5185\u7f6e\u4e86\u4e00\u5957\u9ed8\u8ba4\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u8131\u654f\u5904\u7406")," \u7a0b\u5e8f\uff0c\u4e5f\u652f\u6301\u81ea\u5b9a\u4e49\u8131\u654f\u5904\u7406\u7a0b\u5e8f\u3002"),(0,a.kt)("h3",{id:"3031-\u81ea\u5b9a\u4e49-isensitivedetectionprovider-\u7a0b\u5e8f\u5982"},"30.3.1 \u81ea\u5b9a\u4e49 ",(0,a.kt)("inlineCode",{parentName:"h3"},"ISensitiveDetectionProvider")," \u7a0b\u5e8f\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,15,25,36}",showLineNumbers:!0,"":!0,"{4,15,25,36}":!0},'/// \n/// \u81ea\u5b9a\u4e49\u8131\u654f\u8bcd\u6c47\u68c0\u6d4b\u5668\n/// \npublic class YourSensitiveDetectionProvider : ISensitiveDetectionProvider\n{\n // \u652f\u6301\u6784\u9020\u51fd\u6570\u6ce8\u5165\n public YourSensitiveDetectionProvider()\n {\n }\n\n /// \n /// \u8fd4\u56de\u6240\u6709\u8131\u654f\u8bcd\u6c47\n /// \n /// \n public async Task> GetWordsAsync()\n {\n // \u8fd9\u91cc\u5199\u4f60\u8131\u654f\u8bcd\u6c47\u6570\u636e\u7684\u6765\u6e90\uff08\u5982\u4ece\u6570\u636e\u5e93\u8bfb\u53d6\uff09\uff0c\u5efa\u8bae\u505a\u597d\u7f13\u5b58\u64cd\u4f5c\n }\n\n /// \n /// \u5224\u65ad\u8131\u654f\u8bcd\u6c47\u662f\u5426\u6709\u6548\n /// \n /// \n /// \n public async Task VaildedAsync(string text)\n {\n // \u8fd9\u91cc\u5199\u4f60\u5982\u4f55\u5224\u65ad\u662f\u6b63\u5e38\u7684\u5b57\u7b26\uff0c\u8fd4\u56de true \u6b63\u5e38\uff0c\u8fd4\u56de false \u8868\u793a\u662f\u4e2a\u8131\u654f\u8bcd\u6c47\n }\n\n /// \n /// \u66ff\u6362\u8131\u654f\u8bcd\u6c47\n /// \n /// \n /// \n /// \n public async Task ReplaceAsync(string text, char transfer = \'*\')\n {\n // \u8fd9\u91cc\u5199\u4f60\u66ff\u6362\u975e\u6b63\u5e38\u5b57\u7b26\u4e3a\u6307\u5b9a\u5b57\u7b26\n }\n}\n')),(0,a.kt)("h3",{id:"3032-\u6ce8\u518c\u81ea\u5b9a\u4e49\u8131\u654f\u63d0\u4f9b\u5668"},"30.3.2 \u6ce8\u518c\u81ea\u5b9a\u4e49\u8131\u654f\u63d0\u4f9b\u5668"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {3}",showLineNumbers:!0,"":!0,"{3}":!0},"public void ConfigureServices(IServiceCollection services)\n{\n services.AddSensitiveDetection();\n}\n")),(0,a.kt)("p",null,"\u4e4b\u540e\u7cfb\u7edf\u5c06\u81ea\u52a8\u91c7\u7528\u81ea\u5b9a\u4e49\u7684\u65b9\u5f0f\u8fdb\u884c\u8131\u654f\u5904\u7406\u3002"),(0,a.kt)("h2",{id:"304-\u53cd\u9988\u4e0e\u5efa\u8bae"},"30.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,a.kt)("hr",null))}v.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/b6492972.05854844.js b/handbook/build/assets/js/b6492972.05854844.js new file mode 100644 index 0000000000..e46da8efc0 --- /dev/null +++ b/handbook/build/assets/js/b6492972.05854844.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[7300],{3905:function(e,t,n){n.d(t,{Zo:function(){return p},kt:function(){return u}});var i=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function o(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=i.createContext({}),c=function(e){var t=i.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},p=function(e){var t=c(e.components);return i.createElement(s.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},m=i.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),m=c(n),u=a,C=m["".concat(s,".").concat(u)]||m[u]||d[u]||r;return n?i.createElement(C,o(o({ref:t},p),{},{components:n})):i.createElement(C,o({ref:t},p))}));function u(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,o=new Array(r);o[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var c=2;cPerson",id:"92021-\u521b\u5efa\u5b9e\u4f53\u6a21\u578b-person",level:3},{value:"9.20.2.2 \u6253\u5f00 \u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0",id:"92022-\u6253\u5f00-\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0",level:3},{value:"9.20.2.3 \u5207\u6362\u9ed8\u8ba4\u9879\u76ee",id:"92023-\u5207\u6362\u9ed8\u8ba4\u9879\u76ee",level:3},{value:"9.20.2.4 \u521b\u5efa\u6a21\u578b\u7248\u672c",id:"92024-\u521b\u5efa\u6a21\u578b\u7248\u672c",level:3},{value:"9.20.2.5 \u66f4\u65b0\u5230\u6570\u636e\u5e93",id:"92025-\u66f4\u65b0\u5230\u6570\u636e\u5e93",level:3},{value:"9.20.3 \u66f4\u65b0\u6a21\u578b",id:"9203-\u66f4\u65b0\u6a21\u578b",level:2},{value:"9.20.4 \u5bfc\u51fa Sql",id:"9204-\u5bfc\u51fa-sql",level:2},{value:"9.20.5 VS Code/Rider/\u4efb\u4f55IDE/\u64cd\u4f5c\u7cfb\u7edf \u65b9\u5f0f",id:"9205-vs-coderider\u4efb\u4f55ide\u64cd\u4f5c\u7cfb\u7edf-\u65b9\u5f0f",level:2},{value:"9.20.5.1 \u5b89\u88c5 dotnet ef",id:"92051-\u5b89\u88c5-dotnet-ef",level:3},{value:"9.20.5.2 cd \u76ee\u5f55",id:"92052-cd-\u76ee\u5f55",level:3},{value:"9.20.5.3 \u6267\u884c\u547d\u4ee4",id:"92053-\u6267\u884c\u547d\u4ee4",level:3},{value:"9.20.6 \u5e94\u7528\u542f\u52a8\u65f6\u81ea\u52a8\u751f\u6210\u6570\u636e\u5e93",id:"9206-\u5e94\u7528\u542f\u52a8\u65f6\u81ea\u52a8\u751f\u6210\u6570\u636e\u5e93",level:2},{value:"9.20.6.1 \u5bf9\u5df2\u7ecf\u751f\u6210 Migrations \u6587\u4ef6\u60c5\u51b5",id:"92061-\u5bf9\u5df2\u7ecf\u751f\u6210-migrations-\u6587\u4ef6\u60c5\u51b5",level:3},{value:"9.20.6.2 \u5982\u679c\u6ca1\u6709\u751f\u6210\u8fc7 Migrations \u6587\u4ef6\u60c5\u51b5",id:"92062-\u5982\u679c\u6ca1\u6709\u751f\u6210\u8fc7-migrations-\u6587\u4ef6\u60c5\u51b5",level:3},{value:"9.20.7 MySql.EntityFrameworkCore \u5728 .NET 6.0.8+ \u95ee\u9898",id:"9207-mysqlentityframeworkcore-\u5728-net-608-\u95ee\u9898",level:2},{value:"9.20.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9208-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],u={toc:m};function C(e){var t=e.components,n=(0,a.Z)(e,l);return(0,r.kt)("wrapper",(0,i.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("admonition",{title:"\u5f00\u59cb\u4e4b\u524d",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Fur.Web.Entry")," \u5c42\u9700\u8981\u5b89\u88c5 ",(0,r.kt)("inlineCode",{parentName:"p"},"Microsoft.EntityFrameworkCore.Tools")," \u5305\u3002")),(0,r.kt)("h2",{id:"9201-\u6570\u636e\u5e93\u5f00\u53d1\u65b9\u5f0f"},"9.20.1 \u6570\u636e\u5e93\u5f00\u53d1\u65b9\u5f0f"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e24\u79cd\u4e3b\u8981\u65b9\u6cd5\u6765 ",(0,r.kt)("strong",{parentName:"p"},"\u4fdd\u6301\u5b9e\u4f53\u6a21\u578b\u548c\u6570\u636e\u5e93\u67b6\u6784\u540c\u6b65"),"\u3002"),(0,r.kt)("p",null,"\u81f3\u4e8e\u6211\u4eec\u5e94\u8be5\u9009\u7528\u54ea\u4e2a\u65b9\u6cd5\uff0c\u8bf7\u786e\u5b9a\u4f60\u662f\u5e0c\u671b\u4ee5\u5b9e\u4f53\u6a21\u578b\u4e3a\u51c6\u8fd8\u662f\u4ee5\u6570\u636e\u5e93\u4e3a\u51c6\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"\u5982\u679c\u5e0c\u671b ",(0,r.kt)("strong",{parentName:"p"},"\u4ee5\u5b9e\u4f53\u6a21\u578b\u4e3a\u51c6"),"\uff0c\u8bf7\u4f7f\u7528\u6b63\u5411\u5de5\u7a0b\uff08Code First\uff09\u3002 \u5bf9\u5b9e\u4f53\u6a21\u578b\u8fdb\u884c\u66f4\u6539\u65f6\uff0c\u6b64\u65b9\u6cd5\u4f1a\u4ee5\u589e\u91cf\u65b9\u5f0f\u5c06\u76f8\u5e94\u67b6\u6784\u66f4\u6539\u5e94\u7528\u5230\u6570\u636e\u5e93\uff0c\u4ee5\u4f7f\u6570\u636e\u5e93\u4fdd\u6301\u4e0e\u5b9e\u4f53\u6a21\u578b\u517c\u5bb9\u3002")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"\u5982\u679c\u5e0c\u671b ",(0,r.kt)("strong",{parentName:"p"},"\u4ee5\u6570\u636e\u5e93\u67b6\u6784\u4e3a\u51c6"),"\uff0c\u8bf7\u4f7f\u7528\u53cd\u5411\u5de5\u7a0b\uff08Database First\uff09\u3002 \u4f7f\u7528\u6b64\u65b9\u6cd5\uff0c\u53ef\u901a\u8fc7\u5c06\u6570\u636e\u5e93\u67b6\u6784\u53cd\u5411\u5de5\u7a0b\u5230\u5b9e\u4f53\u6a21\u578b\u6765\u751f\u6210\u76f8\u5e94\u7684\u5b9e\u4f53\u7c7b\u578b\u3002"))),(0,r.kt)("p",null,"\u672c\u7ae0\u8282\u662f ",(0,r.kt)("strong",{parentName:"p"},"\u6b63\u5411\u5de5\u7a0b\uff08Code First\uff09")," \u7684\u76f8\u5173\u5185\u5bb9\u3002"),(0,r.kt)("h2",{id:"9202-\u64cd\u4f5c\u6307\u5357"},"9.20.2 \u64cd\u4f5c\u6307\u5357"),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u9ed8\u8ba4\u6570\u636e\u8fc1\u79fb\u7684\u7a0b\u5e8f\u96c6\u4e3a\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Database.Migrations"),"\uff0c\u6240\u4ee5\u5982\u679c\u60a8\u6539\u4e86\u7a0b\u5e8f\u96c6\u540d\u79f0\u6216\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"Nuget")," \u65b9\u5f0f\u5b89\u88c5\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\uff0c\u5219\u9700\u8981\u914d\u7f6e\u8fc1\u79fb\u7a0b\u5e8f\u96c6\u540d\u79f0\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},'services.AddDatabaseAccessor(options =>\n{\n options.AddDbPool(DbProvider.Sqlite);\n}, "\u5b58\u653e\u8fc1\u79fb\u6587\u4ef6\u7684\u9879\u76ee\u540d\u79f0");\n')),(0,r.kt)("p",{parentName:"admonition"},"\u53e6\u5916\uff0c\u5982\u679c\u5e94\u7528\u4e2d\u914d\u7f6e\u4e86\u591a\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u90a3\u4e48\u6240\u6709\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"\u8fc1\u79fb\u547d\u4ee4")," \u90fd\u9700\u8981\u6307\u5b9a ",(0,r.kt)("inlineCode",{parentName:"p"},"-Context \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u540d\u79f0")," \u53c2\u6570\u3002\u5982\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Add-Migration v1.0.0 -Context FurionDbContext\n"))),(0,r.kt)("h3",{id:"92021-\u521b\u5efa\u5b9e\u4f53\u6a21\u578b-person"},"9.20.2.1 \u521b\u5efa\u5b9e\u4f53\u6a21\u578b ",(0,r.kt)("inlineCode",{parentName:"h3"},"Person")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,6,8}",showLineNumbers:!0,"":!0,"{1,6,8}":!0},"using Furion.DatabaseAccessor;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Furion.Core\n{\n public class Person : Entity\n {\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n public Person()\n {\n CreatedTime = DateTime.Now;\n IsDeleted = false;\n }\n\n /// \n /// \u59d3\u540d\n /// \n [MaxLength(32)]\n public string Name { get; set; }\n\n /// \n /// \u5e74\u9f84\n /// \n public int Age { get; set; }\n\n /// \n /// \u4f4f\u5740\n /// \n public string Address { get; set; }\n }\n}\n")),(0,r.kt)("admonition",{title:"\u5b9e\u4f53\u7ea6\u5b9a",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u6240\u6709\u6570\u636e\u5e93\u5b9e\u4f53\u5fc5\u987b\u76f4\u63a5\u6216\u95f4\u63a5\u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"p"},"IEntity")," \u63a5\u53e3\u3002")),(0,r.kt)("h3",{id:"92022-\u6253\u5f00-\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0"},"9.20.2.2 \u6253\u5f00 ",(0,r.kt)("inlineCode",{parentName:"h3"},"\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0")),(0,r.kt)("img",{src:(0,o.Z)("img/dbfirst1.png")}),(0,r.kt)("h3",{id:"92023-\u5207\u6362\u9ed8\u8ba4\u9879\u76ee"},"9.20.2.3 \u5207\u6362\u9ed8\u8ba4\u9879\u76ee"),(0,r.kt)("p",null,"\u5c06 ",(0,r.kt)("inlineCode",{parentName:"p"},"\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0")," \u9ed8\u8ba4\u9879\u76ee\u8bbe\u7f6e\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Database.Migrations")),(0,r.kt)("img",{src:(0,o.Z)("img/codefirst1.png")}),(0,r.kt)("h3",{id:"92024-\u521b\u5efa\u6a21\u578b\u7248\u672c"},"9.20.2.4 \u521b\u5efa\u6a21\u578b\u7248\u672c"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Add-Migration v1.0.0\n")),(0,r.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("strong",{parentName:"p"},"v1.0.0")," \u662f\u6b64\u5904\u6570\u636e\u5e93\u66f4\u6539\u7684\u7248\u672c\u53f7\uff0c\u53ef\u4ee5\u5199\u4efb\u4f55\u5b57\u7b26\u4e32\uff0c\u4f46\u63a8\u8350\u5199\u7248\u672c\u53f7\uff0c\u6bcf\u6b21 ",(0,r.kt)("strong",{parentName:"p"},"+1"),"\u3002")),(0,r.kt)("p",null,"\u6700\u7ec8\u547d\u4ee4\u5982\u4e0b\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"PM> Add-Migration v1.0.0\nBuild started...\nBuild succeeded.\nMicrosoft.EntityFrameworkCore.Model.Validation[10400]\n Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data, this mode should only be enabled during development.\nMicrosoft.EntityFrameworkCore.Infrastructure[10403]\n Entity Framework Core 5.0.0-rc.1.20451.13 initialized 'FurionDbContext' using provider 'Microsoft.EntityFrameworkCore.Sqlite' with options: SensitiveDataLoggingEnabled DetailedErrorsEnabled MaxPoolSize=100 MigrationsAssembly=Furion.Database.Migrations\nTo undo this action, use Remove-Migration.\nPM>\n")),(0,r.kt)("p",null,"\u751f\u6210\u6210\u529f\u540e\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Database.Migrations")," \u9879\u76ee\u4e0b\u4f1a\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"p"},"Migrations")," \u6587\u4ef6\u5939\uff08\u5982\u679c\u6ca1\u6709\uff09\uff0c\u540c\u65f6\u672c\u6b21\u7684\u67b6\u6784\u751f\u6210\u6587\u4ef6\uff0c\u5982\uff1a"),(0,r.kt)("img",{src:(0,o.Z)("img/codefirst3.png")}),(0,r.kt)("h3",{id:"92025-\u66f4\u65b0\u5230\u6570\u636e\u5e93"},"9.20.2.5 \u66f4\u65b0\u5230\u6570\u636e\u5e93"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Update-Database\n")),(0,r.kt)("p",null,"\u6267\u884c\u8be5\u547d\u4ee4\u540e\uff0c\u6570\u636e\u5e93\u5c31\u4f1a\u81ea\u52a8\u6839\u636e\u6a21\u578b\u751f\u6210\u5bf9\u5e94\u7684\u8868\u3002"),(0,r.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"\u5982\u679c ",(0,r.kt)("inlineCode",{parentName:"p"},"Update-Database")," \u540e\u9762\u5e26\u5b57\u7b26\u4e32\u53c2\u6570\uff0c\u5219\u4f1a\u81ea\u52a8\u8fd8\u539f\u6570\u636e\u5e93\u5230\u6307\u5b9a\u7248\u672c\uff0c\u5982\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Update-Database v0.0.3\n")),(0,r.kt)("p",{parentName:"admonition"},"\u5c06\u6570\u636e\u5e93\u8fd8\u539f\u5230 ",(0,r.kt)("inlineCode",{parentName:"p"},"v0.0.3")," \u7248\u672c")),(0,r.kt)("h2",{id:"9203-\u66f4\u65b0\u6a21\u578b"},"9.20.3 \u66f4\u65b0\u6a21\u578b"),(0,r.kt)("p",null,"\u5982\u679c\u6a21\u578b\u6539\u53d8\u4e86\uff0c\u91cd\u590d\u4e0a\u9762\u64cd\u4f5c\u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Add-Migration v1.0.1\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Update-Database\n")),(0,r.kt)("h2",{id:"9204-\u5bfc\u51fa-sql"},"9.20.4 \u5bfc\u51fa ",(0,r.kt)("inlineCode",{parentName:"h2"},"Sql")),(0,r.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u6ca1\u6709\u76f4\u63a5\u66f4\u65b0\u6570\u636e\u5e93\u7684\u6743\u9650\uff0c\u6216\u8005\u6015\u51fa\u95ee\u9898\uff0c\u6211\u4eec\u90fd\u4f1a\u5148\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"p"},"Sql")," \u770b\u770b\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"Script-Migration")," \u5bfc\u51fa\u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Script-Migration\n")),(0,r.kt)("img",{src:(0,o.Z)("img/codefirst2.png")}),(0,r.kt)("h2",{id:"9205-vs-coderider\u4efb\u4f55ide\u64cd\u4f5c\u7cfb\u7edf-\u65b9\u5f0f"},"9.20.5 ",(0,r.kt)("inlineCode",{parentName:"h2"},"VS Code/Rider/\u4efb\u4f55IDE/\u64cd\u4f5c\u7cfb\u7edf")," \u65b9\u5f0f"),(0,r.kt)("h3",{id:"92051-\u5b89\u88c5-dotnet-ef"},"9.20.5.1 \u5b89\u88c5 ",(0,r.kt)("inlineCode",{parentName:"h3"},"dotnet ef")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool install --global dotnet-ef --version 5.0.0-rc.2.20475.6\n")),(0,r.kt)("h3",{id:"92052-cd-\u76ee\u5f55"},"9.20.5.2 ",(0,r.kt)("inlineCode",{parentName:"h3"},"cd")," \u76ee\u5f55"),(0,r.kt)("p",null,"\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"VS Code")," \u6253\u5f00 ",(0,r.kt)("inlineCode",{parentName:"p"},".sln")," \u6240\u5728\u7684\u76ee\u5f55\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"framework"),"\u3002"),(0,r.kt)("p",null,"\u4e4b\u540e\u8fdb\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Database.Migrations")," \u76ee\u5f55"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"cd Furion.Database.Migrations\n")),(0,r.kt)("h3",{id:"92053-\u6267\u884c\u547d\u4ee4"},"9.20.5.3 \u6267\u884c\u547d\u4ee4"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},'dotnet ef migrations add v1.0.0 -s "../Furion.Web.Entry"\n')),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},'dotnet ef database update -s "../Furion.Web.Entry"\n')),(0,r.kt)("h2",{id:"9206-\u5e94\u7528\u542f\u52a8\u65f6\u81ea\u52a8\u751f\u6210\u6570\u636e\u5e93"},"9.20.6 \u5e94\u7528\u542f\u52a8\u65f6\u81ea\u52a8\u751f\u6210\u6570\u636e\u5e93"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u5efa\u8bae\u5927\u5bb6\u4f7f\u7528\u547d\u4ee4\u65b9\u5f0f\u64cd\u4f5c\u6570\u636e\u5e93\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u5b8c\u5168\u4e0d\u63a8\u8350\u81ea\u52a8\u5316\u751f\u6210\u6570\u636e\u5e93"),"\uff0c\u4f46\u662f\u6709\u4e9b\u7279\u6b8a\u60c5\u51b5\u4e0b\uff0c\u6709\u8fd9\u4e2a\u5fc5\u8981\uff0c\u6545\u5c06\u6b64\u529f\u80fd\u5199\u51fa\uff1a"),(0,r.kt)("h3",{id:"92061-\u5bf9\u5df2\u7ecf\u751f\u6210-migrations-\u6587\u4ef6\u60c5\u51b5"},"9.20.6.1 \u5bf9\u5df2\u7ecf\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Migrations")," \u6587\u4ef6\u60c5\u51b5"),(0,r.kt)("p",null,"\u5982\u679c\u5df2\u7ecf\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"p"},"Migrations")," \u6587\u4ef6\uff0c\u90a3\u4e48\u53ef\u4ee5\u76f4\u63a5\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4ee3\u7801\u4e2d\u5b9e\u73b0\u7a0b\u5e8f\u542f\u52a8\u65f6\u81ea\u52a8\u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"p"},"update-database")," \u547d\u4ee4\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4,6,8-9}",showLineNumbers:!0,"":!0,"{1,4,6,8-9}":!0},"public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n // \u5224\u65ad\u5f00\u53d1\u73af\u5883\uff01\uff01\uff01\u5fc5\u987b\uff01\uff01\uff01\uff01\n if (env.IsDevelopment())\n {\n Scoped.Create((_, scope) =>\n {\n var context = scope.ServiceProvider.GetRequiredService();\n context.Database.Migrate();\n });\n }\n\n // \u5176\u4ed6\u4ee3\u7801\n}\n")),(0,r.kt)("h3",{id:"92062-\u5982\u679c\u6ca1\u6709\u751f\u6210\u8fc7-migrations-\u6587\u4ef6\u60c5\u51b5"},"9.20.6.2 \u5982\u679c\u6ca1\u6709\u751f\u6210\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Migrations")," \u6587\u4ef6\u60c5\u51b5"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4,6,8-9}",showLineNumbers:!0,"":!0,"{1,4,6,8-9}":!0},"public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n // \u5224\u65ad\u5f00\u53d1\u73af\u5883\uff01\uff01\uff01\u5fc5\u987b\uff01\uff01\uff01\uff01\n if (env.IsDevelopment())\n {\n Scoped.Create((_, scope) =>\n {\n var context = scope.ServiceProvider.GetRequiredService();\n context.Database.EnsureCreated();\n });\n }\n\n // \u5176\u4ed6\u4ee3\u7801\n}\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u5982\u679c\u9700\u8981\u5728\u521b\u5efa\u6570\u636e\u5e93\u4e4b\u524d\u5148\u5220\u9664\u65e7\u7684\uff0c\u53ef\u5148\u8c03\u7528 ",(0,r.kt)("inlineCode",{parentName:"strong"},"context.Database.EnsureDeleted();")," \u4ee3\u7801\u3002\u614e\u91cd\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01")),(0,r.kt)("h2",{id:"9207-mysqlentityframeworkcore-\u5728-net-608-\u95ee\u9898"},"9.20.7 ",(0,r.kt)("inlineCode",{parentName:"h2"},"MySql.EntityFrameworkCore")," \u5728 ",(0,r.kt)("inlineCode",{parentName:"h2"},".NET 6.0.8+")," \u95ee\u9898"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET 6.0.8+")," \u7248\u672c\uff0c\u5fae\u8f6f\u5e95\u5c42\u4fee\u6539\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"IDesignTimeServices")," \u903b\u8f91\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"p"},"MySql.EntityFrameworkCore")," \u7248\u672c\u6ca1\u6709\u53ca\u65f6\u66f4\u65b0\u5bfc\u81f4\u4e00\u4e0b\u9519\u8bef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers {51}",showLineNumbers:!0,"{51}":!0},"PM> Add-Migration v0.0.1\nBuild started...\nBuild succeeded.\nMicrosoft.EntityFrameworkCore.Model.Validation[10400]\n Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data; this mode should only be enabled during development.\nMicrosoft.EntityFrameworkCore.Infrastructure[10403]\n Entity Framework Core 6.0.8 initialized 'DefaultDbContext' using provider 'MySql.EntityFrameworkCore:6.0.4+MySQL8.0.30' with options: SensitiveDataLoggingEnabled DetailedErrorsEnabled MaxPoolSize=100 MigrationsAssembly=Furion.TestMS.Database.Migrations \nSystem.InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.Storage.TypeMappingSourceDependencies' while attempting to activate 'MySql.EntityFrameworkCore.Storage.Internal.MySQLTypeMappingSource'.\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateEnumerable(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType)\n at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)\n at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)\n at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)\n at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)\n at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)\n at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)\n at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()\n at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.b__0()\n at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)\nUnable to resolve service for type 'Microsoft.EntityFrameworkCore.Storage.TypeMappingSourceDependencies' while attempting to activate 'MySql.EntityFrameworkCore.Storage.Internal.MySQLTypeMappingSource'.\nPM> \n")),(0,r.kt)("p",null,"\u89e3\u51b3\u529e\u6cd5\u4e5f\u5f88\u7b80\u5355\uff0c\u53ea\u9700\u8981\u5728\u542f\u52a8\u5c42\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"MysqlEntityFrameworkDesignTimeServices.cs")," \u5e76\u5199\u5165\u4ee5\u4e0b\u5185\u5bb9\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,6}",showLineNumbers:!0,"{4,6}":!0},"using Microsoft.EntityFrameworkCore.Design;\nusing MySql.EntityFrameworkCore.Extensions;\n\nnamespace YourProject.Web.Entry;\n\npublic class MysqlEntityFrameworkDesignTimeServices : IDesignTimeServices\n{\n public void ConfigureDesignTimeServices(IServiceCollection serviceCollection)\n {\n serviceCollection.AddEntityFrameworkMySQL();\n new EntityFrameworkRelationalDesignServicesBuilder(serviceCollection)\n .TryAddCoreServices();\n }\n}\n")),(0,r.kt)("p",null,"\u76f8\u5173 ",(0,r.kt)("inlineCode",{parentName:"p"},"Issue")," \u8ba8\u8bba\uff1a",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/I5O5ER"},"https://gitee.com/dotnetchina/Furion/issues/I5O5ER")),(0,r.kt)("h2",{id:"9208-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.20.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,r.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,r.kt)("hr",null),(0,r.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"p"},"\u6b63\u5411\u5de5\u5382")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli"},"EF Core - \u7ba1\u7406\u6570\u636e\u5e93\u67b6\u6784")," \u7ae0\u8282\u3002")))}C.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/b6492972.9d788011.js b/handbook/build/assets/js/b6492972.9d788011.js deleted file mode 100644 index 791a0a2722..0000000000 --- a/handbook/build/assets/js/b6492972.9d788011.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[7300],{4707:function(e,t,n){n.r(t),n.d(t,{assets:function(){return d},contentTitle:function(){return c},default:function(){return C},frontMatter:function(){return s},metadata:function(){return p},toc:function(){return m}});var i=n(3117),a=n(102),r=(n(7294),n(3905)),o=n(1402),l=["components"],s={id:"dbcontext-code-first",title:"9.20 \u6a21\u578b\u751f\u6210\u6570\u636e\u5e93",sidebar_label:"9.20 \u6a21\u578b\u751f\u6210\u6570\u636e\u5e93 (Code First)"},c=void 0,p={unversionedId:"dbcontext-code-first",id:"dbcontext-code-first",title:"9.20 \u6a21\u578b\u751f\u6210\u6570\u636e\u5e93",description:"",source:"@site/docs/dbcontext-code-first.mdx",sourceDirName:".",slug:"/dbcontext-code-first",permalink:"/furion/docs/dbcontext-code-first",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/dbcontext-code-first.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1661501054,formattedLastUpdatedAt:"Aug 26, 2022",frontMatter:{id:"dbcontext-code-first",title:"9.20 \u6a21\u578b\u751f\u6210\u6570\u636e\u5e93",sidebar_label:"9.20 \u6a21\u578b\u751f\u6210\u6570\u636e\u5e93 (Code First)"},sidebar:"docs",previous:{title:"9.19 \u6570\u636e\u5e93\u751f\u6210\u6a21\u578b (Db First)",permalink:"/furion/docs/dbcontext-db-first"},next:{title:"9.21 \u5b9e\u4f53\u79cd\u5b50\u6570\u636e",permalink:"/furion/docs/dbcontext-seed-data"}},d={},m=[{value:"9.20.1 \u6570\u636e\u5e93\u5f00\u53d1\u65b9\u5f0f",id:"9201-\u6570\u636e\u5e93\u5f00\u53d1\u65b9\u5f0f",level:2},{value:"9.20.2 \u64cd\u4f5c\u6307\u5357",id:"9202-\u64cd\u4f5c\u6307\u5357",level:2},{value:"9.20.2.1 \u521b\u5efa\u5b9e\u4f53\u6a21\u578b Person",id:"92021-\u521b\u5efa\u5b9e\u4f53\u6a21\u578b-person",level:3},{value:"9.20.2.2 \u6253\u5f00 \u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0",id:"92022-\u6253\u5f00-\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0",level:3},{value:"9.20.2.3 \u5207\u6362\u9ed8\u8ba4\u9879\u76ee",id:"92023-\u5207\u6362\u9ed8\u8ba4\u9879\u76ee",level:3},{value:"9.20.2.4 \u521b\u5efa\u6a21\u578b\u7248\u672c",id:"92024-\u521b\u5efa\u6a21\u578b\u7248\u672c",level:3},{value:"9.20.2.5 \u66f4\u65b0\u5230\u6570\u636e\u5e93",id:"92025-\u66f4\u65b0\u5230\u6570\u636e\u5e93",level:3},{value:"9.20.3 \u66f4\u65b0\u6a21\u578b",id:"9203-\u66f4\u65b0\u6a21\u578b",level:2},{value:"9.20.4 \u5bfc\u51fa Sql",id:"9204-\u5bfc\u51fa-sql",level:2},{value:"9.20.5 VS Code/Rider/\u4efb\u4f55IDE/\u64cd\u4f5c\u7cfb\u7edf \u65b9\u5f0f",id:"9205-vs-coderider\u4efb\u4f55ide\u64cd\u4f5c\u7cfb\u7edf-\u65b9\u5f0f",level:2},{value:"9.20.5.1 \u5b89\u88c5 dotnet ef",id:"92051-\u5b89\u88c5-dotnet-ef",level:3},{value:"9.20.5.2 cd \u76ee\u5f55",id:"92052-cd-\u76ee\u5f55",level:3},{value:"9.20.5.3 \u6267\u884c\u547d\u4ee4",id:"92053-\u6267\u884c\u547d\u4ee4",level:3},{value:"9.20.6 \u5e94\u7528\u542f\u52a8\u65f6\u81ea\u52a8\u751f\u6210\u6570\u636e\u5e93",id:"9206-\u5e94\u7528\u542f\u52a8\u65f6\u81ea\u52a8\u751f\u6210\u6570\u636e\u5e93",level:2},{value:"9.20.6.1 \u5bf9\u5df2\u7ecf\u751f\u6210 Migrations \u6587\u4ef6\u60c5\u51b5",id:"92061-\u5bf9\u5df2\u7ecf\u751f\u6210-migrations-\u6587\u4ef6\u60c5\u51b5",level:3},{value:"9.20.6.2 \u5982\u679c\u6ca1\u6709\u751f\u6210\u8fc7 Migrations \u6587\u4ef6\u60c5\u51b5",id:"92062-\u5982\u679c\u6ca1\u6709\u751f\u6210\u8fc7-migrations-\u6587\u4ef6\u60c5\u51b5",level:3},{value:"9.20.7 MySql.EntityFrameworkCore \u5728 .NET 6.0.8+ \u95ee\u9898",id:"9207-mysqlentityframeworkcore-\u5728-net-608-\u95ee\u9898",level:2},{value:"9.20.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9208-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],u={toc:m};function C(e){var t=e.components,n=(0,a.Z)(e,l);return(0,r.kt)("wrapper",(0,i.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("admonition",{title:"\u5f00\u59cb\u4e4b\u524d",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Fur.Web.Entry")," \u5c42\u9700\u8981\u5b89\u88c5 ",(0,r.kt)("inlineCode",{parentName:"p"},"Microsoft.EntityFrameworkCore.Tools")," \u5305\u3002")),(0,r.kt)("h2",{id:"9201-\u6570\u636e\u5e93\u5f00\u53d1\u65b9\u5f0f"},"9.20.1 \u6570\u636e\u5e93\u5f00\u53d1\u65b9\u5f0f"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e24\u79cd\u4e3b\u8981\u65b9\u6cd5\u6765 ",(0,r.kt)("strong",{parentName:"p"},"\u4fdd\u6301\u5b9e\u4f53\u6a21\u578b\u548c\u6570\u636e\u5e93\u67b6\u6784\u540c\u6b65"),"\u3002"),(0,r.kt)("p",null,"\u81f3\u4e8e\u6211\u4eec\u5e94\u8be5\u9009\u7528\u54ea\u4e2a\u65b9\u6cd5\uff0c\u8bf7\u786e\u5b9a\u4f60\u662f\u5e0c\u671b\u4ee5\u5b9e\u4f53\u6a21\u578b\u4e3a\u51c6\u8fd8\u662f\u4ee5\u6570\u636e\u5e93\u4e3a\u51c6\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"\u5982\u679c\u5e0c\u671b ",(0,r.kt)("strong",{parentName:"p"},"\u4ee5\u5b9e\u4f53\u6a21\u578b\u4e3a\u51c6"),"\uff0c\u8bf7\u4f7f\u7528\u6b63\u5411\u5de5\u7a0b\uff08Code First\uff09\u3002 \u5bf9\u5b9e\u4f53\u6a21\u578b\u8fdb\u884c\u66f4\u6539\u65f6\uff0c\u6b64\u65b9\u6cd5\u4f1a\u4ee5\u589e\u91cf\u65b9\u5f0f\u5c06\u76f8\u5e94\u67b6\u6784\u66f4\u6539\u5e94\u7528\u5230\u6570\u636e\u5e93\uff0c\u4ee5\u4f7f\u6570\u636e\u5e93\u4fdd\u6301\u4e0e\u5b9e\u4f53\u6a21\u578b\u517c\u5bb9\u3002")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"\u5982\u679c\u5e0c\u671b ",(0,r.kt)("strong",{parentName:"p"},"\u4ee5\u6570\u636e\u5e93\u67b6\u6784\u4e3a\u51c6"),"\uff0c\u8bf7\u4f7f\u7528\u53cd\u5411\u5de5\u7a0b\uff08Database First\uff09\u3002 \u4f7f\u7528\u6b64\u65b9\u6cd5\uff0c\u53ef\u901a\u8fc7\u5c06\u6570\u636e\u5e93\u67b6\u6784\u53cd\u5411\u5de5\u7a0b\u5230\u5b9e\u4f53\u6a21\u578b\u6765\u751f\u6210\u76f8\u5e94\u7684\u5b9e\u4f53\u7c7b\u578b\u3002"))),(0,r.kt)("p",null,"\u672c\u7ae0\u8282\u662f ",(0,r.kt)("strong",{parentName:"p"},"\u6b63\u5411\u5de5\u7a0b\uff08Code First\uff09")," \u7684\u76f8\u5173\u5185\u5bb9\u3002"),(0,r.kt)("h2",{id:"9202-\u64cd\u4f5c\u6307\u5357"},"9.20.2 \u64cd\u4f5c\u6307\u5357"),(0,r.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"important"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u9ed8\u8ba4\u6570\u636e\u8fc1\u79fb\u7684\u7a0b\u5e8f\u96c6\u4e3a\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Database.Migrations"),"\uff0c\u6240\u4ee5\u5982\u679c\u60a8\u6539\u4e86\u7a0b\u5e8f\u96c6\u540d\u79f0\u6216\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"Nuget")," \u65b9\u5f0f\u5b89\u88c5\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\uff0c\u5219\u9700\u8981\u914d\u7f6e\u8fc1\u79fb\u7a0b\u5e8f\u96c6\u540d\u79f0\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},'services.AddDatabaseAccessor(options =>\n{\n options.AddDbPool(DbProvider.Sqlite);\n}, "\u5b58\u653e\u8fc1\u79fb\u6587\u4ef6\u7684\u9879\u76ee\u540d\u79f0");\n')),(0,r.kt)("p",{parentName:"admonition"},"\u53e6\u5916\uff0c\u5982\u679c\u5e94\u7528\u4e2d\u914d\u7f6e\u4e86\u591a\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u90a3\u4e48\u6240\u6709\u7684 ",(0,r.kt)("inlineCode",{parentName:"p"},"\u8fc1\u79fb\u547d\u4ee4")," \u90fd\u9700\u8981\u6307\u5b9a ",(0,r.kt)("inlineCode",{parentName:"p"},"-Context \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u540d\u79f0")," \u53c2\u6570\u3002\u5982\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Add-Migration v1.0.0 -Context FurionDbContext\n"))),(0,r.kt)("h3",{id:"92021-\u521b\u5efa\u5b9e\u4f53\u6a21\u578b-person"},"9.20.2.1 \u521b\u5efa\u5b9e\u4f53\u6a21\u578b ",(0,r.kt)("inlineCode",{parentName:"h3"},"Person")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,6,8}",showLineNumbers:!0,"":!0,"{1,6,8}":!0},"using Furion.DatabaseAccessor;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Furion.Core\n{\n public class Person : Entity\n {\n /// \n /// \u6784\u9020\u51fd\u6570\n /// \n public Person()\n {\n CreatedTime = DateTime.Now;\n IsDeleted = false;\n }\n\n /// \n /// \u59d3\u540d\n /// \n [MaxLength(32)]\n public string Name { get; set; }\n\n /// \n /// \u5e74\u9f84\n /// \n public int Age { get; set; }\n\n /// \n /// \u4f4f\u5740\n /// \n public string Address { get; set; }\n }\n}\n")),(0,r.kt)("admonition",{title:"\u5b9e\u4f53\u7ea6\u5b9a",type:"important"},(0,r.kt)("p",{parentName:"admonition"},"\u6240\u6709\u6570\u636e\u5e93\u5b9e\u4f53\u5fc5\u987b\u76f4\u63a5\u6216\u95f4\u63a5\u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"p"},"IEntity")," \u63a5\u53e3\u3002")),(0,r.kt)("h3",{id:"92022-\u6253\u5f00-\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0"},"9.20.2.2 \u6253\u5f00 ",(0,r.kt)("inlineCode",{parentName:"h3"},"\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0")),(0,r.kt)("img",{src:(0,o.Z)("img/dbfirst1.png")}),(0,r.kt)("h3",{id:"92023-\u5207\u6362\u9ed8\u8ba4\u9879\u76ee"},"9.20.2.3 \u5207\u6362\u9ed8\u8ba4\u9879\u76ee"),(0,r.kt)("p",null,"\u5c06 ",(0,r.kt)("inlineCode",{parentName:"p"},"\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0")," \u9ed8\u8ba4\u9879\u76ee\u8bbe\u7f6e\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Database.Migrations")),(0,r.kt)("img",{src:(0,o.Z)("img/codefirst1.png")}),(0,r.kt)("h3",{id:"92024-\u521b\u5efa\u6a21\u578b\u7248\u672c"},"9.20.2.4 \u521b\u5efa\u6a21\u578b\u7248\u672c"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Add-Migration v1.0.0\n")),(0,r.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("strong",{parentName:"p"},"v1.0.0")," \u662f\u6b64\u5904\u6570\u636e\u5e93\u66f4\u6539\u7684\u7248\u672c\u53f7\uff0c\u53ef\u4ee5\u5199\u4efb\u4f55\u5b57\u7b26\u4e32\uff0c\u4f46\u63a8\u8350\u5199\u7248\u672c\u53f7\uff0c\u6bcf\u6b21 ",(0,r.kt)("strong",{parentName:"p"},"+1"),"\u3002")),(0,r.kt)("p",null,"\u6700\u7ec8\u547d\u4ee4\u5982\u4e0b\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"PM> Add-Migration v1.0.0\nBuild started...\nBuild succeeded.\nMicrosoft.EntityFrameworkCore.Model.Validation[10400]\n Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data, this mode should only be enabled during development.\nMicrosoft.EntityFrameworkCore.Infrastructure[10403]\n Entity Framework Core 5.0.0-rc.1.20451.13 initialized 'FurionDbContext' using provider 'Microsoft.EntityFrameworkCore.Sqlite' with options: SensitiveDataLoggingEnabled DetailedErrorsEnabled MaxPoolSize=100 MigrationsAssembly=Furion.Database.Migrations\nTo undo this action, use Remove-Migration.\nPM>\n")),(0,r.kt)("p",null,"\u751f\u6210\u6210\u529f\u540e\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Database.Migrations")," \u9879\u76ee\u4e0b\u4f1a\u65b0\u589e ",(0,r.kt)("inlineCode",{parentName:"p"},"Migrations")," \u6587\u4ef6\u5939\uff08\u5982\u679c\u6ca1\u6709\uff09\uff0c\u540c\u65f6\u672c\u6b21\u7684\u67b6\u6784\u751f\u6210\u6587\u4ef6\uff0c\u5982\uff1a"),(0,r.kt)("img",{src:(0,o.Z)("img/codefirst3.png")}),(0,r.kt)("h3",{id:"92025-\u66f4\u65b0\u5230\u6570\u636e\u5e93"},"9.20.2.5 \u66f4\u65b0\u5230\u6570\u636e\u5e93"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Update-Database\n")),(0,r.kt)("p",null,"\u6267\u884c\u8be5\u547d\u4ee4\u540e\uff0c\u6570\u636e\u5e93\u5c31\u4f1a\u81ea\u52a8\u6839\u636e\u6a21\u578b\u751f\u6210\u5bf9\u5e94\u7684\u8868\u3002"),(0,r.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"\u5982\u679c ",(0,r.kt)("inlineCode",{parentName:"p"},"Update-Database")," \u540e\u9762\u5e26\u5b57\u7b26\u4e32\u53c2\u6570\uff0c\u5219\u4f1a\u81ea\u52a8\u8fd8\u539f\u6570\u636e\u5e93\u5230\u6307\u5b9a\u7248\u672c\uff0c\u5982\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Update-Database v0.0.3\n")),(0,r.kt)("p",{parentName:"admonition"},"\u5c06\u6570\u636e\u5e93\u8fd8\u539f\u5230 ",(0,r.kt)("inlineCode",{parentName:"p"},"v0.0.3")," \u7248\u672c")),(0,r.kt)("h2",{id:"9203-\u66f4\u65b0\u6a21\u578b"},"9.20.3 \u66f4\u65b0\u6a21\u578b"),(0,r.kt)("p",null,"\u5982\u679c\u6a21\u578b\u6539\u53d8\u4e86\uff0c\u91cd\u590d\u4e0a\u9762\u64cd\u4f5c\u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Add-Migration v1.0.1\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Update-Database\n")),(0,r.kt)("h2",{id:"9204-\u5bfc\u51fa-sql"},"9.20.4 \u5bfc\u51fa ",(0,r.kt)("inlineCode",{parentName:"h2"},"Sql")),(0,r.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u6ca1\u6709\u76f4\u63a5\u66f4\u65b0\u6570\u636e\u5e93\u7684\u6743\u9650\uff0c\u6216\u8005\u6015\u51fa\u95ee\u9898\uff0c\u6211\u4eec\u90fd\u4f1a\u5148\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"p"},"Sql")," \u770b\u770b\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"Script-Migration")," \u5bfc\u51fa\u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"Script-Migration\n")),(0,r.kt)("img",{src:(0,o.Z)("img/codefirst2.png")}),(0,r.kt)("h2",{id:"9205-vs-coderider\u4efb\u4f55ide\u64cd\u4f5c\u7cfb\u7edf-\u65b9\u5f0f"},"9.20.5 ",(0,r.kt)("inlineCode",{parentName:"h2"},"VS Code/Rider/\u4efb\u4f55IDE/\u64cd\u4f5c\u7cfb\u7edf")," \u65b9\u5f0f"),(0,r.kt)("h3",{id:"92051-\u5b89\u88c5-dotnet-ef"},"9.20.5.1 \u5b89\u88c5 ",(0,r.kt)("inlineCode",{parentName:"h3"},"dotnet ef")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet tool install --global dotnet-ef --version 5.0.0-rc.2.20475.6\n")),(0,r.kt)("h3",{id:"92052-cd-\u76ee\u5f55"},"9.20.5.2 ",(0,r.kt)("inlineCode",{parentName:"h3"},"cd")," \u76ee\u5f55"),(0,r.kt)("p",null,"\u901a\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"p"},"VS Code")," \u6253\u5f00 ",(0,r.kt)("inlineCode",{parentName:"p"},".sln")," \u6240\u5728\u7684\u76ee\u5f55\uff0c\u5982\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"framework"),"\u3002"),(0,r.kt)("p",null,"\u4e4b\u540e\u8fdb\u5165 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion.Database.Migrations")," \u76ee\u5f55"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},"cd Furion.Database.Migrations\n")),(0,r.kt)("h3",{id:"92053-\u6267\u884c\u547d\u4ee4"},"9.20.5.3 \u6267\u884c\u547d\u4ee4"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},'dotnet ef migrations add v1.0.0 -s "../Furion.Web.Entry"\n')),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell",metastring:"showLineNumbers",showLineNumbers:!0},'dotnet ef database update -s "../Furion.Web.Entry"\n')),(0,r.kt)("h2",{id:"9206-\u5e94\u7528\u542f\u52a8\u65f6\u81ea\u52a8\u751f\u6210\u6570\u636e\u5e93"},"9.20.6 \u5e94\u7528\u542f\u52a8\u65f6\u81ea\u52a8\u751f\u6210\u6570\u636e\u5e93"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u5efa\u8bae\u5927\u5bb6\u4f7f\u7528\u547d\u4ee4\u65b9\u5f0f\u64cd\u4f5c\u6570\u636e\u5e93\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u5b8c\u5168\u4e0d\u63a8\u8350\u81ea\u52a8\u5316\u751f\u6210\u6570\u636e\u5e93"),"\uff0c\u4f46\u662f\u6709\u4e9b\u7279\u6b8a\u60c5\u51b5\u4e0b\uff0c\u6709\u8fd9\u4e2a\u5fc5\u8981\uff0c\u6545\u5c06\u6b64\u529f\u80fd\u5199\u51fa\uff1a"),(0,r.kt)("h3",{id:"92061-\u5bf9\u5df2\u7ecf\u751f\u6210-migrations-\u6587\u4ef6\u60c5\u51b5"},"9.20.6.1 \u5bf9\u5df2\u7ecf\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Migrations")," \u6587\u4ef6\u60c5\u51b5"),(0,r.kt)("p",null,"\u5982\u679c\u5df2\u7ecf\u751f\u6210 ",(0,r.kt)("inlineCode",{parentName:"p"},"Migrations")," \u6587\u4ef6\uff0c\u90a3\u4e48\u53ef\u4ee5\u76f4\u63a5\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4ee3\u7801\u4e2d\u5b9e\u73b0\u7a0b\u5e8f\u542f\u52a8\u65f6\u81ea\u52a8\u6267\u884c ",(0,r.kt)("inlineCode",{parentName:"p"},"update-database")," \u547d\u4ee4\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4,6,8-9}",showLineNumbers:!0,"":!0,"{1,4,6,8-9}":!0},"public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n // \u5224\u65ad\u5f00\u53d1\u73af\u5883\uff01\uff01\uff01\u5fc5\u987b\uff01\uff01\uff01\uff01\n if (env.IsDevelopment())\n {\n Scoped.Create((_, scope) =>\n {\n var context = scope.ServiceProvider.GetRequiredService();\n context.Database.Migrate();\n });\n }\n\n // \u5176\u4ed6\u4ee3\u7801\n}\n")),(0,r.kt)("h3",{id:"92062-\u5982\u679c\u6ca1\u6709\u751f\u6210\u8fc7-migrations-\u6587\u4ef6\u60c5\u51b5"},"9.20.6.2 \u5982\u679c\u6ca1\u6709\u751f\u6210\u8fc7 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Migrations")," \u6587\u4ef6\u60c5\u51b5"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4,6,8-9}",showLineNumbers:!0,"":!0,"{1,4,6,8-9}":!0},"public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n // \u5224\u65ad\u5f00\u53d1\u73af\u5883\uff01\uff01\uff01\u5fc5\u987b\uff01\uff01\uff01\uff01\n if (env.IsDevelopment())\n {\n Scoped.Create((_, scope) =>\n {\n var context = scope.ServiceProvider.GetRequiredService();\n context.Database.EnsureCreated();\n });\n }\n\n // \u5176\u4ed6\u4ee3\u7801\n}\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u5982\u679c\u9700\u8981\u5728\u521b\u5efa\u6570\u636e\u5e93\u4e4b\u524d\u5148\u5220\u9664\u65e7\u7684\uff0c\u53ef\u5148\u8c03\u7528 ",(0,r.kt)("inlineCode",{parentName:"strong"},"context.Database.EnsureDeleted();")," \u4ee3\u7801\u3002\u614e\u91cd\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01\uff01")),(0,r.kt)("h2",{id:"9207-mysqlentityframeworkcore-\u5728-net-608-\u95ee\u9898"},"9.20.7 ",(0,r.kt)("inlineCode",{parentName:"h2"},"MySql.EntityFrameworkCore")," \u5728 ",(0,r.kt)("inlineCode",{parentName:"h2"},".NET 6.0.8+")," \u95ee\u9898"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET 6.0.8+")," \u7248\u672c\uff0c\u5fae\u8f6f\u5e95\u5c42\u4fee\u6539\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"IDesignTimeServices")," \u903b\u8f91\u5bfc\u81f4 ",(0,r.kt)("inlineCode",{parentName:"p"},"MySql.EntityFrameworkCore")," \u7248\u672c\u6ca1\u6709\u53ca\u65f6\u66f4\u65b0\u5bfc\u81f4\u4e00\u4e0b\u9519\u8bef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers {51}",showLineNumbers:!0,"{51}":!0},"PM> Add-Migration v0.0.1\nBuild started...\nBuild succeeded.\nMicrosoft.EntityFrameworkCore.Model.Validation[10400]\n Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data; this mode should only be enabled during development.\nMicrosoft.EntityFrameworkCore.Infrastructure[10403]\n Entity Framework Core 6.0.8 initialized 'DefaultDbContext' using provider 'MySql.EntityFrameworkCore:6.0.4+MySQL8.0.30' with options: SensitiveDataLoggingEnabled DetailedErrorsEnabled MaxPoolSize=100 MigrationsAssembly=Furion.TestMS.Database.Migrations \nSystem.InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.Storage.TypeMappingSourceDependencies' while attempting to activate 'MySql.EntityFrameworkCore.Storage.Internal.MySQLTypeMappingSource'.\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateEnumerable(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)\n at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType)\n at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)\n at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)\n at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)\n at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)\n at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)\n at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)\n at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()\n at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.b__0()\n at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)\nUnable to resolve service for type 'Microsoft.EntityFrameworkCore.Storage.TypeMappingSourceDependencies' while attempting to activate 'MySql.EntityFrameworkCore.Storage.Internal.MySQLTypeMappingSource'.\nPM> \n")),(0,r.kt)("p",null,"\u89e3\u51b3\u529e\u6cd5\u4e5f\u5f88\u7b80\u5355\uff0c\u53ea\u9700\u8981\u5728\u542f\u52a8\u5c42\u6dfb\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"MysqlEntityFrameworkDesignTimeServices.cs")," \u5e76\u5199\u5165\u4ee5\u4e0b\u5185\u5bb9\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4,6}",showLineNumbers:!0,"{4,6}":!0},"using Microsoft.EntityFrameworkCore.Design;\nusing MySql.EntityFrameworkCore.Extensions;\n\nnamespace YourProject.Web.Entry;\n\npublic class MysqlEntityFrameworkDesignTimeServices : IDesignTimeServices\n{\n public void ConfigureDesignTimeServices(IServiceCollection serviceCollection)\n {\n serviceCollection.AddEntityFrameworkMySQL();\n new EntityFrameworkRelationalDesignServicesBuilder(serviceCollection)\n .TryAddCoreServices();\n }\n}\n")),(0,r.kt)("p",null,"\u76f8\u5173 ",(0,r.kt)("inlineCode",{parentName:"p"},"Issue")," \u8ba8\u8bba\uff1a",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/I5O5ER"},"https://gitee.com/dotnetchina/Furion/issues/I5O5ER")),(0,r.kt)("h2",{id:"9208-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.20.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,r.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,r.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,r.kt)("hr",null),(0,r.kt)("admonition",{title:"\u4e86\u89e3\u66f4\u591a",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a ",(0,r.kt)("inlineCode",{parentName:"p"},"\u6b63\u5411\u5de5\u5382")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli"},"EF Core - \u7ba1\u7406\u6570\u636e\u5e93\u67b6\u6784")," \u7ae0\u8282\u3002")))}C.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return p},kt:function(){return u}});var i=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function o(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=i.createContext({}),c=function(e){var t=i.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},p=function(e){var t=c(e.components);return i.createElement(s.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},m=i.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),m=c(n),u=a,C=m["".concat(s,".").concat(u)]||m[u]||d[u]||r;return n?i.createElement(C,o(o({ref:t},p),{},{components:n})):i.createElement(C,o({ref:t},p))}));function u(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,o=new Array(r);o[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var c=2;cSql",id:"9151-\u5173\u4e8e-sql",level:2},{value:"9.15.2 \u61d2\u4eba\u65e0\u654c Sql \ud83d\udc2e",id:"9152-\u61d2\u4eba\u65e0\u654c-sql-",level:2},{value:"9.15.2.1 \u8fd4\u56de DataTable",id:"91521-\u8fd4\u56de-datatable",level:3},{value:"9.15.2.2 \u8fd4\u56de List<T>",id:"91522-\u8fd4\u56de-listt",level:3},{value:"9.15.2.3 \u8fd4\u56de DataSet",id:"91523-\u8fd4\u56de-dataset",level:3},{value:"9.15.2.4 \u8fd4\u56de Tuple<T1,...T8>",id:"91524-\u8fd4\u56de-tuplet1t8",level:3},{value:"9.15.2.5 \u8fd4\u56de \u5355\u884c\u5355\u5217",id:"91525-\u8fd4\u56de-\u5355\u884c\u5355\u5217",level:3},{value:"9.15.2.6 \u8fd4\u56de \u53d7\u5f71\u54cd\u884c\u6570",id:"91526-\u8fd4\u56de-\u53d7\u5f71\u54cd\u884c\u6570",level:3},{value:"9.15.3 \u61d2\u4eba\u65e0\u654c \u5b58\u50a8\u8fc7\u7a0b \ud83d\udc2e",id:"9153-\u61d2\u4eba\u65e0\u654c-\u5b58\u50a8\u8fc7\u7a0b-",level:2},{value:"9.15.3.1 \u8fd4\u56de DataTable",id:"91531-\u8fd4\u56de-datatable",level:3},{value:"9.15.3.2 \u8fd4\u56de List<T>",id:"91532-\u8fd4\u56de-listt",level:3},{value:"9.15.3.3 \u8fd4\u56de DataSet",id:"91533-\u8fd4\u56de-dataset",level:3},{value:"9.15.3.4 \u8fd4\u56de Tuple<T1,...T8>",id:"91534-\u8fd4\u56de-tuplet1t8",level:3},{value:"9.15.3.5 \u8fd4\u56de \u5355\u884c\u5355\u5217",id:"91535-\u8fd4\u56de-\u5355\u884c\u5355\u5217",level:3},{value:"9.15.3.6 \u8fd4\u56de \u53d7\u5f71\u54cd\u884c\u6570",id:"91536-\u8fd4\u56de-\u53d7\u5f71\u54cd\u884c\u6570",level:3},{value:"9.15.3.7 \u5e26 OUTPUT/RETURN \u8fd4\u56de",id:"91537-\u5e26-outputreturn-\u8fd4\u56de",level:3},{value:"9.15.4 \u61d2\u4eba\u65e0\u654c \u51fd\u6570 \ud83d\udc2e",id:"9154-\u61d2\u4eba\u65e0\u654c-\u51fd\u6570-",level:2},{value:"9.15.4.1 \u6807\u91cf\u51fd\u6570",id:"91541-\u6807\u91cf\u51fd\u6570",level:3},{value:"9.15.4.2 \u8868\u503c\u51fd\u6570",id:"91542-\u8868\u503c\u51fd\u6570",level:3},{value:"9.15.5 \u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4",id:"9155-\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4",level:2},{value:"9.15.6 ISqlRepository \u64cd\u4f5c",id:"9156-isqlrepository-\u64cd\u4f5c",level:2},{value:"9.15.7 IRepository \u64cd\u4f5c",id:"9157-irepository-\u64cd\u4f5c",level:2},{value:"9.15.8 IRepository<TEntity> \u64cd\u4f5c",id:"9158-irepositorytentity-\u64cd\u4f5c",level:2},{value:"9.15.9 \u5173\u4e8e Sql \u53c2\u6570",id:"9159-\u5173\u4e8e-sql-\u53c2\u6570",level:2},{value:"9.15.10 \u591a\u6570\u636e\u5e93 Sql \u64cd\u4f5c \ud83d\udcaf \ud83d\udc9b",id:"91510-\u591a\u6570\u636e\u5e93-sql-\u64cd\u4f5c--",level:2},{value:"9.15.10.1 \u61d2\u4eba\u65e0\u654c \ud83d\udc2e \u65b9\u5f0f",id:"915101-\u61d2\u4eba\u65e0\u654c--\u65b9\u5f0f",level:3},{value:"9.15.10.2 ISqlRepository \u65b9\u5f0f",id:"915102-isqlrepository-\u65b9\u5f0f",level:3},{value:"9.15.10.3 IRepository \u65b9\u5f0f",id:"915103-irepository-\u65b9\u5f0f",level:3},{value:"9.15.10.4 IRepository<TEntity> \u65b9\u5f0f",id:"915104-irepositorytentity-\u65b9\u5f0f",level:3},{value:"9.15.11 \u5207\u6362\u6570\u636e\u5e93",id:"91511-\u5207\u6362\u6570\u636e\u5e93",level:2},{value:"9.15.12 \u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df",id:"91512-\u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df",level:2},{value:"9.15.13 \u9759\u6001 Default \u65b9\u5f0f\u6784\u5efa",id:"91513-\u9759\u6001-default-\u65b9\u5f0f\u6784\u5efa",level:2},{value:"9.15.14 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"91514-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:p};function c(e){var n=e.components,t=(0,a.Z)(e,o);return(0,i.kt)("wrapper",(0,r.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{title:"\u6e29\u99a8\u63d0\u793a",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u4f7f\u7528 \u300a",(0,i.kt)("a",{parentName:"p",href:"/furion/docs/dbcontext-sql-proxy"},"9.17 Sql \u9ad8\u7ea7\u4ee3\u7406"),"\u300b\u4ee3\u66ff\u672c\u7ae0\u8282\u529f\u80fd\u3002",(0,i.kt)("inlineCode",{parentName:"p"},"Sql \u9ad8\u7ea7\u4ee3\u7406")," \u80fd\u591f\u63d0\u4f9b\u66f4\u5bb9\u6613\u4e14\u66f4\u6613\u7ef4\u62a4\u7684\u65b9\u5f0f\u3002")),(0,i.kt)("admonition",{title:"\u4f8b\u5b50\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u672c\u7ae0\u8282\u4f8b\u5b50\u5747\u4ee5 ",(0,i.kt)("inlineCode",{parentName:"p"},"sql server")," \u6570\u636e\u5e93\u5199\u7684\u4f8b\u5b50\uff0c\u547d\u4ee4\u53c2\u6570\u7edf\u4e00\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"@")," \u7b26\u53f7\uff0c\u4f46\u4e0d\u540c\u6570\u636e\u5e93\u7684\u53c2\u6570\u524d\u7f00\u6709\u6240\u4e0d\u540c\uff0c\u5982\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"sql server")," \u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"@"),"\uff0coracle \u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},":"),"\uff0cmy sql \u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"?"),"\u3002")),(0,i.kt)("h2",{id:"9151-\u5173\u4e8e-sql"},"9.15.1 \u5173\u4e8e ",(0,i.kt)("inlineCode",{parentName:"h2"},"Sql")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u975e\u5e38\u591a\u4e14\u7075\u6d3b\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"sql")," \u64cd\u4f5c\u65b9\u6cd5\uff0c\u4e14\u6027\u80fd\u4e0d\u8f93\u4e8e ",(0,i.kt)("inlineCode",{parentName:"p"},"dapper"),"\uff0c\u540c\u65f6\u903c\u8fd1 ",(0,i.kt)("inlineCode",{parentName:"p"},"ADO.NET")," \u539f\u751f\u64cd\u4f5c\u3002"),(0,i.kt)("h2",{id:"9152-\u61d2\u4eba\u65e0\u654c-sql-"},"9.15.2 \u61d2\u4eba\u65e0\u654c ",(0,i.kt)("inlineCode",{parentName:"h2"},"Sql")," \ud83d\udc2e"),(0,i.kt)("h3",{id:"91521-\u8fd4\u56de-datatable"},"9.15.2.1 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"DataTable")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataTable = "select * from person".SqlQuery();\n\n// \u793a\u4f8b\u4e8c\nvar dataTable = "select top 10 * from person where id > @id".SqlQuery(new {id = 10});\n\n// \u793a\u4f8b\u4e09\nvar dataTable = "select Id, Name, Age from person where name like @name".SqlQuery(new Dictionary{ {"name", "%Furion%"} });\n\n// \u793a\u4f8b\u56db\nvar dataTable = "select * from person where name=@name limit 1,10".SqlQuery(new []{ new MySqlParameter("name","Furion") });\n\n// \u793a\u4f8b\u4e94\nvar dataTable = "select * from person where id>@id and name like @name".SqlQuery(new YourModel { Id = 1, Name = "%Furion%" });\n\n// \u793a\u4f8b\u516d\nvar dataTable = "exec PROC_GetPerson @id".SqlQuery(new {id = 10});\n\n// \u793a\u4f8b\u4e03\nvar dataTable = "select * from FN_GetPersons(@id)".SqlQuery(new {id = 10});\n\n// \u793a\u4f8b\u516b\nvar dataTable = @"\nselect * from person p\nleft join personDetail pd on p.Id == pd.pid\nwhere p.Id > @id;".SqlQuery(new {id = 10});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataTable = await "select * from person".SqlQueryAsync();\n\n// \u793a\u4f8b\u4e8c\nvar dataTable = await "select top 10 * from person where id > @id".SqlQueryAsync(new {id = 10});\n\n// \u793a\u4f8b\u4e09\nvar dataTable = await "select Id, Name, Age from person where name like @name".SqlQueryAsync(new Dictionary{ {"name", "%Furion%"} });\n\n// \u793a\u4f8b\u56db\nvar dataTable = await "select * from person where name=@name limit 1,10".SqlQueryAsync(new []{ new MySqlParameter("name","Furion") });\n\n// \u793a\u4f8b\u4e94\nvar dataTable = await "select * from person where id>@id and name like @name".SqlQueryAsync(new YourModel { Id = 1, Name = "%Furion%" });\n\n// \u793a\u4f8b\u516d\nvar dataTable = await "exec PROC_GetPerson @id".SqlQueryAsync(new {id = 10});\n\n// \u793a\u4f8b\u4e03\nvar dataTable = await "select * from FN_GetPersons(@id)".SqlQueryAsync(new {id = 10});\n\n// \u793a\u4f8b\u516b\nvar dataTable = await @"\nselect * from person p\nleft join personDetail pd on p.Id == pd.pid\nwhere p.Id > @id;".SqlQueryAsync(new {id = 10});\n')),(0,i.kt)("h3",{id:"91522-\u8fd4\u56de-listt"},"9.15.2.2 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"List")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = "select * from person".SqlQuery();\n\n// \u793a\u4f8b\u4e8c\nvar persons = "select top 10 * from person where id > @id".SqlQuery(new {id = 10});\n\n// \u793a\u4f8b\u4e09\nvar persons = "select Id, Name, Age from person where name like @name".SqlQuery(new Dictionary{ {"name", "%Furion%"} });\n\n// \u793a\u4f8b\u56db\nvar persons = "select * from person where name=@name limit 1,10".SqlQuery(new []{ new MySqlParameter("name","Furion") });\n\n// \u793a\u4f8b\u4e94\nvar persons = "select * from person where id>@id and name like @name".SqlQuery(new YourModel { Id = 1, Name = "%Furion%" });\n\n// \u793a\u4f8b\u516d\nvar persons = "exec PROC_GetPerson @id".SqlQuery(new {id = 10});\n\n// \u793a\u4f8b\u4e03\nvar persons = "select * from FN_GetPersons(@id)".SqlQuery(new {id = 10});\n\n// \u793a\u4f8b\u516b\nvar persons = @"\nselect * from person p\nleft join personDetail pd on p.Id == pd.pid\nwhere p.Id > @id;".SqlQuery(new {id = 10});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = await "select * from person".SqlQueryAsync();\n\n// \u793a\u4f8b\u4e8c\nvar persons = await "select top 10 * from person where id > @id".SqlQueryAsync(new {id = 10});\n\n// \u793a\u4f8b\u4e09\nvar persons = await "select Id, Name, Age from person where name like @name".SqlQueryAsync(new Dictionary{ {"name", "%Furion%"} });\n\n// \u793a\u4f8b\u56db\nvar persons = await "select * from person where name=@name limit 1,10".SqlQueryAsync(new []{ new MySqlParameter("name","Furion") });\n\n// \u793a\u4f8b\u4e94\nvar persons = await "select * from person where id>@id and name like @name".SqlQueryAsync(new YourModel { Id = 1, Name = "%Furion%" });\n\n// \u793a\u4f8b\u516d\nvar persons = await "exec PROC_GetPerson @id".SqlQueryAsync(new {id = 10});\n\n// \u793a\u4f8b\u4e03\nvar persons = await "select * from FN_GetPersons(@id)".SqlQueryAsync(new {id = 10});\n\n// \u793a\u4f8b\u516b\nvar persons = await @"\nselect * from person p\nleft join personDetail pd on p.Id == pd.pid\nwhere p.Id > @id;".SqlQueryAsync(new {id = 10});\n')),(0,i.kt)("h3",{id:"91523-\u8fd4\u56de-dataset"},"9.15.2.3 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"DataSet")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataSet = @"\nselect * from person;\nselect * from student;".SqlQueries();\n\n// \u793a\u4f8b\u4e8c\nvar dataSet = @"\nselect * from person where Id > @id;\nselect * from student where Name like @name;".SqlQueries(new {id = 1, name = "%furion%"});\n\n// \u793a\u4f8b\u4e09\nvar dataSet = @"\nselect * from person;\nexec PROC_GetStudents(@id);\nselect \'Furion\';\nselect * from FN_GetPerson(@id);".SqlQueries(new {id = 1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataSet = await @"\nselect * from person;\nselect * from student;".SqlQueriesAsync();\n\n// \u793a\u4f8b\u4e8c\nvar dataSet = await @"\nselect * from person where Id > @id;\nselect * from student where Name like @name;".SqlQueriesAsync(new {id = 1, name = "%furion%"});\n\n// \u793a\u4f8b\u4e09\nvar dataSet = await @"\nselect * from person;\nexec PROC_GetStudents(@id);\nselect \'Furion\';\nselect * from FN_GetPerson(@id);".SqlQueriesAsync(new {id = 1});\n')),(0,i.kt)("h3",{id:"91524-\u8fd4\u56de-tuplet1t8"},"9.15.2.4 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"Tuple")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar (persons, students) = @"\nselect * from person;\nselect * from student;".SqlQueries();\n\n// \u793a\u4f8b\u4e8c\nvar (persons, students) = @"\nselect * from person where Id > @id;\nselect * from student where Name like @name;".SqlQueries(new {id = 1, name = "%furion%"});\n\n// \u793a\u4f8b\u4e09\nvar (persons, students, string, PersonDto) = @"\nselect * from person;\nexec PROC_GetStudents(@id);\nselect \'Furion\';\nselect * from FN_GetPerson(@id);".SqlQueries(new {id = 1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar (persons, students) = await @"\nselect * from person;\nselect * from student;".SqlQueriesAsync();\n\n// \u793a\u4f8b\u4e8c\nvar (persons, students) = await @"\nselect * from person where Id > @id;\nselect * from student where Name like @name;".SqlQueriesAsync(new {id = 1, name = "%furion%"});\n\n// \u793a\u4f8b\u4e09\nvar (persons, students, string, PersonDto) = await @"\nselect * from person;\nexec PROC_GetStudents(@id);\nselect \'Furion\';\nselect * from FN_GetPerson(@id);".SqlQueriesAsync(new {id = 1});\n')),(0,i.kt)("h3",{id:"91525-\u8fd4\u56de-\u5355\u884c\u5355\u5217"},"9.15.2.5 \u8fd4\u56de \u5355\u884c\u5355\u5217"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar value = "select Name from person where id = @id".SqlScalar(new {id = 1});\n\n// \u793a\u4f8b\u4e8c\nvar value = "select Name from person where id = @id".SqlScalar(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar value = "select Age from person where id = @id".SqlScalar(new {id = 1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar value = await "select Name from person where id = @id".SqlScalarAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e8c\nvar value = await "select Name from person where id = @id".SqlScalarAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar value = await "select Age from person where id = @id".SqlScalarAsync(new {id = 1});\n')),(0,i.kt)("h3",{id:"91526-\u8fd4\u56de-\u53d7\u5f71\u54cd\u884c\u6570"},"9.15.2.6 \u8fd4\u56de \u53d7\u5f71\u54cd\u884c\u6570"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar rowEffects = "insert into person(Name,Age,Address) values(@name,@age,@address)".SqlNonQuery(person);\n\n// \u793a\u4f8b\u4e8c\nvar rowEffects = @"\ninsert into person(Name,Age,Address) values(@name,@age,@address);\ninsert into person(Name,Age,Address) values(@name,@age,@address);".SqlNonQuery(persons);\n\n// \u793a\u4f8b\u4e09\nvar rowEffects = "update person set name=@name where id=@id".SqlNonQuery(new {id=1, name="\u767e\u5c0f\u50e7"});\n\n// \u793a\u4f8b\u56db\nvar rowEffects = "delete from person where @id > 10".SqlNonQuery(new {id=1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar rowEffects = await "insert into person(Name,Age,Address) values(@name,@age,@address)".SqlNonQueryAsync(person);\n\n// \u793a\u4f8b\u4e8c\nvar rowEffects = @"\ninsert into person(Name,Age,Address) values(@name,@age,@address);\ninsert into person(Name,Age,Address) values(@name,@age,@address);".SqlNonQueryAsync(persons);\n\n// \u793a\u4f8b\u4e09\nvar rowEffects = await "update person set name=@name where id=@id".SqlNonQueryAsync(new {id=1, name="\u767e\u5c0f\u50e7"});\n\n// \u793a\u4f8b\u56db\nvar rowEffects = await "delete from person where @id > 10".SqlNonQueryAsync(new {id=1});\n')),(0,i.kt)("h2",{id:"9153-\u61d2\u4eba\u65e0\u654c-\u5b58\u50a8\u8fc7\u7a0b-"},"9.15.3 \u61d2\u4eba\u65e0\u654c ",(0,i.kt)("inlineCode",{parentName:"h2"},"\u5b58\u50a8\u8fc7\u7a0b")," \ud83d\udc2e"),(0,i.kt)("h3",{id:"91531-\u8fd4\u56de-datatable"},"9.15.3.1 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"DataTable")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataTable = "PROC_Name".SqlProcedureQuery();\n\n// \u793a\u4f8b\u4e8c\nvar dataTable = "PROC_Name".SqlProcedureQuery(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar dataTable = "PROC_Name".SqlProcedureQuery(new {id = 1, age = 27});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataTable = await "PROC_Name".SqlProcedureQueryAsync();\n\n// \u793a\u4f8b\u4e8c\nvar dataTable = await "PROC_Name".SqlProcedureQueryAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar dataTable = await "PROC_Name".SqlProcedureQueryAsync(new {id = 1, age = 27});\n')),(0,i.kt)("h3",{id:"91532-\u8fd4\u56de-listt"},"9.15.3.2 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"List")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = "PROC_Name".SqlProcedureQuery();\n\n// \u793a\u4f8b\u4e8c\nvar persons = "PROC_Name".SqlProcedureQuery(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar persons = "PROC_Name".SqlProcedureQuery(new {id = 1, age = 27});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = await "PROC_Name".SqlProcedureQueryAsync();\n\n// \u793a\u4f8b\u4e8c\nvar persons = await "PROC_Name".SqlProcedureQueryAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar persons = await "PROC_Name".SqlProcedureQueryAsync(new {id = 1, age = 27});\n')),(0,i.kt)("h3",{id:"91533-\u8fd4\u56de-dataset"},"9.15.3.3 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"DataSet")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataSet = "PROC_Name".SqlProcedureQueries();\n\n// \u793a\u4f8b\u4e8c\nvar dataSet = "PROC_Name".SqlProcedureQueries(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar dataSet = "PROC_Name".SqlProcedureQueries(new {id = 1, age = 27});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataSet = await "PROC_Name".SqlProcedureQueriesAsync();\n\n// \u793a\u4f8b\u4e8c\nvar dataSet = await "PROC_Name".SqlProcedureQueriesAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar dataSet = await "PROC_Name".SqlProcedureQueriesAsync(new {id = 1, age = 27});\n')),(0,i.kt)("h3",{id:"91534-\u8fd4\u56de-tuplet1t8"},"9.15.3.4 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"Tuple")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = "PROC_Name".SqlProcedureQueries();\n\n// \u793a\u4f8b\u4e8c\nvar (persons,students) = "PROC_Name".SqlProcedureQueries(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar (persons,students,string) = "PROC_Name".SqlProcedureQueries(new {id = 1, age = 27});\n\n// \u793a\u4f8b\u56db\nvar (persons,students,personDetail,string) = "PROC_Name".SqlProcedureQueries(new {id = 1, age = 27});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = await "PROC_Name".SqlProcedureQueriesAsync();\n\n// \u793a\u4f8b\u4e8c\nvar (persons,students) = await "PROC_Name".SqlProcedureQueriesAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar (persons,students,string) = await "PROC_Name".SqlProcedureQueriesAsync(new {id = 1, age = 27});\n\n// \u793a\u4f8b\u56db\nvar (persons,students,personDetail,string) = await "PROC_Name".SqlProcedureQueriesAsync(new {id = 1, age = 27});\n')),(0,i.kt)("h3",{id:"91535-\u8fd4\u56de-\u5355\u884c\u5355\u5217"},"9.15.3.5 \u8fd4\u56de \u5355\u884c\u5355\u5217"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar value = "PROC_Name".SqlProcedureScalar(new {id = 1});\n\n// \u793a\u4f8b\u4e8c\nvar value = "PROC_Name".SqlProcedureScalar(new {id = 1, name = "\u65b0\u751f\u5e1d", address ="\u5e7f\u4e1c\u7701\u4e2d\u5c71\u5e02"});\n\n// \u793a\u4f8b\u4e09\nvar value = "PROC_Name".SqlProcedureScalar(new {id = 1, address ="\u5e7f\u4e1c\u7701\u4e2d\u5c71\u5e02"});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar value = await "PROC_Name".SqlProcedureScalarAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e8c\nvar value = await "PROC_Name".SqlProcedureScalarAsync(new {id = 1, name = "\u65b0\u751f\u5e1d", address ="\u5e7f\u4e1c\u7701\u4e2d\u5c71\u5e02"});\n\n// \u793a\u4f8b\u4e09\nvar value = await "PROC_Name".SqlProcedureScalarAsync(new {id = 1, address ="\u5e7f\u4e1c\u7701\u4e2d\u5c71\u5e02"});\n')),(0,i.kt)("h3",{id:"91536-\u8fd4\u56de-\u53d7\u5f71\u54cd\u884c\u6570"},"9.15.3.6 \u8fd4\u56de \u53d7\u5f71\u54cd\u884c\u6570"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar rowEffects = "PROC_Name".SqlProcedureNonQuery(person);\n\n// \u793a\u4f8b\u4e8c\nvar rowEffects = "PROC_Name".SqlProcedureNonQuery(new {id = 1, name = "\u65b0\u751f\u5e1d", address ="\u5e7f\u4e1c\u7701\u4e2d\u5c71\u5e02"});\n\n// \u793a\u4f8b\u4e09\nvar rowEffects = "PROC_Name".SqlProcedureNonQuery(new {id=1, name="\u767e\u5c0f\u50e7"});\n\n// \u793a\u4f8b\u56db\nvar rowEffects = "PROC_Name".SqlProcedureNonQuery(new {id=1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(person);\n\n// \u793a\u4f8b\u4e8c\nvar rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new {id = 1, name = "\u65b0\u751f\u5e1d", address ="\u5e7f\u4e1c\u7701\u4e2d\u5c71\u5e02"});\n\n// \u793a\u4f8b\u4e09\nvar rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new {id=1, name="\u767e\u5c0f\u50e7"});\n\n// \u793a\u4f8b\u56db\nvar rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new {id=1});\n')),(0,i.kt)("h3",{id:"91537-\u5e26-outputreturn-\u8fd4\u56de"},"9.15.3.7 \u5e26 ",(0,i.kt)("inlineCode",{parentName:"h3"},"OUTPUT/RETURN")," \u8fd4\u56de"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sql",metastring:"showLineNumbers {3,4,10-12,15-17,22}",showLineNumbers:!0,"":!0,"{3,4,10-12,15-17,22}":!0},"CREATE PROC PROC_Output\n @Id INT, // \u8f93\u5165\u53c2\u6570\n @Name NVARCHAR(32) OUTPUT, // \u8f93\u51fa\u53c2\u6570\uff0c\u8fd8\u5e26\u957f\u5ea6\n @Age INT OUTPUT // \u8f93\u51fa\u53c2\u6570\nAS\nBEGIN\n SET @Name = 'Furion Output';\n\n // \u8f93\u51fa\u7ed3\u679c\u96c6\n SELECT *\n FROM dbo.Test\n WHERE Id > @Id;\n\n // \u8f93\u51fa\u7ed3\u679c\u96c6\n SELECT TOP 10\n *\n FROM dbo.Test;\n\n SET @Age = 27;\n\n // \u5e26 RETURN \u8fd4\u56de\n RETURN 10;\nEND;\n")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,10,13,16}",showLineNumbers:!0,"":!0,"{1,10,13,16}":!0},"using Furion.DatabaseAccessor;\nusing System.Data;\n\nnamespace Furion.Application\n{\n public class ProcOutputModel\n {\n public int Id { get; set; } // \u8f93\u5165\u53c2\u6570\n\n [DbParameter(ParameterDirection.Output, Size = 32)]\n public string Name { get; set; } // \u8f93\u51fa\u53c2\u6570\n\n [DbParameter(ParameterDirection.Output)]\n public int Age { get; set; } // \u8f93\u51fa\u53c2\u6570\n\n [DbParameter(ParameterDirection.ReturnValue)]\n public int ReturnValue { get; set; } // \u8fd4\u56de\u503c\n }\n}\n")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nProcedureOutputResult result = "PROC_Name".SqlProcedureOutput(new ProcOutputModel{ Id=1});\n\n// \u793a\u4f8b\u4e8c\nProcedureOutputResult result = "PROC_Name".SqlProcedureOutput(new ProcOutputModel{ Id=1});\n\n// \u793a\u4f8b\u4e09\nProcedureOutputResult<(List, List)> result = "PROC_Name".SqlProcedureOutput<(List, List)>(new ProcOutputModel{ Id=1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n// \u793a\u4f8b\u4e00\nProcedureOutputResult result = await "PROC_Name".SqlProcedureOutputAsync(new ProcOutputModel{ Id=1});\n\n// \u793a\u4f8b\u4e8c\nProcedureOutputResult result = await "PROC_Name".SqlProcedureOutputAsync(new ProcOutputModel{ Id=1});\n\n// \u793a\u4f8b\u4e09\nProcedureOutputResult<(List, List)> result = await "PROC_Name".SqlProcedureOutputAsync<(List, List)>(new ProcOutputModel{ Id=1});\n')),(0,i.kt)("h2",{id:"9154-\u61d2\u4eba\u65e0\u654c-\u51fd\u6570-"},"9.15.4 \u61d2\u4eba\u65e0\u654c ",(0,i.kt)("inlineCode",{parentName:"h2"},"\u51fd\u6570")," \ud83d\udc2e"),(0,i.kt)("h3",{id:"91541-\u6807\u91cf\u51fd\u6570"},"9.15.4.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"\u6807\u91cf\u51fd\u6570")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar value = "FN_Name".SqlFunctionScalar();\n\n// \u793a\u4f8b\u4e8c\nvar value = "FN_Name".SqlFunctionScalar(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar value = "FN_Name".SqlFunctionScalar();\n\n// \u793a\u4f8b\u56db\nvar value = "FN_Name".SqlFunctionScalar(new {id = 1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar value = await "FN_Name".SqlFunctionScalarAsync();\n\n// \u793a\u4f8b\u4e8c\nvar value = await "FN_Name".SqlFunctionScalarAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar value = await "FN_Name".SqlFunctionScalarAsync();\n\n// \u793a\u4f8b\u56db\nvar value = await "FN_Name".SqlFunctionScalarAsync(new {id = 1});\n')),(0,i.kt)("h3",{id:"91542-\u8868\u503c\u51fd\u6570"},"9.15.4.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"\u8868\u503c\u51fd\u6570")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataTable = "FN_Name".SqlFunctionQuery();\n\n// \u793a\u4f8b\u4e8c\nvar dataTable = "FN_Name".SqlFunctionQuery(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar persons = "FN_Name".SqlFunctionQuery();\n\n// \u793a\u4f8b\u56db\nvar persons = "FN_Name".SqlFunctionQuery(new {id = 1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataTable = await "FN_Name".SqlFunctionQueryAsync();\n\n// \u793a\u4f8b\u4e8c\nvar dataTable = await "FN_Name".SqlFunctionQueryAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar persons = await "FN_Name".SqlFunctionQueryAsync();\n\n// \u793a\u4f8b\u56db\nvar persons = await "FN_Name".SqlFunctionQueryAsync(new {id = 1});\n')),(0,i.kt)("h2",{id:"9155-\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4"},"9.15.5 \u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var data = "select * from table".SetCommandTimeout(100).SqlQuery(); // \u5355\u4f4d\u79d2\n')),(0,i.kt)("h2",{id:"9156-isqlrepository-\u64cd\u4f5c"},"9.15.6 ",(0,i.kt)("inlineCode",{parentName:"h2"},"ISqlRepository")," \u64cd\u4f5c"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"ISqlRepository")," \u4ed3\u50a8\u662f\u4e13\u95e8\u5904\u7406 ",(0,i.kt)("inlineCode",{parentName:"p"},"Sql")," \u64cd\u4f5c\u7684\uff0c\u65e0\u9700\u5b9e\u4f53\u65b9\u5f0f\uff0c\u6240\u6709\u63a5\u53e3\u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"\u61d2\u4eba\u65e0\u654c")," \u65b9\u5f0f\u4e00\u6837\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u793a\u4f8b\u4e00\nvar dataTable = sqlRepository.SqlQuery("select * from person");\n\n// \u793a\u4f8b\u4e8c\nvar dataTable = sqlRepository.SqlQuery("select * from person where id > @id", new { id = 10});\n\n// \u793a\u4f8b\u56db\nvar persons = sqlRepository.SqlQuery("select * from person");\n\n// \u793a\u4f8b\u4e94\nvar persons = sqlRepository.SqlQuery("select * from person where id > @id", new { id = 10});\n\n// \u4e0d\u518d\u4e3e\u4f8b\u5b50\u3002\u3002\u3002\n')),(0,i.kt)("admonition",{title:"\u8865\u5145\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u4e0d\u7ba1\u662f\u54ea\u79cd\u65b9\u5f0f\u64cd\u4f5c ",(0,i.kt)("inlineCode",{parentName:"p"},"Sql")," \uff0c\u65b9\u6cd5\u540d\u53c2\u6570\u90fd\u662f\u4e00\u81f4\u7684\uff0c\u5982\uff1a"),(0,i.kt)("ul",{parentName:"admonition"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlQuery")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlQueryAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlQueries")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlQueriesAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlNonQuery")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlNonQueryAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlScalar")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlScalarAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureQuery")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureQueryAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureQueries")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureQueriesAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureScalar")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureScalarAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureNonQuery")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureNonQueryAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureOutput")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureOutputAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlFunctionScalar")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlFunctionScalarAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlFunctionQuery")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlFunctionQuery")))),(0,i.kt)("h2",{id:"9157-irepository-\u64cd\u4f5c"},"9.15.7 ",(0,i.kt)("inlineCode",{parentName:"h2"},"IRepository")," \u64cd\u4f5c"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"IRepository")," \u4e5f\u80fd\u64cd\u4f5c ",(0,i.kt)("inlineCode",{parentName:"p"},"sql"),"\uff0c\u8c03\u7528\u65b9\u6cd5\u4e5f\u662f\u548c\u4e0a\u9762\u4e00\u81f4\u7684\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var dataTable = repository.Sql().SqlQuery("select * from person");\n')),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u4e0d\u518d\u5217\u4e3e\u6240\u6709\u4f8b\u5b50\u3002")),(0,i.kt)("h2",{id:"9158-irepositorytentity-\u64cd\u4f5c"},"9.15.8 ",(0,i.kt)("inlineCode",{parentName:"h2"},"IRepository")," \u64cd\u4f5c"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"IRepository")," \u4e5f\u80fd\u64cd\u4f5c ",(0,i.kt)("inlineCode",{parentName:"p"},"sql"),"\uff0c\u8c03\u7528\u65b9\u6cd5\u4e5f\u662f\u548c\u4e0a\u9762\u4e00\u81f4\u7684\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var dataTable = personRepository.SqlQuery("select * from person");\n')),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u4e0d\u518d\u5217\u4e3e\u6240\u6709\u4f8b\u5b50\u3002")),(0,i.kt)("h2",{id:"9159-\u5173\u4e8e-sql-\u53c2\u6570"},"9.15.9 \u5173\u4e8e ",(0,i.kt)("inlineCode",{parentName:"h2"},"Sql")," \u53c2\u6570"),(0,i.kt)("p",null,"\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"sql"),"\u3001",(0,i.kt)("inlineCode",{parentName:"p"},"\u5b58\u50a8\u8fc7\u7a0b"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"\u51fd\u6570")," \u53c2\u6570\u90fd\u652f\u6301\u56db\u79cd\u65b9\u5f0f\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"DbParameter[]"),"\uff1a\u6570\u7ec4\u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"new {}"),"\uff1a\u533f\u540d\u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"new Class{}"),"\uff1a\u5f3a\u7c7b\u578b\u7c7b\u578b\uff08\u652f\u6301\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b\u53c2\u6570\uff09"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Dictionary")," \u7c7b\u578b")),(0,i.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u5efa\u8bae\u9664\u4e86\u590d\u6742\u7684\u5b58\u50a8\u8fc7\u7a0b\uff08\u5e26 ",(0,i.kt)("inlineCode",{parentName:"p"},"OUTPUT/RETURN"),"\uff09\u7684\u4ee5\u5916\uff0c\u6240\u6709\u53c2\u6570\u5efa\u8bae\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"new {}")," \u533f\u540d\u7c7b\u578b\uff0c\u5982\u679c\u9700\u8981\u52a8\u6001\u53c2\u6570\uff0c\u5219\u53ef\u4ee5\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Dictionary")," \u7c7b\u578b\u3002")),(0,i.kt)("admonition",{title:"\u53c2\u6570\u5927\u5c0f\u5199\u95ee\u9898",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u7531\u4e8e\u4e0d\u540c\u6570\u636e\u5e93\u5bf9\u67e5\u8be2\u53c2\u6570\u5927\u5c0f\u5199\u95ee\u9898\u5904\u7406\u4e0d\u4e00\u81f4\uff0c\u6240\u4ee5",(0,i.kt)("strong",{parentName:"p"},"\u5efa\u8bae\u6240\u6709\u67e5\u8be2\u53c2\u6570\u548c\u53c2\u6570\u540d\u6216\u5c5e\u6027\u540d\u5b8c\u5168\u4e00\u81f4"),"\u3002")),(0,i.kt)("h2",{id:"91510-\u591a\u6570\u636e\u5e93-sql-\u64cd\u4f5c--"},"9.15.10 \u591a\u6570\u636e\u5e93 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Sql")," \u64cd\u4f5c \ud83d\udcaf \ud83d\udc9b"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u62e5\u6709\u975e\u5e38\u7075\u6d3b\u7684\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u65b9\u5f0f\uff0c\u53ea\u9700\u901a\u8fc7\u591a",(0,i.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668"),"\u5373\u53ef\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93\u3002"),(0,i.kt)("h3",{id:"915101-\u61d2\u4eba\u65e0\u654c--\u65b9\u5f0f"},"9.15.10.1 \u61d2\u4eba\u65e0\u654c \ud83d\udc2e \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var dataTable = "select * from person".Change().SqlQuery();\n\nvar persons = "select * from person whre id > @id".Change().SqlQuery();\n')),(0,i.kt)("admonition",{title:"\u8865\u5145\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u61d2\u4eba\u65b9\u5f0f \u53ea\u9700\u8981\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"Change")," \u65b9\u5f0f\u5373\u53ef\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93\u3002")),(0,i.kt)("h3",{id:"915102-isqlrepository-\u65b9\u5f0f"},"9.15.10.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ISqlRepository")," \u65b9\u5f0f"),(0,i.kt)("p",null,"\u53ea\u9700\u8981\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"ISqlRepository")," \u6ce8\u5165\u6216\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"sqlRepository.Change()")," \u5207\u6362\u3002"),(0,i.kt)("h3",{id:"915103-irepository-\u65b9\u5f0f"},"9.15.10.3 ",(0,i.kt)("inlineCode",{parentName:"h3"},"IRepository")," \u65b9\u5f0f"),(0,i.kt)("p",null,"\u53ea\u9700\u8981\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"repository.Change()")," \u83b7\u53d6\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"915104-irepositorytentity-\u65b9\u5f0f"},"9.15.10.4 ",(0,i.kt)("inlineCode",{parentName:"h3"},"IRepository")," \u65b9\u5f0f"),(0,i.kt)("p",null,"\u53ea\u9700\u8981\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"IRepository")," \u6ce8\u5165\u6216\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"personRepository.Change()")," \u5207\u6362\u3002"),(0,i.kt)("h2",{id:"91511-\u5207\u6362\u6570\u636e\u5e93"},"9.15.11 \u5207\u6362\u6570\u636e\u5e93"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u4e0d\u7ba1\u662f\u61d2\u4eba\u6a21\u5f0f\u8fd8\u662f\u4ed3\u50a8\u6a21\u5f0f\u90fd\u662f\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},".Change")," \u65b9\u5f0f\u5207\u6362\u6570\u636e\u5e93\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u61d2\u4eba\u6a21\u5f0f\nvar data = "select * from table".Change().SqlQuery();\n\n// \u4ed3\u50a8\u65b9\u5f0f\nvar data = req.Change().SqlQuery("select * from table");\n')),(0,i.kt)("h2",{id:"91512-\u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df"},"9.15.12 \u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u6240\u6709\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5b57\u7b26\u4e32")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5b9e\u4f53")," \u62d3\u5c55\u90fd\u6709\u81ea\u5df1\u72ec\u7acb\u7ef4\u62a4\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"ServiceProvider")," \u4f5c\u7528\u57df\u3002"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Web")," \u8bf7\u6c42\u4e2d\uff0c\u9ed8\u8ba4\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"HttpContext.RequestServices"),"\uff0c\u4f46\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u975e Web"),"\uff0c\u5982\u591a\u7ebf\u7a0b\u64cd\u4f5c\uff0c\u540e\u53f0\u4efb\u52a1\uff0c\u4e8b\u4ef6\u603b\u7ebf\u7b49\u573a\u666f\u4e0b\u4f1a\u81ea\u52a8\u521b\u5efa\u65b0\u7684\u4f5c\u7528\u57df\uff0c\u5b9e\u9645\u4e0a\u8fd9\u662f\u975e\u5e38\u4e0d\u5fc5\u8981\u7684\u5185\u5b58\u5f00\u9500\u3002"),(0,i.kt)("p",null,"\u8fd9\u65f6\uff0c\u6211\u4eec\u53ea\u9700\u8981\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},".SetXXXScoped(service)")," \u5171\u4eab\u5f53\u524d\u670d\u52a1\u63d0\u4f9b\u5668\u4f5c\u7528\u57df\u5373\u53ef\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'Scoped.Create((fac, scope) => {\n "select * from table".SetContextScoped(scope.ServiceProvider).SqlQuery();\n});\n')),(0,i.kt)("h2",{id:"91513-\u9759\u6001-default-\u65b9\u5f0f\u6784\u5efa"},"9.15.13 \u9759\u6001 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Default")," \u65b9\u5f0f\u6784\u5efa"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SqlExecutePart.Default.SetSqlString("select * from person").SqlQuery();\n')),(0,i.kt)("h2",{id:"91514-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.15.14 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return u},kt:function(){return c}});var r=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function o(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var s=r.createContext({}),d=function(e){var n=r.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},u=function(e){var n=d(e.components);return r.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},m=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=d(t),c=a,N=m["".concat(s,".").concat(c)]||m[c]||p[c]||i;return t?r.createElement(N,o(o({ref:n},u),{},{components:t})):r.createElement(N,o({ref:n},u))}));function c(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,o=new Array(i);o[0]=m;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var d=2;d=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var s=r.createContext({}),d=function(e){var n=r.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},u=function(e){var n=d(e.components);return r.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},m=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=d(t),c=a,N=m["".concat(s,".").concat(c)]||m[c]||p[c]||i;return t?r.createElement(N,o(o({ref:n},u),{},{components:t})):r.createElement(N,o({ref:n},u))}));function c(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,o=new Array(i);o[0]=m;var l={};for(var s in n)hasOwnProperty.call(n,s)&&(l[s]=n[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var d=2;dSql",id:"9151-\u5173\u4e8e-sql",level:2},{value:"9.15.2 \u61d2\u4eba\u65e0\u654c Sql \ud83d\udc2e",id:"9152-\u61d2\u4eba\u65e0\u654c-sql-",level:2},{value:"9.15.2.1 \u8fd4\u56de DataTable",id:"91521-\u8fd4\u56de-datatable",level:3},{value:"9.15.2.2 \u8fd4\u56de List<T>",id:"91522-\u8fd4\u56de-listt",level:3},{value:"9.15.2.3 \u8fd4\u56de DataSet",id:"91523-\u8fd4\u56de-dataset",level:3},{value:"9.15.2.4 \u8fd4\u56de Tuple<T1,...T8>",id:"91524-\u8fd4\u56de-tuplet1t8",level:3},{value:"9.15.2.5 \u8fd4\u56de \u5355\u884c\u5355\u5217",id:"91525-\u8fd4\u56de-\u5355\u884c\u5355\u5217",level:3},{value:"9.15.2.6 \u8fd4\u56de \u53d7\u5f71\u54cd\u884c\u6570",id:"91526-\u8fd4\u56de-\u53d7\u5f71\u54cd\u884c\u6570",level:3},{value:"9.15.3 \u61d2\u4eba\u65e0\u654c \u5b58\u50a8\u8fc7\u7a0b \ud83d\udc2e",id:"9153-\u61d2\u4eba\u65e0\u654c-\u5b58\u50a8\u8fc7\u7a0b-",level:2},{value:"9.15.3.1 \u8fd4\u56de DataTable",id:"91531-\u8fd4\u56de-datatable",level:3},{value:"9.15.3.2 \u8fd4\u56de List<T>",id:"91532-\u8fd4\u56de-listt",level:3},{value:"9.15.3.3 \u8fd4\u56de DataSet",id:"91533-\u8fd4\u56de-dataset",level:3},{value:"9.15.3.4 \u8fd4\u56de Tuple<T1,...T8>",id:"91534-\u8fd4\u56de-tuplet1t8",level:3},{value:"9.15.3.5 \u8fd4\u56de \u5355\u884c\u5355\u5217",id:"91535-\u8fd4\u56de-\u5355\u884c\u5355\u5217",level:3},{value:"9.15.3.6 \u8fd4\u56de \u53d7\u5f71\u54cd\u884c\u6570",id:"91536-\u8fd4\u56de-\u53d7\u5f71\u54cd\u884c\u6570",level:3},{value:"9.15.3.7 \u5e26 OUTPUT/RETURN \u8fd4\u56de",id:"91537-\u5e26-outputreturn-\u8fd4\u56de",level:3},{value:"9.15.4 \u61d2\u4eba\u65e0\u654c \u51fd\u6570 \ud83d\udc2e",id:"9154-\u61d2\u4eba\u65e0\u654c-\u51fd\u6570-",level:2},{value:"9.15.4.1 \u6807\u91cf\u51fd\u6570",id:"91541-\u6807\u91cf\u51fd\u6570",level:3},{value:"9.15.4.2 \u8868\u503c\u51fd\u6570",id:"91542-\u8868\u503c\u51fd\u6570",level:3},{value:"9.15.5 \u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4",id:"9155-\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4",level:2},{value:"9.15.6 ISqlRepository \u64cd\u4f5c",id:"9156-isqlrepository-\u64cd\u4f5c",level:2},{value:"9.15.7 IRepository \u64cd\u4f5c",id:"9157-irepository-\u64cd\u4f5c",level:2},{value:"9.15.8 IRepository<TEntity> \u64cd\u4f5c",id:"9158-irepositorytentity-\u64cd\u4f5c",level:2},{value:"9.15.9 \u5173\u4e8e Sql \u53c2\u6570",id:"9159-\u5173\u4e8e-sql-\u53c2\u6570",level:2},{value:"9.15.10 \u591a\u6570\u636e\u5e93 Sql \u64cd\u4f5c \ud83d\udcaf \ud83d\udc9b",id:"91510-\u591a\u6570\u636e\u5e93-sql-\u64cd\u4f5c--",level:2},{value:"9.15.10.1 \u61d2\u4eba\u65e0\u654c \ud83d\udc2e \u65b9\u5f0f",id:"915101-\u61d2\u4eba\u65e0\u654c--\u65b9\u5f0f",level:3},{value:"9.15.10.2 ISqlRepository \u65b9\u5f0f",id:"915102-isqlrepository-\u65b9\u5f0f",level:3},{value:"9.15.10.3 IRepository \u65b9\u5f0f",id:"915103-irepository-\u65b9\u5f0f",level:3},{value:"9.15.10.4 IRepository<TEntity> \u65b9\u5f0f",id:"915104-irepositorytentity-\u65b9\u5f0f",level:3},{value:"9.15.11 \u5207\u6362\u6570\u636e\u5e93",id:"91511-\u5207\u6362\u6570\u636e\u5e93",level:2},{value:"9.15.12 \u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df",id:"91512-\u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df",level:2},{value:"9.15.13 \u9759\u6001 Default \u65b9\u5f0f\u6784\u5efa",id:"91513-\u9759\u6001-default-\u65b9\u5f0f\u6784\u5efa",level:2},{value:"9.15.14 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"91514-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],m={toc:p};function c(e){var n=e.components,t=(0,a.Z)(e,o);return(0,i.kt)("wrapper",(0,r.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{title:"\u6e29\u99a8\u63d0\u793a",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u63a8\u8350\u4f7f\u7528 \u300a",(0,i.kt)("a",{parentName:"p",href:"/furion/docs/dbcontext-sql-proxy"},"9.17 Sql \u9ad8\u7ea7\u4ee3\u7406"),"\u300b\u4ee3\u66ff\u672c\u7ae0\u8282\u529f\u80fd\u3002",(0,i.kt)("inlineCode",{parentName:"p"},"Sql \u9ad8\u7ea7\u4ee3\u7406")," \u80fd\u591f\u63d0\u4f9b\u66f4\u5bb9\u6613\u4e14\u66f4\u6613\u7ef4\u62a4\u7684\u65b9\u5f0f\u3002")),(0,i.kt)("admonition",{title:"\u4f8b\u5b50\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u672c\u7ae0\u8282\u4f8b\u5b50\u5747\u4ee5 ",(0,i.kt)("inlineCode",{parentName:"p"},"sql server")," \u6570\u636e\u5e93\u5199\u7684\u4f8b\u5b50\uff0c\u547d\u4ee4\u53c2\u6570\u7edf\u4e00\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"@")," \u7b26\u53f7\uff0c\u4f46\u4e0d\u540c\u6570\u636e\u5e93\u7684\u53c2\u6570\u524d\u7f00\u6709\u6240\u4e0d\u540c\uff0c\u5982\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"sql server")," \u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"@"),"\uff0coracle \u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},":"),"\uff0cmy sql \u91c7\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"?"),"\u3002")),(0,i.kt)("h2",{id:"9151-\u5173\u4e8e-sql"},"9.15.1 \u5173\u4e8e ",(0,i.kt)("inlineCode",{parentName:"h2"},"Sql")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u975e\u5e38\u591a\u4e14\u7075\u6d3b\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"sql")," \u64cd\u4f5c\u65b9\u6cd5\uff0c\u4e14\u6027\u80fd\u4e0d\u8f93\u4e8e ",(0,i.kt)("inlineCode",{parentName:"p"},"dapper"),"\uff0c\u540c\u65f6\u903c\u8fd1 ",(0,i.kt)("inlineCode",{parentName:"p"},"ADO.NET")," \u539f\u751f\u64cd\u4f5c\u3002"),(0,i.kt)("h2",{id:"9152-\u61d2\u4eba\u65e0\u654c-sql-"},"9.15.2 \u61d2\u4eba\u65e0\u654c ",(0,i.kt)("inlineCode",{parentName:"h2"},"Sql")," \ud83d\udc2e"),(0,i.kt)("h3",{id:"91521-\u8fd4\u56de-datatable"},"9.15.2.1 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"DataTable")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataTable = "select * from person".SqlQuery();\n\n// \u793a\u4f8b\u4e8c\nvar dataTable = "select top 10 * from person where id > @id".SqlQuery(new {id = 10});\n\n// \u793a\u4f8b\u4e09\nvar dataTable = "select Id, Name, Age from person where name like @name".SqlQuery(new Dictionary{ {"name", "%Furion%"} });\n\n// \u793a\u4f8b\u56db\nvar dataTable = "select * from person where name=@name limit 1,10".SqlQuery(new []{ new MySqlParameter("name","Furion") });\n\n// \u793a\u4f8b\u4e94\nvar dataTable = "select * from person where id>@id and name like @name".SqlQuery(new YourModel { Id = 1, Name = "%Furion%" });\n\n// \u793a\u4f8b\u516d\nvar dataTable = "exec PROC_GetPerson @id".SqlQuery(new {id = 10});\n\n// \u793a\u4f8b\u4e03\nvar dataTable = "select * from FN_GetPersons(@id)".SqlQuery(new {id = 10});\n\n// \u793a\u4f8b\u516b\nvar dataTable = @"\nselect * from person p\nleft join personDetail pd on p.Id == pd.pid\nwhere p.Id > @id;".SqlQuery(new {id = 10});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataTable = await "select * from person".SqlQueryAsync();\n\n// \u793a\u4f8b\u4e8c\nvar dataTable = await "select top 10 * from person where id > @id".SqlQueryAsync(new {id = 10});\n\n// \u793a\u4f8b\u4e09\nvar dataTable = await "select Id, Name, Age from person where name like @name".SqlQueryAsync(new Dictionary{ {"name", "%Furion%"} });\n\n// \u793a\u4f8b\u56db\nvar dataTable = await "select * from person where name=@name limit 1,10".SqlQueryAsync(new []{ new MySqlParameter("name","Furion") });\n\n// \u793a\u4f8b\u4e94\nvar dataTable = await "select * from person where id>@id and name like @name".SqlQueryAsync(new YourModel { Id = 1, Name = "%Furion%" });\n\n// \u793a\u4f8b\u516d\nvar dataTable = await "exec PROC_GetPerson @id".SqlQueryAsync(new {id = 10});\n\n// \u793a\u4f8b\u4e03\nvar dataTable = await "select * from FN_GetPersons(@id)".SqlQueryAsync(new {id = 10});\n\n// \u793a\u4f8b\u516b\nvar dataTable = await @"\nselect * from person p\nleft join personDetail pd on p.Id == pd.pid\nwhere p.Id > @id;".SqlQueryAsync(new {id = 10});\n')),(0,i.kt)("h3",{id:"91522-\u8fd4\u56de-listt"},"9.15.2.2 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"List")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = "select * from person".SqlQuery();\n\n// \u793a\u4f8b\u4e8c\nvar persons = "select top 10 * from person where id > @id".SqlQuery(new {id = 10});\n\n// \u793a\u4f8b\u4e09\nvar persons = "select Id, Name, Age from person where name like @name".SqlQuery(new Dictionary{ {"name", "%Furion%"} });\n\n// \u793a\u4f8b\u56db\nvar persons = "select * from person where name=@name limit 1,10".SqlQuery(new []{ new MySqlParameter("name","Furion") });\n\n// \u793a\u4f8b\u4e94\nvar persons = "select * from person where id>@id and name like @name".SqlQuery(new YourModel { Id = 1, Name = "%Furion%" });\n\n// \u793a\u4f8b\u516d\nvar persons = "exec PROC_GetPerson @id".SqlQuery(new {id = 10});\n\n// \u793a\u4f8b\u4e03\nvar persons = "select * from FN_GetPersons(@id)".SqlQuery(new {id = 10});\n\n// \u793a\u4f8b\u516b\nvar persons = @"\nselect * from person p\nleft join personDetail pd on p.Id == pd.pid\nwhere p.Id > @id;".SqlQuery(new {id = 10});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = await "select * from person".SqlQueryAsync();\n\n// \u793a\u4f8b\u4e8c\nvar persons = await "select top 10 * from person where id > @id".SqlQueryAsync(new {id = 10});\n\n// \u793a\u4f8b\u4e09\nvar persons = await "select Id, Name, Age from person where name like @name".SqlQueryAsync(new Dictionary{ {"name", "%Furion%"} });\n\n// \u793a\u4f8b\u56db\nvar persons = await "select * from person where name=@name limit 1,10".SqlQueryAsync(new []{ new MySqlParameter("name","Furion") });\n\n// \u793a\u4f8b\u4e94\nvar persons = await "select * from person where id>@id and name like @name".SqlQueryAsync(new YourModel { Id = 1, Name = "%Furion%" });\n\n// \u793a\u4f8b\u516d\nvar persons = await "exec PROC_GetPerson @id".SqlQueryAsync(new {id = 10});\n\n// \u793a\u4f8b\u4e03\nvar persons = await "select * from FN_GetPersons(@id)".SqlQueryAsync(new {id = 10});\n\n// \u793a\u4f8b\u516b\nvar persons = await @"\nselect * from person p\nleft join personDetail pd on p.Id == pd.pid\nwhere p.Id > @id;".SqlQueryAsync(new {id = 10});\n')),(0,i.kt)("h3",{id:"91523-\u8fd4\u56de-dataset"},"9.15.2.3 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"DataSet")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataSet = @"\nselect * from person;\nselect * from student;".SqlQueries();\n\n// \u793a\u4f8b\u4e8c\nvar dataSet = @"\nselect * from person where Id > @id;\nselect * from student where Name like @name;".SqlQueries(new {id = 1, name = "%furion%"});\n\n// \u793a\u4f8b\u4e09\nvar dataSet = @"\nselect * from person;\nexec PROC_GetStudents(@id);\nselect \'Furion\';\nselect * from FN_GetPerson(@id);".SqlQueries(new {id = 1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataSet = await @"\nselect * from person;\nselect * from student;".SqlQueriesAsync();\n\n// \u793a\u4f8b\u4e8c\nvar dataSet = await @"\nselect * from person where Id > @id;\nselect * from student where Name like @name;".SqlQueriesAsync(new {id = 1, name = "%furion%"});\n\n// \u793a\u4f8b\u4e09\nvar dataSet = await @"\nselect * from person;\nexec PROC_GetStudents(@id);\nselect \'Furion\';\nselect * from FN_GetPerson(@id);".SqlQueriesAsync(new {id = 1});\n')),(0,i.kt)("h3",{id:"91524-\u8fd4\u56de-tuplet1t8"},"9.15.2.4 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"Tuple")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar (persons, students) = @"\nselect * from person;\nselect * from student;".SqlQueries();\n\n// \u793a\u4f8b\u4e8c\nvar (persons, students) = @"\nselect * from person where Id > @id;\nselect * from student where Name like @name;".SqlQueries(new {id = 1, name = "%furion%"});\n\n// \u793a\u4f8b\u4e09\nvar (persons, students, string, PersonDto) = @"\nselect * from person;\nexec PROC_GetStudents(@id);\nselect \'Furion\';\nselect * from FN_GetPerson(@id);".SqlQueries(new {id = 1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar (persons, students) = await @"\nselect * from person;\nselect * from student;".SqlQueriesAsync();\n\n// \u793a\u4f8b\u4e8c\nvar (persons, students) = await @"\nselect * from person where Id > @id;\nselect * from student where Name like @name;".SqlQueriesAsync(new {id = 1, name = "%furion%"});\n\n// \u793a\u4f8b\u4e09\nvar (persons, students, string, PersonDto) = await @"\nselect * from person;\nexec PROC_GetStudents(@id);\nselect \'Furion\';\nselect * from FN_GetPerson(@id);".SqlQueriesAsync(new {id = 1});\n')),(0,i.kt)("h3",{id:"91525-\u8fd4\u56de-\u5355\u884c\u5355\u5217"},"9.15.2.5 \u8fd4\u56de \u5355\u884c\u5355\u5217"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar value = "select Name from person where id = @id".SqlScalar(new {id = 1});\n\n// \u793a\u4f8b\u4e8c\nvar value = "select Name from person where id = @id".SqlScalar(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar value = "select Age from person where id = @id".SqlScalar(new {id = 1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar value = await "select Name from person where id = @id".SqlScalarAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e8c\nvar value = await "select Name from person where id = @id".SqlScalarAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar value = await "select Age from person where id = @id".SqlScalarAsync(new {id = 1});\n')),(0,i.kt)("h3",{id:"91526-\u8fd4\u56de-\u53d7\u5f71\u54cd\u884c\u6570"},"9.15.2.6 \u8fd4\u56de \u53d7\u5f71\u54cd\u884c\u6570"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar rowEffects = "insert into person(Name,Age,Address) values(@name,@age,@address)".SqlNonQuery(person);\n\n// \u793a\u4f8b\u4e8c\nvar rowEffects = @"\ninsert into person(Name,Age,Address) values(@name,@age,@address);\ninsert into person(Name,Age,Address) values(@name,@age,@address);".SqlNonQuery(persons);\n\n// \u793a\u4f8b\u4e09\nvar rowEffects = "update person set name=@name where id=@id".SqlNonQuery(new {id=1, name="\u767e\u5c0f\u50e7"});\n\n// \u793a\u4f8b\u56db\nvar rowEffects = "delete from person where @id > 10".SqlNonQuery(new {id=1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar rowEffects = await "insert into person(Name,Age,Address) values(@name,@age,@address)".SqlNonQueryAsync(person);\n\n// \u793a\u4f8b\u4e8c\nvar rowEffects = @"\ninsert into person(Name,Age,Address) values(@name,@age,@address);\ninsert into person(Name,Age,Address) values(@name,@age,@address);".SqlNonQueryAsync(persons);\n\n// \u793a\u4f8b\u4e09\nvar rowEffects = await "update person set name=@name where id=@id".SqlNonQueryAsync(new {id=1, name="\u767e\u5c0f\u50e7"});\n\n// \u793a\u4f8b\u56db\nvar rowEffects = await "delete from person where @id > 10".SqlNonQueryAsync(new {id=1});\n')),(0,i.kt)("h2",{id:"9153-\u61d2\u4eba\u65e0\u654c-\u5b58\u50a8\u8fc7\u7a0b-"},"9.15.3 \u61d2\u4eba\u65e0\u654c ",(0,i.kt)("inlineCode",{parentName:"h2"},"\u5b58\u50a8\u8fc7\u7a0b")," \ud83d\udc2e"),(0,i.kt)("h3",{id:"91531-\u8fd4\u56de-datatable"},"9.15.3.1 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"DataTable")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataTable = "PROC_Name".SqlProcedureQuery();\n\n// \u793a\u4f8b\u4e8c\nvar dataTable = "PROC_Name".SqlProcedureQuery(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar dataTable = "PROC_Name".SqlProcedureQuery(new {id = 1, age = 27});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataTable = await "PROC_Name".SqlProcedureQueryAsync();\n\n// \u793a\u4f8b\u4e8c\nvar dataTable = await "PROC_Name".SqlProcedureQueryAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar dataTable = await "PROC_Name".SqlProcedureQueryAsync(new {id = 1, age = 27});\n')),(0,i.kt)("h3",{id:"91532-\u8fd4\u56de-listt"},"9.15.3.2 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"List")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = "PROC_Name".SqlProcedureQuery();\n\n// \u793a\u4f8b\u4e8c\nvar persons = "PROC_Name".SqlProcedureQuery(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar persons = "PROC_Name".SqlProcedureQuery(new {id = 1, age = 27});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = await "PROC_Name".SqlProcedureQueryAsync();\n\n// \u793a\u4f8b\u4e8c\nvar persons = await "PROC_Name".SqlProcedureQueryAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar persons = await "PROC_Name".SqlProcedureQueryAsync(new {id = 1, age = 27});\n')),(0,i.kt)("h3",{id:"91533-\u8fd4\u56de-dataset"},"9.15.3.3 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"DataSet")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataSet = "PROC_Name".SqlProcedureQueries();\n\n// \u793a\u4f8b\u4e8c\nvar dataSet = "PROC_Name".SqlProcedureQueries(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar dataSet = "PROC_Name".SqlProcedureQueries(new {id = 1, age = 27});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataSet = await "PROC_Name".SqlProcedureQueriesAsync();\n\n// \u793a\u4f8b\u4e8c\nvar dataSet = await "PROC_Name".SqlProcedureQueriesAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar dataSet = await "PROC_Name".SqlProcedureQueriesAsync(new {id = 1, age = 27});\n')),(0,i.kt)("h3",{id:"91534-\u8fd4\u56de-tuplet1t8"},"9.15.3.4 \u8fd4\u56de ",(0,i.kt)("inlineCode",{parentName:"h3"},"Tuple")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = "PROC_Name".SqlProcedureQueries();\n\n// \u793a\u4f8b\u4e8c\nvar (persons,students) = "PROC_Name".SqlProcedureQueries(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar (persons,students,string) = "PROC_Name".SqlProcedureQueries(new {id = 1, age = 27});\n\n// \u793a\u4f8b\u56db\nvar (persons,students,personDetail,string) = "PROC_Name".SqlProcedureQueries(new {id = 1, age = 27});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar persons = await "PROC_Name".SqlProcedureQueriesAsync();\n\n// \u793a\u4f8b\u4e8c\nvar (persons,students) = await "PROC_Name".SqlProcedureQueriesAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar (persons,students,string) = await "PROC_Name".SqlProcedureQueriesAsync(new {id = 1, age = 27});\n\n// \u793a\u4f8b\u56db\nvar (persons,students,personDetail,string) = await "PROC_Name".SqlProcedureQueriesAsync(new {id = 1, age = 27});\n')),(0,i.kt)("h3",{id:"91535-\u8fd4\u56de-\u5355\u884c\u5355\u5217"},"9.15.3.5 \u8fd4\u56de \u5355\u884c\u5355\u5217"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar value = "PROC_Name".SqlProcedureScalar(new {id = 1});\n\n// \u793a\u4f8b\u4e8c\nvar value = "PROC_Name".SqlProcedureScalar(new {id = 1, name = "\u65b0\u751f\u5e1d", address ="\u5e7f\u4e1c\u7701\u4e2d\u5c71\u5e02"});\n\n// \u793a\u4f8b\u4e09\nvar value = "PROC_Name".SqlProcedureScalar(new {id = 1, address ="\u5e7f\u4e1c\u7701\u4e2d\u5c71\u5e02"});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar value = await "PROC_Name".SqlProcedureScalarAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e8c\nvar value = await "PROC_Name".SqlProcedureScalarAsync(new {id = 1, name = "\u65b0\u751f\u5e1d", address ="\u5e7f\u4e1c\u7701\u4e2d\u5c71\u5e02"});\n\n// \u793a\u4f8b\u4e09\nvar value = await "PROC_Name".SqlProcedureScalarAsync(new {id = 1, address ="\u5e7f\u4e1c\u7701\u4e2d\u5c71\u5e02"});\n')),(0,i.kt)("h3",{id:"91536-\u8fd4\u56de-\u53d7\u5f71\u54cd\u884c\u6570"},"9.15.3.6 \u8fd4\u56de \u53d7\u5f71\u54cd\u884c\u6570"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar rowEffects = "PROC_Name".SqlProcedureNonQuery(person);\n\n// \u793a\u4f8b\u4e8c\nvar rowEffects = "PROC_Name".SqlProcedureNonQuery(new {id = 1, name = "\u65b0\u751f\u5e1d", address ="\u5e7f\u4e1c\u7701\u4e2d\u5c71\u5e02"});\n\n// \u793a\u4f8b\u4e09\nvar rowEffects = "PROC_Name".SqlProcedureNonQuery(new {id=1, name="\u767e\u5c0f\u50e7"});\n\n// \u793a\u4f8b\u56db\nvar rowEffects = "PROC_Name".SqlProcedureNonQuery(new {id=1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(person);\n\n// \u793a\u4f8b\u4e8c\nvar rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new {id = 1, name = "\u65b0\u751f\u5e1d", address ="\u5e7f\u4e1c\u7701\u4e2d\u5c71\u5e02"});\n\n// \u793a\u4f8b\u4e09\nvar rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new {id=1, name="\u767e\u5c0f\u50e7"});\n\n// \u793a\u4f8b\u56db\nvar rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new {id=1});\n')),(0,i.kt)("h3",{id:"91537-\u5e26-outputreturn-\u8fd4\u56de"},"9.15.3.7 \u5e26 ",(0,i.kt)("inlineCode",{parentName:"h3"},"OUTPUT/RETURN")," \u8fd4\u56de"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sql",metastring:"showLineNumbers {3,4,10-12,15-17,22}",showLineNumbers:!0,"":!0,"{3,4,10-12,15-17,22}":!0},"CREATE PROC PROC_Output\n @Id INT, // \u8f93\u5165\u53c2\u6570\n @Name NVARCHAR(32) OUTPUT, // \u8f93\u51fa\u53c2\u6570\uff0c\u8fd8\u5e26\u957f\u5ea6\n @Age INT OUTPUT // \u8f93\u51fa\u53c2\u6570\nAS\nBEGIN\n SET @Name = 'Furion Output';\n\n // \u8f93\u51fa\u7ed3\u679c\u96c6\n SELECT *\n FROM dbo.Test\n WHERE Id > @Id;\n\n // \u8f93\u51fa\u7ed3\u679c\u96c6\n SELECT TOP 10\n *\n FROM dbo.Test;\n\n SET @Age = 27;\n\n // \u5e26 RETURN \u8fd4\u56de\n RETURN 10;\nEND;\n")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,10,13,16}",showLineNumbers:!0,"":!0,"{1,10,13,16}":!0},"using Furion.DatabaseAccessor;\nusing System.Data;\n\nnamespace Furion.Application\n{\n public class ProcOutputModel\n {\n public int Id { get; set; } // \u8f93\u5165\u53c2\u6570\n\n [DbParameter(ParameterDirection.Output, Size = 32)]\n public string Name { get; set; } // \u8f93\u51fa\u53c2\u6570\n\n [DbParameter(ParameterDirection.Output)]\n public int Age { get; set; } // \u8f93\u51fa\u53c2\u6570\n\n [DbParameter(ParameterDirection.ReturnValue)]\n public int ReturnValue { get; set; } // \u8fd4\u56de\u503c\n }\n}\n")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nProcedureOutputResult result = "PROC_Name".SqlProcedureOutput(new ProcOutputModel{ Id=1});\n\n// \u793a\u4f8b\u4e8c\nProcedureOutputResult result = "PROC_Name".SqlProcedureOutput(new ProcOutputModel{ Id=1});\n\n// \u793a\u4f8b\u4e09\nProcedureOutputResult<(List, List)> result = "PROC_Name".SqlProcedureOutput<(List, List)>(new ProcOutputModel{ Id=1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n// \u793a\u4f8b\u4e00\nProcedureOutputResult result = await "PROC_Name".SqlProcedureOutputAsync(new ProcOutputModel{ Id=1});\n\n// \u793a\u4f8b\u4e8c\nProcedureOutputResult result = await "PROC_Name".SqlProcedureOutputAsync(new ProcOutputModel{ Id=1});\n\n// \u793a\u4f8b\u4e09\nProcedureOutputResult<(List, List)> result = await "PROC_Name".SqlProcedureOutputAsync<(List, List)>(new ProcOutputModel{ Id=1});\n')),(0,i.kt)("h2",{id:"9154-\u61d2\u4eba\u65e0\u654c-\u51fd\u6570-"},"9.15.4 \u61d2\u4eba\u65e0\u654c ",(0,i.kt)("inlineCode",{parentName:"h2"},"\u51fd\u6570")," \ud83d\udc2e"),(0,i.kt)("h3",{id:"91541-\u6807\u91cf\u51fd\u6570"},"9.15.4.1 ",(0,i.kt)("inlineCode",{parentName:"h3"},"\u6807\u91cf\u51fd\u6570")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar value = "FN_Name".SqlFunctionScalar();\n\n// \u793a\u4f8b\u4e8c\nvar value = "FN_Name".SqlFunctionScalar(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar value = "FN_Name".SqlFunctionScalar();\n\n// \u793a\u4f8b\u56db\nvar value = "FN_Name".SqlFunctionScalar(new {id = 1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar value = await "FN_Name".SqlFunctionScalarAsync();\n\n// \u793a\u4f8b\u4e8c\nvar value = await "FN_Name".SqlFunctionScalarAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar value = await "FN_Name".SqlFunctionScalarAsync();\n\n// \u793a\u4f8b\u56db\nvar value = await "FN_Name".SqlFunctionScalarAsync(new {id = 1});\n')),(0,i.kt)("h3",{id:"91542-\u8868\u503c\u51fd\u6570"},"9.15.4.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"\u8868\u503c\u51fd\u6570")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// ==== \u540c\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataTable = "FN_Name".SqlFunctionQuery();\n\n// \u793a\u4f8b\u4e8c\nvar dataTable = "FN_Name".SqlFunctionQuery(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar persons = "FN_Name".SqlFunctionQuery();\n\n// \u793a\u4f8b\u56db\nvar persons = "FN_Name".SqlFunctionQuery(new {id = 1});\n\n// ==== \u5f02\u6b65\u64cd\u4f5c ====\n\n// \u793a\u4f8b\u4e00\nvar dataTable = await "FN_Name".SqlFunctionQueryAsync();\n\n// \u793a\u4f8b\u4e8c\nvar dataTable = await "FN_Name".SqlFunctionQueryAsync(new {id = 1});\n\n// \u793a\u4f8b\u4e09\nvar persons = await "FN_Name".SqlFunctionQueryAsync();\n\n// \u793a\u4f8b\u56db\nvar persons = await "FN_Name".SqlFunctionQueryAsync(new {id = 1});\n')),(0,i.kt)("h2",{id:"9155-\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4"},"9.15.5 \u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var data = "select * from table".SetCommandTimeout(100).SqlQuery(); // \u5355\u4f4d\u79d2\n')),(0,i.kt)("h2",{id:"9156-isqlrepository-\u64cd\u4f5c"},"9.15.6 ",(0,i.kt)("inlineCode",{parentName:"h2"},"ISqlRepository")," \u64cd\u4f5c"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"ISqlRepository")," \u4ed3\u50a8\u662f\u4e13\u95e8\u5904\u7406 ",(0,i.kt)("inlineCode",{parentName:"p"},"Sql")," \u64cd\u4f5c\u7684\uff0c\u65e0\u9700\u5b9e\u4f53\u65b9\u5f0f\uff0c\u6240\u6709\u63a5\u53e3\u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"\u61d2\u4eba\u65e0\u654c")," \u65b9\u5f0f\u4e00\u6837\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u793a\u4f8b\u4e00\nvar dataTable = sqlRepository.SqlQuery("select * from person");\n\n// \u793a\u4f8b\u4e8c\nvar dataTable = sqlRepository.SqlQuery("select * from person where id > @id", new { id = 10});\n\n// \u793a\u4f8b\u56db\nvar persons = sqlRepository.SqlQuery("select * from person");\n\n// \u793a\u4f8b\u4e94\nvar persons = sqlRepository.SqlQuery("select * from person where id > @id", new { id = 10});\n\n// \u4e0d\u518d\u4e3e\u4f8b\u5b50\u3002\u3002\u3002\n')),(0,i.kt)("admonition",{title:"\u8865\u5145\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u4e0d\u7ba1\u662f\u54ea\u79cd\u65b9\u5f0f\u64cd\u4f5c ",(0,i.kt)("inlineCode",{parentName:"p"},"Sql")," \uff0c\u65b9\u6cd5\u540d\u53c2\u6570\u90fd\u662f\u4e00\u81f4\u7684\uff0c\u5982\uff1a"),(0,i.kt)("ul",{parentName:"admonition"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlQuery")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlQueryAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlQueries")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlQueriesAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlNonQuery")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlNonQueryAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlScalar")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlScalarAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureQuery")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureQueryAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureQueries")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureQueriesAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureScalar")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureScalarAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureNonQuery")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureNonQueryAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureOutput")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlProcedureOutputAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlFunctionScalar")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlFunctionScalarAsync")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlFunctionQuery")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"SqlFunctionQuery")))),(0,i.kt)("h2",{id:"9157-irepository-\u64cd\u4f5c"},"9.15.7 ",(0,i.kt)("inlineCode",{parentName:"h2"},"IRepository")," \u64cd\u4f5c"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"IRepository")," \u4e5f\u80fd\u64cd\u4f5c ",(0,i.kt)("inlineCode",{parentName:"p"},"sql"),"\uff0c\u8c03\u7528\u65b9\u6cd5\u4e5f\u662f\u548c\u4e0a\u9762\u4e00\u81f4\u7684\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var dataTable = repository.Sql().SqlQuery("select * from person");\n')),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u4e0d\u518d\u5217\u4e3e\u6240\u6709\u4f8b\u5b50\u3002")),(0,i.kt)("h2",{id:"9158-irepositorytentity-\u64cd\u4f5c"},"9.15.8 ",(0,i.kt)("inlineCode",{parentName:"h2"},"IRepository")," \u64cd\u4f5c"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"IRepository")," \u4e5f\u80fd\u64cd\u4f5c ",(0,i.kt)("inlineCode",{parentName:"p"},"sql"),"\uff0c\u8c03\u7528\u65b9\u6cd5\u4e5f\u662f\u548c\u4e0a\u9762\u4e00\u81f4\u7684\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var dataTable = personRepository.SqlQuery("select * from person");\n')),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7531\u4e8e\u7bc7\u5e45\u6709\u9650\uff0c\u4e0d\u518d\u5217\u4e3e\u6240\u6709\u4f8b\u5b50\u3002")),(0,i.kt)("h2",{id:"9159-\u5173\u4e8e-sql-\u53c2\u6570"},"9.15.9 \u5173\u4e8e ",(0,i.kt)("inlineCode",{parentName:"h2"},"Sql")," \u53c2\u6570"),(0,i.kt)("p",null,"\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"sql"),"\u3001",(0,i.kt)("inlineCode",{parentName:"p"},"\u5b58\u50a8\u8fc7\u7a0b"),"\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"\u51fd\u6570")," \u53c2\u6570\u90fd\u652f\u6301\u56db\u79cd\u65b9\u5f0f\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"DbParameter[]"),"\uff1a\u6570\u7ec4\u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"new {}"),"\uff1a\u533f\u540d\u7c7b\u578b"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"new Class{}"),"\uff1a\u5f3a\u7c7b\u578b\u7c7b\u578b\uff08\u652f\u6301\u590d\u6742\u5b58\u50a8\u8fc7\u7a0b\u53c2\u6570\uff09"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"Dictionary")," \u7c7b\u578b")),(0,i.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"\u5efa\u8bae\u9664\u4e86\u590d\u6742\u7684\u5b58\u50a8\u8fc7\u7a0b\uff08\u5e26 ",(0,i.kt)("inlineCode",{parentName:"p"},"OUTPUT/RETURN"),"\uff09\u7684\u4ee5\u5916\uff0c\u6240\u6709\u53c2\u6570\u5efa\u8bae\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"new {}")," \u533f\u540d\u7c7b\u578b\uff0c\u5982\u679c\u9700\u8981\u52a8\u6001\u53c2\u6570\uff0c\u5219\u53ef\u4ee5\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Dictionary")," \u7c7b\u578b\u3002")),(0,i.kt)("admonition",{title:"\u53c2\u6570\u5927\u5c0f\u5199\u95ee\u9898",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u7531\u4e8e\u4e0d\u540c\u6570\u636e\u5e93\u5bf9\u67e5\u8be2\u53c2\u6570\u5927\u5c0f\u5199\u95ee\u9898\u5904\u7406\u4e0d\u4e00\u81f4\uff0c\u6240\u4ee5",(0,i.kt)("strong",{parentName:"p"},"\u5efa\u8bae\u6240\u6709\u67e5\u8be2\u53c2\u6570\u548c\u53c2\u6570\u540d\u6216\u5c5e\u6027\u540d\u5b8c\u5168\u4e00\u81f4"),"\u3002")),(0,i.kt)("h2",{id:"91510-\u591a\u6570\u636e\u5e93-sql-\u64cd\u4f5c--"},"9.15.10 \u591a\u6570\u636e\u5e93 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Sql")," \u64cd\u4f5c \ud83d\udcaf \ud83d\udc9b"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u62e5\u6709\u975e\u5e38\u7075\u6d3b\u7684\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u65b9\u5f0f\uff0c\u53ea\u9700\u901a\u8fc7\u591a",(0,i.kt)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668"),"\u5373\u53ef\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93\u3002"),(0,i.kt)("h3",{id:"915101-\u61d2\u4eba\u65e0\u654c--\u65b9\u5f0f"},"9.15.10.1 \u61d2\u4eba\u65e0\u654c \ud83d\udc2e \u65b9\u5f0f"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var dataTable = "select * from person".Change().SqlQuery();\n\nvar persons = "select * from person whre id > @id".Change().SqlQuery();\n')),(0,i.kt)("admonition",{title:"\u8865\u5145\u8bf4\u660e",type:"important"},(0,i.kt)("p",{parentName:"admonition"},"\u61d2\u4eba\u65b9\u5f0f \u53ea\u9700\u8981\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"Change")," \u65b9\u5f0f\u5373\u53ef\u52a8\u6001\u5207\u6362\u6570\u636e\u5e93\u3002")),(0,i.kt)("h3",{id:"915102-isqlrepository-\u65b9\u5f0f"},"9.15.10.2 ",(0,i.kt)("inlineCode",{parentName:"h3"},"ISqlRepository")," \u65b9\u5f0f"),(0,i.kt)("p",null,"\u53ea\u9700\u8981\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"ISqlRepository")," \u6ce8\u5165\u6216\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"sqlRepository.Change()")," \u5207\u6362\u3002"),(0,i.kt)("h3",{id:"915103-irepository-\u65b9\u5f0f"},"9.15.10.3 ",(0,i.kt)("inlineCode",{parentName:"h3"},"IRepository")," \u65b9\u5f0f"),(0,i.kt)("p",null,"\u53ea\u9700\u8981\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"repository.Change()")," \u83b7\u53d6\u5373\u53ef\u3002"),(0,i.kt)("h3",{id:"915104-irepositorytentity-\u65b9\u5f0f"},"9.15.10.4 ",(0,i.kt)("inlineCode",{parentName:"h3"},"IRepository")," \u65b9\u5f0f"),(0,i.kt)("p",null,"\u53ea\u9700\u8981\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"IRepository")," \u6ce8\u5165\u6216\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},"personRepository.Change()")," \u5207\u6362\u3002"),(0,i.kt)("h2",{id:"91511-\u5207\u6362\u6570\u636e\u5e93"},"9.15.11 \u5207\u6362\u6570\u636e\u5e93"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u4e0d\u7ba1\u662f\u61d2\u4eba\u6a21\u5f0f\u8fd8\u662f\u4ed3\u50a8\u6a21\u5f0f\u90fd\u662f\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},".Change")," \u65b9\u5f0f\u5207\u6362\u6570\u636e\u5e93\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u61d2\u4eba\u6a21\u5f0f\nvar data = "select * from table".Change().SqlQuery();\n\n// \u4ed3\u50a8\u65b9\u5f0f\nvar data = req.Change().SqlQuery("select * from table");\n')),(0,i.kt)("h2",{id:"91512-\u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df"},"9.15.12 \u591a\u7ebf\u7a0b\u5171\u4eab\u4f5c\u7528\u57df"),(0,i.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u6240\u6709\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5b57\u7b26\u4e32")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"\u5b9e\u4f53")," \u62d3\u5c55\u90fd\u6709\u81ea\u5df1\u72ec\u7acb\u7ef4\u62a4\u7684 ",(0,i.kt)("inlineCode",{parentName:"p"},"ServiceProvider")," \u4f5c\u7528\u57df\u3002"),(0,i.kt)("p",null,"\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"Web")," \u8bf7\u6c42\u4e2d\uff0c\u9ed8\u8ba4\u662f ",(0,i.kt)("inlineCode",{parentName:"p"},"HttpContext.RequestServices"),"\uff0c\u4f46\u5728 ",(0,i.kt)("inlineCode",{parentName:"p"},"\u975e Web"),"\uff0c\u5982\u591a\u7ebf\u7a0b\u64cd\u4f5c\uff0c\u540e\u53f0\u4efb\u52a1\uff0c\u4e8b\u4ef6\u603b\u7ebf\u7b49\u573a\u666f\u4e0b\u4f1a\u81ea\u52a8\u521b\u5efa\u65b0\u7684\u4f5c\u7528\u57df\uff0c\u5b9e\u9645\u4e0a\u8fd9\u662f\u975e\u5e38\u4e0d\u5fc5\u8981\u7684\u5185\u5b58\u5f00\u9500\u3002"),(0,i.kt)("p",null,"\u8fd9\u65f6\uff0c\u6211\u4eec\u53ea\u9700\u8981\u901a\u8fc7 ",(0,i.kt)("inlineCode",{parentName:"p"},".SetXXXScoped(service)")," \u5171\u4eab\u5f53\u524d\u670d\u52a1\u63d0\u4f9b\u5668\u4f5c\u7528\u57df\u5373\u53ef\uff0c\u5982\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'Scoped.Create((fac, scope) => {\n "select * from table".SetContextScoped(scope.ServiceProvider).SqlQuery();\n});\n')),(0,i.kt)("h2",{id:"91513-\u9759\u6001-default-\u65b9\u5f0f\u6784\u5efa"},"9.15.13 \u9759\u6001 ",(0,i.kt)("inlineCode",{parentName:"h2"},"Default")," \u65b9\u5f0f\u6784\u5efa"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'SqlExecutePart.Default.SetSqlString("select * from person").SqlQuery();\n')),(0,i.kt)("h2",{id:"91514-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.15.14 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,i.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/b7a8adf4.7cf903ff.js b/handbook/build/assets/js/b7a8adf4.7cf903ff.js deleted file mode 100644 index 79532c35ef..0000000000 --- a/handbook/build/assets/js/b7a8adf4.7cf903ff.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[4091],{1102:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return p},default:function(){return d},frontMatter:function(){return l},metadata:function(){return u},toc:function(){return s}});var r=n(3117),o=n(102),a=(n(7294),n(3905)),i=["components"],l={id:"tp",title:"15. TP \u9759\u6001\u7c7b",sidebar_label:"15. TP \u9759\u6001\u7c7b"},p=void 0,u={unversionedId:"global/tp",id:"global/tp",title:"15. TP \u9759\u6001\u7c7b",description:"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 Furion 3.5.3 + \u7248\u672c\u4f7f\u7528\u3002",source:"@site/docs/global/tp.mdx",sourceDirName:"global",slug:"/global/tp",permalink:"/furion/docs/global/tp",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/global/tp.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1658676230,formattedLastUpdatedAt:"Jul 24, 2022",frontMatter:{id:"tp",title:"15. TP \u9759\u6001\u7c7b",sidebar_label:"15. TP \u9759\u6001\u7c7b"},sidebar:"global",previous:{title:"14. JWTEncryption \u9759\u6001\u7c7b",permalink:"/furion/docs/global/jwt"},next:{title:"16. Log \u9759\u6001\u7c7b",permalink:"/furion/docs/global/log"}},c={},s=[{value:"15.1 \u751f\u6210\u89c4\u8303\u7684\u65e5\u5fd7\u6a21\u677f",id:"151-\u751f\u6210\u89c4\u8303\u7684\u65e5\u5fd7\u6a21\u677f",level:2}],m={toc:s};function d(e){var t=e.components,n=(0,o.Z)(e,i);return(0,a.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 3.5.3 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,a.kt)("h2",{id:"151-\u751f\u6210\u89c4\u8303\u7684\u65e5\u5fd7\u6a21\u677f"},"15.1 \u751f\u6210\u89c4\u8303\u7684\u65e5\u5fd7\u6a21\u677f"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u751f\u6210\u6a21\u677f\u5b57\u7b26\u4e32\nvar template = TP.Wrapper("Furion \u6846\u67b6", "\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",\n "##\u4f5c\u8005## \u767e\u5c0f\u50e7",\n "##\u5f53\u524d\u7248\u672c## v3.5.3",\n "##\u6587\u6863\u5730\u5740## https://furion.icu",\n "##Copyright## \u767e\u5c0f\u50e7, Baiqian Co.,Ltd.");\n\nConsole.WriteLine(template);\n')),(0,a.kt)("p",null,"\u65e5\u5fd7\u6253\u5370\u6a21\u677f\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"\u250f\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Furion \u6846\u67b6 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u2523 \u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002\n\u2523\n\u2523 \u4f5c\u8005\uff1a \u767e\u5c0f\u50e7\n\u2523 \u5f53\u524d\u7248\u672c\uff1a v3.5.3\n\u2523 \u6587\u6863\u5730\u5740\uff1a https://furion.icu\n\u2523 Copyright\uff1a \u767e\u5c0f\u50e7, Baiqian Co.,Ltd.\n\u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 Furion \u6846\u67b6 \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n")),(0,a.kt)("admonition",{title:"\u5173\u4e8e\u5c5e\u6027\u751f\u6210",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u5217\u8868\u9879\u4ee5 ",(0,a.kt)("inlineCode",{parentName:"p"},"##\u5c5e\u6027\u540d##")," \u5f00\u5934\uff0c\u81ea\u52a8\u751f\u6210 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5c5e\u6027\u540d\uff1a")," \u4f5c\u4e3a\u884c\u9996\u4e14\u81ea\u52a8\u7b49\u5bbd\u5bf9\u9f50\u3002"),(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"Furion 3.9.1")," \u4e4b\u524d\u7248\u672c\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"[\u5c5e\u6027\u540d]")," \u5f00\u5934\u3002")))}d.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return c},kt:function(){return d}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=r.createContext({}),u=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=u(e.components);return r.createElement(p.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,p=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),m=u(n),d=o,f=m["".concat(p,".").concat(d)]||m[d]||s[d]||a;return n?r.createElement(f,i(i({ref:t},c),{},{components:n})):r.createElement(f,i({ref:t},c))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=m;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var u=2;u=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=r.createContext({}),u=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=u(e.components);return r.createElement(p.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,p=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),m=u(n),d=o,f=m["".concat(p,".").concat(d)]||m[d]||s[d]||a;return n?r.createElement(f,i(i({ref:t},c),{},{components:n})):r.createElement(f,i({ref:t},c))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=m;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var u=2;u=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=c(e.components);return r.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=c(n),m=o,f=d["".concat(s,".").concat(m)]||d[m]||p[m]||a;return n?r.createElement(f,i(i({ref:t},u),{},{components:n})):r.createElement(f,i({ref:t},u))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=d;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var c=2;c(str, [options]);\n")),(0,a.kt)("h2",{id:"104-\u83b7\u53d6\u5168\u5c40\u914d\u7f6e"},"10.4 \u83b7\u53d6\u5168\u5c40\u914d\u7f6e"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var options = JSON.GetSerializerOptions();\n")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/b89c6849.8c07483c.js b/handbook/build/assets/js/b89c6849.8c07483c.js deleted file mode 100644 index b0b63dfbef..0000000000 --- a/handbook/build/assets/js/b89c6849.8c07483c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[5630],{9924:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return s},default:function(){return m},frontMatter:function(){return l},metadata:function(){return c},toc:function(){return p}});var r=n(3117),o=n(102),a=(n(7294),n(3905)),i=["components"],l={id:"json",title:"10. JSON \u9759\u6001\u7c7b",sidebar_label:"10. JSON \u9759\u6001\u7c7b"},s=void 0,c={unversionedId:"global/json",id:"global/json",title:"10. JSON \u9759\u6001\u7c7b",description:"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 Furion 1.16.0 + \u7248\u672c\u4f7f\u7528\u3002",source:"@site/docs/global/json.mdx",sourceDirName:"global",slug:"/global/json",permalink:"/furion/docs/global/json",draft:!1,editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/docs/global/json.mdx",tags:[],version:"current",lastUpdatedBy:"MonkSoul",lastUpdatedAt:1651894493,formattedLastUpdatedAt:"May 7, 2022",frontMatter:{id:"json",title:"10. JSON \u9759\u6001\u7c7b",sidebar_label:"10. JSON \u9759\u6001\u7c7b"},sidebar:"global",previous:{title:"9. MessageCenter \u9759\u6001\u7c7b",permalink:"/furion/docs/global/messagecenter"},next:{title:"11. Scoped \u9759\u6001\u7c7b",permalink:"/furion/docs/global/scoped"}},u={},p=[{value:"10.1 \u83b7\u53d6\u5e8f\u5217\u5316\u63d0\u4f9b\u5668",id:"101-\u83b7\u53d6\u5e8f\u5217\u5316\u63d0\u4f9b\u5668",level:2},{value:"10.2 \u5e8f\u5217\u5316",id:"102-\u5e8f\u5217\u5316",level:2},{value:"10.3 \u53cd\u5e8f\u5217\u5316",id:"103-\u53cd\u5e8f\u5217\u5316",level:2},{value:"10.4 \u83b7\u53d6\u5168\u5c40\u914d\u7f6e",id:"104-\u83b7\u53d6\u5168\u5c40\u914d\u7f6e",level:2}],d={toc:p};function m(e){var t=e.components,n=(0,o.Z)(e,i);return(0,a.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 1.16.0 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,a.kt)("h2",{id:"101-\u83b7\u53d6\u5e8f\u5217\u5316\u63d0\u4f9b\u5668"},"10.1 \u83b7\u53d6\u5e8f\u5217\u5316\u63d0\u4f9b\u5668"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var serializer = JSON.GetJsonSerializer();\n")),(0,a.kt)("h2",{id:"102-\u5e8f\u5217\u5316"},"10.2 \u5e8f\u5217\u5316"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var str = JSON.Serialize(obj, [options]);\n")),(0,a.kt)("h2",{id:"103-\u53cd\u5e8f\u5217\u5316"},"10.3 \u53cd\u5e8f\u5217\u5316"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var obj = JSON.Deserialize(str, [options]);\n")),(0,a.kt)("h2",{id:"104-\u83b7\u53d6\u5168\u5c40\u914d\u7f6e"},"10.4 \u83b7\u53d6\u5168\u5c40\u914d\u7f6e"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"var options = JSON.GetSerializerOptions();\n")))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return u},kt:function(){return m}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=c(e.components);return r.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=c(n),m=o,f=d["".concat(s,".").concat(m)]||d[m]||p[m]||a;return n?r.createElement(f,i(i({ref:t},u),{},{components:n})):r.createElement(f,i({ref:t},u))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=d;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var c=2;c=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},u=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=i,f=d["".concat(s,".").concat(m)]||d[m]||c[m]||a;return n?r.createElement(f,o(o({ref:t},u),{},{components:n})):r.createElement(f,o({ref:t},u))}));function m(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=n.length,o=new Array(a);o[0]=d;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:i,o[1]=l;for(var p=2;p=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},u=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=i,f=d["".concat(s,".").concat(m)]||d[m]||c[m]||a;return n?r.createElement(f,o(o({ref:t},u),{},{components:n})):r.createElement(f,o({ref:t},u))}));function m(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=n.length,o=new Array(a);o[0]=d;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:i,o[1]=l;for(var p=2;pIFileProvider \u5b9e\u4f8b",id:"313-\u83b7\u53d6\u6587\u4ef6\u7cfb\u7edf-ifileprovider-\u5b9e\u4f8b",level:2},{value:"31.3.1 Func<FileProviderTypes, object, IFileProvider> \u65b9\u5f0f",id:"3131-funcfileprovidertypes-object-ifileprovider-\u65b9\u5f0f",level:3},{value:"31.3.2 FS \u9759\u6001\u7c7b\u65b9\u5f0f",id:"3132-fs-\u9759\u6001\u7c7b\u65b9\u5f0f",level:3},{value:"31.4 IFileProvider \u5e38\u89c1\u64cd\u4f5c",id:"314-ifileprovider-\u5e38\u89c1\u64cd\u4f5c",level:2},{value:"31.4.1 \u8bfb\u53d6\u6587\u4ef6\u5185\u5bb9",id:"3141-\u8bfb\u53d6\u6587\u4ef6\u5185\u5bb9",level:3},{value:"31.4.2 \u83b7\u53d6\u6587\u4ef6\u76ee\u5f55\u5185\u5bb9\uff08\u9700\u9012\u5f52\u67e5\u627e\uff09",id:"3142-\u83b7\u53d6\u6587\u4ef6\u76ee\u5f55\u5185\u5bb9\u9700\u9012\u5f52\u67e5\u627e",level:3},{value:"31.4.4 \u76d1\u542c\u6587\u4ef6\u53d8\u5316",id:"3144-\u76d1\u542c\u6587\u4ef6\u53d8\u5316",level:3},{value:"31.5 \u6a21\u5757\u5316\u9759\u6001\u8d44\u6e90\u914d\u7f6e",id:"315-\u6a21\u5757\u5316\u9759\u6001\u8d44\u6e90\u914d\u7f6e",level:2},{value:"31.6 \u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d",id:"316-\u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d",level:2},{value:"31.6.1 \u6587\u4ef6\u4e0b\u8f7d",id:"3161-\u6587\u4ef6\u4e0b\u8f7d",level:3},{value:"31.6.2 \u6587\u4ef6\u4e0a\u4f20",id:"3162-\u6587\u4ef6\u4e0a\u4f20",level:3},{value:"31.6.3 \u5c06 IFormFile \u8f6c byte[]",id:"3163-\u5c06-iformfile-\u8f6c-byte",level:3},{value:"31.6.4 \u5c06 byte[] \u8f93\u51fa\u4e3a Url \u5730\u5740",id:"3164-\u5c06-byte-\u8f93\u51fa\u4e3a-url-\u5730\u5740",level:3},{value:"31.7 \u8bf7\u6c42\u5927\u5c0f\u63a7\u5236\uff08\u4e0a\u4f20\u6587\u4ef6\u5927\u5c0f\u63a7\u5236\uff09",id:"317-\u8bf7\u6c42\u5927\u5c0f\u63a7\u5236\u4e0a\u4f20\u6587\u4ef6\u5927\u5c0f\u63a7\u5236",level:2},{value:"31.7.1 \u5bf9\u7279\u5b9a\u7684\u63a5\u53e3\u8fdb\u884c\u63a7\u5236",id:"3171-\u5bf9\u7279\u5b9a\u7684\u63a5\u53e3\u8fdb\u884c\u63a7\u5236",level:3},{value:"31.7.2 \u5bf9\u7279\u5b9a\u63a5\u53e3\u53d6\u6d88\u9650\u5236",id:"3172-\u5bf9\u7279\u5b9a\u63a5\u53e3\u53d6\u6d88\u9650\u5236",level:3},{value:"31.7.3 \u901a\u7528\u4e2d\u95f4\u4ef6\u8fdb\u884c\u63a7\u5236",id:"3173-\u901a\u7528\u4e2d\u95f4\u4ef6\u8fdb\u884c\u63a7\u5236",level:3},{value:"31.7.4 \u5168\u5c40\u914d\u7f6e",id:"3174-\u5168\u5c40\u914d\u7f6e",level:3},{value:"31.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"318-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],u={toc:d};function c(e){var n=e.components,t=(0,r.Z)(e,l);return(0,a.kt)("wrapper",(0,i.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 2.5.0 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,a.kt)("h2",{id:"311-\u5173\u4e8e\u6587\u4ef6\u7cfb\u7edf"},"31.1 \u5173\u4e8e\u6587\u4ef6\u7cfb\u7edf"),(0,a.kt)("p",null,"\u672c\u7ae0\u6240\u8c13\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6587\u4ef6\u7cfb\u7edf")," \u6709\u70b9\u540d\u4e0d\u526f\u5b9e\uff0c\u5176\u5b9e\u6839\u672c\u7b97\u4e0d\u4e0a\u4e00\u4e2a\u7cfb\u7edf\uff0c\u5b83\u4ec5\u4ec5\u662f\u5229\u7528\u4e00\u4e2a\u62bd\u8c61\u5316\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"IFileProvider")," \u4ee5\u7edf\u4e00\u7684\u65b9\u5f0f\u63d0\u4f9b\u6240\u9700\u7684\u6587\u4ef6\u800c\u5df2\u3002\u901a\u8fc7\u8be5 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6587\u4ef6\u7cfb\u7edf")," \u53ef\u4ee5\u8bfb\u53d6\u7269\u7406\u6587\u4ef6\u548c\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6\uff0c\u5305\u62ec\u76ee\u5f55\u7ed3\u679c\u8bfb\u53d6\uff0c\u6587\u4ef6\u5185\u5bb9\u8bfb\u53d6\uff0c\u6587\u4ef6\u5185\u5bb9\u76d1\u542c\u7b49\u7b49\u3002"),(0,a.kt)("h3",{id:"3111-\u6587\u4ef6\u7cfb\u7edf\u7c7b\u578b"},"31.1.1 \u6587\u4ef6\u7cfb\u7edf\u7c7b\u578b"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u4e24\u79cd\u6587\u4ef6\u7cfb\u7edf\u7c7b\u578b\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Physical"),"\uff1a\u7269\u7406\u6587\u4ef6\u7cfb\u7edf\u7c7b\u578b\uff0c\u4e5f\u5c31\u662f\u7269\u7406\u673a\u4e2d\u5b9e\u9645\u5b58\u5728\u7684\u6587\u4ef6"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Embedded"),"\uff1a\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6\u7cfb\u7edf\u7c7b\u578b\uff0c\u4e5f\u5c31\u662f\u8d44\u6e90\u6587\u4ef6\u5d4c\u5165\u5230\u4e86\u7a0b\u5e8f\u96c6\u4e2d\uff0c\u5e38\u7528\u4e8e\u6a21\u5757\u5316\u5f00\u53d1")),(0,a.kt)("h2",{id:"312-\u6ce8\u518c\u865a\u62df\u6587\u4ef6\u7cfb\u7edf\u670d\u52a1"},"31.2 \u6ce8\u518c\u865a\u62df\u6587\u4ef6\u7cfb\u7edf\u670d\u52a1"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddVirtualFileServer();\n")),(0,a.kt)("h2",{id:"313-\u83b7\u53d6\u6587\u4ef6\u7cfb\u7edf-ifileprovider-\u5b9e\u4f8b"},"31.3 \u83b7\u53d6\u6587\u4ef6\u7cfb\u7edf ",(0,a.kt)("inlineCode",{parentName:"h2"},"IFileProvider")," \u5b9e\u4f8b"),(0,a.kt)("h3",{id:"3131-funcfileprovidertypes-object-ifileprovider-\u65b9\u5f0f"},"31.3.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Func")," \u65b9\u5f0f"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"Func")," \u59d4\u6258\u4f9b\u6784\u9020\u51fd\u6570\u6ce8\u5165\u6216\u89e3\u6790\u670d\u52a1\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,8-9,11-12}",showLineNumbers:!0,"":!0,"{6,8-9,11-12}":!0},'public class PersonServices\n{\n private readonly IFileProvider _physicalFileProvider;\n private readonly IFileProvider _embeddedFileProvider;\n\n public PersonServices(Func fileProviderResolve)\n {\n // \u89e3\u6790\u7269\u7406\u6587\u4ef6\u7cfb\u7edf\n _physicalFileProvider = fileProviderResolve(FileProviderTypes.Physical, @"c:/test");\n\n // \u89e3\u6790\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6\u7cfb\u7edf\n _embeddedFileProvider = fileProviderResolve(FileProviderTypes.Embedded, Assembly.GetEntryAssembly());\n }\n}\n')),(0,a.kt)("h3",{id:"3132-fs-\u9759\u6001\u7c7b\u65b9\u5f0f"},"31.3.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"FS")," \u9759\u6001\u7c7b\u65b9\u5f0f"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e5f\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"FS")," \u9759\u6001\u7c7b\u65b9\u5f0f\u521b\u5efa\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u89e3\u6790\u7269\u7406\u6587\u4ef6\u7cfb\u7edf\nvar physicalFileProvider = FS.GetPhysicalFileProvider(@"c:/test");\n\n// \u89e3\u6790\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6\u7cfb\u7edf\nvar embeddedFileProvider = FS.GetEmbeddedFileProvider(Assembly.GetEntryAssembly());\n')),(0,a.kt)("h2",{id:"314-ifileprovider-\u5e38\u89c1\u64cd\u4f5c"},"31.4 ",(0,a.kt)("inlineCode",{parentName:"h2"},"IFileProvider")," \u5e38\u89c1\u64cd\u4f5c"),(0,a.kt)("h3",{id:"3141-\u8bfb\u53d6\u6587\u4ef6\u5185\u5bb9"},"31.4.1 \u8bfb\u53d6\u6587\u4ef6\u5185\u5bb9"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'byte[] buffer;\nusing (Stream readStream = _fileProvider.GetFileInfo("\u4f60\u7684\u6587\u4ef6\u8def\u5f84").CreateReadStream())\n{\n buffer = new byte[readStream.Length];\n await readStream.ReadAsync(buffer.AsMemory(0, buffer.Length));\n}\n\n// \u8bfb\u53d6\u6587\u4ef6\u5185\u5bb9\nvar content = Encoding.UTF8.GetString(buffer);\n')),(0,a.kt)("h3",{id:"3142-\u83b7\u53d6\u6587\u4ef6\u76ee\u5f55\u5185\u5bb9\u9700\u9012\u5f52\u67e5\u627e"},"31.4.2 \u83b7\u53d6\u6587\u4ef6\u76ee\u5f55\u5185\u5bb9\uff08\u9700\u9012\u5f52\u67e5\u627e\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var rootPath = "\u5f53\u524d\u76ee\u5f55\u8def\u5f84";\nvar fileinfos = _fileProvider.GetDirectoryContents(rootPath);\nforeach (var fileinfo in fileinfos)\n{\n if(fileinfo.IsDirectory)\n {\n // \u8fd9\u91cc\u9012\u5f52\u3002\u3002\u3002\n }\n}\n')),(0,a.kt)("h3",{id:"3144-\u76d1\u542c\u6587\u4ef6\u53d8\u5316"},"31.4.4 \u76d1\u542c\u6587\u4ef6\u53d8\u5316"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'ChangeToken.OnChange(() => _fileProvider.Watch("\u76d1\u542c\u7684\u6587\u4ef6"), () =>\n{\n // \u8fd9\u91cc\u5199\u4f60\u7684\u903b\u8f91\n});\n')),(0,a.kt)("h2",{id:"315-\u6a21\u5757\u5316\u9759\u6001\u8d44\u6e90\u914d\u7f6e"},"31.5 \u6a21\u5757\u5316\u9759\u6001\u8d44\u6e90\u914d\u7f6e"),(0,a.kt)("p",null,"\u901a\u5e38\u6211\u4eec\u91c7\u7528\u6a21\u5757\u5316\u5f00\u53d1\uff0c\u9759\u6001\u8d44\u6e90\u90fd\u662f\u5d4c\u5165\u8fdb\u7a0b\u5e8f\u96c6\u4e2d\uff0c\u8fd9\u65f6\u5019\u6211\u4eec\u9700\u8981\u901a\u8fc7\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"p"},"UseFileServer")," \u6307\u5b9a\u6a21\u5757\u9759\u6001\u8d44\u6e90\u8def\u5f84\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u9ed8\u8ba4\u9759\u6001\u8d44\u6e90\u8c03\u7528\uff0cwwwroot\napp.UseStaticFiles();\n\n// \u914d\u7f6e\u6a21\u5757\u5316\u9759\u6001\u8d44\u6e90\napp.UseFileServer(new FileServerOptions\n{\n FileProvider = new EmbeddedFileProvider(\u6a21\u5757\u7a0b\u5e8f\u96c6),\n RequestPath = "/\u6a21\u5757\u540d\u79f0", // \u540e\u7eed\u6240\u6709\u8d44\u6e90\u90fd\u662f\u901a\u8fc7 /\u6a21\u5757\u540d\u79f0/xxx.css \u8c03\u7528\n EnableDirectoryBrowsing = true\n});\n')),(0,a.kt)("h2",{id:"316-\u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d"},"31.6 \u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d"),(0,a.kt)("p",null,"\u5728\u5e94\u7528\u5f00\u53d1\u4e2d\uff0c\u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d\u5c5e\u4e8e\u975e\u5e38\u5e38\u7528\u7684\u529f\u80fd\uff0c\u8fd9\u91cc\u8d34\u51fa\u5e38\u89c1\u7684\u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d\u793a\u4f8b\u3002"),(0,a.kt)("h3",{id:"3161-\u6587\u4ef6\u4e0b\u8f7d"},"31.6.1 \u6587\u4ef6\u4e0b\u8f7d"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u6587\u4ef6\u8def\u5f84\u7684\u65b9\u5f0f")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"{1,5}":!0},'[HttpGet, NonUnify]\npublic IActionResult FileDownload()\n{\n string filePath = "\u8fd9\u91cc\u83b7\u53d6\u5b8c\u6574\u7684\u6587\u4ef6\u4e0b\u8f7d\u8def\u5f84";\n return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") {\n FileDownloadName = fileName // \u914d\u7f6e\u6587\u4ef6\u4e0b\u8f7d\u663e\u793a\u540d\n };\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"byte[]")," \u65b9\u5f0f")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4}",showLineNumbers:!0,"{1,4}":!0},'[HttpGet, NonUnify]\npublic IActionResult FileDownload()\n{\n return new FileStreamResult(byte\u6570\u7ec4, "application/octet-stream") {\n FileDownloadName = fileName // \u914d\u7f6e\u6587\u4ef6\u4e0b\u8f7d\u663e\u793a\u540d\n };\n}\n')),(0,a.kt)("admonition",{title:"\u5173\u4e8e\u524d\u7aef\u83b7\u53d6\u6587\u4ef6\u540d",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u524d\u7aef\u83b7\u53d6\u4e0d\u5230\u6587\u4ef6\u5939\uff0c\u53ef\u6dfb\u52a0\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={\u6587\u4ef6\u540d}");\n_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");\n'))),(0,a.kt)("h3",{id:"3162-\u6587\u4ef6\u4e0a\u4f20"},"31.6.2 \u6587\u4ef6\u4e0a\u4f20"),(0,a.kt)("admonition",{title:"\u5c0f\u63d0\u9192",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"IFormFile")," \u7c7b\u578b\u5bf9\u5e94\u524d\u7aef\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Content-Type")," \u4e3a\uff1a ",(0,a.kt)("inlineCode",{parentName:"p"},"multipart/form-data"))),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5355\u6587\u4ef6 ",(0,a.kt)("inlineCode",{parentName:"strong"},"IFormFile")," \u7c7b\u578b\u53c2\u6570\uff08\u5b58\u50a8\u5230\u786c\u76d8\uff09"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,2,18}",showLineNumbers:!0,"":!0,"{1,2,18}":!0},'[HttpPost]\npublic async Task UploadFileAsync(IFormFile file)\n{\n // \u5982\uff1a\u4fdd\u5b58\u5230\u7f51\u7ad9\u6839\u76ee\u5f55\u4e0b\u7684 uploads \u76ee\u5f55\n var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");\n if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);\n\n //// \u8fd9\u91cc\u8fd8\u53ef\u4ee5\u83b7\u53d6\u6587\u4ef6\u7684\u4fe1\u606f\n // var size = file.Length / 1024.0; // \u6587\u4ef6\u5927\u5c0f KB\n // var clientFileName = file.FileName; // \u5ba2\u6237\u7aef\u4e0a\u4f20\u7684\u6587\u4ef6\u540d\n // var contentType = file.ContentType; // \u83b7\u53d6\u6587\u4ef6 ContentType \u6216\u89e3\u6790 MIME \u7c7b\u578b\n\n // \u907f\u514d\u6587\u4ef6\u540d\u91cd\u590d\uff0c\u91c7\u7528 GUID \u751f\u6210\n var fileName = Guid.NewGuid().ToString("N") + Path.GetExtension(file.FileName);\n var filePath = Path.Combine(savePath, fileName);\n\n // \u4fdd\u5b58\u5230\u6307\u5b9a\u8def\u5f84\n using (var stream = System.IO.File.Create(filePath))\n {\n await file.CopyToAsync(stream);\n }\n\n // \u5728\u52a8\u6001 API \u76f4\u63a5\u8fd4\u56de\u5bf9\u8c61\u5373\u53ef\uff0c\u65e0\u9700 OK \u548c IActionResult\n return Ok(new { filename });\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5355\u6587\u4ef6 ",(0,a.kt)("inlineCode",{parentName:"strong"},"Base64")," \u7c7b\u578b\u53c2\u6570\uff08\u5b58\u50a8\u5230\u786c\u76d8\uff09"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,2,9,19}",showLineNumbers:!0,"":!0,"{1,2,9,19}":!0},'[HttpPost]\npublic async Task UploadFileAsync([FromBody] string fileBase64, string clientFileName)\n{\n // \u5982\uff1a\u4fdd\u5b58\u5230\u7f51\u7ad9\u6839\u76ee\u5f55\u4e0b\u7684 uploads \u76ee\u5f55\n var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");\n if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);\n\n // \u5c06 base64 \u5b57\u7b26\u4e32\u8f6c byte[]\n var bytes = Convert.FromBase64String(fileBase64);\n\n // \u8fd9\u91cc\u8fd8\u53ef\u4ee5\u83b7\u53d6\u6587\u4ef6\u7684\u4fe1\u606f\n // var size = bytes.Length / 1024.0; // \u6587\u4ef6\u5927\u5c0f KB\n\n // \u907f\u514d\u6587\u4ef6\u540d\u91cd\u590d\uff0c\u91c7\u7528 GUID \u751f\u6210\n var fileName = Guid.NewGuid().ToString("N") + Path.GetExtension(clientFileName);\n var filePath = Path.Combine(savePath, fileName);\n\n // \u4fdd\u5b58\u5230\u6307\u5b9a\u8def\u5f84\n using (var fs = new FileStream(filePath, FileMode.Create))\n {\n await fs.WriteAsync(bytes);\n }\n\n // \u5728\u52a8\u6001 API \u76f4\u63a5\u8fd4\u56de\u5bf9\u8c61\u5373\u53ef\uff0c\u65e0\u9700 OK \u548c IActionResult\n return Ok(new { fileName });\n}\n')),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u6587\u4ef6 ",(0,a.kt)("inlineCode",{parentName:"p"},"Base64")," \u5b57\u7b26\u4e32\u5982\u679c\u5e26 ",(0,a.kt)("inlineCode",{parentName:"p"},"data:text/plain;base64,")," \u5f00\u5934\u5219\uff0c\u9700\u8981\u624b\u52a8\u53bb\u6389 ",(0,a.kt)("inlineCode",{parentName:"p"},",")," \u4e4b\u524d\uff08\u542b\u9017\u53f7\uff09\u7684\u5b57\u7b26\u4e32\u3002")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u591a\u6587\u4ef6 ",(0,a.kt)("inlineCode",{parentName:"strong"},"List")," \u7c7b\u578b\u53c2\u6570\uff08\u5b58\u50a8\u5230\u786c\u76d8\uff09"))),(0,a.kt)("p",null,"\u4ee3\u7801\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5355\u6587\u4ef6\u5904\u7406\u4e00\u81f4"),"\uff0c\u53ea\u9700 ",(0,a.kt)("inlineCode",{parentName:"p"},"foreach")," \u5373\u53ef\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,12}",showLineNumbers:!0,"":!0,"{1,12}":!0},'[HttpPost]\npublic async Task UploadFileAsync(List files)\n{\n // \u4fdd\u5b58\u5230\u7f51\u7ad9\u6839\u76ee\u5f55\u4e0b\u7684 uploads \u76ee\u5f55\n var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");\n if(!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);\n\n // \u603b\u4e0a\u4f20\u5927\u5c0f\n long size = files.Sum(f => f.Length);\n\n // \u904d\u5386\u6240\u6709\u6587\u4ef6\u9010\u4e00\u4e0a\u4f20\n foreach (var formFile in files)\n {\n if (formFile.Length > 0)\n {\n // \u907f\u514d\u6587\u4ef6\u540d\u91cd\u590d\uff0c\u91c7\u7528 GUID \u751f\u6210\n var fileName = Guid.NewGuid().ToString("N") + Path.GetExtension(clientFileName);\n var filePath = Path.Combine(savePath, fileName);\n\n // \u4fdd\u5b58\u5230\u6307\u5b9a\u8def\u5f84\n using (var stream = System.IO.File.Create(filePath))\n {\n await formFile.CopyToAsync(stream);\n }\n }\n }\n\n // \u5728\u52a8\u6001 API \u76f4\u63a5\u8fd4\u56de\u5bf9\u8c61\u5373\u53ef\uff0c\u65e0\u9700 OK \u548c IActionResult\n return Ok(new { count = files.Count, size });\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u591a\u6587\u4ef6 ",(0,a.kt)("inlineCode",{parentName:"strong"},"List")," ",(0,a.kt)("inlineCode",{parentName:"strong"},"Base64")," \u7c7b\u578b\u53c2\u6570\uff08\u5b58\u50a8\u5230\u786c\u76d8\uff09"))),(0,a.kt)("p",null,"\u4ee3\u7801\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5355\u6587\u4ef6\u5904\u7406\u4e00\u81f4"),"\uff0c\u53ea\u9700 ",(0,a.kt)("inlineCode",{parentName:"p"},"foreach")," \u5373\u53ef\uff08\u53c2\u4e0a\uff09\u3002"),(0,a.kt)("h3",{id:"3163-\u5c06-iformfile-\u8f6c-byte"},"31.6.3 \u5c06 ",(0,a.kt)("inlineCode",{parentName:"h3"},"IFormFile")," \u8f6c ",(0,a.kt)("inlineCode",{parentName:"h3"},"byte[]")),(0,a.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u5c06\u6587\u4ef6\u8f6c\u6362\u6210 ",(0,a.kt)("inlineCode",{parentName:"p"},"byte[]")," \u5b58\u50a8\u5230\u6570\u636e\u5e93\uff0c\u800c\u4e0d\u662f\u5b58\u50a8\u5230\u786c\u76d8\u4e2d\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4-8}",showLineNumbers:!0,"{4-8}":!0},"[HttpPost]\npublic async Task UploadFileAsync(IFormFile file)\n{\n var fileLength = file.Length;\n using var stream = file.OpenReadStream();\n var bytes = new byte[fileLength];\n\n stream.Read(bytes, 0, (int)fileLength);\n\n // \u8fd9\u91cc\u5c06 bytes \u5b58\u50a8\u5230\u4f60\u60f3\u8981\u7684\u4ecb\u8d28\u4e2d\u5373\u53ef\n}\n")),(0,a.kt)("admonition",{title:"\u4fbf\u6377\u62d3\u5c55\u65b9\u6cd5",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5728 Furion ",(0,a.kt)("inlineCode",{parentName:"p"},"v3.2.0")," \u65b0\u589e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"IFormFile")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"ToByteArray")," \u62d3\u5c55\uff0c\u5982:"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"[HttpPost]\npublic async Task UploadFileAsync(IFormFile file)\n{\n var bytes = file.ToByteArray();\n\n // \u8fd9\u91cc\u5c06 bytes \u5b58\u50a8\u5230\u4f60\u60f3\u8981\u7684\u4ecb\u8d28\u4e2d\u5373\u53ef\n}\n"))),(0,a.kt)("h3",{id:"3164-\u5c06-byte-\u8f93\u51fa\u4e3a-url-\u5730\u5740"},"31.6.4 \u5c06 ",(0,a.kt)("inlineCode",{parentName:"h3"},"byte[]")," \u8f93\u51fa\u4e3a ",(0,a.kt)("inlineCode",{parentName:"h3"},"Url")," \u5730\u5740"),(0,a.kt)("p",null,"\u7531\u4e8e\u4e00\u4e9b\u9879\u76ee\u76f4\u63a5\u5c06\u6587\u4ef6\u4e8c\u8fdb\u5236\u5b58\u50a8\u5728\u6570\u636e\u5e93\u4e2d\uff0c\u8bfb\u53d6\u5230\u5185\u5b58\u7684\u65f6\u5019\u90fd\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"byte[]")," \u6570\u7ec4\uff0c\u6bd4\u5982\u6211\u4eec\u5c06\u56fe\u7247\u6587\u4ef6\u5b58\u50a8\u5728\u6570\u636e\u5e93\u4e2d\uff0c\u7136\u540e\u524d\u7aef\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"Url")," \u94fe\u63a5\u8fdb\u884c\u8bbf\u95ee\uff0c\u8fd9\u4e2a\u65f6\u5019\u5c31\u9700\u8981\u5c06 ",(0,a.kt)("inlineCode",{parentName:"p"},"byte[]")," \u8f6c\u6362\u4e3a\u6709\u6548\u7684\u8d44\u6e90\u8def\u5f84\u683c\u5f0f\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,7}",showLineNumbers:!0,"{1,7}":!0},"[NonUnify, HttpGet, AllowAnonymous]\npublic async Task attachment(string resourceId)\n{\n // \u6839\u636e resourceId \u67e5\u8be2 byte[] \u5b57\u8282\u6570\u7ec4\u548c content-type\n\n // \u8fd4\u56de FileContentResult \u7c7b\u578b\n return new FileContentResult(\u5b57\u8282\u6570\u7ec4\uff0ccontent-type);\n}\n")),(0,a.kt)("p",null,"\u4e4b\u540e\u6211\u4eec\u5c31\u53ef\u4ee5\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"https://localhost/attachment/\u8d44\u6e90id")," \u8bbf\u95ee\u6587\u4ef6\u6216\u56fe\u7247\u4e86\u3002"),(0,a.kt)("h2",{id:"317-\u8bf7\u6c42\u5927\u5c0f\u63a7\u5236\u4e0a\u4f20\u6587\u4ef6\u5927\u5c0f\u63a7\u5236"},"31.7 \u8bf7\u6c42\u5927\u5c0f\u63a7\u5236\uff08\u4e0a\u4f20\u6587\u4ef6\u5927\u5c0f\u63a7\u5236\uff09"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u9879\u76ee\u4e2d\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Kestrel")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpSys")," \u90fd\u5f3a\u5236\u5b9e\u65bd ",(0,a.kt)("inlineCode",{parentName:"p"},"30M (~28.6MiB)")," \u7684\u6700\u5927\u8bf7\u6c42\u6b63\u6587\u5927\u5c0f\u9650\u5236\uff0c\u5982\u679c\u8bf7\u6c42\u6b63\u6587\u5927\u5c0f\u8d85\u8fc7\u914d\u7f6e\u7684\u6700\u5927\u8bf7\u6c42\u6b63\u6587\u5927\u5c0f\u9650\u5236\uff0c\u5219\u5f15\u53d1 ",(0,a.kt)("inlineCode",{parentName:"p"},"Request body too large. The max request body size is xxxxx")," \u5f02\u5e38\uff0c\u72b6\u6001\u7801\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"413")," \u6216 ",(0,a.kt)("inlineCode",{parentName:"p"},"500"),"\u3002"),(0,a.kt)("h3",{id:"3171-\u5bf9\u7279\u5b9a\u7684\u63a5\u53e3\u8fdb\u884c\u63a7\u5236"},"31.7.1 \u5bf9\u7279\u5b9a\u7684\u63a5\u53e3\u8fdb\u884c\u63a7\u5236"),(0,a.kt)("p",null,"\u53ef\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"[RequestSizeLimit]")," \u7279\u6027\u8fdb\u884c\u7279\u5b9a\u9650\u5236"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},"[HttpPost]\n[RequestSizeLimit(100_000_000)]\npublic IActionResult MyAction([FromBody] MyViewModel data)\n{\n}\n")),(0,a.kt)("h3",{id:"3172-\u5bf9\u7279\u5b9a\u63a5\u53e3\u53d6\u6d88\u9650\u5236"},"31.7.2 \u5bf9\u7279\u5b9a\u63a5\u53e3\u53d6\u6d88\u9650\u5236"),(0,a.kt)("p",null,"\u5982\u679c\u4e0d\u9700\u8981\u5bf9\u8bf7\u6c42\u5927\u5c0f\u8fdb\u884c\u9650\u5236\uff0c\u4e5f\u5c31\u662f\u652f\u6301\u63d0\u4ea4\u65e0\u9650\u5927\u5c0f\uff0c\u5219\u8d34 ",(0,a.kt)("inlineCode",{parentName:"p"},"[DisableRequestSizeLimit]")," \u7279\u6027\u5373\u53ef\u3002"),(0,a.kt)("h3",{id:"3173-\u901a\u7528\u4e2d\u95f4\u4ef6\u8fdb\u884c\u63a7\u5236"},"31.7.3 \u901a\u7528\u4e2d\u95f4\u4ef6\u8fdb\u884c\u63a7\u5236"),(0,a.kt)("p",null,"\u6211\u4eec\u4e5f\u53ef\u4ee5\u901a\u8fc7\u4e2d\u95f4\u4ef6\u7684\u65b9\u5f0f\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u8fdb\u884c\u914d\u7f6e\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3}",showLineNumbers:!0,"{1,3}":!0},"app.Run(async context =>\n{\n context.Features.Get().MaxRequestBodySize = 100_000_000; // \u8bbe\u7f6e null \u5c31\u662f\u4e0d\u9650\u5236\uff0c\u5177\u4f53\u503c\u5c31\u662f\u9650\u5236\u6700\u5927\u591a\u5c11 M\n}\n")),(0,a.kt)("p",null,"\u5982\u679c\u8bbe\u7f6e ",(0,a.kt)("inlineCode",{parentName:"p"},"MaxRequestBodySize")," \u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"null")," \uff0c\u5219\u7b49\u540c\u4e8e\u53d6\u6d88\u9650\u5236\uff0c\u4e5f\u5c31\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"[DisableRequestSizeLimit]")," \u7684\u6548\u679c\u3002"),(0,a.kt)("admonition",{title:"\u5c0f\u6ce8\u610f",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u6709\u65f6\u5019\u914d\u7f6e\u4e86\u4e2d\u95f4\u4ef6\u6548\u679c\u53d1\u73b0\u6ca1\u8d77\u4f5c\u7528\uff0c\u5f88\u6709\u53ef\u80fd\u548c\u4e2d\u95f4\u4ef6\u987a\u5e8f\u6709\u5173\uff0c\u53ef\u4ee5\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},".IsReadOnly")," \u5c5e\u6027\u5224\u65ad\uff0c\u5982\u679c\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"true")," \uff0c\u8bf4\u660e\u4f60\u7684\u914d\u7f6e\u65e0\u6548\uff0c\u53ea\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},"false")," \u624d\u6709\u6548\u3002")),(0,a.kt)("h3",{id:"3174-\u5168\u5c40\u914d\u7f6e"},"31.7.4 \u5168\u5c40\u914d\u7f6e"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IIS")," \u65b9\u5f0f\uff1a")),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("strong",{parentName:"li"},"\u5f00\u53d1\u73af\u5883\uff08IISExpress\uff09"))),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u542f\u52a8\u5c42\uff08\u901a\u5e38\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"XXX.Web.Entry"),"\uff09\u6839\u76ee\u5f55\u4e0b\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"web.config")," \u6587\u4ef6\uff0c\u5185\u5bb9\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-xml",metastring:"showLineNumbers {3-9}",showLineNumbers:!0,"{3-9}":!0},'\n\n \n \n \n \n \n \n \n\n')),(0,a.kt)("ol",{start:2},(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("strong",{parentName:"li"},"\u751f\u4ea7\u73af\u5883"))),(0,a.kt)("p",null,"\u901a\u5e38\u751f\u4ea7\u73af\u5883 ",(0,a.kt)("inlineCode",{parentName:"p"},"IIS")," \u81ea\u52a8\u9879\u76ee\u6dfb\u52a0\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"web.config")," \u6587\u4ef6\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"")," \u8282\u70b9\u4e0b\u6dfb\u52a0\u4e0b\u9762\u5185\u5bb9\u5373\u53ef\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-xml",metastring:"showLineNumbers {3-5}",showLineNumbers:!0,"{3-5}":!0},'\n \n \n \n \n \n\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Kestrel")," \u65b9\u5f0f\uff1a")),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u672a\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IIS")," \u6258\u7ba1\u65f6\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u9ed8\u8ba4\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Kestrel")," \u65b9\u5f0f\u3002")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,8}",showLineNumbers:!0,"{1,8}":!0},"// .NET5 \u65b9\u5f0f\uff0c\u5728 .ConfigureWebHostDefaults \u91cc\u9762\u914d\u7f6e\n.UseStartup()\n.UseKestrel(options =>\n{\n options.Limits.MaxRequestBodySize = null; // \u8bbe\u7f6e null \u5c31\u662f\u4e0d\u9650\u5236\uff0c\u5177\u4f53\u503c\u5c31\u662f\u9650\u5236\u6700\u5927\u591a\u5c11 M\n}\n\n// .NET6 \u65b9\u5f0f,\u5728 progame.cs \u6587\u4ef6 var app = builder.Build(); \u4e4b\u540e\u914d\u7f6e\napp.Configuration.Get().ConfigureKestrel(options =>\n{\n options.Limits.MaxRequestBodySize = null; // \u8bbe\u7f6e null \u5c31\u662f\u4e0d\u9650\u5236\uff0c\u5177\u4f53\u503c\u5c31\u662f\u9650\u5236\u6700\u5927\u591a\u5c11 M\n});\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"HttpSys")," \u65b9\u5f0f\uff1a")),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"HTTP.sys")," \u662f\u4ec5\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Windows")," \u4e0a\u8fd0\u884c\u7684\u9002\u7528\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u670d\u52a1\u5668\u3002 ",(0,a.kt)("inlineCode",{parentName:"p"},"HTTP.sys")," \u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"Kestrel")," \u670d\u52a1\u5668\u7684\u66ff\u4ee3\u9009\u62e9\uff0c\u63d0\u4f9b\u4e86\u4e00\u4e9b ",(0,a.kt)("inlineCode",{parentName:"p"},"Kestrel")," \u4e0d\u63d0\u4f9b\u7684\u529f\u80fd\u3002")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// .NET5 \u65b9\u5f0f\u540c\u4e0a\n.UseHttpSys(options =>\n{\n options.MaxRequestBodySize = 100_000_000; // \u8bbe\u7f6e null \u5c31\u662f\u4e0d\u9650\u5236\uff0c\u5177\u4f53\u503c\u5c31\u662f\u9650\u5236\u6700\u5927\u591a\u5c11 M\n}\n\n// .NET6 \u65b9\u5f0f\u540c\u4e0a\n")),(0,a.kt)("h2",{id:"318-\u53cd\u9988\u4e0e\u5efa\u8bae"},"31.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,a.kt)("hr",null))}c.isMDXComponent=!0},3905:function(e,n,t){t.d(n,{Zo:function(){return m},kt:function(){return c}});var i=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function l(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=i.createContext({}),p=function(e){var n=i.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},m=function(e){var n=p(e.components);return i.createElement(s.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},u=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,s=e.parentName,m=o(e,["components","mdxType","originalType","parentName"]),u=p(t),c=r,k=u["".concat(s,".").concat(c)]||u[c]||d[c]||a;return t?i.createElement(k,l(l({ref:n},m),{},{components:t})):i.createElement(k,l({ref:n},m))}));function c(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,l=new Array(a);l[0]=u;var o={};for(var s in n)hasOwnProperty.call(n,s)&&(o[s]=n[s]);o.originalType=e,o.mdxType="string"==typeof e?e:r,l[1]=o;for(var p=2;p=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=i.createContext({}),p=function(e){var n=i.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},m=function(e){var n=p(e.components);return i.createElement(s.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},u=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,s=e.parentName,m=o(e,["components","mdxType","originalType","parentName"]),u=p(t),c=r,k=u["".concat(s,".").concat(c)]||u[c]||d[c]||a;return t?i.createElement(k,l(l({ref:n},m),{},{components:t})):i.createElement(k,l({ref:n},m))}));function c(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,l=new Array(a);l[0]=u;var o={};for(var s in n)hasOwnProperty.call(n,s)&&(o[s]=n[s]);o.originalType=e,o.mdxType="string"==typeof e?e:r,l[1]=o;for(var p=2;pIFileProvider \u5b9e\u4f8b",id:"313-\u83b7\u53d6\u6587\u4ef6\u7cfb\u7edf-ifileprovider-\u5b9e\u4f8b",level:2},{value:"31.3.1 Func<FileProviderTypes, object, IFileProvider> \u65b9\u5f0f",id:"3131-funcfileprovidertypes-object-ifileprovider-\u65b9\u5f0f",level:3},{value:"31.3.2 FS \u9759\u6001\u7c7b\u65b9\u5f0f",id:"3132-fs-\u9759\u6001\u7c7b\u65b9\u5f0f",level:3},{value:"31.4 IFileProvider \u5e38\u89c1\u64cd\u4f5c",id:"314-ifileprovider-\u5e38\u89c1\u64cd\u4f5c",level:2},{value:"31.4.1 \u8bfb\u53d6\u6587\u4ef6\u5185\u5bb9",id:"3141-\u8bfb\u53d6\u6587\u4ef6\u5185\u5bb9",level:3},{value:"31.4.2 \u83b7\u53d6\u6587\u4ef6\u76ee\u5f55\u5185\u5bb9\uff08\u9700\u9012\u5f52\u67e5\u627e\uff09",id:"3142-\u83b7\u53d6\u6587\u4ef6\u76ee\u5f55\u5185\u5bb9\u9700\u9012\u5f52\u67e5\u627e",level:3},{value:"31.4.4 \u76d1\u542c\u6587\u4ef6\u53d8\u5316",id:"3144-\u76d1\u542c\u6587\u4ef6\u53d8\u5316",level:3},{value:"31.5 \u6a21\u5757\u5316\u9759\u6001\u8d44\u6e90\u914d\u7f6e",id:"315-\u6a21\u5757\u5316\u9759\u6001\u8d44\u6e90\u914d\u7f6e",level:2},{value:"31.6 \u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d",id:"316-\u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d",level:2},{value:"31.6.1 \u6587\u4ef6\u4e0b\u8f7d",id:"3161-\u6587\u4ef6\u4e0b\u8f7d",level:3},{value:"31.6.2 \u6587\u4ef6\u4e0a\u4f20",id:"3162-\u6587\u4ef6\u4e0a\u4f20",level:3},{value:"31.6.3 \u5c06 IFormFile \u8f6c byte[]",id:"3163-\u5c06-iformfile-\u8f6c-byte",level:3},{value:"31.6.4 \u5c06 byte[] \u8f93\u51fa\u4e3a Url \u5730\u5740",id:"3164-\u5c06-byte-\u8f93\u51fa\u4e3a-url-\u5730\u5740",level:3},{value:"31.7 \u8bf7\u6c42\u5927\u5c0f\u63a7\u5236\uff08\u4e0a\u4f20\u6587\u4ef6\u5927\u5c0f\u63a7\u5236\uff09",id:"317-\u8bf7\u6c42\u5927\u5c0f\u63a7\u5236\u4e0a\u4f20\u6587\u4ef6\u5927\u5c0f\u63a7\u5236",level:2},{value:"31.7.1 \u5bf9\u7279\u5b9a\u7684\u63a5\u53e3\u8fdb\u884c\u63a7\u5236",id:"3171-\u5bf9\u7279\u5b9a\u7684\u63a5\u53e3\u8fdb\u884c\u63a7\u5236",level:3},{value:"31.7.2 \u5bf9\u7279\u5b9a\u63a5\u53e3\u53d6\u6d88\u9650\u5236",id:"3172-\u5bf9\u7279\u5b9a\u63a5\u53e3\u53d6\u6d88\u9650\u5236",level:3},{value:"31.7.3 \u901a\u7528\u4e2d\u95f4\u4ef6\u8fdb\u884c\u63a7\u5236",id:"3173-\u901a\u7528\u4e2d\u95f4\u4ef6\u8fdb\u884c\u63a7\u5236",level:3},{value:"31.7.4 \u5168\u5c40\u914d\u7f6e",id:"3174-\u5168\u5c40\u914d\u7f6e",level:3},{value:"31.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"318-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],u={toc:d};function c(e){var n=e.components,t=(0,r.Z)(e,l);return(0,a.kt)("wrapper",(0,i.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{title:"\u7248\u672c\u8bf4\u660e",type:"important"},(0,a.kt)("p",{parentName:"admonition"},"\u4ee5\u4e0b\u5185\u5bb9\u4ec5\u9650 ",(0,a.kt)("inlineCode",{parentName:"p"},"Furion 2.5.0 +")," \u7248\u672c\u4f7f\u7528\u3002")),(0,a.kt)("h2",{id:"311-\u5173\u4e8e\u6587\u4ef6\u7cfb\u7edf"},"31.1 \u5173\u4e8e\u6587\u4ef6\u7cfb\u7edf"),(0,a.kt)("p",null,"\u672c\u7ae0\u6240\u8c13\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6587\u4ef6\u7cfb\u7edf")," \u6709\u70b9\u540d\u4e0d\u526f\u5b9e\uff0c\u5176\u5b9e\u6839\u672c\u7b97\u4e0d\u4e0a\u4e00\u4e2a\u7cfb\u7edf\uff0c\u5b83\u4ec5\u4ec5\u662f\u5229\u7528\u4e00\u4e2a\u62bd\u8c61\u5316\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"IFileProvider")," \u4ee5\u7edf\u4e00\u7684\u65b9\u5f0f\u63d0\u4f9b\u6240\u9700\u7684\u6587\u4ef6\u800c\u5df2\u3002\u901a\u8fc7\u8be5 ",(0,a.kt)("inlineCode",{parentName:"p"},"\u6587\u4ef6\u7cfb\u7edf")," \u53ef\u4ee5\u8bfb\u53d6\u7269\u7406\u6587\u4ef6\u548c\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6\uff0c\u5305\u62ec\u76ee\u5f55\u7ed3\u679c\u8bfb\u53d6\uff0c\u6587\u4ef6\u5185\u5bb9\u8bfb\u53d6\uff0c\u6587\u4ef6\u5185\u5bb9\u76d1\u542c\u7b49\u7b49\u3002"),(0,a.kt)("h3",{id:"3111-\u6587\u4ef6\u7cfb\u7edf\u7c7b\u578b"},"31.1.1 \u6587\u4ef6\u7cfb\u7edf\u7c7b\u578b"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u63d0\u4f9b\u4e86\u4e24\u79cd\u6587\u4ef6\u7cfb\u7edf\u7c7b\u578b\uff1a"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Physical"),"\uff1a\u7269\u7406\u6587\u4ef6\u7cfb\u7edf\u7c7b\u578b\uff0c\u4e5f\u5c31\u662f\u7269\u7406\u673a\u4e2d\u5b9e\u9645\u5b58\u5728\u7684\u6587\u4ef6"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Embedded"),"\uff1a\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6\u7cfb\u7edf\u7c7b\u578b\uff0c\u4e5f\u5c31\u662f\u8d44\u6e90\u6587\u4ef6\u5d4c\u5165\u5230\u4e86\u7a0b\u5e8f\u96c6\u4e2d\uff0c\u5e38\u7528\u4e8e\u6a21\u5757\u5316\u5f00\u53d1")),(0,a.kt)("h2",{id:"312-\u6ce8\u518c\u865a\u62df\u6587\u4ef6\u7cfb\u7edf\u670d\u52a1"},"31.2 \u6ce8\u518c\u865a\u62df\u6587\u4ef6\u7cfb\u7edf\u670d\u52a1"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"services.AddVirtualFileServer();\n")),(0,a.kt)("h2",{id:"313-\u83b7\u53d6\u6587\u4ef6\u7cfb\u7edf-ifileprovider-\u5b9e\u4f8b"},"31.3 \u83b7\u53d6\u6587\u4ef6\u7cfb\u7edf ",(0,a.kt)("inlineCode",{parentName:"h2"},"IFileProvider")," \u5b9e\u4f8b"),(0,a.kt)("h3",{id:"3131-funcfileprovidertypes-object-ifileprovider-\u65b9\u5f0f"},"31.3.1 ",(0,a.kt)("inlineCode",{parentName:"h3"},"Func")," \u65b9\u5f0f"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"Func")," \u59d4\u6258\u4f9b\u6784\u9020\u51fd\u6570\u6ce8\u5165\u6216\u89e3\u6790\u670d\u52a1\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {6,8-9,11-12}",showLineNumbers:!0,"":!0,"{6,8-9,11-12}":!0},'public class PersonServices\n{\n private readonly IFileProvider _physicalFileProvider;\n private readonly IFileProvider _embeddedFileProvider;\n\n public PersonServices(Func fileProviderResolve)\n {\n // \u89e3\u6790\u7269\u7406\u6587\u4ef6\u7cfb\u7edf\n _physicalFileProvider = fileProviderResolve(FileProviderTypes.Physical, @"c:/test");\n\n // \u89e3\u6790\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6\u7cfb\u7edf\n _embeddedFileProvider = fileProviderResolve(FileProviderTypes.Embedded, Assembly.GetEntryAssembly());\n }\n}\n')),(0,a.kt)("h3",{id:"3132-fs-\u9759\u6001\u7c7b\u65b9\u5f0f"},"31.3.2 ",(0,a.kt)("inlineCode",{parentName:"h3"},"FS")," \u9759\u6001\u7c7b\u65b9\u5f0f"),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e5f\u63d0\u4f9b\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"FS")," \u9759\u6001\u7c7b\u65b9\u5f0f\u521b\u5efa\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u89e3\u6790\u7269\u7406\u6587\u4ef6\u7cfb\u7edf\nvar physicalFileProvider = FS.GetPhysicalFileProvider(@"c:/test");\n\n// \u89e3\u6790\u5d4c\u5165\u8d44\u6e90\u6587\u4ef6\u7cfb\u7edf\nvar embeddedFileProvider = FS.GetEmbeddedFileProvider(Assembly.GetEntryAssembly());\n')),(0,a.kt)("h2",{id:"314-ifileprovider-\u5e38\u89c1\u64cd\u4f5c"},"31.4 ",(0,a.kt)("inlineCode",{parentName:"h2"},"IFileProvider")," \u5e38\u89c1\u64cd\u4f5c"),(0,a.kt)("h3",{id:"3141-\u8bfb\u53d6\u6587\u4ef6\u5185\u5bb9"},"31.4.1 \u8bfb\u53d6\u6587\u4ef6\u5185\u5bb9"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'byte[] buffer;\nusing (Stream readStream = _fileProvider.GetFileInfo("\u4f60\u7684\u6587\u4ef6\u8def\u5f84").CreateReadStream())\n{\n buffer = new byte[readStream.Length];\n await readStream.ReadAsync(buffer.AsMemory(0, buffer.Length));\n}\n\n// \u8bfb\u53d6\u6587\u4ef6\u5185\u5bb9\nvar content = Encoding.UTF8.GetString(buffer);\n')),(0,a.kt)("h3",{id:"3142-\u83b7\u53d6\u6587\u4ef6\u76ee\u5f55\u5185\u5bb9\u9700\u9012\u5f52\u67e5\u627e"},"31.4.2 \u83b7\u53d6\u6587\u4ef6\u76ee\u5f55\u5185\u5bb9\uff08\u9700\u9012\u5f52\u67e5\u627e\uff09"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'var rootPath = "\u5f53\u524d\u76ee\u5f55\u8def\u5f84";\nvar fileinfos = _fileProvider.GetDirectoryContents(rootPath);\nforeach (var fileinfo in fileinfos)\n{\n if(fileinfo.IsDirectory)\n {\n // \u8fd9\u91cc\u9012\u5f52\u3002\u3002\u3002\n }\n}\n')),(0,a.kt)("h3",{id:"3144-\u76d1\u542c\u6587\u4ef6\u53d8\u5316"},"31.4.4 \u76d1\u542c\u6587\u4ef6\u53d8\u5316"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'ChangeToken.OnChange(() => _fileProvider.Watch("\u76d1\u542c\u7684\u6587\u4ef6"), () =>\n{\n // \u8fd9\u91cc\u5199\u4f60\u7684\u903b\u8f91\n});\n')),(0,a.kt)("h2",{id:"315-\u6a21\u5757\u5316\u9759\u6001\u8d44\u6e90\u914d\u7f6e"},"31.5 \u6a21\u5757\u5316\u9759\u6001\u8d44\u6e90\u914d\u7f6e"),(0,a.kt)("p",null,"\u901a\u5e38\u6211\u4eec\u91c7\u7528\u6a21\u5757\u5316\u5f00\u53d1\uff0c\u9759\u6001\u8d44\u6e90\u90fd\u662f\u5d4c\u5165\u8fdb\u7a0b\u5e8f\u96c6\u4e2d\uff0c\u8fd9\u65f6\u5019\u6211\u4eec\u9700\u8981\u901a\u8fc7\u914d\u7f6e ",(0,a.kt)("inlineCode",{parentName:"p"},"UseFileServer")," \u6307\u5b9a\u6a21\u5757\u9759\u6001\u8d44\u6e90\u8def\u5f84\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'// \u9ed8\u8ba4\u9759\u6001\u8d44\u6e90\u8c03\u7528\uff0cwwwroot\napp.UseStaticFiles();\n\n// \u914d\u7f6e\u6a21\u5757\u5316\u9759\u6001\u8d44\u6e90\napp.UseFileServer(new FileServerOptions\n{\n FileProvider = new EmbeddedFileProvider(\u6a21\u5757\u7a0b\u5e8f\u96c6),\n RequestPath = "/\u6a21\u5757\u540d\u79f0", // \u540e\u7eed\u6240\u6709\u8d44\u6e90\u90fd\u662f\u901a\u8fc7 /\u6a21\u5757\u540d\u79f0/xxx.css \u8c03\u7528\n EnableDirectoryBrowsing = true\n});\n')),(0,a.kt)("h2",{id:"316-\u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d"},"31.6 \u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d"),(0,a.kt)("p",null,"\u5728\u5e94\u7528\u5f00\u53d1\u4e2d\uff0c\u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d\u5c5e\u4e8e\u975e\u5e38\u5e38\u7528\u7684\u529f\u80fd\uff0c\u8fd9\u91cc\u8d34\u51fa\u5e38\u89c1\u7684\u6587\u4ef6\u4e0a\u4f20\u4e0b\u8f7d\u793a\u4f8b\u3002"),(0,a.kt)("h3",{id:"3161-\u6587\u4ef6\u4e0b\u8f7d"},"31.6.1 \u6587\u4ef6\u4e0b\u8f7d"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\u6587\u4ef6\u8def\u5f84\u7684\u65b9\u5f0f")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,5}",showLineNumbers:!0,"{1,5}":!0},'[HttpGet, NonUnify]\npublic IActionResult FileDownload()\n{\n string filePath = "\u8fd9\u91cc\u83b7\u53d6\u5b8c\u6574\u7684\u6587\u4ef6\u4e0b\u8f7d\u8def\u5f84";\n return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") {\n FileDownloadName = fileName // \u914d\u7f6e\u6587\u4ef6\u4e0b\u8f7d\u663e\u793a\u540d\n };\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"byte[]")," \u65b9\u5f0f")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,4}",showLineNumbers:!0,"{1,4}":!0},'[HttpGet, NonUnify]\npublic IActionResult FileDownload()\n{\n return new FileStreamResult(byte\u6570\u7ec4, "application/octet-stream") {\n FileDownloadName = fileName // \u914d\u7f6e\u6587\u4ef6\u4e0b\u8f7d\u663e\u793a\u540d\n };\n}\n')),(0,a.kt)("admonition",{title:"\u5173\u4e8e\u524d\u7aef\u83b7\u53d6\u6587\u4ef6\u540d",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u5982\u679c\u524d\u7aef\u83b7\u53d6\u4e0d\u5230\u6587\u4ef6\u5939\uff0c\u53ef\u6dfb\u52a0\u4ee5\u4e0b\u914d\u7f6e\uff1a"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={\u6587\u4ef6\u540d}");\n_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");\n'))),(0,a.kt)("h3",{id:"3162-\u6587\u4ef6\u4e0a\u4f20"},"31.6.2 \u6587\u4ef6\u4e0a\u4f20"),(0,a.kt)("admonition",{title:"\u5c0f\u63d0\u9192",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"IFormFile")," \u7c7b\u578b\u5bf9\u5e94\u524d\u7aef\u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Content-Type")," \u4e3a\uff1a ",(0,a.kt)("inlineCode",{parentName:"p"},"multipart/form-data"))),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5355\u6587\u4ef6 ",(0,a.kt)("inlineCode",{parentName:"strong"},"IFormFile")," \u7c7b\u578b\u53c2\u6570\uff08\u5b58\u50a8\u5230\u786c\u76d8\uff09"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,2,18}",showLineNumbers:!0,"":!0,"{1,2,18}":!0},'[HttpPost]\npublic async Task UploadFileAsync(IFormFile file)\n{\n // \u5982\uff1a\u4fdd\u5b58\u5230\u7f51\u7ad9\u6839\u76ee\u5f55\u4e0b\u7684 uploads \u76ee\u5f55\n var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");\n if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);\n\n //// \u8fd9\u91cc\u8fd8\u53ef\u4ee5\u83b7\u53d6\u6587\u4ef6\u7684\u4fe1\u606f\n // var size = file.Length / 1024.0; // \u6587\u4ef6\u5927\u5c0f KB\n // var clientFileName = file.FileName; // \u5ba2\u6237\u7aef\u4e0a\u4f20\u7684\u6587\u4ef6\u540d\n // var contentType = file.ContentType; // \u83b7\u53d6\u6587\u4ef6 ContentType \u6216\u89e3\u6790 MIME \u7c7b\u578b\n\n // \u907f\u514d\u6587\u4ef6\u540d\u91cd\u590d\uff0c\u91c7\u7528 GUID \u751f\u6210\n var fileName = Guid.NewGuid().ToString("N") + Path.GetExtension(file.FileName);\n var filePath = Path.Combine(savePath, fileName);\n\n // \u4fdd\u5b58\u5230\u6307\u5b9a\u8def\u5f84\n using (var stream = System.IO.File.Create(filePath))\n {\n await file.CopyToAsync(stream);\n }\n\n // \u5728\u52a8\u6001 API \u76f4\u63a5\u8fd4\u56de\u5bf9\u8c61\u5373\u53ef\uff0c\u65e0\u9700 OK \u548c IActionResult\n return Ok(new { filename });\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u5355\u6587\u4ef6 ",(0,a.kt)("inlineCode",{parentName:"strong"},"Base64")," \u7c7b\u578b\u53c2\u6570\uff08\u5b58\u50a8\u5230\u786c\u76d8\uff09"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,2,9,19}",showLineNumbers:!0,"":!0,"{1,2,9,19}":!0},'[HttpPost]\npublic async Task UploadFileAsync([FromBody] string fileBase64, string clientFileName)\n{\n // \u5982\uff1a\u4fdd\u5b58\u5230\u7f51\u7ad9\u6839\u76ee\u5f55\u4e0b\u7684 uploads \u76ee\u5f55\n var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");\n if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);\n\n // \u5c06 base64 \u5b57\u7b26\u4e32\u8f6c byte[]\n var bytes = Convert.FromBase64String(fileBase64);\n\n // \u8fd9\u91cc\u8fd8\u53ef\u4ee5\u83b7\u53d6\u6587\u4ef6\u7684\u4fe1\u606f\n // var size = bytes.Length / 1024.0; // \u6587\u4ef6\u5927\u5c0f KB\n\n // \u907f\u514d\u6587\u4ef6\u540d\u91cd\u590d\uff0c\u91c7\u7528 GUID \u751f\u6210\n var fileName = Guid.NewGuid().ToString("N") + Path.GetExtension(clientFileName);\n var filePath = Path.Combine(savePath, fileName);\n\n // \u4fdd\u5b58\u5230\u6307\u5b9a\u8def\u5f84\n using (var fs = new FileStream(filePath, FileMode.Create))\n {\n await fs.WriteAsync(bytes);\n }\n\n // \u5728\u52a8\u6001 API \u76f4\u63a5\u8fd4\u56de\u5bf9\u8c61\u5373\u53ef\uff0c\u65e0\u9700 OK \u548c IActionResult\n return Ok(new { fileName });\n}\n')),(0,a.kt)("admonition",{title:"\u7279\u522b\u6ce8\u610f",type:"warning"},(0,a.kt)("p",{parentName:"admonition"},"\u6587\u4ef6 ",(0,a.kt)("inlineCode",{parentName:"p"},"Base64")," \u5b57\u7b26\u4e32\u5982\u679c\u5e26 ",(0,a.kt)("inlineCode",{parentName:"p"},"data:text/plain;base64,")," \u5f00\u5934\u5219\uff0c\u9700\u8981\u624b\u52a8\u53bb\u6389 ",(0,a.kt)("inlineCode",{parentName:"p"},",")," \u4e4b\u524d\uff08\u542b\u9017\u53f7\uff09\u7684\u5b57\u7b26\u4e32\u3002")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u591a\u6587\u4ef6 ",(0,a.kt)("inlineCode",{parentName:"strong"},"List")," \u7c7b\u578b\u53c2\u6570\uff08\u5b58\u50a8\u5230\u786c\u76d8\uff09"))),(0,a.kt)("p",null,"\u4ee3\u7801\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5355\u6587\u4ef6\u5904\u7406\u4e00\u81f4"),"\uff0c\u53ea\u9700 ",(0,a.kt)("inlineCode",{parentName:"p"},"foreach")," \u5373\u53ef\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,12}",showLineNumbers:!0,"":!0,"{1,12}":!0},'[HttpPost]\npublic async Task UploadFileAsync(List files)\n{\n // \u4fdd\u5b58\u5230\u7f51\u7ad9\u6839\u76ee\u5f55\u4e0b\u7684 uploads \u76ee\u5f55\n var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");\n if(!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);\n\n // \u603b\u4e0a\u4f20\u5927\u5c0f\n long size = files.Sum(f => f.Length);\n\n // \u904d\u5386\u6240\u6709\u6587\u4ef6\u9010\u4e00\u4e0a\u4f20\n foreach (var formFile in files)\n {\n if (formFile.Length > 0)\n {\n // \u907f\u514d\u6587\u4ef6\u540d\u91cd\u590d\uff0c\u91c7\u7528 GUID \u751f\u6210\n var fileName = Guid.NewGuid().ToString("N") + Path.GetExtension(clientFileName);\n var filePath = Path.Combine(savePath, fileName);\n\n // \u4fdd\u5b58\u5230\u6307\u5b9a\u8def\u5f84\n using (var stream = System.IO.File.Create(filePath))\n {\n await formFile.CopyToAsync(stream);\n }\n }\n }\n\n // \u5728\u52a8\u6001 API \u76f4\u63a5\u8fd4\u56de\u5bf9\u8c61\u5373\u53ef\uff0c\u65e0\u9700 OK \u548c IActionResult\n return Ok(new { count = files.Count, size });\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"\u591a\u6587\u4ef6 ",(0,a.kt)("inlineCode",{parentName:"strong"},"List")," ",(0,a.kt)("inlineCode",{parentName:"strong"},"Base64")," \u7c7b\u578b\u53c2\u6570\uff08\u5b58\u50a8\u5230\u786c\u76d8\uff09"))),(0,a.kt)("p",null,"\u4ee3\u7801\u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"\u5355\u6587\u4ef6\u5904\u7406\u4e00\u81f4"),"\uff0c\u53ea\u9700 ",(0,a.kt)("inlineCode",{parentName:"p"},"foreach")," \u5373\u53ef\uff08\u53c2\u4e0a\uff09\u3002"),(0,a.kt)("h3",{id:"3163-\u5c06-iformfile-\u8f6c-byte"},"31.6.3 \u5c06 ",(0,a.kt)("inlineCode",{parentName:"h3"},"IFormFile")," \u8f6c ",(0,a.kt)("inlineCode",{parentName:"h3"},"byte[]")),(0,a.kt)("p",null,"\u6709\u65f6\u5019\u6211\u4eec\u9700\u8981\u5c06\u6587\u4ef6\u8f6c\u6362\u6210 ",(0,a.kt)("inlineCode",{parentName:"p"},"byte[]")," \u5b58\u50a8\u5230\u6570\u636e\u5e93\uff0c\u800c\u4e0d\u662f\u5b58\u50a8\u5230\u786c\u76d8\u4e2d\u3002"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4-8}",showLineNumbers:!0,"{4-8}":!0},"[HttpPost]\npublic async Task UploadFileAsync(IFormFile file)\n{\n var fileLength = file.Length;\n using var stream = file.OpenReadStream();\n var bytes = new byte[fileLength];\n\n stream.Read(bytes, 0, (int)fileLength);\n\n // \u8fd9\u91cc\u5c06 bytes \u5b58\u50a8\u5230\u4f60\u60f3\u8981\u7684\u4ecb\u8d28\u4e2d\u5373\u53ef\n}\n")),(0,a.kt)("admonition",{title:"\u4fbf\u6377\u62d3\u5c55\u65b9\u6cd5",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u5728 Furion ",(0,a.kt)("inlineCode",{parentName:"p"},"v3.2.0")," \u65b0\u589e\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"IFormFile")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"ToByteArray")," \u62d3\u5c55\uff0c\u5982:"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {4}",showLineNumbers:!0,"":!0,"{4}":!0},"[HttpPost]\npublic async Task UploadFileAsync(IFormFile file)\n{\n var bytes = file.ToByteArray();\n\n // \u8fd9\u91cc\u5c06 bytes \u5b58\u50a8\u5230\u4f60\u60f3\u8981\u7684\u4ecb\u8d28\u4e2d\u5373\u53ef\n}\n"))),(0,a.kt)("h3",{id:"3164-\u5c06-byte-\u8f93\u51fa\u4e3a-url-\u5730\u5740"},"31.6.4 \u5c06 ",(0,a.kt)("inlineCode",{parentName:"h3"},"byte[]")," \u8f93\u51fa\u4e3a ",(0,a.kt)("inlineCode",{parentName:"h3"},"Url")," \u5730\u5740"),(0,a.kt)("p",null,"\u7531\u4e8e\u4e00\u4e9b\u9879\u76ee\u76f4\u63a5\u5c06\u6587\u4ef6\u4e8c\u8fdb\u5236\u5b58\u50a8\u5728\u6570\u636e\u5e93\u4e2d\uff0c\u8bfb\u53d6\u5230\u5185\u5b58\u7684\u65f6\u5019\u90fd\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"byte[]")," \u6570\u7ec4\uff0c\u6bd4\u5982\u6211\u4eec\u5c06\u56fe\u7247\u6587\u4ef6\u5b58\u50a8\u5728\u6570\u636e\u5e93\u4e2d\uff0c\u7136\u540e\u524d\u7aef\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"Url")," \u94fe\u63a5\u8fdb\u884c\u8bbf\u95ee\uff0c\u8fd9\u4e2a\u65f6\u5019\u5c31\u9700\u8981\u5c06 ",(0,a.kt)("inlineCode",{parentName:"p"},"byte[]")," \u8f6c\u6362\u4e3a\u6709\u6548\u7684\u8d44\u6e90\u8def\u5f84\u683c\u5f0f\uff0c\u5982\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,7}",showLineNumbers:!0,"{1,7}":!0},"[NonUnify, HttpGet, AllowAnonymous]\npublic async Task attachment(string resourceId)\n{\n // \u6839\u636e resourceId \u67e5\u8be2 byte[] \u5b57\u8282\u6570\u7ec4\u548c content-type\n\n // \u8fd4\u56de FileContentResult \u7c7b\u578b\n return new FileContentResult(\u5b57\u8282\u6570\u7ec4\uff0ccontent-type);\n}\n")),(0,a.kt)("p",null,"\u4e4b\u540e\u6211\u4eec\u5c31\u53ef\u4ee5\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"https://localhost/attachment/\u8d44\u6e90id")," \u8bbf\u95ee\u6587\u4ef6\u6216\u56fe\u7247\u4e86\u3002"),(0,a.kt)("h2",{id:"317-\u8bf7\u6c42\u5927\u5c0f\u63a7\u5236\u4e0a\u4f20\u6587\u4ef6\u5927\u5c0f\u63a7\u5236"},"31.7 \u8bf7\u6c42\u5927\u5c0f\u63a7\u5236\uff08\u4e0a\u4f20\u6587\u4ef6\u5927\u5c0f\u63a7\u5236\uff09"),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u9879\u76ee\u4e2d\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"Kestrel")," \u548c ",(0,a.kt)("inlineCode",{parentName:"p"},"HttpSys")," \u90fd\u5f3a\u5236\u5b9e\u65bd ",(0,a.kt)("inlineCode",{parentName:"p"},"30M (~28.6MiB)")," \u7684\u6700\u5927\u8bf7\u6c42\u6b63\u6587\u5927\u5c0f\u9650\u5236\uff0c\u5982\u679c\u8bf7\u6c42\u6b63\u6587\u5927\u5c0f\u8d85\u8fc7\u914d\u7f6e\u7684\u6700\u5927\u8bf7\u6c42\u6b63\u6587\u5927\u5c0f\u9650\u5236\uff0c\u5219\u5f15\u53d1 ",(0,a.kt)("inlineCode",{parentName:"p"},"Request body too large. The max request body size is xxxxx")," \u5f02\u5e38\uff0c\u72b6\u6001\u7801\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"413")," \u6216 ",(0,a.kt)("inlineCode",{parentName:"p"},"500"),"\u3002"),(0,a.kt)("h3",{id:"3171-\u5bf9\u7279\u5b9a\u7684\u63a5\u53e3\u8fdb\u884c\u63a7\u5236"},"31.7.1 \u5bf9\u7279\u5b9a\u7684\u63a5\u53e3\u8fdb\u884c\u63a7\u5236"),(0,a.kt)("p",null,"\u53ef\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},"[RequestSizeLimit]")," \u7279\u6027\u8fdb\u884c\u7279\u5b9a\u9650\u5236"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {2}",showLineNumbers:!0,"{2}":!0},"[HttpPost]\n[RequestSizeLimit(100_000_000)]\npublic IActionResult MyAction([FromBody] MyViewModel data)\n{\n}\n")),(0,a.kt)("h3",{id:"3172-\u5bf9\u7279\u5b9a\u63a5\u53e3\u53d6\u6d88\u9650\u5236"},"31.7.2 \u5bf9\u7279\u5b9a\u63a5\u53e3\u53d6\u6d88\u9650\u5236"),(0,a.kt)("p",null,"\u5982\u679c\u4e0d\u9700\u8981\u5bf9\u8bf7\u6c42\u5927\u5c0f\u8fdb\u884c\u9650\u5236\uff0c\u4e5f\u5c31\u662f\u652f\u6301\u63d0\u4ea4\u65e0\u9650\u5927\u5c0f\uff0c\u5219\u8d34 ",(0,a.kt)("inlineCode",{parentName:"p"},"[DisableRequestSizeLimit]")," \u7279\u6027\u5373\u53ef\u3002"),(0,a.kt)("h3",{id:"3173-\u901a\u7528\u4e2d\u95f4\u4ef6\u8fdb\u884c\u63a7\u5236"},"31.7.3 \u901a\u7528\u4e2d\u95f4\u4ef6\u8fdb\u884c\u63a7\u5236"),(0,a.kt)("p",null,"\u6211\u4eec\u4e5f\u53ef\u4ee5\u901a\u8fc7\u4e2d\u95f4\u4ef6\u7684\u65b9\u5f0f\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u8fdb\u884c\u914d\u7f6e\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3}",showLineNumbers:!0,"{1,3}":!0},"app.Run(async context =>\n{\n context.Features.Get().MaxRequestBodySize = 100_000_000; // \u8bbe\u7f6e null \u5c31\u662f\u4e0d\u9650\u5236\uff0c\u5177\u4f53\u503c\u5c31\u662f\u9650\u5236\u6700\u5927\u591a\u5c11 M\n}\n")),(0,a.kt)("p",null,"\u5982\u679c\u8bbe\u7f6e ",(0,a.kt)("inlineCode",{parentName:"p"},"MaxRequestBodySize")," \u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"null")," \uff0c\u5219\u7b49\u540c\u4e8e\u53d6\u6d88\u9650\u5236\uff0c\u4e5f\u5c31\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"[DisableRequestSizeLimit]")," \u7684\u6548\u679c\u3002"),(0,a.kt)("admonition",{title:"\u5c0f\u6ce8\u610f",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u6709\u65f6\u5019\u914d\u7f6e\u4e86\u4e2d\u95f4\u4ef6\u6548\u679c\u53d1\u73b0\u6ca1\u8d77\u4f5c\u7528\uff0c\u5f88\u6709\u53ef\u80fd\u548c\u4e2d\u95f4\u4ef6\u987a\u5e8f\u6709\u5173\uff0c\u53ef\u4ee5\u901a\u8fc7 ",(0,a.kt)("inlineCode",{parentName:"p"},".IsReadOnly")," \u5c5e\u6027\u5224\u65ad\uff0c\u5982\u679c\u4e3a ",(0,a.kt)("inlineCode",{parentName:"p"},"true")," \uff0c\u8bf4\u660e\u4f60\u7684\u914d\u7f6e\u65e0\u6548\uff0c\u53ea\u6709 ",(0,a.kt)("inlineCode",{parentName:"p"},"false")," \u624d\u6709\u6548\u3002")),(0,a.kt)("h3",{id:"3174-\u5168\u5c40\u914d\u7f6e"},"31.7.4 \u5168\u5c40\u914d\u7f6e"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"IIS")," \u65b9\u5f0f\uff1a")),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("strong",{parentName:"li"},"\u5f00\u53d1\u73af\u5883\uff08IISExpress\uff09"))),(0,a.kt)("p",null,"\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u542f\u52a8\u5c42\uff08\u901a\u5e38\u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"XXX.Web.Entry"),"\uff09\u6839\u76ee\u5f55\u4e0b\u521b\u5efa ",(0,a.kt)("inlineCode",{parentName:"p"},"web.config")," \u6587\u4ef6\uff0c\u5185\u5bb9\u5982\u4e0b\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-xml",metastring:"showLineNumbers {3-9}",showLineNumbers:!0,"{3-9}":!0},'\n\n \n \n \n \n \n \n \n\n')),(0,a.kt)("ol",{start:2},(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("strong",{parentName:"li"},"\u751f\u4ea7\u73af\u5883"))),(0,a.kt)("p",null,"\u901a\u5e38\u751f\u4ea7\u73af\u5883 ",(0,a.kt)("inlineCode",{parentName:"p"},"IIS")," \u81ea\u52a8\u9879\u76ee\u6dfb\u52a0\u4e86 ",(0,a.kt)("inlineCode",{parentName:"p"},"web.config")," \u6587\u4ef6\uff0c\u8fd9\u65f6\u5019\u53ea\u9700\u8981\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"")," \u8282\u70b9\u4e0b\u6dfb\u52a0\u4e0b\u9762\u5185\u5bb9\u5373\u53ef\uff1a"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-xml",metastring:"showLineNumbers {3-5}",showLineNumbers:!0,"{3-5}":!0},'\n \n \n \n \n \n\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Kestrel")," \u65b9\u5f0f\uff1a")),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"\u672a\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"IIS")," \u6258\u7ba1\u65f6\uff0c",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u9ed8\u8ba4\u4f7f\u7528 ",(0,a.kt)("inlineCode",{parentName:"p"},"Kestrel")," \u65b9\u5f0f\u3002")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,8}",showLineNumbers:!0,"{1,8}":!0},"// .NET5 \u65b9\u5f0f\uff0c\u5728 .ConfigureWebHostDefaults \u91cc\u9762\u914d\u7f6e\n.UseStartup()\n.UseKestrel(options =>\n{\n options.Limits.MaxRequestBodySize = null; // \u8bbe\u7f6e null \u5c31\u662f\u4e0d\u9650\u5236\uff0c\u5177\u4f53\u503c\u5c31\u662f\u9650\u5236\u6700\u5927\u591a\u5c11 M\n}\n\n// .NET6 \u65b9\u5f0f,\u5728 progame.cs \u6587\u4ef6 var app = builder.Build(); \u4e4b\u540e\u914d\u7f6e\napp.Configuration.Get().ConfigureKestrel(options =>\n{\n options.Limits.MaxRequestBodySize = null; // \u8bbe\u7f6e null \u5c31\u662f\u4e0d\u9650\u5236\uff0c\u5177\u4f53\u503c\u5c31\u662f\u9650\u5236\u6700\u5927\u591a\u5c11 M\n});\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"HttpSys")," \u65b9\u5f0f\uff1a")),(0,a.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"tip"},(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("inlineCode",{parentName:"p"},"HTTP.sys")," \u662f\u4ec5\u5728 ",(0,a.kt)("inlineCode",{parentName:"p"},"Windows")," \u4e0a\u8fd0\u884c\u7684\u9002\u7528\u4e8e ",(0,a.kt)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u7684 ",(0,a.kt)("inlineCode",{parentName:"p"},"Web")," \u670d\u52a1\u5668\u3002 ",(0,a.kt)("inlineCode",{parentName:"p"},"HTTP.sys")," \u662f ",(0,a.kt)("inlineCode",{parentName:"p"},"Kestrel")," \u670d\u52a1\u5668\u7684\u66ff\u4ee3\u9009\u62e9\uff0c\u63d0\u4f9b\u4e86\u4e00\u4e9b ",(0,a.kt)("inlineCode",{parentName:"p"},"Kestrel")," \u4e0d\u63d0\u4f9b\u7684\u529f\u80fd\u3002")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"// .NET5 \u65b9\u5f0f\u540c\u4e0a\n.UseHttpSys(options =>\n{\n options.MaxRequestBodySize = 100_000_000; // \u8bbe\u7f6e null \u5c31\u662f\u4e0d\u9650\u5236\uff0c\u5177\u4f53\u503c\u5c31\u662f\u9650\u5236\u6700\u5927\u591a\u5c11 M\n}\n\n// .NET6 \u65b9\u5f0f\u540c\u4e0a\n")),(0,a.kt)("h2",{id:"318-\u53cd\u9988\u4e0e\u5efa\u8bae"},"31.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),(0,a.kt)("admonition",{title:"\u4e0e\u6211\u4eec\u4ea4\u6d41",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\u7ed9 Furion \u63d0 ",(0,a.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/issues/new?issue"},"Issue"),"\u3002")),(0,a.kt)("hr",null))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/c0812ddb.233de97c.js b/handbook/build/assets/js/c0812ddb.233de97c.js new file mode 100644 index 0000000000..2ccfd4f290 --- /dev/null +++ b/handbook/build/assets/js/c0812ddb.233de97c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[5827],{3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return m}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},s=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=o,f=d["".concat(u,".").concat(m)]||d[m]||c[m]||i;return n?r.createElement(f,a(a({ref:t},s),{},{components:n})):r.createElement(f,a({ref:t},s))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var p=2;p.NET 6 Preview 6 SDK",id:"\u5b89\u88c5-net-6-preview-6-sdk",level:2},{value:"\u65e7\u9879\u76ee\u5347\u7ea7",id:"\u65e7\u9879\u76ee\u5347\u7ea7",level:2},{value:"\u65b0\u9879\u76ee\u4f7f\u7528",id:"\u65b0\u9879\u76ee\u4f7f\u7528",level:2},{value:"\u5347\u7ea7 Visual Studio 2019",id:"\u5347\u7ea7-visual-studio-2019",level:3},{value:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:3},{value:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",level:3}],d={toc:c};function m(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"2021 \u5e74 08 \u6708 11 \u65e5\uff0c\u5fae\u8f6f\u53d1\u5e03\u4e86 ",(0,i.kt)("inlineCode",{parentName:"strong"},".NET 6 Preview 7")," \u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5728\u5f53\u5929\u7b2c\u4e00\u65f6\u95f4\u9002\u914d\u4e86\u8be5\u7248\u672c\uff0c\u5e76\u53d1\u5e03 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v3.0.0-rc.2")," \u7248\u672c\u3002")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/tree/3.0.0-rc.2/"},"Furion .NET 6 Preview 7 \u6e90\u7801\u5730\u5740")),(0,i.kt)("h2",{id:"\u5b89\u88c5-net-6-preview-6-sdk"},"\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h2"},".NET 6 Preview 6 SDK")),(0,i.kt)("p",null,"\u5c1d\u9c9c\u4e4b\u524d\uff0c\u9996\u5148\u5148\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 7 SDK"),"\uff0c\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/download/dotnet/6.0"},"https://dotnet.microsoft.com/download/dotnet/6.0")),(0,i.kt)("p",null,"\u4e0b\u8f7d\u5bf9\u5e94\u7cfb\u7edf\u548c\u5904\u7406\u5668\u7248\u672c\u5373\u53ef\u3002"),(0,i.kt)("h2",{id:"\u65e7\u9879\u76ee\u5347\u7ea7"},"\u65e7\u9879\u76ee\u5347\u7ea7"),(0,i.kt)("p",null,"\u7f16\u8f91\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},".csproj")," \u9879\u76ee\uff0c\u4fee\u6539 ",(0,i.kt)("inlineCode",{parentName:"p"},"net5.0")," \u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"net6.0"),"\u3002"),(0,i.kt)("p",null,"\u540c\u65f6\u5347\u7ea7\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"Microsoft")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\u4e3a\u6700\u65b0\u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6700\u65b0\u7248\u672c\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"v3.0.0-rc.1"),"\u3002"),(0,i.kt)("h2",{id:"\u65b0\u9879\u76ee\u4f7f\u7528"},"\u65b0\u9879\u76ee\u4f7f\u7528"),(0,i.kt)("h3",{id:"\u5347\u7ea7-visual-studio-2019"},"\u5347\u7ea7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Visual Studio 2019")),(0,i.kt)("p",null,"\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 7")," \u652f\u6301\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview 16.11.0 Preview 4.0")," \u7248\u672c\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u662f ",(0,i.kt)("inlineCode",{parentName:"strong"},"Preview")," \u6700\u65b0\u7248\u672c"),"\u3002\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16"},"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16")),(0,i.kt)("p",null,"\u5df2\u7ecf\u5b89\u88c5\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview")," \u7248\u672c\u7684\u670b\u53cb\u76f4\u63a5\u5347\u7ea7\u5230\u6700\u65b0\u7248\u5373\u53ef\u3002"),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio Code")," \u5f00\u53d1\uff0c\u53ef\u5ffd\u7565\u6b64\u9009\u9879\u3002")),(0,i.kt)("h3",{id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion v3.0.0-rc.2")," \u76ee\u524d\u63d0\u4f9b\u4e86\u6240\u6709\u7c7b\u578b\u7684\u811a\u624b\u67b6\uff0c\u7248\u672c\u53f7\u7edf\u4e00 ",(0,i.kt)("inlineCode",{parentName:"p"},"3.0.0-rc.2"),"\u3002"),(0,i.kt)("p",null,"\u5b89\u88c5\u811a\u624b\u67b6\uff0c\u6253\u5f00 ",(0,i.kt)("inlineCode",{parentName:"p"},"CMD/Powershell")," \u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new --install Furion.Template.Api::3.0.0-rc.2\n")),(0,i.kt)("p",null,"\u521b\u5efa\u9879\u76ee"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new furionapi -n FurionNET6\n")),(0,i.kt)("h3",{id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"},"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"),(0,i.kt)("p",null,"\u6253\u5f00\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u5373\u53ef\u3002"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/assets/js/c0812ddb.48ff70af.js b/handbook/build/assets/js/c0812ddb.48ff70af.js deleted file mode 100644 index 98963b10a0..0000000000 --- a/handbook/build/assets/js/c0812ddb.48ff70af.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkfurion=self.webpackChunkfurion||[]).push([[5827],{5461:function(e,t,n){n.r(t),n.d(t,{assets:function(){return s},contentTitle:function(){return u},default:function(){return m},frontMatter:function(){return l},metadata:function(){return p},toc:function(){return c}});var r=n(3117),o=n(102),i=(n(7294),n(3905)),a=(n(1402),["components"]),l={slug:"net6-preview7",title:"6. .NET 6 Preview 7 \u5c1d\u9c9c",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5",".net6"]},u=void 0,p={permalink:"/furion/blog/net6-preview7",editUrl:"https://gitee.com/dotnetchina/Furion/tree/net6/handbook/blog/2021-08-11-net6-preview7.mdx",source:"@site/blog/2021-08-11-net6-preview7.mdx",title:"6. .NET 6 Preview 7 \u5c1d\u9c9c",description:"",date:"2021-08-11T00:00:00.000Z",formattedDate:"August 11, 2021",tags:[{label:"furion",permalink:"/furion/blog/tags/furion"},{label:"furos",permalink:"/furion/blog/tags/furos"},{label:".net",permalink:"/furion/blog/tags/net"},{label:".netcore",permalink:"/furion/blog/tags/netcore"},{label:".net5",permalink:"/furion/blog/tags/net-5"},{label:".net6",permalink:"/furion/blog/tags/net-6"}],readingTime:1.485,hasTruncateMarker:!1,authors:[{name:"dotNET China",title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",url:"https://www.chinadot.net",imageURL:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png"}],frontMatter:{slug:"net6-preview7",title:"6. .NET 6 Preview 7 \u5c1d\u9c9c",author:"dotNET China",author_title:"\u8ba9 .NET \u5f00\u53d1\u66f4\u7b80\u5355\uff0c\u66f4\u901a\u7528\uff0c\u66f4\u6d41\u884c\u3002",author_url:"https://www.chinadot.net",author_image_url:"https://i.loli.net/2021/01/19/M8q5a3OTZWUKicl.png",tags:["furion","furos",".net",".netcore",".net5",".net6"]},prevItem:{title:"7. GlobalUsings \u7684\u4f7f\u7528",permalink:"/furion/blog/global-usings"},nextItem:{title:"5. \u5728\u63a7\u5236\u53f0\u4e2d\u4f7f\u7528",permalink:"/furion/blog/console"}},s={authorsImageUrls:[void 0]},c=[{value:"\u5b89\u88c5 .NET 6 Preview 6 SDK",id:"\u5b89\u88c5-net-6-preview-6-sdk",level:2},{value:"\u65e7\u9879\u76ee\u5347\u7ea7",id:"\u65e7\u9879\u76ee\u5347\u7ea7",level:2},{value:"\u65b0\u9879\u76ee\u4f7f\u7528",id:"\u65b0\u9879\u76ee\u4f7f\u7528",level:2},{value:"\u5347\u7ea7 Visual Studio 2019",id:"\u5347\u7ea7-visual-studio-2019",level:3},{value:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50",level:3},{value:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee",level:3}],d={toc:c};function m(e){var t=e.components,n=(0,o.Z)(e,a);return(0,i.kt)("wrapper",(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"2021 \u5e74 08 \u6708 11 \u65e5\uff0c\u5fae\u8f6f\u53d1\u5e03\u4e86 ",(0,i.kt)("inlineCode",{parentName:"strong"},".NET 6 Preview 7")," \u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion")," \u5728\u5f53\u5929\u7b2c\u4e00\u65f6\u95f4\u9002\u914d\u4e86\u8be5\u7248\u672c\uff0c\u5e76\u53d1\u5e03 ",(0,i.kt)("inlineCode",{parentName:"strong"},"Furion v3.0.0-rc.2")," \u7248\u672c\u3002")),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://gitee.com/dotnetchina/Furion/tree/3.0.0-rc.2/"},"Furion .NET 6 Preview 7 \u6e90\u7801\u5730\u5740")),(0,i.kt)("h2",{id:"\u5b89\u88c5-net-6-preview-6-sdk"},"\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"h2"},".NET 6 Preview 6 SDK")),(0,i.kt)("p",null,"\u5c1d\u9c9c\u4e4b\u524d\uff0c\u9996\u5148\u5148\u5b89\u88c5 ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 7 SDK"),"\uff0c\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://dotnet.microsoft.com/download/dotnet/6.0"},"https://dotnet.microsoft.com/download/dotnet/6.0")),(0,i.kt)("p",null,"\u4e0b\u8f7d\u5bf9\u5e94\u7cfb\u7edf\u548c\u5904\u7406\u5668\u7248\u672c\u5373\u53ef\u3002"),(0,i.kt)("h2",{id:"\u65e7\u9879\u76ee\u5347\u7ea7"},"\u65e7\u9879\u76ee\u5347\u7ea7"),(0,i.kt)("p",null,"\u7f16\u8f91\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},".csproj")," \u9879\u76ee\uff0c\u4fee\u6539 ",(0,i.kt)("inlineCode",{parentName:"p"},"net5.0")," \u4e3a ",(0,i.kt)("inlineCode",{parentName:"p"},"net6.0"),"\u3002"),(0,i.kt)("p",null,"\u540c\u65f6\u5347\u7ea7\u6240\u6709 ",(0,i.kt)("inlineCode",{parentName:"p"},"Microsoft")," \u548c ",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u5305\u4e3a\u6700\u65b0\u7248\u672c\uff0c",(0,i.kt)("inlineCode",{parentName:"p"},"Furion")," \u6700\u65b0\u7248\u672c\u4e3a\uff1a",(0,i.kt)("inlineCode",{parentName:"p"},"v3.0.0-rc.1"),"\u3002"),(0,i.kt)("h2",{id:"\u65b0\u9879\u76ee\u4f7f\u7528"},"\u65b0\u9879\u76ee\u4f7f\u7528"),(0,i.kt)("h3",{id:"\u5347\u7ea7-visual-studio-2019"},"\u5347\u7ea7 ",(0,i.kt)("inlineCode",{parentName:"h3"},"Visual Studio 2019")),(0,i.kt)("p",null,"\u76ee\u524d ",(0,i.kt)("inlineCode",{parentName:"p"},".NET 6 Preview 7")," \u652f\u6301\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview 16.11.0 Preview 4.0")," \u7248\u672c\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6ce8\u610f\u662f ",(0,i.kt)("inlineCode",{parentName:"strong"},"Preview")," \u6700\u65b0\u7248\u672c"),"\u3002\u4e0b\u8f7d\u5730\u5740\uff1a",(0,i.kt)("a",{parentName:"p",href:"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16"},"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16")),(0,i.kt)("p",null,"\u5df2\u7ecf\u5b89\u88c5\u4e86 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio 2019 Preview")," \u7248\u672c\u7684\u670b\u53cb\u76f4\u63a5\u5347\u7ea7\u5230\u6700\u65b0\u7248\u5373\u53ef\u3002"),(0,i.kt)("admonition",{title:"\u7279\u522b\u8bf4\u660e",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"\u5982\u679c\u4f7f\u7528 ",(0,i.kt)("inlineCode",{parentName:"p"},"Visual Studio Code")," \u5f00\u53d1\uff0c\u53ef\u5ffd\u7565\u6b64\u9009\u9879\u3002")),(0,i.kt)("h3",{id:"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"},"\u7b2c\u4e00\u4e2a\u4f8b\u5b50"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Furion v3.0.0-rc.2")," \u76ee\u524d\u63d0\u4f9b\u4e86\u6240\u6709\u7c7b\u578b\u7684\u811a\u624b\u67b6\uff0c\u7248\u672c\u53f7\u7edf\u4e00 ",(0,i.kt)("inlineCode",{parentName:"p"},"3.0.0-rc.2"),"\u3002"),(0,i.kt)("p",null,"\u5b89\u88c5\u811a\u624b\u67b6\uff0c\u6253\u5f00 ",(0,i.kt)("inlineCode",{parentName:"p"},"CMD/Powershell")," \u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new --install Furion.Template.Api::3.0.0-rc.2\n")),(0,i.kt)("p",null,"\u521b\u5efa\u9879\u76ee"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"dotnet new furionapi -n FurionNET6\n")),(0,i.kt)("h3",{id:"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"},"\u6253\u5f00\u5e76\u542f\u52a8\u9879\u76ee"),(0,i.kt)("p",null,"\u6253\u5f00\u6d4f\u89c8\u5668\u67e5\u770b\u6548\u679c\u5373\u53ef\u3002"))}m.isMDXComponent=!0},3905:function(e,t,n){n.d(t,{Zo:function(){return s},kt:function(){return m}});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),p=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},s=function(e){var t=p(e.components);return r.createElement(u.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=o,f=d["".concat(u,".").concat(m)]||d[m]||c[m]||i;return n?r.createElement(f,a(a({ref:t},s),{},{components:n})):r.createElement(f,a({ref:t},s))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var p=2;pSignalR",id:"243-\u5173\u4e8e-signalr",level:2},{value:"24.3.1 \u5fae\u8f6f\u5b98\u65b9\u4ecb\u7ecd",id:"2431-\u5fae\u8f6f\u5b98\u65b9\u4ecb\u7ecd",level:3},{value:"24.4 \u6ce8\u518c SignalR \u670d\u52a1",id:"244-\u6ce8\u518c-signalr-\u670d\u52a1",level:2},{value:"24.5 SignalR \u957f\u8fde\u63a5\u548c\u96c6\u7ebf\u5668",id:"245-signalr-\u957f\u8fde\u63a5\u548c\u96c6\u7ebf\u5668",level:2},{value:"25.5.1 \u6301\u4e45\u6027\u8fde\u63a5",id:"2551-\u6301\u4e45\u6027\u8fde\u63a5",level:3},{value:"24.5.2 \u96c6\u7ebf\u5668",id:"2452-\u96c6\u7ebf\u5668",level:3},{value:"24.6 \u96c6\u7ebf\u5668 Hub \u5b9a\u4e49",id:"246-\u96c6\u7ebf\u5668-hub-\u5b9a\u4e49",level:2},{value:"24.6.1 \u4e24\u79cd\u5b9a\u4e49\u65b9\u5f0f",id:"2461-\u4e24\u79cd\u5b9a\u4e49\u65b9\u5f0f",level:3},{value:"24.6.2 [MapHub] \u914d\u7f6e\u8fde\u63a5\u5730\u5740",id:"2462-maphub-\u914d\u7f6e\u8fde\u63a5\u5730\u5740",level:3},{value:"24.6.3 Hub \u6ce8\u518c\u66f4\u591a\u914d\u7f6e",id:"2463-hub-\u6ce8\u518c\u66f4\u591a\u914d\u7f6e",level:3},{value:"24.7 \u670d\u52a1\u7aef\u548c\u5ba2\u6237\u7aef\u53cc\u5de5\u901a\u4fe1",id:"247-\u670d\u52a1\u7aef\u548c\u5ba2\u6237\u7aef\u53cc\u5de5\u901a\u4fe1",level:2},{value:"24.7.1 \u89e6\u53d1\u6240\u6709\u5ba2\u6237\u7aef\u4ee3\u7801",id:"2471-\u89e6\u53d1\u6240\u6709\u5ba2\u6237\u7aef\u4ee3\u7801",level:3},{value:"24.7.2 \u89e6\u53d1\u8c03\u7528\u8005\u5ba2\u6237\u7aef",id:"2472-\u89e6\u53d1\u8c03\u7528\u8005\u5ba2\u6237\u7aef",level:3},{value:"24.7.3 \u89e6\u53d1\u9664\u4e86\u8c03\u7528\u8005\u4ee5\u5916\u7684\u5ba2\u6237\u7aef",id:"2473-\u89e6\u53d1\u9664\u4e86\u8c03\u7528\u8005\u4ee5\u5916\u7684\u5ba2\u6237\u7aef",level:3},{value:"24.7.4 \u89e6\u53d1\u7279\u5b9a\u7528\u6237\u5ba2\u6237\u7aef",id:"2474-\u89e6\u53d1\u7279\u5b9a\u7528\u6237\u5ba2\u6237\u7aef",level:3},{value:"24.7.5 \u89e6\u53d1\u591a\u4e2a\u7528\u6237\u5ba2\u6237\u7aef",id:"2475-\u89e6\u53d1\u591a\u4e2a\u7528\u6237\u5ba2\u6237\u7aef",level:3},{value:"24.7.6 \u89e6\u53d1\u5206\u7ec4\u5185\u5ba2\u6237\u7aef",id:"2476-\u89e6\u53d1\u5206\u7ec4\u5185\u5ba2\u6237\u7aef",level:3},{value:"24.7.7 \u89e6\u53d1\u591a\u4e2a\u5206\u7ec4\u5ba2\u6237\u7aef",id:"2477-\u89e6\u53d1\u591a\u4e2a\u5206\u7ec4\u5ba2\u6237\u7aef",level:3},{value:"24.7.8 \u89e6\u53d1\u5206\u7ec4\u5916\u7684\u5ba2\u6237\u7aef",id:"2478-\u89e6\u53d1\u5206\u7ec4\u5916\u7684\u5ba2\u6237\u7aef",level:3},{value:"24.8 \u81ea\u5b9a\u4e49\u7528\u6237\u552f\u4e00\u6807\u8bc6",id:"248-\u81ea\u5b9a\u4e49\u7528\u6237\u552f\u4e00\u6807\u8bc6",level:2},{value:"24.9 \u5206\u7ec4\u7ba1\u7406",id:"249-\u5206\u7ec4\u7ba1\u7406",level:2},{value:"24.10 \u5404\u4e2a\u5ba2\u6237\u7aef\u8fde\u63a5 API",id:"2410-\u5404\u4e2a\u5ba2\u6237\u7aef\u8fde\u63a5-api",level:2},{value:"24.10.1 Javascript \u5ba2\u6237\u7aef",id:"24101-javascript-\u5ba2\u6237\u7aef",level:3},{value:"24.10.2 Typescript \u5ba2\u6237\u7aef",id:"24102-typescript-\u5ba2\u6237\u7aef",level:3},{value:"\u5728 vue3.2+ \u4e2d\u4f7f\u7528",id:"\u5728-vue32-\u4e2d\u4f7f\u7528",level:4},{value:"24.10.3 .NET \u5ba2\u6237\u7aef",id:"24103-net-\u5ba2\u6237\u7aef",level:3},{value:"24.10.4 Java \u5ba2\u6237\u7aef",id:"24104-java-\u5ba2\u6237\u7aef",level:3},{value:"24.11 \u5e38\u89c1\u4f8b\u5b50",id:"2411-\u5e38\u89c1\u4f8b\u5b50",level:2},{value:"24.11.1 \u5b9e\u73b0\u6d88\u606f\u5e7f\u64ad\u3001\u63a8\u9001",id:"24111-\u5b9e\u73b0\u6d88\u606f\u5e7f\u64ad\u63a8\u9001",level:3},{value:"24.11.2 \u5b9e\u73b0\u804a\u5929\u529f\u80fd",id:"24112-\u5b9e\u73b0\u804a\u5929\u529f\u80fd",level:3},{value:"24.11.3 \u5b9e\u73b0 \u4f60\u753b\u6211\u6765\u731c",id:"24113-\u5b9e\u73b0-\u4f60\u753b\u6211\u6765\u731c",level:3},{value:"24.12 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"2412-\u53cd\u9988\u4e0e\u5efa\u8bae",level:2}],d={toc:c};function m(e){var n=e.components,t=(0,a.Z)(e,s);return(0,r.kt)("wrapper",(0,i.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"241-\u4ec0\u4e48\u662f\u5373\u65f6\u901a\u8baf"},"24.1 \u4ec0\u4e48\u662f\u5373\u65f6\u901a\u8baf"),(0,r.kt)("p",null,"\u5373\u65f6\u901a\u8baf\uff08Instant messaging\uff0c\u7b80\u79f0 IM\uff09\u901a\u5e38\u662f\u6307\u4e92\u8054\u7f51\u4e0a\u7528\u4ee5\u8fdb\u884c\u5b9e\u65f6\u901a\u8baf\u7684\u7cfb\u7edf\uff0c\u5141\u8bb8\u4e24\u4eba\u6216\u591a\u4eba\u4f7f\u7528\u7f51\u7edc\u5373\u65f6\u7684\u4f20\u9012\u6587\u5b57\u4fe1\u606f\u3001\u6587\u6863\u3001\u8bed\u97f3\u4e0e\u89c6\u9891\u4ea4\u6d41\u3002"),(0,r.kt)("p",null,"\u5373\u65f6\u901a\u8baf\u4e0d\u540c\u4e8e e-mail \u5728\u4e8e\u5b83\u7684\u4ea4\u8c08\u662f\u5b9e\u65f6\u7684\u3002\u5927\u90e8\u5206\u7684\u5373\u65f6\u901a\u8baf\u670d\u52a1\u63d0\u4f9b\u4e86\u72b6\u6001\u4fe1\u606f\u7684\u7279\u6027 \u2500\u2500 \u663e\u793a\u8054\u7edc\u4eba\u540d\u5355\uff0c\u8054\u7edc\u4eba\u662f\u5426\u5728\u7ebf\u4e0a\u4e0e\u80fd\u5426\u4e0e\u8054\u7edc\u4eba\u4ea4\u8c08\u3002"),(0,r.kt)("p",null,"\u5728\u4e92\u8054\u7f51\u4e0a\u76ee\u524d\u4f7f\u7528\u8f83\u5e7f\u7684\u5373\u65f6\u901a\u8baf\u670d\u52a1\u5305\u62ec Windows Live Messenger\u3001AOL Instant Messenger\u3001skype\u3001Yahoo! Messenger\u3001NET Messenger Service\u3001Jabber\u3001ICQ \u4e0e QQ \u7b49\u3002"),(0,r.kt)("h2",{id:"242-\u5373\u65f6\u901a\u8baf\u5e94\u7528\u573a\u666f"},"24.2 \u5373\u65f6\u901a\u8baf\u5e94\u7528\u573a\u666f"),(0,r.kt)("p",null,"\u5373\u65f6\u901a\u8baf\u5e94\u7528\u573a\u666f\u975e\u5e38\u5e7f\u6cdb\uff0c\u9700\u8981\u5b9e\u65f6\u4ea4\u4e92\u6d88\u606f\u7684\u90fd\u9700\u8981\u3002\u5982\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u804a\u5929\u5de5\u5177\uff1aQQ\u3001WeChat\u3001\u5728\u7ebf\u5ba2\u670d\u7b49"),(0,r.kt)("li",{parentName:"ul"},"\u624b\u6e38\u7f51\u6e38\uff1a\u738b\u8005\u8363\u8000\u3001\u9b54\u517d\u7b49"),(0,r.kt)("li",{parentName:"ul"},"\u7f51\u7edc\u76f4\u64ad\uff1a\u817e\u8baf\u8bfe\u5802\u3001\u6296\u97f3\u76f4\u64ad\u7b49"),(0,r.kt)("li",{parentName:"ul"},"\u8ba2\u5355\u63a8\u9001\uff1a\u7f8e\u56e2\u3001\u9910\u996e\u4e0b\u5355\u7cfb\u7edf\u7b49"),(0,r.kt)("li",{parentName:"ul"},"\u534f\u540c\u529e\u516c\uff1a\u516c\u53f8\u5185\u90e8\u6587\u4ef6\u5206\u4eab\u3001\u5de5\u4f5c\u5b89\u6392\u3001\u5728\u7ebf\u4f1a\u8bae\u7b49\u3002")),(0,r.kt)("p",null,"\u4ee5\u4e0a\u53ea\u662f\u5217\u4e3e\u4e86\u6bd4\u8f83\u5e38\u7528\u7684\u5e94\u7528\u573a\u666f\uff0c\u4f46\u5373\u65f6\u901a\u8baf\u7684\u4f5c\u7528\u8fdc\u4e0d\u6b62\u4e8e\u6b64\u3002"),(0,r.kt)("p",null,"\u6587\u6863\u7d27\u6025\u7f16\u5199\u4e2d\uff0c\u53ef\u4ee5\u5148\u770b\u5b98\u65b9\u6587\u6863\uff1a",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction?view=aspnetcore-5.0"},"https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction?view=aspnetcore-5.0")),(0,r.kt)("h2",{id:"243-\u5173\u4e8e-signalr"},"24.3 \u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"h2"},"SignalR")),(0,r.kt)("p",null,"\u5373\u65f6\u901a\u8baf\u6280\u672f\u5b9e\u73b0\u662f\u590d\u6742\u4e14\u8fc7\u4e8e\u5e95\u5c42\u5316\uff0c\u6240\u4ee5\u5fae\u8f6f\u4e3a\u4e86\u7b80\u5316\u5373\u65f6\u901a\u8baf\u5e94\u7528\u7a0b\u5e8f\uff0c\u5f00\u53d1\u51fa\u4e86\u4e00\u4e2a\u5f3a\u5927\u4e14\u7b80\u6613\u4f7f\u7528\u7684\u901a\u4fe1\u5e93\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"SignalR"),"\uff0c\u901a\u8fc7\u8be5\u5e93\u6211\u4eec\u53ef\u4ee5\u8f7b\u677e\u5b9e\u73b0\u7c7b\u4f3c QQ\u3001\u5fae\u4fe1\u8fd9\u7c7b IM \u804a\u5929\u5de5\u5177\uff0c\u4e5f\u80fd\u5feb\u901f\u5b9e\u73b0\u6d88\u606f\u63a8\u9001\u3001\u8ba2\u5355\u63a8\u9001\u8fd9\u6837\u7684\u7cfb\u7edf\u3002"),(0,r.kt)("h3",{id:"2431-\u5fae\u8f6f\u5b98\u65b9\u4ecb\u7ecd"},"24.3.1 \u5fae\u8f6f\u5b98\u65b9\u4ecb\u7ecd"),(0,r.kt)("p",null,"ASP.NET Core SignalR \u662f\u4e00\u79cd\u5f00\u653e\u6e90\u4ee3\u7801\u5e93\uff0c\u53ef\u7b80\u5316\u5c06\u5b9e\u65f6 web \u529f\u80fd\u6dfb\u52a0\u5230\u5e94\u7528\u7a0b\u5e8f\u7684\u529f\u80fd\u3002 \u5b9e\u65f6 web \u529f\u80fd\u4f7f\u670d\u52a1\u5668\u7aef\u4ee3\u7801\u53ef\u4ee5\u7acb\u5373\u5c06\u5185\u5bb9\u63a8\u9001\u5230\u5ba2\u6237\u7aef\u3002"),(0,r.kt)("p",null,"\u9002\u7528\u4e8e SignalR \uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u9700\u8981\u4ece\u670d\u52a1\u5668\u8fdb\u884c\u9ad8\u9891\u7387\u66f4\u65b0\u7684\u5e94\u7528\u3002 \u793a\u4f8b\u5305\u62ec\u6e38\u620f\u3001\u793e\u4ea4\u7f51\u7edc\u3001\u6295\u7968\u3001\u62cd\u5356\u3001\u5730\u56fe\u548c GPS \u5e94\u7528\u3002"),(0,r.kt)("li",{parentName:"ul"},"\u4eea\u8868\u677f\u548c\u76d1\u89c6\u5e94\u7528\u3002 \u793a\u4f8b\u5305\u62ec\u516c\u53f8\u4eea\u8868\u677f\u3001\u5373\u65f6\u9500\u552e\u66f4\u65b0\u6216\u65c5\u884c\u8b66\u62a5\u3002"),(0,r.kt)("li",{parentName:"ul"},"\u534f\u4f5c\u5e94\u7528\u3002 \u534f\u4f5c\u5e94\u7528\u7684\u793a\u4f8b\u5305\u62ec\u767d\u677f\u5e94\u7528\u548c\u56e2\u961f\u4f1a\u8bae\u8f6f\u4ef6\u3002"),(0,r.kt)("li",{parentName:"ul"},"\u9700\u8981\u901a\u77e5\u7684\u5e94\u7528\u3002 \u793e\u4ea4\u7f51\u7edc\u3001\u7535\u5b50\u90ae\u4ef6\u3001\u804a\u5929\u3001\u6e38\u620f\u3001\u65c5\u884c\u8b66\u62a5\u548c\u5f88\u591a\u5176\u4ed6\u5e94\u7528\u90fd\u9700\u4f7f\u7528\u901a\u77e5\u3002")),(0,r.kt)("p",null,"\u76ee\u524d ",(0,r.kt)("inlineCode",{parentName:"p"},"SignalR")," \u5df2\u7ecf\u5185\u7f6e\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},".NET 5 SDK")," \u4e2d\u3002\u540c\u65f6 ",(0,r.kt)("inlineCode",{parentName:"p"},"SignalR")," \u652f\u6301 ",(0,r.kt)("inlineCode",{parentName:"p"},"Web\u3001App\u3001Console\u3001Desktop")," \u7b49\u591a\u4e2a\u5e94\u7528\u5e73\u53f0\u3002"),(0,r.kt)("h2",{id:"244-\u6ce8\u518c-signalr-\u670d\u52a1"},"24.4 \u6ce8\u518c ",(0,r.kt)("inlineCode",{parentName:"h2"},"SignalR")," \u670d\u52a1"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u4e2d\uff0c\u4efb\u4f55\u670d\u52a1\u529f\u80fd\u90fd\u9700\u8981\u5148\u6ce8\u518c\u540e\u518d\u4f7f\u7528\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"SignalR")," \u4e5f\u4e0d\u4f8b\u5916\u3002\u53ea\u9700\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6dfb\u52a0\u6ce8\u518c\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,15,22,25}",showLineNumbers:!0,"":!0,"{1,15,22,25}":!0},'using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Furion.Web.Core\n{\n public sealed class Startup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n // \u5176\u4ed6\u4ee3\u7801...\n\n // \u6dfb\u52a0\u5373\u65f6\u901a\u8baf\n services.AddSignalR();\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n // \u5176\u4ed6\u4ee3\u7801...\n\n app.UseEndpoints(endpoints =>\n {\n // \u6ce8\u518c\u96c6\u7ebf\u5668\n endpoints.MapHubs();\n\n endpoints.MapControllerRoute(\n name: "default",\n pattern: "{controller=Home}/{action=Index}/{id?}");\n });\n }\n }\n}\n')),(0,r.kt)("h2",{id:"245-signalr-\u957f\u8fde\u63a5\u548c\u96c6\u7ebf\u5668"},"24.5 ",(0,r.kt)("inlineCode",{parentName:"h2"},"SignalR")," \u957f\u8fde\u63a5\u548c\u96c6\u7ebf\u5668"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"SignalR")," \u5305\u542b\u4e24\u79cd\u7528\u4e8e\u5728\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u5668\u4e4b\u95f4\u8fdb\u884c\u901a\u4fe1\u7684\u6a21\u578b\uff1a",(0,r.kt)("inlineCode",{parentName:"p"},"\u6301\u4e45\u6027\u8fde\u63a5"),"\u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"\u96c6\u7ebf\u5668")," \u4e2d\u5fc3\u3002"),(0,r.kt)("h3",{id:"2551-\u6301\u4e45\u6027\u8fde\u63a5"},"25.5.1 \u6301\u4e45\u6027\u8fde\u63a5"),(0,r.kt)("p",null,"\u8fde\u63a5\u8868\u793a\u7528\u4e8e\u53d1\u9001\u5355\u63a5\u6536\u65b9\u3001\u5206\u7ec4\u6216\u5e7f\u64ad\u6d88\u606f\u7684\u7b80\u5355\u7ec8\u7ed3\u70b9\u3002 ",(0,r.kt)("inlineCode",{parentName:"p"},"\u6301\u4e45\u6027\u8fde\u63a5")," (\u5728 .NET \u4ee3\u7801\u4e2d\u7531 PersistentConnection \u7c7b\u8868\u793a\uff0c\u5728 ASP.NET Core SignalR \u4e2d \uff0cPersistentConnection \u7c7b\u5df2\u88ab\u5220\u9664\u3002) \u4f7f\u5f00\u53d1\u4eba\u5458\u80fd\u591f\u76f4\u63a5\u8bbf\u95ee ",(0,r.kt)("inlineCode",{parentName:"p"},"SignalR")," \u516c\u5f00\u7684\u4f4e\u7ea7\u522b\u901a\u4fe1\u534f\u8bae\u3002 \u4f7f\u7528\u57fa\u4e8e\u8fde\u63a5\u7684 Api \uff08\u5982 Windows Communication Foundation\uff09\u7684\u5f00\u53d1\u4eba\u5458\u5c06\u5bf9\u4f7f\u7528\u8fde\u63a5\u901a\u4fe1\u6a21\u578b\u975e\u5e38\u719f\u6089\u3002"),(0,r.kt)("h3",{id:"2452-\u96c6\u7ebf\u5668"},"24.5.2 \u96c6\u7ebf\u5668"),(0,r.kt)("p",null,"\u96c6\u7ebf\u5668\u662f\u4e00\u79cd\u57fa\u4e8e\u8fde\u63a5 API \u6784\u5efa\u7684\u66f4\u9ad8\u7ea7\u522b\u7ba1\u9053\uff0c",(0,r.kt)("strong",{parentName:"p"},"\u5b83\u5141\u8bb8\u5ba2\u6237\u7aef\u548c\u670d\u52a1\u5668\u76f4\u63a5\u8c03\u7528\u65b9\u6cd5"),"\u3002 ",(0,r.kt)("inlineCode",{parentName:"p"},"SignalR")," \u5c31\u50cf\u9b54\u672f\u4e00\u6837\u5904\u7406\u8de8\u673a\u5668\u8fb9\u754c\u7684\u8c03\u5ea6\uff0c\u4f7f\u5ba2\u6237\u7aef\u80fd\u591f\u50cf\u672c\u5730\u65b9\u6cd5\u4e00\u6837\u8f7b\u677e\u5730\u8c03\u7528\u670d\u52a1\u5668\u4e0a\u7684\u65b9\u6cd5\uff0c\u53cd\u4e4b\u4ea6\u7136\u3002 \u5982\u679c\u5f00\u53d1\u4eba\u5458\u5df2\u4f7f\u7528\u8fdc\u7a0b\u8c03\u7528 \uff08\u5982 .NET \u8fdc\u7a0b\u5904\u7406\uff09\uff0c\u5219\u5c06\u5bf9\u4f7f\u7528\u4e2d\u5fc3\u901a\u4fe1\u6a21\u578b\u975e\u5e38\u719f\u6089\u3002 \u4f7f\u7528\u96c6\u7ebf\u5668\u8fd8\u53ef\u4ee5\u5c06\u5f3a\u7c7b\u578b\u53c2\u6570\u4f20\u9012\u7ed9\u65b9\u6cd5\uff0c\u4ece\u800c\u542f\u7528\u6a21\u578b\u7ed1\u5b9a\u3002"),(0,r.kt)("admonition",{title:"\u5c0f\u77e5\u8bc6",type:"note"},(0,r.kt)("p",{parentName:"admonition"},"\u60f3\u4e86\u89e3\u66f4\u591a\u5173\u4e8e ",(0,r.kt)("inlineCode",{parentName:"p"},"\u6301\u4e45\u6027\u8fde\u63a5")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"\u96c6\u7ebf\u5668\u4e2d\u5fc3")," \u53ef\u67e5\u9605 ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/signalr/overview/getting-started/introduction-to-signalr#connections-and-hubs"},"SignalR \u5b98\u65b9\u6587\u6863"))),(0,r.kt)("h2",{id:"246-\u96c6\u7ebf\u5668-hub-\u5b9a\u4e49"},"24.6 \u96c6\u7ebf\u5668 ",(0,r.kt)("inlineCode",{parentName:"h2"},"Hub")," \u5b9a\u4e49"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u5728\u672c\u7ae0\u8282\u4e2d\u4e3b\u8981\u63a8\u8350\u4f7f\u7528\u96c6\u7ebf\u5668\u901a\u4fe1\u6a21\u578b\u65b9\u5f0f\u3002"),"\u8fd9\u91cc\u4e3b\u8981\u8bf4\u660e ",(0,r.kt)("inlineCode",{parentName:"p"},"Hub")," \u5b9a\u4e49\uff0c\u5982\u679c\u65e0\u6cd5\u7406\u89e3\u8be5\u901a\u4fe1\u6a21\u578b\u7684\u4f5c\u7528\u4e5f\u6ca1\u5173\u7cfb\uff0c\u63a5\u4e0b\u6765\u7684\u4f8b\u5b50\u4f1a\u5e26\u5927\u5bb6\u6162\u6162\u719f\u6089\u5e76\u4f7f\u7528\u3002"),(0,r.kt)("h3",{id:"2461-\u4e24\u79cd\u5b9a\u4e49\u65b9\u5f0f"},"24.6.1 \u4e24\u79cd\u5b9a\u4e49\u65b9\u5f0f"),(0,r.kt)("p",null,"\u5b9a\u4e49\u96c6\u7ebf\u5668\u53ea\u9700\u8981\u7ee7\u627f ",(0,r.kt)("inlineCode",{parentName:"p"},"Hub")," \u6216 ",(0,r.kt)("inlineCode",{parentName:"p"},"Hub")," \u6cdb\u578b\u57fa\u7c7b\u5373\u53ef\uff0c\u5982\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Hub")," \u65b9\u5f0f")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {9}",showLineNumbers:!0,"":!0,"{9}":!0},'using Furion.InstantMessaging;\nusing Microsoft.AspNetCore.SignalR;\n\nnamespace Furion.Core\n{\n /// \n /// \u804a\u5929\u96c6\u7ebf\u5668\n /// \n public class ChatHub : Hub\n {\n // \u5b9a\u4e49\u4e00\u4e2a\u65b9\u6cd5\u4f9b\u5ba2\u6237\u7aef\u8c03\u7528\n public Task SendMessage(string user, string message)\n {\n // \u89e6\u53d1\u5ba2\u6237\u7aef\u5b9a\u4e49\u76d1\u542c\u7684\u65b9\u6cd5\n return Clients.All.SendAsync("ReceiveMessage", user, message);\n }\n }\n}\n')),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Hub")," \u7c7b\u578b\u65b9\u5f0f")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"public interface IChatClient\n{\n Task ReceiveMessage(string user, string message);\n}\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1}",showLineNumbers:!0,"":!0,"{1}":!0},"public class StronglyTypedChatHub : Hub\n{\n // \u5b9a\u4e49\u4e00\u4e2a\u65b9\u6cd5\u4f9b\u5ba2\u6237\u7aef\u8c03\u7528\n public async Task SendMessage(string user, string message)\n {\n // \u89e6\u53d1\u5ba2\u6237\u7aef\u5b9a\u4e49\u76d1\u542c\u7684\u65b9\u6cd5\n await Clients.All.ReceiveMessage(user, message);\n }\n}\n")),(0,r.kt)("p",null,"\u901a\u8fc7\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"Hub")," \u53ef\u4ee5\u5bf9\u5ba2\u6237\u7aef\u65b9\u6cd5\u8fdb\u884c\u7f16\u8bd1\u65f6\u68c0\u67e5\u3002 \u8fd9\u53ef\u4ee5\u9632\u6b62\u7531\u4e8e\u4f7f\u7528\u795e\u5947\u5b57\u7b26\u4e32\u800c\u5bfc\u81f4\u7684\u95ee\u9898\uff0c\u56e0\u4e3a ",(0,r.kt)("inlineCode",{parentName:"p"},"Hub")," \u53ea\u80fd\u63d0\u4f9b\u5bf9\u5728\u63a5\u53e3\u4e2d\u5b9a\u4e49\u7684\u65b9\u6cd5\u7684\u8bbf\u95ee\u3002"),(0,r.kt)("h3",{id:"2462-maphub-\u914d\u7f6e\u8fde\u63a5\u5730\u5740"},"24.6.2 ",(0,r.kt)("inlineCode",{parentName:"h3"},"[MapHub]")," \u914d\u7f6e\u8fde\u63a5\u5730\u5740"),(0,r.kt)("p",null,"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"SignalR")," \u5e93\u4e2d\u8981\u6c42\u6bcf\u4e00\u4e2a\u516c\u5f00\u7684\u96c6\u7ebf\u5668\u90fd\u9700\u8981\u914d\u7f6e\u5ba2\u6237\u7aef\u8fde\u63a5\u5730\u5740\uff0c\u6240\u4ee5\uff0c",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u6846\u67b6\u63d0\u4f9b\u4e86\u66f4\u52a0 ",(0,r.kt)("inlineCode",{parentName:"p"},"[MapHub]")," \u914d\u7f6e\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,11}",showLineNumbers:!0,"":!0,"{1,11}":!0},'using Furion.InstantMessaging;\nusing Microsoft.AspNetCore.SignalR;\nusing System;\nusing System.Threading.Tasks;\n\nnamespace Furion.Core\n{\n /// \n /// \u804a\u5929\u96c6\u7ebf\u5668\n /// \n [MapHub("/hubs/chathub")]\n public class ChatHub : Hub\n {\n // ...\n }\n}\n')),(0,r.kt)("admonition",{type:"important"},(0,r.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"mdxAdmonitionTitle"},"SignalR")," \u539f\u751f\u914d\u7f6e\u65b9\u5f0f"),(0,r.kt)("p",{parentName:"admonition"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Furion")," \u4e2d\u63a8\u8350\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"[MapHub]")," \u65b9\u5f0f\u914d\u7f6e\u96c6\u7ebf\u5668\u5ba2\u6237\u7aef\u8fde\u63a5\u5730\u5740\uff0c\u5f53\u7136\u4e5f\u53ef\u4ee5\u4f7f\u7528 ",(0,r.kt)("inlineCode",{parentName:"p"},"SignalR")," \u63d0\u4f9b\u7684\u65b9\u5f0f\uff0c\u5982\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u914d\u7f6e\uff1a"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {10}",showLineNumbers:!0,"":!0,"{10}":!0},'public sealed class Startup : AppStartup\n{\n // \u5176\u4ed6\u4ee3\u7801\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n // \u5176\u4ed6\u4ee3\u7801...\n app.UseEndpoints(endpoints =>\n {\n // \u6ce8\u518c\u96c6\u7ebf\u5668\n endpoints.MapHub("/hubs/chathub");\n });\n }\n}\n'))),(0,r.kt)("h3",{id:"2463-hub-\u6ce8\u518c\u66f4\u591a\u914d\u7f6e"},"24.6.3 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Hub")," \u6ce8\u518c\u66f4\u591a\u914d\u7f6e"),(0,r.kt)("p",null,"\u6709\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u9700\u8981\u6ce8\u518c ",(0,r.kt)("inlineCode",{parentName:"p"},"Hub")," \u65f6\u914d\u7f6e\u66f4\u591a\u53c2\u6570\uff0c\u6bd4\u5982\u6743\u9650\u3001\u8de8\u57df\u7b49\uff0c\u8fd9\u65f6\u53ea\u9700\u8981\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Hub")," \u6d3e\u751f\u7c7b\u4e2d\u7f16\u5199\u4ee5\u4e0b\u9759\u6001\u65b9\u6cd5\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,8,13,18}",showLineNumbers:!0,"":!0,"{1,8,13,18}":!0},'using Furion.InstantMessaging;\nusing Microsoft.AspNetCore.SignalR;\nusing System;\nusing System.Threading.Tasks;\n\nnamespace Furion.Core\n{\n [MapHub("/hubs/chathub")]\n public class ChatHub : Hub\n {\n // \u5176\u4ed6\u4ee3\u7801\n\n public static void HttpConnectionDispatcherOptionsSettings(HttpConnectionDispatcherOptions options)\n {\n // \u914d\u7f6e\n }\n\n public static void HubEndpointConventionBuilderSettings(HubEndpointConventionBuilder Builder)\n {\n // \u914d\u7f6e\n }\n }\n}\n')),(0,r.kt)("p",null,"\u4ee5\u4e0a\u914d\u7f6e\u7b49\u4ef7\u4e8e ",(0,r.kt)("inlineCode",{parentName:"p"},"SignalR")," \u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u7684\u914d\u7f6e\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'app.UseEndpoints(endpoints =>\n{\n var builder = endpoints.MapHub("/hubs/chathub", options =>\n {\n // \u914d\u7f6e\n });\n});\n')),(0,r.kt)("h2",{id:"247-\u670d\u52a1\u7aef\u548c\u5ba2\u6237\u7aef\u53cc\u5de5\u901a\u4fe1"},"24.7 \u670d\u52a1\u7aef\u548c\u5ba2\u6237\u7aef\u53cc\u5de5\u901a\u4fe1"),(0,r.kt)("h3",{id:"2471-\u89e6\u53d1\u6240\u6709\u5ba2\u6237\u7aef\u4ee3\u7801"},"24.7.1 \u89e6\u53d1\u6240\u6709\u5ba2\u6237\u7aef\u4ee3\u7801"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"Clients.All.\u5ba2\u6237\u7aef\u65b9\u6cd5(\u53c2\u6570);\n")),(0,r.kt)("h3",{id:"2472-\u89e6\u53d1\u8c03\u7528\u8005\u5ba2\u6237\u7aef"},"24.7.2 \u89e6\u53d1\u8c03\u7528\u8005\u5ba2\u6237\u7aef"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"Clients.Caller.\u5ba2\u6237\u7aef\u65b9\u6cd5(\u53c2\u6570);\n")),(0,r.kt)("h3",{id:"2473-\u89e6\u53d1\u9664\u4e86\u8c03\u7528\u8005\u4ee5\u5916\u7684\u5ba2\u6237\u7aef"},"24.7.3 \u89e6\u53d1\u9664\u4e86\u8c03\u7528\u8005\u4ee5\u5916\u7684\u5ba2\u6237\u7aef"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"Clients.Others.\u5ba2\u6237\u7aef\u65b9\u6cd5(\u53c2\u6570);\n")),(0,r.kt)("h3",{id:"2474-\u89e6\u53d1\u7279\u5b9a\u7528\u6237\u5ba2\u6237\u7aef"},"24.7.4 \u89e6\u53d1\u7279\u5b9a\u7528\u6237\u5ba2\u6237\u7aef"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'Clients.User("\u7528\u6237").\u5ba2\u6237\u7aef\u65b9\u6cd5(\u53c2\u6570);\n')),(0,r.kt)("h3",{id:"2475-\u89e6\u53d1\u591a\u4e2a\u7528\u6237\u5ba2\u6237\u7aef"},"24.7.5 \u89e6\u53d1\u591a\u4e2a\u7528\u6237\u5ba2\u6237\u7aef"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'Clients.Users("\u7528\u6237","\u7528\u62372",...).\u5ba2\u6237\u7aef\u65b9\u6cd5(\u53c2\u6570);\n')),(0,r.kt)("h3",{id:"2476-\u89e6\u53d1\u5206\u7ec4\u5185\u5ba2\u6237\u7aef"},"24.7.6 \u89e6\u53d1\u5206\u7ec4\u5185\u5ba2\u6237\u7aef"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'Clients.Group("\u5206\u7ec4").\u5ba2\u6237\u7aef\u65b9\u6cd5(\u53c2\u6570);\n')),(0,r.kt)("h3",{id:"2477-\u89e6\u53d1\u591a\u4e2a\u5206\u7ec4\u5ba2\u6237\u7aef"},"24.7.7 \u89e6\u53d1\u591a\u4e2a\u5206\u7ec4\u5ba2\u6237\u7aef"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'Clients.Groups("\u5206\u7ec4","\u5206\u7ec42",...).\u5ba2\u6237\u7aef\u65b9\u6cd5(\u53c2\u6570);\n')),(0,r.kt)("h3",{id:"2478-\u89e6\u53d1\u5206\u7ec4\u5916\u7684\u5ba2\u6237\u7aef"},"24.7.8 \u89e6\u53d1\u5206\u7ec4\u5916\u7684\u5ba2\u6237\u7aef"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},'Clients.GroupExcept("\u5206\u7ec4").\u5ba2\u6237\u7aef\u65b9\u6cd5(\u53c2\u6570);\n')),(0,r.kt)("h2",{id:"248-\u81ea\u5b9a\u4e49\u7528\u6237\u552f\u4e00\u6807\u8bc6"},"24.8 \u81ea\u5b9a\u4e49\u7528\u6237\u552f\u4e00\u6807\u8bc6"),(0,r.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b ",(0,r.kt)("inlineCode",{parentName:"p"},"SignalR")," \u4f1a\u4e3a\u6bcf\u4e00\u4e2a\u94fe\u63a5\u521b\u5efa ",(0,r.kt)("inlineCode",{parentName:"p"},"ConnectionId"),"\uff0c\u4f46\u662f\u8fd9\u4e2a ",(0,r.kt)("inlineCode",{parentName:"p"},"ConnectionId")," \u5e76\u6ca1\u6709\u548c\u6211\u4eec\u7cfb\u7edf\u7684\u7528\u6237\u7ed1\u5173\u8054\u8d77\u6765\uff0c\u6240\u4ee5\u9700\u8981\u91c7\u7528\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"p"},"ConnectionId"),"\uff0c\u5982\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers {1,3}",showLineNumbers:!0,"{1,3}":!0},"public class YourUserIdProvider : IUserIdProvider\n{\n public virtual string GetUserId(HubConnectionContext connection)\n {\n // \u4f60\u5982\u4f55\u83b7\u53d6 UserId\uff0c\u53ef\u4ee5\u901a\u8fc7 connection.User \u83b7\u53d6 JWT \u6388\u6743\u7684\u7528\u6237\n }\n}\n")),(0,r.kt)("p",null,"\u7136\u540e\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"Startup.cs")," \u4e2d\u6ce8\u518c\u5373\u53ef\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"builder.Services.AddSingleton();\n")),(0,r.kt)("p",null,"\u4e4b\u540e\u5c31\u53ef\u4ee5\u901a\u8fc7\u81ea\u5b9a\u4e49 ",(0,r.kt)("inlineCode",{parentName:"p"},"UserId")," \u53d1\u9001\u6d88\u606f\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cs",metastring:"showLineNumbers",showLineNumbers:!0},"Clients.User(userId).\u5ba2\u6237\u7aef\u65b9\u6cd5(\u53c2\u6570);\n")),(0,r.kt)("p",null,"\u67e5\u770b\u66f4\u591a\u6587\u6863 ",(0,r.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/zh-cn/aspnet/core/signalr/authn-and-authz?view=aspnetcore-6.0#use-claims-to-customize-identity-handling"},"https://docs.microsoft.com/zh-cn/aspnet/core/signalr/authn-and-authz?view=aspnetcore-6.0#use-claims-to-customize-identity-handling")),(0,r.kt)("h2",{id:"249-\u5206\u7ec4\u7ba1\u7406"},"24.9 \u5206\u7ec4\u7ba1\u7406"),(0,r.kt)("h2",{id:"2410-\u5404\u4e2a\u5ba2\u6237\u7aef\u8fde\u63a5-api"},"24.10 \u5404\u4e2a\u5ba2\u6237\u7aef\u8fde\u63a5 API"),(0,r.kt)("h3",{id:"24101-javascript-\u5ba2\u6237\u7aef"},"24.10.1 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Javascript")," \u5ba2\u6237\u7aef"),(0,r.kt)("h3",{id:"24102-typescript-\u5ba2\u6237\u7aef"},"24.10.2 ",(0,r.kt)("inlineCode",{parentName:"h3"},"Typescript")," \u5ba2\u6237\u7aef"),(0,r.kt)("h4",{id:"\u5728-vue32-\u4e2d\u4f7f\u7528"},"\u5728 ",(0,r.kt)("inlineCode",{parentName:"h4"},"vue3.2+")," \u4e2d\u4f7f\u7528"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"\u5b89\u88c5\u5fae\u8f6f\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"signalr typescript")," \u5ba2\u6237\u7aef\u5305\uff0c\u4e3b\u8981\u7528\u4e8e\u8c03\u7528\u670d\u52a1\u7aef\u65b9\u6cd5\uff0c\u5982\uff08 ",(0,r.kt)("inlineCode",{parentName:"li"},"Hub")," \u4e2d\u7684 ",(0,r.kt)("inlineCode",{parentName:"li"},"SendMessage")," \u65b9\u6cd5\uff09\uff1a")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash",metastring:"showLineNumbers",showLineNumbers:!0},"npm i @microsoft/signalr @types/node\n")),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},"\u793a\u4f8b\u4ee3\u7801")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript",metastring:"showLineNumbers",showLineNumbers:!0},'import { HubConnectionBuilder } from "@microsoft/signalr";\n\nArchive | Furion - - + + + - - +
演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/console/index.html b/handbook/build/blog/console/index.html index 36ef21a351..4c9c70d99f 100644 --- a/handbook/build/blog/console/index.html +++ b/handbook/build/blog/console/index.html @@ -2,22 +2,21 @@ - - - + +5. 在控制台中使用 | Furion -5. 在控制台中使用 | Furion - - + + +
-

5. 在控制台中使用

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

演练场
- - +

5. 在控制台中使用

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/fileupload-download/index.html b/handbook/build/blog/fileupload-download/index.html index 583dfa2215..c2788a4dae 100644 --- a/handbook/build/blog/fileupload-download/index.html +++ b/handbook/build/blog/fileupload-download/index.html @@ -2,22 +2,21 @@ - - - + +2. 文件上传下载 | Furion -2. 文件上传下载 | Furion - - + + +
-

2. 文件上传下载

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

文件上传

[HttpPost, NonUnify]public async Task<IActionResult> UploadFileAsync(List<IFormFile> files){    // 保存到网站根目录下的 uploads 目录    var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");    if(!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);    long size = files.Sum(f => f.Length);    foreach (var formFile in files)    {        if (formFile.Length > 0)        {            // 避免文件名重复,采用 GUID 生成            var filePath = Path.Combine(savePath, Guid.NewGuid().ToString("N") + Path.GetExtension(formFile.FileName));  // 可以替代为你需要存储的真实路径            using (var stream = System.IO.File.Create(filePath))            {                await formFile.CopyToAsync(stream);            }        }    }    // 在动态 API 直接返回对象即可,无需 OK 和 IActionResult    return Ok(new { count = files.Count, size });}
关于使用axios上传文件,方法获取到参数files.Count=0

axios请求配置

    let formData = new FormData();    formData.append("files", this.file); //files需与方法里的参数files名称一样    let config = {      headers: {        "Content-Type": "multipart/form-data",      },    };    axios.post(this.uploadURL, formData, config).then((res) => {//需引入axios      console.log(res);    });
演练场
- - +

2. 文件上传下载

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

文件上传

[HttpPost, NonUnify]public async Task<IActionResult> UploadFileAsync(List<IFormFile> files){    // 保存到网站根目录下的 uploads 目录    var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");    if(!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);    long size = files.Sum(f => f.Length);    foreach (var formFile in files)    {        if (formFile.Length > 0)        {            // 避免文件名重复,采用 GUID 生成            var filePath = Path.Combine(savePath, Guid.NewGuid().ToString("N") + Path.GetExtension(formFile.FileName));  // 可以替代为你需要存储的真实路径            using (var stream = System.IO.File.Create(filePath))            {                await formFile.CopyToAsync(stream);            }        }    }    // 在动态 API 直接返回对象即可,无需 OK 和 IActionResult    return Ok(new { count = files.Count, size });}
关于使用axios上传文件,方法获取到参数files.Count=0

axios请求配置

    let formData = new FormData();    formData.append("files", this.file); //files需与方法里的参数files名称一样    let config = {      headers: {        "Content-Type": "multipart/form-data",      },    };    axios.post(this.uploadURL, formData, config).then((res) => {//需引入axios      console.log(res);    });
演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/global-usings/index.html b/handbook/build/blog/global-usings/index.html index a3cc0a00f3..45c07b2deb 100644 --- a/handbook/build/blog/global-usings/index.html +++ b/handbook/build/blog/global-usings/index.html @@ -2,22 +2,21 @@ - - - + +7. GlobalUsings 的使用 | Furion -7. GlobalUsings 的使用 | Furion - - + + +
-

7. GlobalUsings 的使用

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

演练场
- - +

7. GlobalUsings 的使用

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/httpcontext/index.html b/handbook/build/blog/httpcontext/index.html index c4cd458c14..927cf6e4b0 100644 --- a/handbook/build/blog/httpcontext/index.html +++ b/handbook/build/blog/httpcontext/index.html @@ -2,22 +2,21 @@ - - - + +1. HttpContext 应用 | Furion -1. HttpContext 应用 | Furion - - + + +
-

1. HttpContext 应用

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

ControllerBase 派生类中

ControllerBase 派生类中,我们可以直接通过 HttpContext 属性获取 HttpContext 对象。

通过注入 IHttpContextAccessor

Furion 框架中,默认已经注册了 IHttpContextAccessor 服务,所以我们可以通过构造函数注入该对象获取。

public class AppService{    public AppService(IHttpContextAccessor httpContextAccessor)    {        var httpContext = httpContextAccessor.HttpContext;    }}

通过 App.HttpContext

App 静态类也提供了 App.HttpContext 获取 HttpContext 对象。

HttpContext 拓展方法

Furion 框架也提供了一些常用的 HttpContext 拓展方法

获取当前请求的特性

var attribute = httpContext.GetMetadata<SomeAttribute>();

设置 Swagger 自动授权

httpContext.SigninToSwagger("你的token");

退出 Swagger 授权

httpContext.SignoutToSwagger();

获取本地 IP 地址

var ipv4 = httpContext.GetLocalIpAddressToIPv4();var ipv6 = httpContext.GetLocalIpAddressToIPv6();

获取客户端 IP 地址

var ipv4 = httpContext.GetRemoteIpAddressToIPv4();var ipv6 = httpContext.GetRemoteIpAddressToIPv6();
演练场
- - +

1. HttpContext 应用

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

ControllerBase 派生类中

ControllerBase 派生类中,我们可以直接通过 HttpContext 属性获取 HttpContext 对象。

通过注入 IHttpContextAccessor

Furion 框架中,默认已经注册了 IHttpContextAccessor 服务,所以我们可以通过构造函数注入该对象获取。

public class AppService{    public AppService(IHttpContextAccessor httpContextAccessor)    {        var httpContext = httpContextAccessor.HttpContext;    }}

通过 App.HttpContext

App 静态类也提供了 App.HttpContext 获取 HttpContext 对象。

HttpContext 拓展方法

Furion 框架也提供了一些常用的 HttpContext 拓展方法

获取当前请求的特性

var attribute = httpContext.GetMetadata<SomeAttribute>();

设置 Swagger 自动授权

httpContext.SigninToSwagger("你的token");

退出 Swagger 授权

httpContext.SignoutToSwagger();

获取本地 IP 地址

var ipv4 = httpContext.GetLocalIpAddressToIPv4();var ipv6 = httpContext.GetLocalIpAddressToIPv6();

获取客户端 IP 地址

var ipv4 = httpContext.GetRemoteIpAddressToIPv4();var ipv6 = httpContext.GetRemoteIpAddressToIPv6();
演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/index.html b/handbook/build/blog/index.html index e21db6abcc..d76f334a00 100644 --- a/handbook/build/blog/index.html +++ b/handbook/build/blog/index.html @@ -2,22 +2,21 @@ - - - + +Blog | Furion -Blog | Furion - - + + +
-

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

演练场
- - +

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/net6-preview5/index.html b/handbook/build/blog/net6-preview5/index.html index bd884e5626..223f1e0c95 100644 --- a/handbook/build/blog/net6-preview5/index.html +++ b/handbook/build/blog/net6-preview5/index.html @@ -2,22 +2,21 @@ - - - + +3. .NET 6 Preview 5 尝鲜 | Furion -3. .NET 6 Preview 5 尝鲜 | Furion - - + + +
-

3. .NET 6 Preview 5 尝鲜

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

演练场
- - +

3. .NET 6 Preview 5 尝鲜

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/net6-preview6/index.html b/handbook/build/blog/net6-preview6/index.html index a0e2242842..0de95401ed 100644 --- a/handbook/build/blog/net6-preview6/index.html +++ b/handbook/build/blog/net6-preview6/index.html @@ -2,22 +2,21 @@ - - - + +4. .NET 6 Preview 6 尝鲜 | Furion -4. .NET 6 Preview 6 尝鲜 | Furion - - + + +
-

4. .NET 6 Preview 6 尝鲜

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

演练场
- - +

4. .NET 6 Preview 6 尝鲜

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/net6-preview7/index.html b/handbook/build/blog/net6-preview7/index.html index c0974f8cb8..06aefc64b3 100644 --- a/handbook/build/blog/net6-preview7/index.html +++ b/handbook/build/blog/net6-preview7/index.html @@ -2,22 +2,21 @@ - - - + +6. .NET 6 Preview 7 尝鲜 | Furion -6. .NET 6 Preview 7 尝鲜 | Furion - - + + +
-

6. .NET 6 Preview 7 尝鲜

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

演练场
- - +

6. .NET 6 Preview 7 尝鲜

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/tags/download/index.html b/handbook/build/blog/tags/download/index.html index 7d507c85cf..3bd7081629 100644 --- a/handbook/build/blog/tags/download/index.html +++ b/handbook/build/blog/tags/download/index.html @@ -2,22 +2,21 @@ - - - + +One post tagged with "download" | Furion -One post tagged with "download" | Furion - - + + +
-

One post tagged with "download"

View All Tags

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
演练场
- - +

One post tagged with "download"

View All Tags

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/tags/furion/index.html b/handbook/build/blog/tags/furion/index.html index 5a744ba3de..a862637fe3 100644 --- a/handbook/build/blog/tags/furion/index.html +++ b/handbook/build/blog/tags/furion/index.html @@ -2,22 +2,21 @@ - - - + +7 posts tagged with "furion" | Furion -7 posts tagged with "furion" | Furion - - + + +
-

7 posts tagged with "furion"

View All Tags

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

演练场
- - +

7 posts tagged with "furion"

View All Tags

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/tags/furos/index.html b/handbook/build/blog/tags/furos/index.html index b67b219add..f0b2c83d9a 100644 --- a/handbook/build/blog/tags/furos/index.html +++ b/handbook/build/blog/tags/furos/index.html @@ -2,22 +2,21 @@ - - - + +7 posts tagged with "furos" | Furion -7 posts tagged with "furos" | Furion - - + + +
-

7 posts tagged with "furos"

View All Tags

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

演练场
- - +

7 posts tagged with "furos"

View All Tags

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/tags/httpcontext/index.html b/handbook/build/blog/tags/httpcontext/index.html index 82e4450e2d..6c350c2289 100644 --- a/handbook/build/blog/tags/httpcontext/index.html +++ b/handbook/build/blog/tags/httpcontext/index.html @@ -2,22 +2,21 @@ - - - + +One post tagged with "httpcontext" | Furion -One post tagged with "httpcontext" | Furion - - + + +
-

One post tagged with "httpcontext"

View All Tags

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

演练场
- - +

One post tagged with "httpcontext"

View All Tags

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/tags/index.html b/handbook/build/blog/tags/index.html index b58ba04964..ca8f0cb5b1 100644 --- a/handbook/build/blog/tags/index.html +++ b/handbook/build/blog/tags/index.html @@ -2,22 +2,21 @@ - - - + +Tags | Furion -Tags | Furion - - + + + - - +
演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/tags/net-5/index.html b/handbook/build/blog/tags/net-5/index.html index 8b5928fb2a..984e17265c 100644 --- a/handbook/build/blog/tags/net-5/index.html +++ b/handbook/build/blog/tags/net-5/index.html @@ -2,22 +2,21 @@ - - - + +7 posts tagged with ".net5" | Furion -7 posts tagged with ".net5" | Furion - - + + +
-

7 posts tagged with ".net5"

View All Tags

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

演练场
- - +

7 posts tagged with ".net5"

View All Tags

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/tags/net-6/index.html b/handbook/build/blog/tags/net-6/index.html index 4886ae4b54..30de425f4c 100644 --- a/handbook/build/blog/tags/net-6/index.html +++ b/handbook/build/blog/tags/net-6/index.html @@ -2,22 +2,21 @@ - - - + +5 posts tagged with ".net6" | Furion -5 posts tagged with ".net6" | Furion - - + + +
-

5 posts tagged with ".net6"

View All Tags

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

演练场
- - +

5 posts tagged with ".net6"

View All Tags

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/tags/net/index.html b/handbook/build/blog/tags/net/index.html index 508c5b3129..9330aebce7 100644 --- a/handbook/build/blog/tags/net/index.html +++ b/handbook/build/blog/tags/net/index.html @@ -2,22 +2,21 @@ - - - + +7 posts tagged with ".net" | Furion -7 posts tagged with ".net" | Furion - - + + +
-

7 posts tagged with ".net"

View All Tags

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

演练场
- - +

7 posts tagged with ".net"

View All Tags

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/tags/netcore/index.html b/handbook/build/blog/tags/netcore/index.html index c070f5c252..dc4692e0fb 100644 --- a/handbook/build/blog/tags/netcore/index.html +++ b/handbook/build/blog/tags/netcore/index.html @@ -2,22 +2,21 @@ - - - + +7 posts tagged with ".netcore" | Furion -7 posts tagged with ".netcore" | Furion - - + + +
-

7 posts tagged with ".netcore"

View All Tags

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

演练场
- - +

7 posts tagged with ".netcore"

View All Tags

· 3 min read
dotNET China

简介

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

· 2 min read
dotNET China

2021 年 08 月 11 日,微软发布了 .NET 6 Preview 7 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.2 版本。

Furion .NET 6 Preview 7 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 7 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 7 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 4.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.2 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.2

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.2

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· One min read
dotNET China

Furionv2.15.3+ 版本开始,支持全平台应用程序开发,包括 Web控制台WinFormWPFXamarin/MAUI 等。

在控制台中使用示例:

using Furion;using Furion.DependencyInjection;using Furion.RemoteRequest.Extensions;using Microsoft.Extensions.DependencyInjection;using System;namespace ConsoleApp1{    class Program    {        static void Main(string[] args)        {            // 创建一个服务容器            var services = Inject.Create();            // 注册服务            services.AddRemoteRequest();            // 所有服务注册完毕后调用 Build() 构建            services.Build();            // 使用            var helloService = App.GetService<IHelloService>();            Console.WriteLine(helloService.SayHello());            Console.WriteLine("=============");            var baidu = "https://www.baidu.com".GetAsStringAsync().GetAwaiter().GetResult();            Console.WriteLine(baidu);        }    }    public interface IHelloService    {        string SayHello();    }    public class HelloService : IHelloService, ITransient    {        public string SayHello()        {            return "Hello Furion.";        }    }}

以上代码通过 var services = Inject.Create(); 创建一个服务集合,最后通过 services.Build() 即可完成初始化。

· 2 min read
dotNET China

2021 年 07 月 15 日,微软发布了 .NET 6 Preview 6 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-rc.1 版本。

Furion .NET 6 Preview 6 源码地址

安装 .NET 6 Preview 6 SDK

尝鲜之前,首先先安装 .NET 6 Preview 6 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

旧项目升级

编辑所有 .csproj 项目,修改 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>

同时升级所有 MicrosoftFurion 包为最新版本,Furion 最新版本为:v3.0.0-rc.1

新项目使用

升级 Visual Studio 2019

目前 .NET 6 Preview 6 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 3.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-rc.1 目前提供了所有类型的脚手架,版本号统一 3.0.0-rc.1

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-rc.1

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

2021 年 06 月 18 日,微软发布了 .NET 6 Preview 5 版本,Furion 在当天第一时间适配了该版本,并发布 Furion v3.0.0-preview.5.21301.9 版本。

Furion .NET 6 Preview 5 源码地址

等不及尝鲜了

安装 .NET 6 Preview 5 SDK

尝鲜之前,首先先安装 .NET 6 Preview 5 SDK,下载地址:https://dotnet.microsoft.com/download/dotnet/6.0

下载对应系统和处理器版本即可。

升级 Visual Studio 2019

目前 .NET 6 Preview 5 支持使用 Visual Studio 2019 Preview 16.11.0 Preview 2.0 版本,注意是 Preview 最新版本。下载地址:https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=enterprise&ch=pre&rel=16

已经安装了 Visual Studio 2019 Preview 版本的朋友直接升级到最新版即可。

特别说明

如果使用 Visual Studio Code 开发,可忽略此选项。

第一个例子

Furion v3.0.0-preview.5.21301.9 目前提供了所有类型的脚手架,版本号统一 3.0.0-preview.5.21301.9

安装脚手架,打开 CMD/Powershell 执行以下命令:

dotnet new --install Furion.Template.Api::3.0.0-preview.5.21301.9

创建项目

dotnet new furionapi -n FurionNET6

打开并启动项目

打开浏览器查看效果即可。

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

· 2 min read
dotNET China

HttpContext 重大调整

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

HttpContext 多种获取方式

演练场
+ + \ No newline at end of file diff --git a/handbook/build/blog/tags/upload/index.html b/handbook/build/blog/tags/upload/index.html index 9aa602e7da..585a22d5f7 100644 --- a/handbook/build/blog/tags/upload/index.html +++ b/handbook/build/blog/tags/upload/index.html @@ -2,22 +2,21 @@ - - - + +One post tagged with "upload" | Furion -One post tagged with "upload" | Furion - - + + +
-

One post tagged with "upload"

View All Tags

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
演练场
- - +

One post tagged with "upload"

View All Tags

· 2 min read
dotNET China

文件下载

[HttpGet, NonUnify]public IActionResult FileDownload(string path, string fileName){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/appstartup/index.html b/handbook/build/docs/appstartup/index.html index b61b796cab..5a02c67a92 100644 --- a/handbook/build/docs/appstartup/index.html +++ b/handbook/build/docs/appstartup/index.html @@ -2,22 +2,21 @@ - - - + +3.1 AppStartup 启动 | Furion -3.1 AppStartup 启动 | Furion - - + + +
-

3.1 AppStartup 启动

3.1.1 Startup

Startup 类是 ASP.NET Core 应用程序启动默认调用的类,该类是在 Program.cs 中配置:

.NET5 方式

Furion.Web.Entry\Program.cs
using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.Hosting;namespace Furion.Web.Entry{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args)        {            return Host.CreateDefaultBuilder(args)                .ConfigureWebHostDefaults(webBuilder =>                {                    webBuilder.UseStartup<Startup>();                });        }    }}

.NET6 方式

.NET6 中微软已不再推荐 UseStartup<TStarup>() 方式。

3.1.1.1 Startup 两个重要方法

Startup 默认有两个重要的方法:

  • ConfigureServices:配置应用所需服务,在该方法中可以添加应用所需要的功能或服务
  • Configure:配置应用请求处理管道

默认代码如下:

Furion.Web.Entry\Startup.cs
using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Entry{    public class Startup    {        public void ConfigureServices(IServiceCollection services)        {        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {        }    }}

在这里,不打算详细讲 Startup 类的具体功能和作用。

了解更多

想了解更多 Startup 知识可查阅 ASP.NET Core - Startup 类 章节。

3.1.2 AppStartup

Furion 框架中,提供了更为灵活的 Startup 类配置方式,无需在 Web 启用层 中配置,可将配置放到任何项目层。

可能会有读者有疑问,为什么要多此一举呢?原因有几点:

  • Startup 类默认和 Web 应用层 绑定在一起,这样就会导致如果我创建了新的 Web 应用层Startup 又要重新配置
  • 随着业务的增长,需要集成越来越多的第三方服务,这时候 Startup 类就会变得越来越臃肿,难以维护
  • Startup 类无法与其他项目类型进行共用

所以,Furion 提供了更加灵活的配置方式:AppStartup

注意事项

如果 AppStartup 的派生类所在的项目层没有被启动层直接或间接添加引用,那么这个 Startup.cs 就会被忽略,也就是不会自动载入注册。

3.1.2.1 如何配置 AppStartup

AppStartup 是一个抽象的空类,没有任何定义成员。正是因为这样,才提供更加灵活的配置方式。

3.1.2.2 AppStartup 约定

AppStartup 派生类只有两个小约定:

  • 任何公开、非静态、返回值为 void 且方法第一个参数是 IServiceCollection 类型,那么他就是一个 ConfigureServices 方法
  • 任何公开、非静态、返回值为 void 且方法第一个参数是 IApplicationBuilder 类型,第二个参数是 IWebHostEnvironment 类型,那么他就是一个 Configure 方法

所以,我们可以自由的编写方法,只要遵循约定即可,如:

using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    public class MyStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddDataValidation();        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            app.UseSwagger();        }        // 可以随意定义名字和方法        public void XXXXName(IServiceCollection services)        {        }        // 可以随意定义名字和方法        public void ZZZName(IApplicationBuilder app, IWebHostEnvironment env)        {        }    }}

3.1.2.3 AppStartup 配置顺序

默认情况下,AppStartup 配置顺序由所在程序集的名称进行正序调用,如果我们需要配置执行顺序,只需要在 AppStartup 派生类中贴 [AppStartup(order)] 特性即可。

order 数值越大,越在前面调用,如:

using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(10)]    public class FirstStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {        }    }}
using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(9)]    public class SecondStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {        }    }}

FirstStartup 会在 SecondStartup 之前调用。

3.1.2.4 AppStartup 方法调用顺序

AppStartup 方法调用顺序和方法的书写先后有关,越在前面的方法越先调用。

3.1.3 Startup 配置最佳实践

v3.6.3+ 说明

Furion v3.6.3+ 版本之后无需创建空 Startup.cs 类,内部已实现 FakeStartup 模式。

建议 Web 启动层的 Startup.cs 保持为空方法体,如:

Furion.Web.Entry\Startup.cs
using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Entry{    public class Startup    {        public void ConfigureServices(IServiceCollection services)        {        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {        }    }}

将所有 Web 应用层 配置迁移到 Furion.Web.Core.Startup.cs 中,如:

Furion.Web.Core\Startup.cs
using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace Furion.Web.Core{    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddCorsAccessor();            services.AddControllers().AddInject();        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            if (env.IsDevelopment())            {                app.UseDeveloperExceptionPage();            }            app.UseHttpsRedirection();            app.UseRouting();            app.UseCorsAccessor();            app.UseAuthentication();            app.UseAuthorization();            app.UseInject();            app.UseEndpoints(endpoints =>            {                endpoints.MapControllers();            });        }    }}

这样,后续更换 Web 应用层 也无需重新配置 Startup.cs

3.1.4 构造函数注入说明

AppStartup 的派生类并未提供依赖注入的功能,也即是无法通过构造函数进行注入服务。原因是 AppStartup 是个空类,目的是用来查找 Startup 的。

那如何像 Startup.cs 一样使用服务呢?

  • 获取配置 IConfiguration 实例:通过 App.Configuration
  • 解析服务:通过 App.GetService<TService>()app.ApplicationServices.GetService<TService>()
关于 Configure 方法注入

AppStartup 针对 Configure 方法提供了参数解析注入功能,也就是只要在方法中声明接口参数即可自动注入,如:

// app 和 env 会自动注入public void Configure(IApplicationBuilder app, IWebHostEnvironment env){}

3.1.5 关于 appsettings.json

在默认情况下,ASP.NET Core 配置放在 appsettings.json 中配置,但是这样的方式和 Startup.cs 配置一样的道理,一旦我们更换了 Web 应用层,那么 appsettings.json 又要重新配置一次。

所以,Furion 框架提供了更加灵活的方式配置 appsettings.json只需要在任何项目层根目录下创建 .json 文件即可。Furion 框架最后会自动合并所有分散的配置文件。

如我们在 Furion.EntityFramework.Core 层创建 dbsettings.json 配置数据库连接字符串,如:

Furion.EntityFramework.Core\dbsettings.json
{  "ConnectionStrings": {    "DbConnectionString": "Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;",    "Sqlite3ConnectionString": "Data Source=./Furion.db"  }}

无需在 appsettings.json 中配置,下面是 appsettings.json 默认代码:

{  "Logging": {    "LogLevel": {      "Default": "Information",      "Microsoft": "Warning",      "Microsoft.Hosting.Lifetime": "Information",      "Microsoft.EntityFrameworkCore": "Information"    }  },  "AllowedHosts": "*"}

这样我们把配置文件分散在不同项目层之后,就可以实现共用和共享了。

特别注意

其他层的配置文件不能以 appsettings.json 命名,会导致覆盖启动层的配置。

另外,在其他层创建的 *.json 文件必须设置文件属性为 始终复制或较新复制

3.1.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

3.1 AppStartup 启动

3.1.1 Startup

Startup 类是 ASP.NET Core 应用程序启动默认调用的类,该类是在 Program.cs 中配置:

.NET5 方式

Furion.Web.Entry\Program.cs
using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.Hosting;namespace Furion.Web.Entry{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args)        {            return Host.CreateDefaultBuilder(args)                .ConfigureWebHostDefaults(webBuilder =>                {                    webBuilder.UseStartup<Startup>();                });        }    }}

.NET6 方式

.NET6 中微软已不再推荐 UseStartup<TStarup>() 方式。

3.1.1.1 Startup 两个重要方法

Startup 默认有两个重要的方法:

  • ConfigureServices:配置应用所需服务,在该方法中可以添加应用所需要的功能或服务
  • Configure:配置应用请求处理管道

默认代码如下:

Furion.Web.Entry\Startup.cs
using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Entry{    public class Startup    {        public void ConfigureServices(IServiceCollection services)        {        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {        }    }}

在这里,不打算详细讲 Startup 类的具体功能和作用。

了解更多

想了解更多 Startup 知识可查阅 ASP.NET Core - Startup 类 章节。

3.1.2 AppStartup

Furion 框架中,提供了更为灵活的 Startup 类配置方式,无需在 Web 启用层 中配置,可将配置放到任何项目层。

可能会有读者有疑问,为什么要多此一举呢?原因有几点:

  • Startup 类默认和 Web 应用层 绑定在一起,这样就会导致如果我创建了新的 Web 应用层Startup 又要重新配置
  • 随着业务的增长,需要集成越来越多的第三方服务,这时候 Startup 类就会变得越来越臃肿,难以维护
  • Startup 类无法与其他项目类型进行共用

所以,Furion 提供了更加灵活的配置方式:AppStartup

注意事项

如果 AppStartup 的派生类所在的项目层没有被启动层直接或间接添加引用,那么这个 Startup.cs 就会被忽略,也就是不会自动载入注册。

3.1.2.1 如何配置 AppStartup

AppStartup 是一个抽象的空类,没有任何定义成员。正是因为这样,才提供更加灵活的配置方式。

3.1.2.2 AppStartup 约定

AppStartup 派生类只有两个小约定:

  • 任何公开、非静态、返回值为 void 且方法第一个参数是 IServiceCollection 类型,那么他就是一个 ConfigureServices 方法
  • 任何公开、非静态、返回值为 void 且方法第一个参数是 IApplicationBuilder 类型,第二个参数是 IWebHostEnvironment 类型,那么他就是一个 Configure 方法

所以,我们可以自由的编写方法,只要遵循约定即可,如:

using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    public class MyStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddDataValidation();        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            app.UseSwagger();        }        // 可以随意定义名字和方法        public void XXXXName(IServiceCollection services)        {        }        // 可以随意定义名字和方法        public void ZZZName(IApplicationBuilder app, IWebHostEnvironment env)        {        }    }}

3.1.2.3 AppStartup 配置顺序

默认情况下,AppStartup 配置顺序由所在程序集的名称进行正序调用,如果我们需要配置执行顺序,只需要在 AppStartup 派生类中贴 [AppStartup(order)] 特性即可。

order 数值越大,越在前面调用,如:

using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(10)]    public class FirstStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {        }    }}
using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(9)]    public class SecondStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {        }    }}

FirstStartup 会在 SecondStartup 之前调用。

3.1.2.4 AppStartup 方法调用顺序

AppStartup 方法调用顺序和方法的书写先后有关,越在前面的方法越先调用。

3.1.3 Startup 配置最佳实践

v3.6.3+ 说明

Furion v3.6.3+ 版本之后无需创建空 Startup.cs 类,内部已实现 FakeStartup 模式。

建议 Web 启动层的 Startup.cs 保持为空方法体,如:

Furion.Web.Entry\Startup.cs
using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Entry{    public class Startup    {        public void ConfigureServices(IServiceCollection services)        {        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {        }    }}

将所有 Web 应用层 配置迁移到 Furion.Web.Core.Startup.cs 中,如:

Furion.Web.Core\Startup.cs
using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace Furion.Web.Core{    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddCorsAccessor();            services.AddControllers().AddInject();        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            if (env.IsDevelopment())            {                app.UseDeveloperExceptionPage();            }            app.UseHttpsRedirection();            app.UseRouting();            app.UseCorsAccessor();            app.UseAuthentication();            app.UseAuthorization();            app.UseInject();            app.UseEndpoints(endpoints =>            {                endpoints.MapControllers();            });        }    }}

这样,后续更换 Web 应用层 也无需重新配置 Startup.cs

3.1.4 构造函数注入说明

AppStartup 的派生类并未提供依赖注入的功能,也即是无法通过构造函数进行注入服务。原因是 AppStartup 是个空类,目的是用来查找 Startup 的。

那如何像 Startup.cs 一样使用服务呢?

  • 获取配置 IConfiguration 实例:通过 App.Configuration
  • 解析服务:通过 App.GetService<TService>()app.ApplicationServices.GetService<TService>()
关于 Configure 方法注入

AppStartup 针对 Configure 方法提供了参数解析注入功能,也就是只要在方法中声明接口参数即可自动注入,如:

// app 和 env 会自动注入public void Configure(IApplicationBuilder app, IWebHostEnvironment env){}

3.1.5 关于 appsettings.json

在默认情况下,ASP.NET Core 配置放在 appsettings.json 中配置,但是这样的方式和 Startup.cs 配置一样的道理,一旦我们更换了 Web 应用层,那么 appsettings.json 又要重新配置一次。

所以,Furion 框架提供了更加灵活的方式配置 appsettings.json只需要在任何项目层根目录下创建 .json 文件即可。Furion 框架最后会自动合并所有分散的配置文件。

如我们在 Furion.EntityFramework.Core 层创建 dbsettings.json 配置数据库连接字符串,如:

Furion.EntityFramework.Core\dbsettings.json
{  "ConnectionStrings": {    "DbConnectionString": "Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;",    "Sqlite3ConnectionString": "Data Source=./Furion.db"  }}

无需在 appsettings.json 中配置,下面是 appsettings.json 默认代码:

{  "Logging": {    "LogLevel": {      "Default": "Information",      "Microsoft": "Warning",      "Microsoft.Hosting.Lifetime": "Information",      "Microsoft.EntityFrameworkCore": "Information"    }  },  "AllowedHosts": "*"}

这样我们把配置文件分散在不同项目层之后,就可以实现共用和共享了。

特别注意

其他层的配置文件不能以 appsettings.json 命名,会导致覆盖启动层的配置。

另外,在其他层创建的 *.json 文件必须设置文件属性为 始终复制或较新复制

3.1.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/audit/index.html b/handbook/build/docs/audit/index.html index 75ed1f9adb..0c6a3e4d42 100644 --- a/handbook/build/docs/audit/index.html +++ b/handbook/build/docs/audit/index.html @@ -2,22 +2,21 @@ - - - + +5.4 请求审计日志 | Furion -5.4 请求审计日志 | Furion - - + + +
-

5.4 请求审计日志

5.4.1 审计日志

在一个企业应用系统中,用户对系统所有的操作包括请求、数据库操作等等都应该记录起来,那么这些日志我们称为操作日志,也可以说审计日志。

关于数据库操作审计日志

如需实现 sql 操作,数据库操作 的审计日志可查阅 【9.22 审计日志章节

5.4.2 请求审计日志

实现原理

在这里,结合 【5.3 筛选器】 实现请求审计日志功能。

请求审计日志通常指的是记录请求地址,来源地址,操作人,传递参数等。这个主要是通过 IAsyncActionFilter 筛选器实现,如:

  1. 定义 RequestAuditFilter 并实现 IAsyncActionFilter
using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc.Filters;using System;using System.Security.Claims;using System.Threading.Tasks;namespace Furion.Web.Core{    public class RequestAuditFilter : IAsyncActionFilter    {        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)        {            //============== 这里是执行方法之前获取数据 ====================            // 获取控制器、路由信息            var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;            // 获取请求的方法            var method = actionDescriptor.MethodInfo;            // 获取 HttpContext 和 HttpRequest 对象            var httpContext = context.HttpContext;            var httpRequest = httpContext.Request;            // 获取客户端 Ipv4 地址            var remoteIPv4 = httpContext.GetRemoteIpAddressToIPv4();            // 获取请求的 Url 地址            var requestUrl = httpRequest.GetRequestUrlAddress();            // 获取来源 Url 地址            var refererUrl = httpRequest.GetRefererUrlAddress();            // 获取请求参数(写入日志,需序列化成字符串后存储)            var parameters = context.ActionArguments;            // 获取操作人(必须授权访问才有值)"userId" 为你存储的 claims type,jwt 授权对应的是 payload 中存储的键名            var userId = httpContext.User?.FindFirstValue("userId");            // 请求时间            var requestedTime = DateTimeOffset.Now;            //============== 这里是执行方法之后获取数据 ====================            var actionContext = await next();            // 获取返回的结果            var returnResult = actionContext.Result;            // 判断是否请求成功,没有异常就是请求成功            var isRequestSucceed = actionContext.Exception == null;            // 获取调用堆栈信息,提供更加简单明了的调用和异常堆栈            var stackTrace = EnhancedStackTrace.Current();            // 这里写入日志,或存储到数据库中!!!~~~~~~~~~~~~~~~~~~~~        }    }}
  1. 注册 RequestAuditFilter 筛选器
services.AddMvcFilter<RequestAuditFilter>();

5.4.3 LoggingMonitor 审计日志

小知识

Furion 提供了非常强大的 LoggingMonitor 审计日志功能,可直接使用:LoggingMonitor 文档

┏━━━━━━━━━━━  Logging Monitor ━━━━━━━━━━━┣ Furion.Application.TestLoggerServices.GetPerson (Furion.Application)┣ 控制器名称:              TestLoggerServices┣ 操作名称:                GetPerson┣ 路由信息:                [area]: ; [controller]: test-logger; [action]: person┣ 请求方式:                POST┣ 请求地址:                https://localhost:44316/api/test-logger/person/11┣ 来源地址:                https://localhost:44316/api/index.html┣ 浏览器标识:              Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62┣ 客户端 IP 地址:          0.0.0.1┣ 服务端 IP 地址:          0.0.0.1┣ 服务端运行环境:          Development┣ 执行耗时:                31ms┣ ━━━━━━━━━━━━━━━  授权信息 ━━━━━━━━━━━━━━━┣ JWT Token:               Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjEsIkFjY291bnQiOiJhZG1pbiIsImlhdCI6MTY1ODcxNjc5NywibmJmIjoxNjU4NzE2Nzk3LCJleHAiOjE2NTg3MTc5OTcsImlzcyI6ImRvdG5ldGNoaW5hIiwiYXVkIjoicG93ZXJieSBGdXJpb24ifQ.VYZkwwqCwlUy3aJjuL-og62I0rkxNQ96kSjEm3VgXtg┣ UserId (integer)1┣ Account (string):        admin┣ iat (integer)1658716797┣ nbf (integer)1658716797┣ exp (integer)1658717997┣ iss (string):            dotnetchina┣ aud (string):            powerby Furion┣ ━━━━━━━━━━━━━━━  参数列表 ━━━━━━━━━━━━━━━┣ Content-Type:id (Int32)11┣ ━━━━━━━━━━━━━━━  返回信息 ━━━━━━━━━━━━━━━┣ 类型:                    Furion.Application.Persons.PersonDto┣ 返回值:                  {"Id":11,"Name":null,"Age":0,"Address":null,"PhoneNumber":null,"QQ":null,"CreatedTime":"0001-01-01T00:00:00+00:00","Childrens":null,"Posts":null}┗━━━━━━━━━━━  Logging Monitor ━━━━━━━━━━━

5.4.4 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

5.4 请求审计日志

5.4.1 审计日志

在一个企业应用系统中,用户对系统所有的操作包括请求、数据库操作等等都应该记录起来,那么这些日志我们称为操作日志,也可以说审计日志。

关于数据库操作审计日志

如需实现 sql 操作,数据库操作 的审计日志可查阅 【9.22 审计日志章节

5.4.2 请求审计日志

实现原理

在这里,结合 【5.3 筛选器】 实现请求审计日志功能。

请求审计日志通常指的是记录请求地址,来源地址,操作人,传递参数等。这个主要是通过 IAsyncActionFilter 筛选器实现,如:

  1. 定义 RequestAuditFilter 并实现 IAsyncActionFilter
using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc.Filters;using System;using System.Security.Claims;using System.Threading.Tasks;namespace Furion.Web.Core{    public class RequestAuditFilter : IAsyncActionFilter    {        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)        {            //============== 这里是执行方法之前获取数据 ====================            // 获取控制器、路由信息            var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;            // 获取请求的方法            var method = actionDescriptor.MethodInfo;            // 获取 HttpContext 和 HttpRequest 对象            var httpContext = context.HttpContext;            var httpRequest = httpContext.Request;            // 获取客户端 Ipv4 地址            var remoteIPv4 = httpContext.GetRemoteIpAddressToIPv4();            // 获取请求的 Url 地址            var requestUrl = httpRequest.GetRequestUrlAddress();            // 获取来源 Url 地址            var refererUrl = httpRequest.GetRefererUrlAddress();            // 获取请求参数(写入日志,需序列化成字符串后存储)            var parameters = context.ActionArguments;            // 获取操作人(必须授权访问才有值)"userId" 为你存储的 claims type,jwt 授权对应的是 payload 中存储的键名            var userId = httpContext.User?.FindFirstValue("userId");            // 请求时间            var requestedTime = DateTimeOffset.Now;            //============== 这里是执行方法之后获取数据 ====================            var actionContext = await next();            // 获取返回的结果            var returnResult = actionContext.Result;            // 判断是否请求成功,没有异常就是请求成功            var isRequestSucceed = actionContext.Exception == null;            // 获取调用堆栈信息,提供更加简单明了的调用和异常堆栈            var stackTrace = EnhancedStackTrace.Current();            // 这里写入日志,或存储到数据库中!!!~~~~~~~~~~~~~~~~~~~~        }    }}
  1. 注册 RequestAuditFilter 筛选器
services.AddMvcFilter<RequestAuditFilter>();

5.4.3 LoggingMonitor 审计日志

小知识

Furion 提供了非常强大的 LoggingMonitor 审计日志功能,可直接使用:LoggingMonitor 文档

┏━━━━━━━━━━━  Logging Monitor ━━━━━━━━━━━┣ Furion.Application.TestLoggerServices.GetPerson (Furion.Application)┣ 控制器名称:              TestLoggerServices┣ 操作名称:                GetPerson┣ 路由信息:                [area]: ; [controller]: test-logger; [action]: person┣ 请求方式:                POST┣ 请求地址:                https://localhost:44316/api/test-logger/person/11┣ 来源地址:                https://localhost:44316/api/index.html┣ 浏览器标识:              Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62┣ 客户端 IP 地址:          0.0.0.1┣ 服务端 IP 地址:          0.0.0.1┣ 服务端运行环境:          Development┣ 执行耗时:                31ms┣ ━━━━━━━━━━━━━━━  授权信息 ━━━━━━━━━━━━━━━┣ JWT Token:               Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjEsIkFjY291bnQiOiJhZG1pbiIsImlhdCI6MTY1ODcxNjc5NywibmJmIjoxNjU4NzE2Nzk3LCJleHAiOjE2NTg3MTc5OTcsImlzcyI6ImRvdG5ldGNoaW5hIiwiYXVkIjoicG93ZXJieSBGdXJpb24ifQ.VYZkwwqCwlUy3aJjuL-og62I0rkxNQ96kSjEm3VgXtg┣ UserId (integer)1┣ Account (string):        admin┣ iat (integer)1658716797┣ nbf (integer)1658716797┣ exp (integer)1658717997┣ iss (string):            dotnetchina┣ aud (string):            powerby Furion┣ ━━━━━━━━━━━━━━━  参数列表 ━━━━━━━━━━━━━━━┣ Content-Type:id (Int32)11┣ ━━━━━━━━━━━━━━━  返回信息 ━━━━━━━━━━━━━━━┣ 类型:                    Furion.Application.Persons.PersonDto┣ 返回值:                  {"Id":11,"Name":null,"Age":0,"Address":null,"PhoneNumber":null,"QQ":null,"CreatedTime":"0001-01-01T00:00:00+00:00","Childrens":null,"Posts":null}┗━━━━━━━━━━━  Logging Monitor ━━━━━━━━━━━

5.4.4 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/auth-control/index.html b/handbook/build/docs/auth-control/index.html index 95f0f32d68..3efa694d48 100644 --- a/handbook/build/docs/auth-control/index.html +++ b/handbook/build/docs/auth-control/index.html @@ -2,23 +2,22 @@ - - - + +15. 安全鉴权 | Furion -15. 安全鉴权 | Furion - - + + +
-

15. 安全鉴权

15.1 什么是鉴权

鉴权实际上就是一种身份认证

由用户提供凭据,然后将其与存储在操作系统、数据库、应用或资源中的凭据进行比较。 在授权过程中,如果凭据匹配,则用户身份验证成功,可执行已向其授权的操作。 授权指判断允许用户执行的操作的过程。 +

15. 安全鉴权

15.1 什么是鉴权

鉴权实际上就是一种身份认证

由用户提供凭据,然后将其与存储在操作系统、数据库、应用或资源中的凭据进行比较。 在授权过程中,如果凭据匹配,则用户身份验证成功,可执行已向其授权的操作。 授权指判断允许用户执行的操作的过程。 也可以将身份验证理解为进入空间(例如服务器、数据库、应用或资源)的一种方式,而授权是用户可以对该空间(服务器、数据库或应用)内的哪些对象执行哪些操作。

15.1.1 常见的鉴权方式

  • HTTP Basic Authentication

这是 HTTP 协议实现的基本认证方式,我们在浏览网页时,从浏览器正上方弹出的对话框要求我们输入账号密码,正是使用了这种认证方式

  • Session + Cookie

利用服务器端的 session(会话)和浏览器端的 cookie 来实现前后端的认证,由于 http 请求时是无状态的,服务器正常情况下是不知道当前请求之前有没有来过,这个时候我们如果要记录状态,就需要在服务器端创建一个会话(session),将同一个客户端的请求都维护在各自的会话中,每当请求到达服务器端的时候,先去查一下该客户端有没有在服务器端创建 session,如果有则已经认证成功了,否则就没有认证。

  • Token

客户端在首次登陆以后,服务端再次接收 HTTP 请求的时候,就只认 Token 了,请求只要每次把 Token 带上就行了,服务器端会拦截所有的请求,然后校验 Token 的合法性,合法就放行,不合法就返回 401(鉴权失败)

Token验证比较灵活,适用于大部分场景。常用的 Token 鉴权方式的解决方案是 JWTJWT 是通过对带有相关用户信息的进行加密,加密的方式比较灵活,可以根据需求具体设计。

  • OAuth

OAuth(开放授权)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容,为了保护用户数据的安全和隐私,第三方网站访问用户数据前都需要显式的向用户征求授权。我们常见的提供 OAuth 认证服务的厂商有支付宝、QQ 和微信。

OAuth 协议又有 1.0 和 2.0 两个版本。相比较 1.0 版,2.0 版整个授权验证流程更简单更安全,也是目前最主要的用户身份验证和授权方式。

15.2 如何使用

配置之前

在添加授权服务之前,请先确保 Startup.csConfigure 是否添加了以下两个中间件:

app.UseAuthentication();app.UseAuthorization();
使用说明

如果您使用的是 WebAPI,则该小节可忽略,通常 WebAPI 使用的是 JWT 授权方式,而非 Cookie

// Cookies单独身份验证services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)        .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, b =>        {            b.LoginPath = "/Home/Login";        });

15.2.2 添加 Jwt 身份验证

  • 安装 Furion.Extras.Authentication.JwtBearer 拓展包

  • Startup.cs 中注册 AddJwt 服务,注意,必须在 .AddControllers() 之前注册!!

// 默认授权机制,需授权的即可(方法)需贴 `[Authorize]` 特性services.AddJwt();// 启用全局授权,这样每个接口都必须授权才能访问,无需贴 `[Authorize]` 特性,推荐!!!!!!!!!❤️// services.AddJwt<JwtHandler>(enableGlobalAuthorize:true);
额外补充

默认 JwtHandler 代码:

using Furion.Authorization;using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Http;using System.Threading.Tasks;namespace FurionApi.Web.Core;public class JwtHandler : AppAuthorizeHandler{    public override Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)    {        // 这里写您的授权判断逻辑,授权通过返回 true,否则返回 false        return Task.FromResult(true);    }}
  • 自定义 Jwt 配置(默认无需配置
{  "JWTSettings": {    "ValidateIssuerSigningKey": true, // 是否验证密钥,bool 类型,默认true    "IssuerSigningKey": "你的密钥", // 密钥,string 类型,必须是复杂密钥,长度大于16    "ValidateIssuer": true, // 是否验证签发方,bool 类型,默认true    "ValidIssuer": "签发方", // 签发方,string 类型    "ValidateAudience": true, // 是否验证签收方,bool 类型,默认true    "ValidAudience": "签收方", // 签收方,string 类型    "ValidateLifetime": true, // 是否验证过期时间,bool 类型,默认true,建议true    "ExpiredTime": 20, // 过期时间,long 类型,单位分钟,默认20分钟    "ClockSkew": 5, // 过期时间容错值,long 类型,单位秒,默认 5秒    "Algorithm": "HS256" // 加密算法,string 类型,默认 HS256  }}
系统安全注意事项

Furion 框架为了方便开发,已经自动添加了 Jwt 默认配置。建议每个项目都应该单独配置 IssuerSigningKeyValidIssuerValidAudience 这三个。否则同样用了 Furion 框架生成的 Token 可能存在相互访问各自系统的风险。

Algorithm 算法支持列表

目前支持的加密算法

  • HS256
  • HS384
  • HS512
  • PS256
  • PS384
  • PS512
  • RS256
  • RS384
  • RS512
  • ES256
  • ES256K
  • ES384
  • ES512
  • EdDSA

详情请查阅 SecurityAlgorithms

  • ❤️ ❤️ 生成 Token

通常我们需要在登录成功之后生成 JWT Token 并返回,可通过 JWTEncryption.Encrypt 静态方法生成,如:

关于 Token 的值

字典 Dictionary 中的值支持所有基元类型和基元类型组成的值,但应尽可能避免使用 数组 值。

// 生成 tokenvar accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>()            {                { "UserId", user.Id },  // 存储Id                { "Account",user.Account }, // 存储用户名            });

15.2.3 混合身份验证

// JWT 和 Cookies 混合身份验证services.AddJwt(options =>{      options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;      options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>{       options.LoginPath = "/Home/Login";});
特别注意

如果启用了混合身份验证后,WebApi 需在控制器/Action 中指定 Scheme 类型为 JwtBearerDefaults.AuthenticationScheme,如:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]public class ApiServices : IDynamicApiController{}

如果不设置 Scheme 那么在混合授权的 Swagger 中将默认采用 Cookie 方式,也就是授权失败会将整个 登录页面 内容返回。

15.3 高级自定义授权

Furion 框架提供了非常灵活的高级策略鉴权和授权方式,通过该策略授权方式可以实现任何自定义授权。

15.3.1 AppAuthorizeHandler

Furion 框架提供了 AppAuthorizeHandler 策略授权处理程序提供基类,只需要创建自己的 Handler 继承它即可。如:JwtHandler

using Furion.Authorization;using Furion.Core;using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Http;using Microsoft.IdentityModel.JsonWebTokens;namespace Furion.Web.Core{    /// <summary>    /// JWT 授权自定义处理程序    /// </summary>    public class JwtHandler : AppAuthorizeHandler    {        /// <summary>        /// 请求管道        /// </summary>        /// <param name="context"></param>        /// <param name="httpContext"></param>        /// <returns></returns>        public override Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)        {            // 此处已经自动验证 Jwt token的有效性了,无需手动验证            // 检查权限,如果方法是异步的就不用 Task.FromResult 包裹,直接使用 async/await 即可            return Task.FromResult(CheckAuthorzie(httpContext));        }        /// <summary>        /// 检查权限        /// </summary>        /// <param name="httpContext"></param>        /// <returns></returns>        private static bool CheckAuthorzie(DefaultHttpContext httpContext)        {            // 获取权限特性            var securityDefineAttribute = httpContext.GetMetadata<SecurityDefineAttribute>();            if (securityDefineAttribute == null) return true;            return "查询数据库返回是否有权限";        }    }}

之后注册 JwtHandler 即可:

services.AddJwt<JwtHandler>();

15.3.2 完全自定义授权

有些时候可能针对不同的平台采用不一样的授权方式,比如合作信任的第三方机构可以免授权,这时候我们只需要重写 HandleAsync 方法即可。如:

using Furion.Authorization;using Furion.Core;using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Http;using System.Threading.Tasks;namespace Furion.Web.Core{    public class JwtHandler : AppAuthorizeHandler    {        public override async Task HandleAsync(AuthorizationHandlerContext context)        {            // 常规授权(可以判断是不是第三方)            var isAuthenticated = context.User.Identity.IsAuthenticated;            // 第三方授权自定义            if(是第三方){                foreach (var requirement in pendingRequirements)                {                    // 授权成功                   context.Succeed(requirement);                }            }            // 授权失败            else context.Fail();        }    }}

15.4 授权特性及全局授权

默认情况下,所有的路由都是允许匿名访问的,所以如果需要对某个 ActionController 设定授权访问,只需要在 ActionController[AppAuthorize][Authorize] 特性即可。

如果需要对特定的 ActionController 允许匿名访问,则贴 [AllowAnonymous] 即可。

15.4.1 全局授权

services.AddJwt<JwtHandler>(enableGlobalAuthorize:true);

15.4.2 匿名访问

如果需要对特定的 ActionController 允许匿名访问,则贴 [AllowAnonymous] 即可。

15.5 自动刷新 Token

15.5.1 后端登录部分

当用户登录成功之后,返回 accessToken 字符串,之后通过 JWTEncryption.GenerateRefreshToken() 获取 刷新Token,并通过响应报文头返回,如:

// tokenvar accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>()            {                { "UserId", user.Id },  // 存储Id                { "Account",user.Account }, // 存储用户名            });// 获取刷新 tokenvar refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, 43200); // 第二个参数是刷新 token 的有效期(分钟),默认三十天// 设置响应报文头httpContextAccessor.HttpContext.Response.Headers["access-token"] = accessToken;httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;

用户登录成功之后把 accessTokenrefreshToken 一起返回给客户端存储起来。

15.5.2 后端授权 Handler 部分

using Furion.Authorization;using Furion.Core;using Furion.DataEncryption;using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Http;using Microsoft.Extensions.DependencyInjection;using System.Threading.Tasks;namespace Furion.Web.Core{    /// <summary>    /// JWT 授权自定义处理程序    /// </summary>    public class JwtHandler : AppAuthorizeHandler    {        /// <summary>        /// 重写 Handler 添加自动刷新收取逻辑        /// </summary>        /// <param name="context"></param>        /// <returns></returns>        public override async Task HandleAsync(AuthorizationHandlerContext context)        {            // 自动刷新 token            if (JWTEncryption.AutoRefreshToken(context, context.GetCurrentHttpContext()))            {                await AuthorizeHandleAsync(context);            }            else context.Fail();    // 授权失败        }        /// <summary>        /// 验证管道,也就是验证核心代码        /// </summary>        /// <param name="context"></param>        /// <param name="httpContext"></param>        /// <returns></returns>        public override Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)        {            // 检查权限,如果方法是异步的就不用 Task.FromResult 包裹,直接使用 async/await 即可            return Task.FromResult(true);        }    }}

15.5.3 客户端部分

客户端每次请求需将 accessTokenrefreshToken 放到请求报文头中传送到服务端,格式为:

Authorization: Bearer 你的token
X-Authorization: Bearer 你的刷新token

这里简单贴出使用 axios 自动刷新 token 拦截配置示例:

查看完整代码 - https://gitee.com/dotnetchina/Furion/tree/net6/clients/axios_vue_react

小建议

建议使用自动生成 Vue/React/Angular 代理方式:5.6 Vue/React/Angular 接口代理

// token 键定义const accessTokenKey = "access-token";const refreshAccessTokenKey = `x-${accessTokenKey}`;// 清除 tokenconst clearAccessTokens = () => {  window.localStorage.removeItem(accessTokenKey);  window.localStorage.removeItem(refreshAccessTokenKey);};/** * axios 默认实例 */export const axiosInstance: AxiosInstance = globalAxios;// 这里可以配置 axios 更多选项 =========================================// axios 请求拦截axiosInstance.interceptors.request.use(  (conf) => {    // 将 token 添加到请求报文头中    conf.headers!["Authorization"] = `Bearer ${window.localStorage.getItem(      accessTokenKey    )}`;    conf.headers!["X-Authorization"] = `Bearer ${window.localStorage.getItem(      refreshAccessTokenKey    )}`;    // 这里编写请求拦截代码 =========================================    return conf;  },  (error) => {    // 这里编写请求错误代码    return Promise.reject(error);  });// axios 响应拦截axiosInstance.interceptors.response.use(  (res) => {    // 获取状态码和返回数据    var status = res.status;    var serve = res.data;    // 处理 401    if (status === 401) {      clearAccessTokens();    }    // 处理未进行规范化处理的    if (status >= 400) {      throw new Error(res.statusText || "Request Error.");    }    // 处理规范化结果错误    if (serve && serve.hasOwnProperty("errors") && serve.errors) {      throw new Error(JSON.stringify(serve.errors || "Request Error."));    }    // 读取响应报文头 token 信息    var accessToken = res.headers[accessTokenKey];    var refreshAccessToken = res.headers[refreshAccessTokenKey];    // 判断是否是无效 token    if (accessToken === "invalid_token") {      clearAccessTokens();    }    // 判断是否存在刷新 token,如果存在则存储在本地    else if (      refreshAccessToken &&      accessToken &&      accessToken !== "invalid_token"    ) {      window.localStorage.setItem(accessTokenKey, accessToken);      window.localStorage.setItem(refreshAccessTokenKey, refreshAccessToken);    }    // 这里编写响应拦截代码 =========================================    return res;  },  (error) => {    // 这里编写响应错误代码    return Promise.reject(error);  });
特别注意

在正常开发中,refreshToken 无需每次请求携带,而是 accessToken 即将过期之后携带即可。可以在客户端自行判断 accessToken 是否即将过期。

如果 Token 过期,那么 Furion 将自动根据有效期内的 refreshToken 自动生成新的 AccessToken,并在 响应报文头 中返回,如:

access-token: 新的token
x-access-token: 新的刷新token
存储新的 Token

前端需要获取 响应报文头 新的 token 和刷新 token 替换之前在客户处存储旧的 token 和刷新 token。

15.6 获取 Jwt 存储的信息

// 获取 `Jwt` 存储的信息var userId = App.User?.FindFirstValue("键");

注意引入 System.Security.Claims 命名空间

获取不到 Token 信息说明

请确保 .AddJwt 服务已注册且启用了 全局授权 或该接口(方法)贴有 [Authorize] 特性。

15.7 前端解密 JWT 信息

通常在用户登录成功后我们会将 JWT Token 存储到浏览器中,这时候就需要在浏览器端解析 token 里面存储的信息,可以通过调用下面方法实现:

  • TypeScript 版本
/** * 解密 JWT token 的信息 * @param token jwt token 字符串 * @returns <any>object */function decryptJWT(token: string): any {  token = token.replace(/_/g, "/").replace(/-/g, "+");  var json = decodeURIComponent(escape(window.atob(token.split(".")[1])));  return JSON.parse(json);}
  • JavaScript 版本
/** * 解密 JWT token 的信息 * @param token jwt token 字符串 * @returns <any>object */function decryptJWT(token) {  token = token.replace(/_/g, "/").replace(/-/g, "+");  var json = decodeURIComponent(escape(window.atob(token.split(".")[1])));  return JSON.parse(json);}

这样就可以把后端放在 token 里面的信息解析出来了。

小知识

可以在解密之后读取 过期时间 exp 来解决请求时是否需要带刷新 Token,比如即将过期前 5 分钟。

15.8 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 鉴权授权 知识可查阅 ASP.NET Core - 安全和标识 章节。

演练场
- - + + \ No newline at end of file diff --git a/handbook/build/docs/author/index.html b/handbook/build/docs/author/index.html index d7ee260bd8..031a37cda2 100644 --- a/handbook/build/docs/author/index.html +++ b/handbook/build/docs/author/index.html @@ -2,22 +2,21 @@ - - - + +1.2 关于作者 | Furion -1.2 关于作者 | Furion - - + + +
-

1.2 关于作者

~

纵你阅人何其多,再无一人恰似我。

网名

  • 百小僧
  • MonkSoul
  • Rustln

专属头像

于 2016 年 07 月 14 日,亲自设计了该头像。

个性签名

成在经营,败在管理,错在不学习。

奉献宣言

无私奉献不是天方夜谭,有时候,我们也可以做到。

开源初衷

开源如同人的脸,好坏一面便知,缺点可能会受到嘲讽批评,优点也会收获赞扬尊重。别担心,他们正在塑造更好的你。

兴趣爱好

对新技术颇感兴趣,喜欢开源事业,喜欢分享技术,喜欢赛车,喜欢纹身文化,喜欢科技产品,喜欢穿越火线和我的世界游戏。

喜欢逛开源中国、IT 之家、Gitee/Github、刷抖音、看动漫、看美剧。

个人主页

https://gitee.com/monksoul

https://github.com/monksoul

技术能力

小僧不才,自 2008 年 接触 IT 行业有十余载,对互联网主流技术略懂皮毛,最喜欢的编程技术是 RustReact

常用工具

Vim/NeoVimVisual Studio CodePostgreSQLVisual Studio 2022

领域兴趣

对软件工程、架构、底层、算法、嵌入式/单片机、网络编程等颇感兴趣。

演练场
- - +

1.2 关于作者

~

纵你阅人何其多,再无一人恰似我。

网名

  • 百小僧
  • MonkSoul
  • Rustln

专属头像

于 2016 年 07 月 14 日,亲自设计了该头像。

个性签名

成在经营,败在管理,错在不学习。

奉献宣言

无私奉献不是天方夜谭,有时候,我们也可以做到。

开源初衷

开源如同人的脸,好坏一面便知,缺点可能会受到嘲讽批评,优点也会收获赞扬尊重。别担心,他们正在塑造更好的你。

兴趣爱好

对新技术颇感兴趣,喜欢开源事业,喜欢分享技术,喜欢赛车,喜欢纹身文化,喜欢科技产品,喜欢穿越火线和我的世界游戏。

喜欢逛开源中国、IT 之家、Gitee/Github、刷抖音、看动漫、看美剧。

个人主页

https://gitee.com/monksoul

https://github.com/monksoul

技术能力

小僧不才,自 2008 年 接触 IT 行业有十余载,对互联网主流技术略懂皮毛,最喜欢的编程技术是 RustReact

常用工具

Vim/NeoVimVisual Studio CodePostgreSQLVisual Studio 2022

领域兴趣

对软件工程、架构、底层、算法、嵌入式/单片机、网络编程等颇感兴趣。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/benchmark/index.html b/handbook/build/docs/benchmark/index.html index abdca185a5..f37f2a534f 100644 --- a/handbook/build/docs/benchmark/index.html +++ b/handbook/build/docs/benchmark/index.html @@ -2,22 +2,21 @@ - - - + +36.3 基准测试 | Furion -36.3 基准测试 | Furion - - + + +
-

36.3 基准测试

36.3.1 基准测试

基准测试(benchmarking)是一种测量和评估软件性能指标的活动。你可以在某个时候通过基准测试建立一个已知的性能水平(称为基准线),当系统的软硬件环境发生变化之后再进行一次基准测试以确定那些变化对性能的影响。这是基准测试最常见的用途。其他用途包括测定某种负载水平下的性能极限、管理系统或环境的变化、发现可能导致性能问题的条件,等等。

36.3.2 基准测试特质及意义

36.3.2.1 特质

  • 可重复性:可进行重复性的测试,这样做有利于比较每次的测试结果,得到性能结果的长期变化趋势,为系统调优和上线前的容量规划做参考。
  • 可观测性:通过全方位的监控(包括测试开始到结束,执行机、服务器、数据库),及时了解和分析测试过程发生了什么。
  • 可展示性:相关人员可以直观明了的了解测试结果(web 界面、仪表盘、折线图树状图等形式)。
  • 真实性:测试的结果反映了客户体验到的真实的情况(真实准确的业务场景+与生产一致的配置+合理正确的测试方法)。
  • 可执行性:相关人员可以快速的进行测试验证修改调优(可定位可分析)。

36.3.2.2 意义

  • 为容量规划确定系统和应用程序的极限;
  • 为配置测试的参数和配置选项提供参考依据;
  • 为验收测试确定系统是否具备自己所宣称的能力;
  • 为性能基线的建立提供长期的数据统计来源以及比较基准;

36.3.3 BenchmarkDotNet

BenchmarkDotNet.NET 平台提供的基准测试工具,BenchmarkDotNet 可帮助您将方法转换为基准,跟踪其性能,并共享可重复的测量实验。BenchmarkDotNet 可保护您免受流行的基准测试错误,并在基准设计或获得的测量中出现问题时警告您。结果以用户友好的形式呈现,突出显示了有关实验的所有重要事实。

36.3.3.1 如何使用

创建一个 控制台 应用程序,并通过 Nuget 安装 BenchmarkDotNet 拓展包。编写测试:

using System;using System.Security.Cryptography;using BenchmarkDotNet.Attributes;using BenchmarkDotNet.Running;namespace MyBenchmarks{    public class Md5VsSha256    {        private const int N = 10000;        private readonly byte[] data;        private readonly SHA256 sha256 = SHA256.Create();        private readonly MD5 md5 = MD5.Create();        public Md5VsSha256()        {            data = new byte[N];            new Random(42).NextBytes(data);        }        [Benchmark]        public byte[] Sha256() => sha256.ComputeHash(data);        [Benchmark]        public byte[] Md5() => md5.ComputeHash(data);    }    public class Program    {        public static void Main(string[] args)        {            var summary = BenchmarkRunner.Run<Md5VsSha256>();        }    }}

36.3.3.2 查看结果

运行控制器程序,将得到以下结果

BenchmarkDotNet=v0.12.0, OS=Windows 10.0.17763.805 (1809/October2018Update/Redstone5)
Intel Core i7-7700K CPU 4.20GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
[Host] : .NET Framework 4.7.2 (4.7.3468.0), X64 RyuJIT
Net472 : .NET Framework 4.7.2 (4.7.3468.0), X64 RyuJIT
NetCoreApp30 : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), X64 RyuJIT
CoreRt30 : .NET CoreRT 1.0.28236.02 @Commit: 741d61493c560ba96e8151f9e56876d4d3828489, X64 AOT
Mono : Mono 6.4.0 (Visual Studio), X64
MethodRuntimeNMeanErrorStdDevRatio
Sha256.NET 4.7.210007.735 us0.1913 us0.4034 us1.00
Sha256.NET Core 3.010003.989 us0.0796 us0.0745 us0.50
Sha256CoreRt 3.010004.091 us0.0811 us0.1562 us0.53
Sha256Mono100013.117 us0.2485 us0.5019 us1.70
Md5.NET 4.7.210002.872 us0.0552 us0.0737 us1.00
Md5.NET Core 3.010001.848 us0.0348 us0.0326 us0.64
Md5CoreRt 3.010001.817 us0.0359 us0.0427 us0.63
Md5Mono10003.574 us0.0678 us0.0753 us1.24
Sha256.NET 4.7.21000074.509 us1.5787 us4.6052 us1.00
Sha256.NET Core 3.01000036.049 us0.7151 us1.0025 us0.49
Sha256CoreRt 3.01000036.253 us0.7076 us0.7571 us0.49
Sha256Mono10000116.350 us2.2555 us3.0110 us1.58
Md5.NET 4.7.21000017.308 us0.3361 us0.4250 us1.00
Md5.NET Core 3.01000015.726 us0.2064 us0.1930 us0.90
Md5CoreRt 3.01000015.627 us0.2631 us0.2461 us0.89
Md5Mono1000030.205 us0.5868 us0.6522 us1.74

36.3.3.3 导出报表

也可以导出各种图表

36.3.4 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 BenchmarkDotNet 知识可查阅 BenchmarkDotNet 官网

演练场
- - +

36.3 基准测试

36.3.1 基准测试

基准测试(benchmarking)是一种测量和评估软件性能指标的活动。你可以在某个时候通过基准测试建立一个已知的性能水平(称为基准线),当系统的软硬件环境发生变化之后再进行一次基准测试以确定那些变化对性能的影响。这是基准测试最常见的用途。其他用途包括测定某种负载水平下的性能极限、管理系统或环境的变化、发现可能导致性能问题的条件,等等。

36.3.2 基准测试特质及意义

36.3.2.1 特质

  • 可重复性:可进行重复性的测试,这样做有利于比较每次的测试结果,得到性能结果的长期变化趋势,为系统调优和上线前的容量规划做参考。
  • 可观测性:通过全方位的监控(包括测试开始到结束,执行机、服务器、数据库),及时了解和分析测试过程发生了什么。
  • 可展示性:相关人员可以直观明了的了解测试结果(web 界面、仪表盘、折线图树状图等形式)。
  • 真实性:测试的结果反映了客户体验到的真实的情况(真实准确的业务场景+与生产一致的配置+合理正确的测试方法)。
  • 可执行性:相关人员可以快速的进行测试验证修改调优(可定位可分析)。

36.3.2.2 意义

  • 为容量规划确定系统和应用程序的极限;
  • 为配置测试的参数和配置选项提供参考依据;
  • 为验收测试确定系统是否具备自己所宣称的能力;
  • 为性能基线的建立提供长期的数据统计来源以及比较基准;

36.3.3 BenchmarkDotNet

BenchmarkDotNet.NET 平台提供的基准测试工具,BenchmarkDotNet 可帮助您将方法转换为基准,跟踪其性能,并共享可重复的测量实验。BenchmarkDotNet 可保护您免受流行的基准测试错误,并在基准设计或获得的测量中出现问题时警告您。结果以用户友好的形式呈现,突出显示了有关实验的所有重要事实。

36.3.3.1 如何使用

创建一个 控制台 应用程序,并通过 Nuget 安装 BenchmarkDotNet 拓展包。编写测试:

using System;using System.Security.Cryptography;using BenchmarkDotNet.Attributes;using BenchmarkDotNet.Running;namespace MyBenchmarks{    public class Md5VsSha256    {        private const int N = 10000;        private readonly byte[] data;        private readonly SHA256 sha256 = SHA256.Create();        private readonly MD5 md5 = MD5.Create();        public Md5VsSha256()        {            data = new byte[N];            new Random(42).NextBytes(data);        }        [Benchmark]        public byte[] Sha256() => sha256.ComputeHash(data);        [Benchmark]        public byte[] Md5() => md5.ComputeHash(data);    }    public class Program    {        public static void Main(string[] args)        {            var summary = BenchmarkRunner.Run<Md5VsSha256>();        }    }}

36.3.3.2 查看结果

运行控制器程序,将得到以下结果

BenchmarkDotNet=v0.12.0, OS=Windows 10.0.17763.805 (1809/October2018Update/Redstone5)
Intel Core i7-7700K CPU 4.20GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
[Host] : .NET Framework 4.7.2 (4.7.3468.0), X64 RyuJIT
Net472 : .NET Framework 4.7.2 (4.7.3468.0), X64 RyuJIT
NetCoreApp30 : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), X64 RyuJIT
CoreRt30 : .NET CoreRT 1.0.28236.02 @Commit: 741d61493c560ba96e8151f9e56876d4d3828489, X64 AOT
Mono : Mono 6.4.0 (Visual Studio), X64
MethodRuntimeNMeanErrorStdDevRatio
Sha256.NET 4.7.210007.735 us0.1913 us0.4034 us1.00
Sha256.NET Core 3.010003.989 us0.0796 us0.0745 us0.50
Sha256CoreRt 3.010004.091 us0.0811 us0.1562 us0.53
Sha256Mono100013.117 us0.2485 us0.5019 us1.70
Md5.NET 4.7.210002.872 us0.0552 us0.0737 us1.00
Md5.NET Core 3.010001.848 us0.0348 us0.0326 us0.64
Md5CoreRt 3.010001.817 us0.0359 us0.0427 us0.63
Md5Mono10003.574 us0.0678 us0.0753 us1.24
Sha256.NET 4.7.21000074.509 us1.5787 us4.6052 us1.00
Sha256.NET Core 3.01000036.049 us0.7151 us1.0025 us0.49
Sha256CoreRt 3.01000036.253 us0.7076 us0.7571 us0.49
Sha256Mono10000116.350 us2.2555 us3.0110 us1.58
Md5.NET 4.7.21000017.308 us0.3361 us0.4250 us1.00
Md5.NET Core 3.01000015.726 us0.2064 us0.1930 us0.90
Md5CoreRt 3.01000015.627 us0.2631 us0.2461 us0.89
Md5Mono1000030.205 us0.5868 us0.6522 us1.74

36.3.3.3 导出报表

也可以导出各种图表

36.3.4 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 BenchmarkDotNet 知识可查阅 BenchmarkDotNet 官网

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/bingfa/index.html b/handbook/build/docs/bingfa/index.html index 11c1c030d5..2a1e55085d 100644 --- a/handbook/build/docs/bingfa/index.html +++ b/handbook/build/docs/bingfa/index.html @@ -2,22 +2,21 @@ - - - + +36.4 并发测试 | Furion -36.4 并发测试 | Furion - - + + + - - +
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/cache/index.html b/handbook/build/docs/cache/index.html index 1de6bcd1cc..08bdc2f869 100644 --- a/handbook/build/docs/cache/index.html +++ b/handbook/build/docs/cache/index.html @@ -2,23 +2,22 @@ - - - + +14. 分布式缓存 | Furion -14. 分布式缓存 | Furion - - + + +
-

14. 分布式缓存

14.1 什么是缓存

缓存可以减少生成内容所需的工作,从而显著提高应用程序的性能和可伸缩性。 缓存适用于不经常更改的数据,因为生成成本很高。 通过缓存,可比从数据源返回数据的副本速度快得多。 应该对应用进行编写和测试,使其不要永远依赖于缓存的数据。

14.2 缓存类型

  • 内存缓存:顾名思义,就是缓存在应用部署所在服务器的内存中
  • 分布式缓存:分布式缓存是由多个应用服务器共享的缓存
  • 响应缓存:缓存服务器端 Not Modified 的数据

14.3 内存缓存使用

内存缓存是最常用的缓存方式,具有存取快,效率高特点。

内存缓存通过注入 IMemoryCache 方式注入即可。

备注

Furion 框架中,内存缓存服务已经默认注册,无需手动注册。

14.3.1 基本使用

如,缓存当前时间:

using Furion.DynamicApiController;using Microsoft.Extensions.Caching.Memory;using System;namespace Furion.Application{    public class CacheServices : IDynamicApiController    {        private const string _timeCacheKey = "cache_time";        private readonly IMemoryCache _memoryCache;        public CacheServices(IMemoryCache memoryCache)        {            _memoryCache = memoryCache;        }        [ApiDescriptionSettings(KeepName = true)]        public DateTimeOffset GetOrCreate()        {            return _memoryCache.GetOrCreate(_timeCacheKey, entry =>            {                return DateTimeOffset.UtcNow;            });        }    }}

14.3.2 设置缓存选项

内存缓存支持设置缓存时间、缓存大小、及绝对缓存过期时间等

_memoryCache.GetOrCreate(_timeCacheKey, entry =>{    entry.SlidingExpiration = TimeSpan.FromSeconds(3);  // 滑动缓存时间    return DateTimeOffset.UtcNow;});await _memoryCache.GetOrCreateAsync(_timeCacheKey, async entry =>{    // 这里可以使用异步~~});
关于缓存时间

具有可调过期的缓存项集存在过时的风险。 如果访问的时间比滑动过期时间间隔更频繁,则该项将永不过期。

将弹性过期与绝对过期组合在一起,以保证项目在其绝对过期时间通过后过期。 绝对过期会将项的上限设置为可缓存项的时间,同时仍允许项在可调整过期时间间隔内未请求时提前过期。

如果同时指定了绝对过期和可调过期时间,则过期时间以逻辑方式运算。 如果滑动过期时间间隔 或 绝对过期时间通过,则从缓存中逐出该项。

如:

_memoryCache.GetOrCreate(_timeCacheKey, entry =>{    entry.SetSlidingExpiration(TimeSpan.FromSeconds(3));    entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(20);    return DateTime.Now;});

前面的代码保证数据的缓存时间不超过绝对时间。

14.3.3 手动设置缓存选项

除了上面的 Func<MemoryCacheEntryOptions, object> 方式设置缓存选项,我们可以手动创建并设置,如:

var cacheEntryOptions = new MemoryCacheEntryOptions()                .SetSlidingExpiration(TimeSpan.FromSeconds(3));_memoryCache.Set(_timeCacheKey, DateTimeOffset.UtcNow, cacheEntryOptions);

14.3.4 缓存依赖关系

下面的示例演示如何在依赖条目过期后使缓存条目过期。 CancellationChangeToken 添加到缓存的项。 当 Cancel 在上调用时 CancellationTokenSource ,将逐出两个缓存项。

public IActionResult CreateDependentEntries(){    var cts = new CancellationTokenSource();    _cache.Set(CacheKeys.DependentCTS, cts);    using (var entry = _cache.CreateEntry(CacheKeys.Parent))    {        // expire this entry if the dependant entry expires.        entry.Value = DateTime.Now;        entry.RegisterPostEvictionCallback(DependentEvictionCallback, this);        _cache.Set(CacheKeys.Child,            DateTime.Now,            new CancellationChangeToken(cts.Token));    }    return RedirectToAction("GetDependentEntries");}public IActionResult GetDependentEntries(){    return View("Dependent", new DependentViewModel    {        ParentCachedTime = _cache.Get<DateTime?>(CacheKeys.Parent),        ChildCachedTime = _cache.Get<DateTime?>(CacheKeys.Child),        Message = _cache.Get<string>(CacheKeys.DependentMessage)    });}public IActionResult RemoveChildEntry(){    _cache.Get<CancellationTokenSource>(CacheKeys.DependentCTS).Cancel();    return RedirectToAction("GetDependentEntries");}private static void DependentEvictionCallback(object key, object value,    EvictionReason reason, object state){    var message = $"Parent entry was evicted. Reason: {reason}.";    ((HomeController)state)._cache.Set(CacheKeys.DependentMessage, message);}

使用 CancellationTokenSource 允许将多个缓存条目作为一个组逐出。 using 在上面的代码中,在块中创建的缓存条目 using 将继承触发器和过期设置。

了解更多

想了解更多 内存中的缓存 知识可查阅 ASP.NET Core - 内存缓存 章节。

14.4 分布式缓存

分布式缓存是由多个应用服务器共享的缓存,通常作为外部服务在访问它的应用服务器上维护。 分布式缓存可以提高 ASP.NET Core 应用程序的性能和可伸缩性,尤其是在应用程序由云服务或服务器场托管时。

与其他缓存方案相比,分布式缓存具有多项优势,其中缓存的数据存储在单个应用服务器上。

当分布式缓存数据时,数据将:

  • (一致性) 跨多个 服务器的请求
  • 存活在服务器重启和应用部署之间
  • 不使用本地内存

分布式缓存配置是特定于实现的。 本文介绍如何配置 SQL ServerRedis 分布式缓存。 第三方实现也可用,例如 GitHub 上的 NCache (NCache) 。

无论选择哪种实现,应用都会使用接口与缓存交互 IDistributedCache

14.4.1 使用条件

  • 若要使用 SQL Server 分布式缓存,则添加 Microsoft.Extensions.Caching.SqlServer
  • 若要使用 Redis 分布式缓存,则添加 Microsoft.Extensions.Caching.StackExchangeRedis
  • 若要使用 NCache 分布式缓存,则添加 NCache.Microsoft.Extensions.Caching.OpenSource

14.4.2 IDistributedCache

IDistributedCache 接口提供以下方法来处理分布式缓存实现中的项:

  • Get/GetAsync:接受字符串键,并检索缓存项作为 byte[] 数组(如果在缓存中找到)
  • Set/SetAsync:使用字符串键将项 (作为 byte[] 数组) 添加到缓存中
  • Refresh/RefreshAsync :根据项的键刷新缓存中的项,重置其滑动过期超时(如果有)
  • Remove/RemoveAsync:根据缓存项的字符串键删除缓存项

14.4.3 分布式内存缓存

分布式内存缓存(AddDistributedMemoryCache)是一个框架提供的实现 IDistributedCache ,它将项存储在内存中。 分布式内存缓存不是实际的分布式缓存,缓存项由应用程序实例存储在运行应用程序的服务器上。

分布式内存缓存优点:

  • 用于开发和测试方案。
  • 在生产环境中使用单一服务器并且内存消耗不是问题。 实现分布式内存缓存会抽象化缓存的数据存储。 如果需要多个节点或容错,可以在将来实现真正的分布式缓存解决方案。
备注

Furion 框架中,分布式内存缓存服务已经默认注册,无需手动调用 services.AddDistributedMemoryCache(); 注册。

14.4.4 分布式 SQL Server 缓存

分布式 SQL Server 缓存实现 (AddDistributedSqlServerCache) 允许分布式缓存使用 SQL Server 数据库作为其后备存储。

若要在 SQL Server 实例中创建 SQL Server 缓存的项表,可以使用 sql-cache 工具。 该工具将创建一个表,其中包含指定的名称和架构。

通过运行命令 sql-cache create 创建一个表,提供 SQL Server 实例 (Data Source) 、数据库 (Initial Catalog) 、架构 (例如) dbo 和表名称。例如 TestCache

dotnet sql-cache create "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache

创建成功后,在 Startup.cs 中注册即可:

services.AddDistributedSqlServerCache(options =>{    options.ConnectionString =        _config["DistCache_ConnectionString"];    options.SchemaName = "dbo";    options.TableName = "TestCache";});

14.4.5 分布式 Redis 缓存

Redis 是内存中数据存储的开源数据存储,通常用作分布式缓存。在使用时通过 services.AddStackExchangeRedisCache() 中注册即可。

这里不细讲 Redis 相关内容,后续章节会使用基本例子演示。

Redis 基本配置:

services.AddStackExchangeRedisCache(options =>{    // 连接字符串,这里也可以读取配置文件    options.Configuration = "192.168.111.134,password=aW1HAyupRKmiZn3Q";    // 键名前缀    options.InstanceName = "furion_";});

14.4.6 分布式 NCache 缓存

NCache 是在 .NET.Net Core 中以本机方式开发的开源内存中分布式缓存。 NCache 在本地工作并配置为分布式缓存群集,适用于在 Azure 或其他托管平台上运行的 ASP.NET Core 应用。 +

14. 分布式缓存

14.1 什么是缓存

缓存可以减少生成内容所需的工作,从而显著提高应用程序的性能和可伸缩性。 缓存适用于不经常更改的数据,因为生成成本很高。 通过缓存,可比从数据源返回数据的副本速度快得多。 应该对应用进行编写和测试,使其不要永远依赖于缓存的数据。

14.2 缓存类型

  • 内存缓存:顾名思义,就是缓存在应用部署所在服务器的内存中
  • 分布式缓存:分布式缓存是由多个应用服务器共享的缓存
  • 响应缓存:缓存服务器端 Not Modified 的数据

14.3 内存缓存使用

内存缓存是最常用的缓存方式,具有存取快,效率高特点。

内存缓存通过注入 IMemoryCache 方式注入即可。

备注

Furion 框架中,内存缓存服务已经默认注册,无需手动注册。

14.3.1 基本使用

如,缓存当前时间:

using Furion.DynamicApiController;using Microsoft.Extensions.Caching.Memory;using System;namespace Furion.Application{    public class CacheServices : IDynamicApiController    {        private const string _timeCacheKey = "cache_time";        private readonly IMemoryCache _memoryCache;        public CacheServices(IMemoryCache memoryCache)        {            _memoryCache = memoryCache;        }        [ApiDescriptionSettings(KeepName = true)]        public DateTimeOffset GetOrCreate()        {            return _memoryCache.GetOrCreate(_timeCacheKey, entry =>            {                return DateTimeOffset.UtcNow;            });        }    }}

14.3.2 设置缓存选项

内存缓存支持设置缓存时间、缓存大小、及绝对缓存过期时间等

_memoryCache.GetOrCreate(_timeCacheKey, entry =>{    entry.SlidingExpiration = TimeSpan.FromSeconds(3);  // 滑动缓存时间    return DateTimeOffset.UtcNow;});await _memoryCache.GetOrCreateAsync(_timeCacheKey, async entry =>{    // 这里可以使用异步~~});
关于缓存时间

具有可调过期的缓存项集存在过时的风险。 如果访问的时间比滑动过期时间间隔更频繁,则该项将永不过期。

将弹性过期与绝对过期组合在一起,以保证项目在其绝对过期时间通过后过期。 绝对过期会将项的上限设置为可缓存项的时间,同时仍允许项在可调整过期时间间隔内未请求时提前过期。

如果同时指定了绝对过期和可调过期时间,则过期时间以逻辑方式运算。 如果滑动过期时间间隔 或 绝对过期时间通过,则从缓存中逐出该项。

如:

_memoryCache.GetOrCreate(_timeCacheKey, entry =>{    entry.SetSlidingExpiration(TimeSpan.FromSeconds(3));    entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(20);    return DateTime.Now;});

前面的代码保证数据的缓存时间不超过绝对时间。

14.3.3 手动设置缓存选项

除了上面的 Func<MemoryCacheEntryOptions, object> 方式设置缓存选项,我们可以手动创建并设置,如:

var cacheEntryOptions = new MemoryCacheEntryOptions()                .SetSlidingExpiration(TimeSpan.FromSeconds(3));_memoryCache.Set(_timeCacheKey, DateTimeOffset.UtcNow, cacheEntryOptions);

14.3.4 缓存依赖关系

下面的示例演示如何在依赖条目过期后使缓存条目过期。 CancellationChangeToken 添加到缓存的项。 当 Cancel 在上调用时 CancellationTokenSource ,将逐出两个缓存项。

public IActionResult CreateDependentEntries(){    var cts = new CancellationTokenSource();    _cache.Set(CacheKeys.DependentCTS, cts);    using (var entry = _cache.CreateEntry(CacheKeys.Parent))    {        // expire this entry if the dependant entry expires.        entry.Value = DateTime.Now;        entry.RegisterPostEvictionCallback(DependentEvictionCallback, this);        _cache.Set(CacheKeys.Child,            DateTime.Now,            new CancellationChangeToken(cts.Token));    }    return RedirectToAction("GetDependentEntries");}public IActionResult GetDependentEntries(){    return View("Dependent", new DependentViewModel    {        ParentCachedTime = _cache.Get<DateTime?>(CacheKeys.Parent),        ChildCachedTime = _cache.Get<DateTime?>(CacheKeys.Child),        Message = _cache.Get<string>(CacheKeys.DependentMessage)    });}public IActionResult RemoveChildEntry(){    _cache.Get<CancellationTokenSource>(CacheKeys.DependentCTS).Cancel();    return RedirectToAction("GetDependentEntries");}private static void DependentEvictionCallback(object key, object value,    EvictionReason reason, object state){    var message = $"Parent entry was evicted. Reason: {reason}.";    ((HomeController)state)._cache.Set(CacheKeys.DependentMessage, message);}

使用 CancellationTokenSource 允许将多个缓存条目作为一个组逐出。 using 在上面的代码中,在块中创建的缓存条目 using 将继承触发器和过期设置。

了解更多

想了解更多 内存中的缓存 知识可查阅 ASP.NET Core - 内存缓存 章节。

14.4 分布式缓存

分布式缓存是由多个应用服务器共享的缓存,通常作为外部服务在访问它的应用服务器上维护。 分布式缓存可以提高 ASP.NET Core 应用程序的性能和可伸缩性,尤其是在应用程序由云服务或服务器场托管时。

与其他缓存方案相比,分布式缓存具有多项优势,其中缓存的数据存储在单个应用服务器上。

当分布式缓存数据时,数据将:

  • (一致性) 跨多个 服务器的请求
  • 存活在服务器重启和应用部署之间
  • 不使用本地内存

分布式缓存配置是特定于实现的。 本文介绍如何配置 SQL ServerRedis 分布式缓存。 第三方实现也可用,例如 GitHub 上的 NCache (NCache) 。

无论选择哪种实现,应用都会使用接口与缓存交互 IDistributedCache

14.4.1 使用条件

  • 若要使用 SQL Server 分布式缓存,则添加 Microsoft.Extensions.Caching.SqlServer
  • 若要使用 Redis 分布式缓存,则添加 Microsoft.Extensions.Caching.StackExchangeRedis
  • 若要使用 NCache 分布式缓存,则添加 NCache.Microsoft.Extensions.Caching.OpenSource

14.4.2 IDistributedCache

IDistributedCache 接口提供以下方法来处理分布式缓存实现中的项:

  • Get/GetAsync:接受字符串键,并检索缓存项作为 byte[] 数组(如果在缓存中找到)
  • Set/SetAsync:使用字符串键将项 (作为 byte[] 数组) 添加到缓存中
  • Refresh/RefreshAsync :根据项的键刷新缓存中的项,重置其滑动过期超时(如果有)
  • Remove/RemoveAsync:根据缓存项的字符串键删除缓存项

14.4.3 分布式内存缓存

分布式内存缓存(AddDistributedMemoryCache)是一个框架提供的实现 IDistributedCache ,它将项存储在内存中。 分布式内存缓存不是实际的分布式缓存,缓存项由应用程序实例存储在运行应用程序的服务器上。

分布式内存缓存优点:

  • 用于开发和测试方案。
  • 在生产环境中使用单一服务器并且内存消耗不是问题。 实现分布式内存缓存会抽象化缓存的数据存储。 如果需要多个节点或容错,可以在将来实现真正的分布式缓存解决方案。
备注

Furion 框架中,分布式内存缓存服务已经默认注册,无需手动调用 services.AddDistributedMemoryCache(); 注册。

14.4.4 分布式 SQL Server 缓存

分布式 SQL Server 缓存实现 (AddDistributedSqlServerCache) 允许分布式缓存使用 SQL Server 数据库作为其后备存储。

若要在 SQL Server 实例中创建 SQL Server 缓存的项表,可以使用 sql-cache 工具。 该工具将创建一个表,其中包含指定的名称和架构。

通过运行命令 sql-cache create 创建一个表,提供 SQL Server 实例 (Data Source) 、数据库 (Initial Catalog) 、架构 (例如) dbo 和表名称。例如 TestCache

dotnet sql-cache create "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache

创建成功后,在 Startup.cs 中注册即可:

services.AddDistributedSqlServerCache(options =>{    options.ConnectionString =        _config["DistCache_ConnectionString"];    options.SchemaName = "dbo";    options.TableName = "TestCache";});

14.4.5 分布式 Redis 缓存

Redis 是内存中数据存储的开源数据存储,通常用作分布式缓存。在使用时通过 services.AddStackExchangeRedisCache() 中注册即可。

这里不细讲 Redis 相关内容,后续章节会使用基本例子演示。

Redis 基本配置:

services.AddStackExchangeRedisCache(options =>{    // 连接字符串,这里也可以读取配置文件    options.Configuration = "192.168.111.134,password=aW1HAyupRKmiZn3Q";    // 键名前缀    options.InstanceName = "furion_";});

14.4.6 分布式 NCache 缓存

NCache 是在 .NET.Net Core 中以本机方式开发的开源内存中分布式缓存。 NCache 在本地工作并配置为分布式缓存群集,适用于在 Azure 或其他托管平台上运行的 ASP.NET Core 应用。 若要在本地计算机上安装和配置 NCache,请参阅 适用于 Windows 的 NCache 入门指南

NCache 基本配置:

  • 安装 Alachisoft.NCache.OpenSource.SDK
  • ncconf 中配置缓存群集
  • 注册 NCache 服务
services.AddNCacheDistributedCache(configuration =>{    configuration.CacheName = "demoClusteredCache";    configuration.EnableLogs = true;    configuration.ExceptionsEnabled = true;});

14.5 分布式缓存使用

若要使用 IDistributedCache 接口,请 IDistributedCache 通过构造函数依赖关系注入。

public class IndexModel : PageModel{    private readonly IDistributedCache _cache;    public IndexModel(IDistributedCache cache)    {        _cache = cache;    }    public string CachedTimeUTC { get; set; }    public async Task OnGetAsync()    {        CachedTimeUTC = "Cached Time Expired";        // 获取分布式缓存        var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");        if (encodedCachedTimeUTC != null)        {            CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);        }    }    public async Task<IActionResult> OnPostResetCachedTime()    {        var currentTimeUTC = DateTime.UtcNow.ToString();        byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);        // 设置分布式缓存        var options = new DistributedCacheEntryOptions()            .SetSlidingExpiration(TimeSpan.FromSeconds(20));        await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);        return RedirectToPage();    }}

14.6 分布式缓存建议

确定 IDistributedCache 最适合你的应用的实现时,请考虑以下事项:

  • 现有基础结构
  • 性能要求
  • 成本
  • 团队经验

缓存解决方案通常依赖于内存中的存储以快速检索缓存的数据,但是,内存是有限的资源,并且很昂贵。 仅将常用数据存储在缓存中。

通常,Redis 缓存提供比 SQL Server 缓存更高的吞吐量和更低的延迟。 但是,通常需要进行基准测试来确定缓存策略的性能特征。

SQL Server 用作分布式缓存后备存储时,对缓存使用同一数据库,并且应用的普通数据存储和检索会对这两种情况的性能产生负面影响。 建议使用分布式缓存后备存储的专用 SQL Server 实例。

14.7 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 分布式缓存 知识可查阅 ASP.NET Core - 分布式缓存 章节。

演练场
- - + + \ No newline at end of file diff --git a/handbook/build/docs/case/index.html b/handbook/build/docs/case/index.html index f31bdb9a52..da7dde9ada 100644 --- a/handbook/build/docs/case/index.html +++ b/handbook/build/docs/case/index.html @@ -2,22 +2,21 @@ - - - + +1.4 框架案例 | Furion -1.4 框架案例 | Furion - - + + +
-

1.4 框架案例

1.4.1 开源案例

越来越多的开发者使用 Furion 框架进行开发,以下是已知且开源的案例:

  • Admin.NET:基于 Furion 的通用权限管理平台
  • BaseNet: 基于Furion + Pear Admin Layui 快速开发基础框架,包含前端、后台权限控制,到手即用 🆕
  • TulingMember: 基于 Furion + IView 开发的极简进销管理系统 🆕
  • WeiXinApi: 基于Furion + SenparcSdk 的微信公众号开发 Demo 🆕
  • Magic.NET:基于 Furion + Sqlsugar 的通用权限管理平台 🆕
  • NiuPi: 基于 Furion + Sqlsugar + Vue-Next-Admin 细粒度权限控制的快速开发框架 🆕
  • 考试君:基于 Furion 的在线考试系统
  • 园丁:基于 Furion + Blazor 的超简单后台管理系统
  • Queer:基于 Furion + Layui 的通用型管理系统
  • Pear Admin:基于 Furion + PearAdmin 管理系统
  • JoyAdmin:基于 Furion + iviewadmin 开发的管理系统
  • YShop:基于 Furion + Vue 开发的移动电商项目
  • Vboot: 基于Furion + Vben 开发的快速开发管理平台

如果您使用了 Furion 进行项目开发,可以告诉我们,点击底部的 Edit this page 进行编辑添加。

演练场
- - +

1.4 框架案例

1.4.1 开源案例

越来越多的开发者使用 Furion 框架进行开发,以下是已知且开源的案例:

  • Admin.NET:基于 Furion 的通用权限管理平台
  • BaseNet: 基于Furion + Pear Admin Layui 快速开发基础框架,包含前端、后台权限控制,到手即用 🆕
  • TulingMember: 基于 Furion + IView 开发的极简进销管理系统 🆕
  • WeiXinApi: 基于Furion + SenparcSdk 的微信公众号开发 Demo 🆕
  • Magic.NET:基于 Furion + Sqlsugar 的通用权限管理平台 🆕
  • NiuPi: 基于 Furion + Sqlsugar + Vue-Next-Admin 细粒度权限控制的快速开发框架 🆕
  • 考试君:基于 Furion 的在线考试系统
  • 园丁:基于 Furion + Blazor 的超简单后台管理系统
  • Queer:基于 Furion + Layui 的通用型管理系统
  • Pear Admin:基于 Furion + PearAdmin 管理系统
  • JoyAdmin:基于 Furion + iviewadmin 开发的管理系统
  • YShop:基于 Furion + Vue 开发的移动电商项目
  • Vboot: 基于Furion + Vben 开发的快速开发管理平台

如果您使用了 Furion 进行项目开发,可以告诉我们,点击底部的 Edit this page 进行编辑添加。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/clayobj/index.html b/handbook/build/docs/clayobj/index.html index 4d914d27fc..783189b6be 100644 --- a/handbook/build/docs/clayobj/index.html +++ b/handbook/build/docs/clayobj/index.html @@ -2,22 +2,21 @@ - - - + +29. 粘土对象 | Furion -29. 粘土对象 | Furion - - + + +
-

29. 粘土对象

版本说明

以下内容仅限 Furion 2.1.12 + 版本使用。

29.1 关于粘土对象

粘土对象是 Furion 框架自创的一种概念,是一种可以模拟弱语言特性的对象,类似 Javascript 一样操作对象。只需通过 Clay 类初始化即可。

为什么起名为 “粘土” 呢?因为这个对象可以自由的添加属性,移除属性,又可以固化成任何对象,具有可拓展、可塑造的特点。

29.1.1 使用场景

粘土对象常用于需要动态构建对象的地方,如 CMS 系统的 ViewModel,或者运行时创建一个新的对象,或者请求第三方 API 情况。

29.1.2 关于性能

粘土性能实际上并不高效,但是性能也并不低下,只不过略输于强类型调用。什么时候使用可以看以上的【使用场景】。

29.2 Clay 对象

Clay 对象是继承自 DynamicObject 的一个特殊对象,提供了像弱语言一样操作对象的方法及索引。

29.3 如何使用

29.3.1 创建一个对象

// 创建一个空的粘土对象dynamic clay = new Clay();// 从现有的对象创建dynamic clay2 = Clay.Object(new {});// 从 json 字符串创建,可用于第三方 API 对接,非常有用dynamic clay3 = Clay.Parse(@"{""foo"":""json"", ""bar"":100, ""nest"":{ ""foobar"":true } }");

29.3.2 读取/获取属性

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    }});var r1 = clay.Foo; // "json" - string类型var r2 = clay.Bar; // 100 - double类型var r3 = clay.Nest.Foobar; // true - bool类型var r4 = clay["Nest"]["Foobar"]; // 还可以和 Javascript 一样通过索引器获取

29.3.3 新增属性

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    }});// 新增clay.Arr = new string[] { "NOR", "XOR" }; // 添加一个数组clay.Obj1 = new City { }; // 新增一个实例对象clay.Obj2 = new { Foo = "abc", Bar = 100 }; // 新增一个匿名类

29.3.4 更新属性值

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    }});// 更新clay.Foo = "Furion";clay["Nest"].Foobar = false;clay.Nest["Foobar"] = true;

29.3.5 删除属性

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    },    Arr = new string[] { "NOR", "XOR" }});// 删除操作clay.Delete("Foo"); // 通过 Delete 方法删除clay.Arr.Delete(0); // 支持数组 Delete 索引删除clay("Bar");    // 支持直接通过对象作为方法删除clay.Arr(1);    // 支持数组作为方法删除

29.3.6 判断属性是否存在

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    },    Arr = new string[] { "NOR", "XOR" }});// 判断属性是否存在var a = clay.IsDefined("Foo"); // truevar b = clay.IsDefined("Foooo"); // falsevar c = clay.Foo(); // truevar d = clay.Foooo(); // false;

29.3.7 遍历对象

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    },    Arr = new string[] { "NOR", "XOR" }});// 遍历数组foreach (string item in clay.Arr){    Console.WriteLine(item); // NOR, XOR}// 遍历整个对象属性及值,类似 JavaScript 的 for (var p in obj)foreach (KeyValuePair<string, dynamic> item in clay){    Console.WriteLine(item.Key + ":" + item.Value); // Foo:json, Bar: 100, Nest: { "Foobar":true}, Arr:["NOR","XOR"]}

29.3.8 转换成具体对象

dynamic clay = new Clay();clay.Arr = new string[] { "Furion", "Fur" };// 数组转换示例var a1 = clay.Arr.Deserialize<string[]>(); // 通过 Deserialize 方法var a2 = (string[])clay.Arr;    // 强制转换string[] a3 = clay.Arr; // 声明方式// 对象转换示例clay.City = new City { Id = 1, Name = "中山市" };var c1 = clay.City.Deserialize<City>(); // 通过 Deserialize 方法var c2 = (City)clay.City;    // 强制转换City c3 = clay.City; // 声明方式

29.3.9 固化粘土

固化粘土在很多时候和序列化很像,但是如果直接调用 Deserialize<object>Deserialize<dynamic> 无法返回实际类型,所以就有了固化类型的功能,如:

// 返回 objectvar obj = clay.Solidify();// 返回 dynamicvar obj1 = clay.Solidify<dynamic>();// 返回其他任意类型var obj2 = clay.Solidify<City>();

29.3.10 输出 JSON

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    },    Arr = new string[] { "NOR", "XOR" }});// 输出 JSONvar json = clay.ToString(); // "{\"Foo\":\"json\",\"Bar\":100,\"Nest\":{\"Foobar\":true},\"Arr\":[\"NOR\",\"XOR\"]}"
Clay 序列化成 JSON 键大小写控制

默认情况下,Clay 输出成 JSON 后将保持原样输出,如果需要实现键命名控制,则需要先转换成 Dictionary 然后再配置 AddJsonOptions 服务,如:

public IActionResult OutputClay(){    dynamic clay = Clay.Object(new    {       // ....    });    // 转换成 dictionary    var dic = clay.ToDictionary();    return new JsonResult(dic);}

配置序列化 Dictionary 键命名策略支持:

services.AddControllers()        .AddJsonOptions(options =>         {            options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;    // 配置 Dictionary 类型序列化输出         });

29.3.11 输出 XML 对象

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    },    Arr = new string[] { "NOR", "XOR" }});// 输出 XElementvar xml = clay.XmlElement;

29.3.12 关键字处理

dynamic clay = new Clay();clay.@int = 1;clay.@event = "事件";

29.3.13 转换成字典类型

dynamic clay = Clay.Object(new { name = "张三" });clay.name = "百小僧";Dictionary<string, object> parms = clay.ToDictionary();

29.4 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

29. 粘土对象

版本说明

以下内容仅限 Furion 2.1.12 + 版本使用。

29.1 关于粘土对象

粘土对象是 Furion 框架自创的一种概念,是一种可以模拟弱语言特性的对象,类似 Javascript 一样操作对象。只需通过 Clay 类初始化即可。

为什么起名为 “粘土” 呢?因为这个对象可以自由的添加属性,移除属性,又可以固化成任何对象,具有可拓展、可塑造的特点。

29.1.1 使用场景

粘土对象常用于需要动态构建对象的地方,如 CMS 系统的 ViewModel,或者运行时创建一个新的对象,或者请求第三方 API 情况。

29.1.2 关于性能

粘土性能实际上并不高效,但是性能也并不低下,只不过略输于强类型调用。什么时候使用可以看以上的【使用场景】。

29.2 Clay 对象

Clay 对象是继承自 DynamicObject 的一个特殊对象,提供了像弱语言一样操作对象的方法及索引。

29.3 如何使用

29.3.1 创建一个对象

// 创建一个空的粘土对象dynamic clay = new Clay();// 从现有的对象创建dynamic clay2 = Clay.Object(new {});// 从 json 字符串创建,可用于第三方 API 对接,非常有用dynamic clay3 = Clay.Parse(@"{""foo"":""json"", ""bar"":100, ""nest"":{ ""foobar"":true } }");

29.3.2 读取/获取属性

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    }});var r1 = clay.Foo; // "json" - string类型var r2 = clay.Bar; // 100 - double类型var r3 = clay.Nest.Foobar; // true - bool类型var r4 = clay["Nest"]["Foobar"]; // 还可以和 Javascript 一样通过索引器获取

29.3.3 新增属性

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    }});// 新增clay.Arr = new string[] { "NOR", "XOR" }; // 添加一个数组clay.Obj1 = new City { }; // 新增一个实例对象clay.Obj2 = new { Foo = "abc", Bar = 100 }; // 新增一个匿名类

29.3.4 更新属性值

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    }});// 更新clay.Foo = "Furion";clay["Nest"].Foobar = false;clay.Nest["Foobar"] = true;

29.3.5 删除属性

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    },    Arr = new string[] { "NOR", "XOR" }});// 删除操作clay.Delete("Foo"); // 通过 Delete 方法删除clay.Arr.Delete(0); // 支持数组 Delete 索引删除clay("Bar");    // 支持直接通过对象作为方法删除clay.Arr(1);    // 支持数组作为方法删除

29.3.6 判断属性是否存在

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    },    Arr = new string[] { "NOR", "XOR" }});// 判断属性是否存在var a = clay.IsDefined("Foo"); // truevar b = clay.IsDefined("Foooo"); // falsevar c = clay.Foo(); // truevar d = clay.Foooo(); // false;

29.3.7 遍历对象

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    },    Arr = new string[] { "NOR", "XOR" }});// 遍历数组foreach (string item in clay.Arr){    Console.WriteLine(item); // NOR, XOR}// 遍历整个对象属性及值,类似 JavaScript 的 for (var p in obj)foreach (KeyValuePair<string, dynamic> item in clay){    Console.WriteLine(item.Key + ":" + item.Value); // Foo:json, Bar: 100, Nest: { "Foobar":true}, Arr:["NOR","XOR"]}

29.3.8 转换成具体对象

dynamic clay = new Clay();clay.Arr = new string[] { "Furion", "Fur" };// 数组转换示例var a1 = clay.Arr.Deserialize<string[]>(); // 通过 Deserialize 方法var a2 = (string[])clay.Arr;    // 强制转换string[] a3 = clay.Arr; // 声明方式// 对象转换示例clay.City = new City { Id = 1, Name = "中山市" };var c1 = clay.City.Deserialize<City>(); // 通过 Deserialize 方法var c2 = (City)clay.City;    // 强制转换City c3 = clay.City; // 声明方式

29.3.9 固化粘土

固化粘土在很多时候和序列化很像,但是如果直接调用 Deserialize<object>Deserialize<dynamic> 无法返回实际类型,所以就有了固化类型的功能,如:

// 返回 objectvar obj = clay.Solidify();// 返回 dynamicvar obj1 = clay.Solidify<dynamic>();// 返回其他任意类型var obj2 = clay.Solidify<City>();

29.3.10 输出 JSON

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    },    Arr = new string[] { "NOR", "XOR" }});// 输出 JSONvar json = clay.ToString(); // "{\"Foo\":\"json\",\"Bar\":100,\"Nest\":{\"Foobar\":true},\"Arr\":[\"NOR\",\"XOR\"]}"
Clay 序列化成 JSON 键大小写控制

默认情况下,Clay 输出成 JSON 后将保持原样输出,如果需要实现键命名控制,则需要先转换成 Dictionary 然后再配置 AddJsonOptions 服务,如:

public IActionResult OutputClay(){    dynamic clay = Clay.Object(new    {       // ....    });    // 转换成 dictionary    var dic = clay.ToDictionary();    return new JsonResult(dic);}

配置序列化 Dictionary 键命名策略支持:

services.AddControllers()        .AddJsonOptions(options =>         {            options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;    // 配置 Dictionary 类型序列化输出         });

29.3.11 输出 XML 对象

dynamic clay = Clay.Object(new{    Foo = "json",    Bar = 100,    Nest = new    {        Foobar = true    },    Arr = new string[] { "NOR", "XOR" }});// 输出 XElementvar xml = clay.XmlElement;

29.3.12 关键字处理

dynamic clay = new Clay();clay.@int = 1;clay.@event = "事件";

29.3.13 转换成字典类型

dynamic clay = Clay.Object(new { name = "张三" });clay.name = "百小僧";Dictionary<string, object> parms = clay.ToDictionary();

29.4 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/clientapi/index.html b/handbook/build/docs/clientapi/index.html index 8fbd301479..a2f305dc01 100644 --- a/handbook/build/docs/clientapi/index.html +++ b/handbook/build/docs/clientapi/index.html @@ -2,22 +2,21 @@ - - - + +5.6 Vue/React/Angular 接口代理 | Furion -5.6 Vue/React/Angular 接口代理 | Furion - - + + +
-

5.6 Vue/React/Angular 接口代理

5.6.1 历史背景

在现在主流的 Web 项目开发中,越来越多的开发者选择使用 Vue/React/Angular 三大框架进行开发,这三大框架和传统开发模式最大的不同是前者采用前后端分离的方式,而后者统一由后端程序员编写。

在前后端分离的模式中,前后端程序员各司其职,后端程序负责编写接口(API),前端程序员负责编写客户端请求后端接口(API)并进行数据绑定。

但这里暴露出了一个工作效率极低且易出错的问题,那就是前端程序需要将后端几百个甚至上千个接口进行一一对应编写,大多都是采用 $.ajaxaxios 的方式。

一旦后端接口参数或返回值发生改变,前端程序员需要一一进行勘正,一旦出现纠正不完全就会导致系统无法响应或接收错误的用户消息从而造成不必要的维护工作和成本浪费。

5.6.2 如何解决?

Furion 框架编写的所有后端接口都会生成规范化的 swagger.json 文件,使用该文件可以在 https://editor.swagger.io 生成任何支持标准 swagger 的界面或客户端代码。

自此,前端程序员再也无需自己手写 $.ajaxaxios 代码,这部分代码全部自动生成,以后开发效率至少提高一半以上。

5.6.3 生成客户端请求代码

关于 TypeScriptJavaScript

以下教程仅适用于 Vue/React/AngularTypeScript 类型项目,暂不支持 JavaScript

为了项目良好的发展和维护,建议使用 TypeScript 进行编写。

5.3.3.1 生成客户端代码

  1. 打开规范化文档(Swagger)首页,并点击顶部 /swagger/xxxx/swagger.json 到新窗口打开。
  1. 接着全选并复制全部内容
  1. 打开 https://editor.swagger.io 官网并粘贴进去
无法联网

Furion 也提供了 Swagger-Editor.rar 离线包,可直接下载解压并双击 index.html 即可。

  1. 最后点击顶部的 Generate Client 选择对应的语言/框架进行生成即可。

5.6.3.2 Vue/React 配置

点击 Generate Client 顶部菜单并选择 typescript-axios 进行下载。

下载成功之后拷贝下图选择的目录和文件:

接着打开你的 VueReact 项目,并在 src 目录下创建 api-services 目录并将刚刚复制的目录文件放在里面。

接下来通过 npmyarn 安装 axios

# npm 方式npm i axios@0.21.4# yarn 方式yarn add axios@0.21.4
axios 版本说明

注意 axios 版本必须是 0.21.4 版本,如果安装其他版本可能会出现无法编译的情况。

接着下载 Furion 提供的 Vue/React 工具库 axios-utils.ts 并拷贝到和 api-services 同级目录下:

axios-utils.ts 下载地址

Vue3 项目不能编译问题

如果在 Vue3 项目中无法编译通过,则需要修改根目录下的 tsconfig.app.jsontsconfig.vite-config.jsontsconfig.vitest.json 文件并添加下列配置即可,如:

"compilerOptions": {    "importsNotUsedAsValues": "remove",    "preserveValueImports": false}

5.6.3.3 Angular 配置

点击 Generate Client 顶部菜单并选择 typescript-angular 进行下载。

下载成功之后拷贝下图选择的目录和文件:

接着打开你的 Angular 项目,并在 src 目录下创建 api-services 目录并将刚刚复制的目录文件放在里面。

接着下载 Furion 提供的 Angular 工具库 angular-utils.ts 并拷贝到和 api-services 同级目录下:

angular-utils.ts 下载地址

Angular 项目不能编译问题

如果在 Angular 项目中无法编译通过,则需要修改根目录下的 api-services/encoder.ts 文件,并在 encodeKeyencodeValue 前添加 override 即可,如:

api-services/encoder.ts
export class CustomHttpUrlEncodingCodec extends HttpUrlEncodingCodec {  override encodeKey(k: string): string {    k = super.encodeKey(k);    return k.replace(/\+/gi, "%2B");  }  override encodeValue(v: string): string {    v = super.encodeValue(v);    return v.replace(/\+/gi, "%2B");  }}

最后在 src/app/app.module.ts 中注册 ServeModule

src/app/app.module.ts
import { NgModule } from "@angular/core";import { BrowserModule } from "@angular/platform-browser";import { AppRoutingModule } from "./app-routing.module";import { AppComponent } from "./app.component";import { ServeModule } from "src/angular-utils";@NgModule({  declarations: [AppComponent],  imports: [    BrowserModule,    AppRoutingModule,    ServeModule, // 注册代理服务模块  ],  providers: [],  bootstrap: [AppComponent],})export class AppModule {}

5.6.4 初始配置

完成上面步骤之后还需要最后一步,那就修改服务端(后端)接口(API)地址。

5.6.4.1 Vue/React 配置

Vue/React 项目中编辑 Furion 框架提供的 axios-utils.ts 文件,并将 serveConfig 修改为对应的后端地址即可,如:

/** * 当前版本:v1.0.3 * 使用描述:https://editor.swagger.io 代码生成 typescript-axios 辅组工具库 * 依赖说明:适配 axios 版本:v0.21.1 * 视频教程:https://www.bilibili.com/video/BV1EW4y1C71D */import globalAxios, { AxiosInstance } from "axios";import { Configuration } from "./api-services";import { BaseAPI, BASE_PATH } from "./api-services/base";// 如果是 Angular 项目,则取消下面注释即可// import { environment } from './environments/environment';/** * 接口服务器配置 */export const serveConfig = new Configuration({  // 如果是 Angular 项目,则取消下面注释,并删除 process.env.NODE_ENV !== "production"  // basePath: !environment.production  basePath:    process.env.NODE_ENV !== "production"      ? "https://localhost:44342" // 开发环境服务器接口地址      : "https://furion.icu", // 生产环境服务器接口地址});// ......

5.6.4.2 Angular 配置

如果是 Angular 项目则编辑 Furion 框架提供的 angular-utils.ts 文件,并将 serveConfig 修改为对应的后端地址即可,如:

/** * 当前版本:v1.0.3 * 使用描述:https://editor.swagger.io 代码生成 typescript-angular 辅组工具库 */import {  HttpClientModule,  HttpEvent,  HttpHandler,  HttpHeaders,  HttpInterceptor,  HttpRequest,  HttpResponse,  HTTP_INTERCEPTORS,} from "@angular/common/http";import { Injectable, NgModule } from "@angular/core";import { finalize, Observable, tap } from "rxjs";import { ApiModule, Configuration } from "./api-services";import { environment } from "./environments/environment";/** * 接口服务器配置 */export const serveConfig = new Configuration({  basePath: !environment.production    ? "https://localhost:44316" // 开发环境服务器接口地址    : "https://furion.icu", // 生产环境服务器接口地址});// ......

5.6.5 基本使用

5.6.5.1 Vue/React 中使用

Vue/React 中使用有两种方式,一种是 Promise,另外一种就是 async/await,推荐使用后者。

  • Promise 方式
import { getAPI } from "../axios-utils"; // 注意项目的路径getAPI(SystemAPI) // SystemAPI 对应的是 Swagger 分组标签名称 + API  .apiGetXXXX()  .then((res) => {    var data = res.data.data!;  })  .catch((err) => {    console.log(err);  })  .finally(() => {    console.log("api request completed.");  });
  • async/await 方式
import { getAPI, feature } from "../axios-utils"; // 注意项目的路径const [err, res] = await feature(getAPI(SystemAPI).apiGetXXX());if (err) {  console.log(err);} else {  var data = res.data.data!;}console.log("api request completed.");

5.6.5.2 Angular 中使用

Angular 项目中,通过构造函数注入对应的服务即可

import { Component } from "@angular/core";import { PersonService } from "src/api-services"; // 注意项目的路径@Component({  selector: "app-root",  templateUrl: "./app.component.html",  styleUrls: ["./app.component.css"],})export class AppComponent {  title = "angulars";  // 注入 PersonService  constructor(private personService: PersonService) {}  ngOnInit(): void {    // 使用 personService    this.personService.apiPersonAllGet().subscribe({      next: (res) => {        // 请求成功        console.log(res);      },      error: (err) => {        // 请求失败      },      complete: () => {        // 请求完成      },    });  }}

5.6.6 重新生成代码

如果后端接口(API)发生改变,只需要删除 api-services 下所有目录文件并重新生成复制进去即可。

关于 Angular 项目

如果是 Angular 项目,可以保留 api-services/encoder.ts 文件并删除其他目录文件,新生成的目录文件无需复制 encoder.ts,这样可以避免每次修改 encoder.ts 文件。

5.6.7 Swagger 多分组生成

在很多大型系统中,为了方便对接口进行归类,往往使用了 Swagger 多分组功能,这样会使系统的接口散落在多个 swagger.json 中。

这个时候,需要在后端规范化文档中启用多分组配置:

{  "SpecificationDocumentSettings": {    "EnableAllGroups": true  }}

启用配置之后在 Swagger 导航栏顶部下拉分组将出现 All Groups 选项,这时候使用这个 All Groupsswagger.json 进行生成。

5.6.8 自定义生成前端方法名

版本说明

以下内容仅限 Furion 4.1.7+ 版本使用。

通过我们根据 swagger.json 生成前端代码时,Swagger 会自动根据路由地址生成调用的 api 名称,但这样的名称往往不易读,这时候可自定义 [OperationId] 来配置生成的前端名称。

using Furion.SpecificationDocument;public class PersonDto{  [OperationId("MyClientMethodName")]  public string TestMethod()  {    // ...  }}

5.6.9 框架客户端工具库介绍

axios-utils.tsangular-utils.tsFurion 框架专门针对 Furion 开发的 WebAPI 项目编写的客户端代理库,在这个代理库中已经处理了跨域,授权,自动刷新 token 以及解密客户端 JWT token 问题。

同时提供了非常方便的 feature 方法,可将异步方法进行同步化处理。

5.6.10 无法连接外网/内网情况/离线包

在一些比较注重代码安全的组织或公司中,可能不能连接外网进行生成,这个时候只需要下载 https://github.com/swagger-api/swagger-editor 代码在本地部署即可。

Furion 官网也提供了 Swagger-Editor.rar 离线包下载:https://gitee.com/dotnetchina/Furion/blob/net6/clients/Swagger-Editor.rar

下载离线包后直接双击 index.html 启动即可

5.6.11 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

5.6 Vue/React/Angular 接口代理

5.6.1 历史背景

在现在主流的 Web 项目开发中,越来越多的开发者选择使用 Vue/React/Angular 三大框架进行开发,这三大框架和传统开发模式最大的不同是前者采用前后端分离的方式,而后者统一由后端程序员编写。

在前后端分离的模式中,前后端程序员各司其职,后端程序负责编写接口(API),前端程序员负责编写客户端请求后端接口(API)并进行数据绑定。

但这里暴露出了一个工作效率极低且易出错的问题,那就是前端程序需要将后端几百个甚至上千个接口进行一一对应编写,大多都是采用 $.ajaxaxios 的方式。

一旦后端接口参数或返回值发生改变,前端程序员需要一一进行勘正,一旦出现纠正不完全就会导致系统无法响应或接收错误的用户消息从而造成不必要的维护工作和成本浪费。

5.6.2 如何解决?

Furion 框架编写的所有后端接口都会生成规范化的 swagger.json 文件,使用该文件可以在 https://editor.swagger.io 生成任何支持标准 swagger 的界面或客户端代码。

自此,前端程序员再也无需自己手写 $.ajaxaxios 代码,这部分代码全部自动生成,以后开发效率至少提高一半以上。

5.6.3 生成客户端请求代码

关于 TypeScriptJavaScript

以下教程仅适用于 Vue/React/AngularTypeScript 类型项目,暂不支持 JavaScript

为了项目良好的发展和维护,建议使用 TypeScript 进行编写。

5.3.3.1 生成客户端代码

  1. 打开规范化文档(Swagger)首页,并点击顶部 /swagger/xxxx/swagger.json 到新窗口打开。
  1. 接着全选并复制全部内容
  1. 打开 https://editor.swagger.io 官网并粘贴进去
无法联网

Furion 也提供了 Swagger-Editor.rar 离线包,可直接下载解压并双击 index.html 即可。

  1. 最后点击顶部的 Generate Client 选择对应的语言/框架进行生成即可。

5.6.3.2 Vue/React 配置

点击 Generate Client 顶部菜单并选择 typescript-axios 进行下载。

下载成功之后拷贝下图选择的目录和文件:

接着打开你的 VueReact 项目,并在 src 目录下创建 api-services 目录并将刚刚复制的目录文件放在里面。

接下来通过 npmyarn 安装 axios

# npm 方式npm i axios@0.21.4# yarn 方式yarn add axios@0.21.4
axios 版本说明

注意 axios 版本必须是 0.21.4 版本,如果安装其他版本可能会出现无法编译的情况。

接着下载 Furion 提供的 Vue/React 工具库 axios-utils.ts 并拷贝到和 api-services 同级目录下:

axios-utils.ts 下载地址

Vue3 项目不能编译问题

如果在 Vue3 项目中无法编译通过,则需要修改根目录下的 tsconfig.app.jsontsconfig.vite-config.jsontsconfig.vitest.json 文件并添加下列配置即可,如:

"compilerOptions": {    "importsNotUsedAsValues": "remove",    "preserveValueImports": false}

5.6.3.3 Angular 配置

点击 Generate Client 顶部菜单并选择 typescript-angular 进行下载。

下载成功之后拷贝下图选择的目录和文件:

接着打开你的 Angular 项目,并在 src 目录下创建 api-services 目录并将刚刚复制的目录文件放在里面。

接着下载 Furion 提供的 Angular 工具库 angular-utils.ts 并拷贝到和 api-services 同级目录下:

angular-utils.ts 下载地址

Angular 项目不能编译问题

如果在 Angular 项目中无法编译通过,则需要修改根目录下的 api-services/encoder.ts 文件,并在 encodeKeyencodeValue 前添加 override 即可,如:

api-services/encoder.ts
export class CustomHttpUrlEncodingCodec extends HttpUrlEncodingCodec {  override encodeKey(k: string): string {    k = super.encodeKey(k);    return k.replace(/\+/gi, "%2B");  }  override encodeValue(v: string): string {    v = super.encodeValue(v);    return v.replace(/\+/gi, "%2B");  }}

最后在 src/app/app.module.ts 中注册 ServeModule

src/app/app.module.ts
import { NgModule } from "@angular/core";import { BrowserModule } from "@angular/platform-browser";import { AppRoutingModule } from "./app-routing.module";import { AppComponent } from "./app.component";import { ServeModule } from "src/angular-utils";@NgModule({  declarations: [AppComponent],  imports: [    BrowserModule,    AppRoutingModule,    ServeModule, // 注册代理服务模块  ],  providers: [],  bootstrap: [AppComponent],})export class AppModule {}

5.6.4 初始配置

完成上面步骤之后还需要最后一步,那就修改服务端(后端)接口(API)地址。

5.6.4.1 Vue/React 配置

Vue/React 项目中编辑 Furion 框架提供的 axios-utils.ts 文件,并将 serveConfig 修改为对应的后端地址即可,如:

/** * 当前版本:v1.0.3 * 使用描述:https://editor.swagger.io 代码生成 typescript-axios 辅组工具库 * 依赖说明:适配 axios 版本:v0.21.1 * 视频教程:https://www.bilibili.com/video/BV1EW4y1C71D */import globalAxios, { AxiosInstance } from "axios";import { Configuration } from "./api-services";import { BaseAPI, BASE_PATH } from "./api-services/base";// 如果是 Angular 项目,则取消下面注释即可// import { environment } from './environments/environment';/** * 接口服务器配置 */export const serveConfig = new Configuration({  // 如果是 Angular 项目,则取消下面注释,并删除 process.env.NODE_ENV !== "production"  // basePath: !environment.production  basePath:    process.env.NODE_ENV !== "production"      ? "https://localhost:44342" // 开发环境服务器接口地址      : "https://furion.icu", // 生产环境服务器接口地址});// ......

5.6.4.2 Angular 配置

如果是 Angular 项目则编辑 Furion 框架提供的 angular-utils.ts 文件,并将 serveConfig 修改为对应的后端地址即可,如:

/** * 当前版本:v1.0.3 * 使用描述:https://editor.swagger.io 代码生成 typescript-angular 辅组工具库 */import {  HttpClientModule,  HttpEvent,  HttpHandler,  HttpHeaders,  HttpInterceptor,  HttpRequest,  HttpResponse,  HTTP_INTERCEPTORS,} from "@angular/common/http";import { Injectable, NgModule } from "@angular/core";import { finalize, Observable, tap } from "rxjs";import { ApiModule, Configuration } from "./api-services";import { environment } from "./environments/environment";/** * 接口服务器配置 */export const serveConfig = new Configuration({  basePath: !environment.production    ? "https://localhost:44316" // 开发环境服务器接口地址    : "https://furion.icu", // 生产环境服务器接口地址});// ......

5.6.5 基本使用

5.6.5.1 Vue/React 中使用

Vue/React 中使用有两种方式,一种是 Promise,另外一种就是 async/await,推荐使用后者。

  • Promise 方式
import { getAPI } from "../axios-utils"; // 注意项目的路径getAPI(SystemAPI) // SystemAPI 对应的是 Swagger 分组标签名称 + API  .apiGetXXXX()  .then((res) => {    var data = res.data.data!;  })  .catch((err) => {    console.log(err);  })  .finally(() => {    console.log("api request completed.");  });
  • async/await 方式
import { getAPI, feature } from "../axios-utils"; // 注意项目的路径const [err, res] = await feature(getAPI(SystemAPI).apiGetXXX());if (err) {  console.log(err);} else {  var data = res.data.data!;}console.log("api request completed.");

5.6.5.2 Angular 中使用

Angular 项目中,通过构造函数注入对应的服务即可

import { Component } from "@angular/core";import { PersonService } from "src/api-services"; // 注意项目的路径@Component({  selector: "app-root",  templateUrl: "./app.component.html",  styleUrls: ["./app.component.css"],})export class AppComponent {  title = "angulars";  // 注入 PersonService  constructor(private personService: PersonService) {}  ngOnInit(): void {    // 使用 personService    this.personService.apiPersonAllGet().subscribe({      next: (res) => {        // 请求成功        console.log(res);      },      error: (err) => {        // 请求失败      },      complete: () => {        // 请求完成      },    });  }}

5.6.6 重新生成代码

如果后端接口(API)发生改变,只需要删除 api-services 下所有目录文件并重新生成复制进去即可。

关于 Angular 项目

如果是 Angular 项目,可以保留 api-services/encoder.ts 文件并删除其他目录文件,新生成的目录文件无需复制 encoder.ts,这样可以避免每次修改 encoder.ts 文件。

5.6.7 Swagger 多分组生成

在很多大型系统中,为了方便对接口进行归类,往往使用了 Swagger 多分组功能,这样会使系统的接口散落在多个 swagger.json 中。

这个时候,需要在后端规范化文档中启用多分组配置:

{  "SpecificationDocumentSettings": {    "EnableAllGroups": true  }}

启用配置之后在 Swagger 导航栏顶部下拉分组将出现 All Groups 选项,这时候使用这个 All Groupsswagger.json 进行生成。

5.6.8 自定义生成前端方法名

版本说明

以下内容仅限 Furion 4.1.7+ 版本使用。

通过我们根据 swagger.json 生成前端代码时,Swagger 会自动根据路由地址生成调用的 api 名称,但这样的名称往往不易读,这时候可自定义 [OperationId] 来配置生成的前端名称。

using Furion.SpecificationDocument;public class PersonDto{  [OperationId("MyClientMethodName")]  public string TestMethod()  {    // ...  }}

5.6.9 框架客户端工具库介绍

axios-utils.tsangular-utils.tsFurion 框架专门针对 Furion 开发的 WebAPI 项目编写的客户端代理库,在这个代理库中已经处理了跨域,授权,自动刷新 token 以及解密客户端 JWT token 问题。

同时提供了非常方便的 feature 方法,可将异步方法进行同步化处理。

5.6.10 无法连接外网/内网情况/离线包

在一些比较注重代码安全的组织或公司中,可能不能连接外网进行生成,这个时候只需要下载 https://github.com/swagger-api/swagger-editor 代码在本地部署即可。

Furion 官网也提供了 Swagger-Editor.rar 离线包下载:https://gitee.com/dotnetchina/Furion/blob/net6/clients/Swagger-Editor.rar

下载离线包后直接双击 index.html 启动即可

5.6.11 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/component/index.html b/handbook/build/docs/component/index.html index 1db47da1c4..54fefac13d 100644 --- a/handbook/build/docs/component/index.html +++ b/handbook/build/docs/component/index.html @@ -2,22 +2,21 @@ - - - + +3.2 组件化启动 | Furion -3.2 组件化启动 | Furion - - + + +
-

3.2 组件化启动

3.2.1 历史背景

.NET Core 2+ 之后,微软创造了 Startup.cs 模式,在这样的模式中,需要任何服务或者中间件处理,只需要在 Startup.cs 文件的两个方法(ConfigureServicesConfigure)中配置即可。

但在 .NET6 之后,微软不再推荐使用 Startup.cs 模式。

在这里,不阐述 Startup.cs 的优点,就列举几个比较明显的缺点:

  • 默认情况下必须放在启动层且主机启动时需通过 .UseStartup<> 进行注册,此问题在 Furion 已解决 AppStartup
  • 配置服务很容易编写出又臭又长的 service.AddXXX()app.AddXXX() 代码,不管是阅读性和灵活性大大减分
  • 对服务注册和中间件注册有顺序要求,不同的顺序可能产生不同的效果,甚至出现异常
  • 不能实现模块化自动装载注册,添加新的模块需要手动注册,注册又得考虑模块化之间依赖顺序问题
  • 不能对模块注册进行监视,比如加载之前,加载失败,加载之后

3.2.2 先看一个例子

在一个大型的 .NET Core 项目中,会经常看到这样的代码:

using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace Furion.Web.Core;public sealed class FurWebCoreStartup : AppStartup{    public void ConfigureServices(IServiceCollection services)    {        services.AddCorsAccessor();        services.AddControllers().AddInject();        services.AddRemoteRequest();        services.AddEventBus();        services.AddAppLocalization();        services.AddViewEngine();        services.AddSensitiveDetection();        services.AddVirtualFileServer();        services.AddX();        services.AddXX();        services.AddXXX();        services.AddXXXX();        services.AddXXXXX();        services.AddXXXXXX();        // .....    }    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    {        if (env.IsDevelopment())        {            app.UseDeveloperExceptionPage();        }        app.UseHttpsRedirection();        app.UseRouting();        app.UseCorsAccessor();        app.UseAuthentication();        app.UseAuthorization();        app.UseInject();        app.UseX();        app.UseXX();        app.UseXXX();        app.UseXXXX();        app.UseXXXXX();        app.UseXXXXXX();        app.UseEndpoints(endpoints =>        {            endpoints.MapControllers();        });    }}

可能对于大部分 .NET 开发者来说貌似没有任何问题,但是仔细瞧瞧,这里充斥着大量的 .AddXXXX().UseXXXX()真的美观,真的好吗?而且稍有不慎移动了它们的注册顺序可能会引发灾难,还有可能多个服务之间相互依赖,要么全部移除,要么全部保留,未来替代你开发岗位的人知道吗?

试问,这个问题是无解吗?

3.2.3 当然有解

Furion 3.7.3+ 版本之后,借助 Docker-Compose 的设计理念,推出了全新的 Component 组件化 模式,通过组件化开发可以实现组件之间相互依赖,相互链接,还可以共享参数,你仅仅需要编写一个入口组件即可。

先看一个例子:

  • 创建 EntryServiceComponent 入口服务组件
// 创建入口服务组件实现 IServeComponent 接口public sealed class EntryServiceComponent : IServiceComponent{    public void Load(IServiceCollection services, ComponentContext componentContext)    {        // 做任何你想做的事情,如 service.AddYourInitService(); 如添加你的模块初始化配置    }}
  • 通过 AddComponent<> 注册入口组件
// 通过 .AddComponent 注册一个入口服务组件Serve.Run(RunOptions.Default.AddComponent<EntryServiceComponent>());

接下来,我们模拟实际项目的开发需求:

  1. 需要添加跨域服务,创建 CorsServiceComponent 组件
public sealed class CorsServiceComponent : IServiceComponent{    public void Load(IServiceCollection services, ComponentContext componentContext)    {        services.AddCorsAccessor();    }}
  1. 需要添加动态 WebAPI 服务,创建 DynamicApiServiceComponent 组件
public sealed class DynamicApiServiceComponent : IServiceComponent{    public void Load(IServiceCollection services, ComponentContext componentContext)    {        services.AddDynamicApiControllers();    }}
  1. 需要添加 XXX 第三方服务,创建 XXXServiceComponent 组件
public sealed class XXXServiceComponent : IServiceComponent{    public void Load(IServiceCollection services, ComponentContext componentContext)    {        services.AddXXX();    }}

有了这么多服务组件,那怎么将它们关联起来呢,而且能够正确的处理它们的顺序呢?比如 AddXXX() 必须等 AddDynamicApiControllers() 注册才能注册,这时候只需要为 XXXServiceComponent 添加依赖即可,如:

[DependsOn(    typeof(DynamicApiServiceComponent))]public sealed class XXXServiceComponent : IServiceComponent{    // ....}

这样表示 XXXServiceComponent 依赖 DynamicApiServiceComponent 组件,只有 DynamicApiServiceComponent 完成注册才会注册 XXXServiceComponent

那么最后的 EntryServiceComponent 的代码将会是:

[DependsOn(    typeof(CorsServiceComponent),    typeof(XXXServiceComponent))]public sealed class EntryServiceComponent : IServiceComponent{   // ....}

最后生成的调用顺序为:AddCorsAccessor() -> AddDynamicApiControllers() -> AddXXX() -> AddEntry()

看到这里,是否已找到答案:每一个项目只有一个入口组件,每个组件只做一件事,组件之间可以通过 DependsOn 配置依赖,组件之间还能共享上下文数据 ComponentContext

没错,这就是 Furion 目前能够想到的最优解决方案。

3.2.4 IComponent

Furion 3.7.3+ 版本,新增了 Components 模块,该模块的根接口为 IComponent,含有两个派生接口 IServiceComponentIApplicationComponent

3.2.4.1 IServiceComponent

IServiceComponent 接口简称服务组件对应的是 Startup.cs 中的 ConfigureService,接口签名为:

namespace System;/// <summary>/// 服务组件依赖接口/// </summary>public interface IServiceComponent : IComponent{    /// <summary>    /// 装载服务    /// </summary>    /// <param name="services"><see cref="IServiceCollection"/></param>    /// <param name="componentContext">组件上下文</param>    void Load(IServiceCollection services, ComponentContext componentContext);}

需要注册服务可在 Load 方法中注册即可。

3.2.4.2 IApplicationComponent

IApplicationComponent 接口简称中间件组件对应的是 Startup.cs 中的 Configure,接口签名为:

namespace System;/// <summary>/// 应用中间件接口/// </summary>public interface IApplicationComponent : IComponent{    /// <summary>    /// 装置中间件    /// </summary>    /// <param name="app"><see cref="IApplicationBuilder"/></param>    /// <param name="env"><see cref="IWebHostEnvironment"/></param>    /// <param name="componentContext">组件上下文</param>    void Load(IApplicationBuilder app, IWebHostEnvironment env, ComponentContext componentContext);}

需要注册中间件可在 Load 方法中注册即可。

3.2.4.3 IWebComponent

IWebComponent 接口简称 Web 组件对应的是 Program.cs 中的 WebApplicationBuilder,接口签名为:

namespace System;/// <summary>/// WebApplicationBuilder 组件依赖接口/// </summary>public interface IWebComponent : IComponent{    /// <summary>    /// 装置 Web 应用构建器    /// </summary>    /// <param name="app"><see cref="WebApplicationBuilder"/></param>    /// <param name="componentContext">组件上下文</param>    void Load(WebApplicationBuilder builder, ComponentContext componentContext);}

需要注册中间件可在 Load 方法中注册即可。

3.2.4.3 注册组件

Furion 提供了多种注册组件的方式:

  • 方式一

通过 RunOptionsLegacyRunOptionsGenericRunOptions 方式:

Serve.Run(RunOptions.Default    .AddComponent<TComponent>()    .UseComponent<TComponent>());// .NET6+ 还支持 AddWebComponent<TComponent>();Serve.Run(RunOptions.Default    .AddWebComponent<TComponent>());
  • 方式二

通过 services.AddComponentapp.UseComponent 方式

// 服务组件service.AddComponent<TComponent>();// 中间件组件app.UseComponent<TComponent>();// .NET6+ 还支持 AddWebComponent<TComponent>();builder.AddWebComponent<TComponent>();
  • 方式三

组件注册可以传递参数,通过最后的参数指定。

// 服务组件service.AddComponent<TComponent>(options);// 中间件组件app.UseComponent<TComponent>(options);// .NET6+ 还支持 AddWebComponent<TComponent>();builder.AddWebComponent<TComponent>(options);
类型 Type 注册方式

除了提供泛型注册组件的方式,还提供了 .AddComponent(typeof(XXXComponent)).UseComponent(typeof(XXXComponent)) 方式。

3.2.5 组件设计原则

3.2.5.1 职责单一性

组件的设计理应遵循职责单一性原则,具有单一性又有职责明确性,通俗点说每一个组件尽可能的只做一件事,如果组件之间有依赖,通过 [DependsOn] 声明配置,如:

[DependsOn(    typeof(OtherServiceComponent),    "Other.Assembly;Other.Assembly.OtherServiceComponent")]public sealed class YourServiceComponent : IServiceComponent{    public void Load(IServiceCollection services, ComponentContext componentContext)    {        services.AddXXX();    }}

3.2.5.2 约定大于配置

由于组件通常包含服务和中间件两个注册,所以推荐组件类的命名统一为:XXXComponent.cs,然后在 XXXComponent.cs 中分别写 IServiceComponentIApplicationComponent 组件。

尽可能每一个服务组件(IServiceComponent)以 ServiceComponent 结尾,每一个中间件组件(IApplicationComponent)以 ApplicationComponent 结尾。如:

XXXComponent.cs
namespace Your.Components;// 服务组件public sealed class XXXServiceComponent : IServiceComponent{    // ....}// 中间件组件public sealed class XXXApplicationComponent : IApplicationComponent{    // ....}// WebApplicationBuilder 组件public sealed class XXXWebComponent : IWebComponent{    // ....}
小知识

如果没有 IServiceComponentIApplicationComponent,则写其一即可。

3.2.6 [DependsOn] 详解

由于组件和组件之间存在依赖方式,甚至没有依赖关系但支持唤醒其他组件功能,所以 Furion 提供了 [DependsOn] 特性。

3.2.6.1 配置介绍

  • DependsOn
    • DependComponents:配置组件依赖关系,Type[] 类型,一旦配置了依赖关系,那么被依赖的组件会先于当前组件注册
    • Links:配置组件链接关系,Type[] 类型,该配置主要解决一些组件并不是从 根组件 进行配置,而是处于和 根组件 平行的情况,类似多入口组件
构造函数说明

DependComponentsDependsOnAttribute 特性的默认构造函数,支持 TypeString 类型,如:

[DependsOn(    typeof(XXXComponent),    typeof(XXXXComponent),    "程序集;类型完整限定名" // 会自动加载程序集中特定的组件,后续模块化开发非常方便)]

如需配置 Links,只需要这样接口:

[DependsOn(    typeof(XXXComponent),    Links = new object[]{        typeof(XXXComponent),        typeof(XXXXComponent)    })]

3.2.6.2 重复依赖问题

Furion 框架中已经处理了组件重复依赖问题,会自动生成好最佳的注册顺序并去除重复依赖注册问题。

3.2.6.3 循环依赖问题

循环依赖实际上是一种错误注册组件的方式,会导致出现内存溢出情况,早期组件化版本框架处理了循环依赖问题,也就是主动忽略或报错,但是考虑此行为本身带有潜在的安全问题,所以移除了循环依赖处理,而是选择在开发阶段抛出异常方式。

3.2.7 ComponentContext 详解

ComponentContext 是组件注册 Load 方法的最后参数,该参数提供了组件之间的一些元数据。

3.2.7.1 属性介绍

  • ComponentContext
    • ComponentType:组件类型,Type 类型
    • CalledContext:上级组件,ComponentContext 类型,也就是 DependsOn 中的组件上下文,如果没有则是前一个组件的上下文
    • RootContext:根组件/入口组件,ComponentContext 类型
    • DependComponents:组件依赖的所有组件列表,Type[] 类型
    • LinkComponents:组件链接的所有组件列表,Type[] 类型

3.2.7.2 参数配置/获取

在注册组件小节中,我们可以通过 .AddComponent.UseComponent 最后的参数来指定组件的参数,那么如何在组件中获取你传递的参数呢?

ComponentContext 提供了多种方法:

  • GetProperty<TComponent, TComponentOptions>():获取组件的参数
  • GetProperty<TComponentOptions>(Type):通过类型获取组件参数
  • GetProperty<TComponentOptions>(string):通过指定 key 获取
  • GetProperties():获取组件所有参数列表(包括依赖,链接等)
  • SetProperty<TComponent>(object):设置特定组件参数
  • SetProperty(Type, object):设置特定类型组件的参数
  • SetProperty(string, object):设置指定 key 的参数值

例子说明

注册时传入 EntryOption 参数

service.AddComponent<EntryServiceComponent>(new EntryOption {});

在组件内部获取:

public sealed class EntryServiceComponent : IServiceComponent{    public void Load(IServiceCollection services, ComponentContext componentContext)    {        var options = componentContext.GetProperty<EntryServiceComponent, EntryOption>();        services.AddXXXX(options);    }}

除此之外,还可以通过 componentContext.SetProperty<XXXServiceComponent>(new xxxOptions{}) 来设置下游组件的参数。

3.2.8 实现 Startup.cs 模式

组件模式是非常强大且灵活的,我们也可以通过组件的模式模拟出传统的 Startup.cs,如:

StartupComponent
// 模拟 ConfigureServicepublic sealed class StartupServiceComponent : IServiceComponent{    public void Load(IServiceCollection services, ComponentContext componentContext)    {         services.AddControllers()                        .AddInject();    }}// 模拟 Configurepublic sealed class StartupApplicationComponent : IApplicationComponent{    public void Load(IApplicationBuilder app, IWebHostEnvironment env, ComponentContext componentContext)    {        app.UseRouting();        app.UseInject(string.Empty);        app.UseEndpoints(endpoints =>        {            endpoints.MapControllers();        });    }}

只需要通过 service.AddComponent<StartupComponent>() 注册即可,如果使用 Serve.Run() 模式将更简单,如:

Serve.Run(RunOptions.Default            .AddComponent<StartupServiceComponent>()            .UseComponent<StartupApplicationComponent>());

是不是很灵活啊~

3.2.9 最佳实践?

在写最佳实践时是最痛苦的,因为最佳实践应该是把微软底层所有的 service.AddXXXapp.AddXXX 独立成一个个组件,比如 servers.AddControllers() 对应一个 ControllersServiceComponent

这样做的话工作量是非常大的,但如果不这样做,组件化就无法彻底。

所以现阶段暂时采用自由定制组件方式,比如自己在项目中编写 ControllersServiceComponent 这类组件。

3.2.10 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

3.2 组件化启动

3.2.1 历史背景

.NET Core 2+ 之后,微软创造了 Startup.cs 模式,在这样的模式中,需要任何服务或者中间件处理,只需要在 Startup.cs 文件的两个方法(ConfigureServicesConfigure)中配置即可。

但在 .NET6 之后,微软不再推荐使用 Startup.cs 模式。

在这里,不阐述 Startup.cs 的优点,就列举几个比较明显的缺点:

  • 默认情况下必须放在启动层且主机启动时需通过 .UseStartup<> 进行注册,此问题在 Furion 已解决 AppStartup
  • 配置服务很容易编写出又臭又长的 service.AddXXX()app.AddXXX() 代码,不管是阅读性和灵活性大大减分
  • 对服务注册和中间件注册有顺序要求,不同的顺序可能产生不同的效果,甚至出现异常
  • 不能实现模块化自动装载注册,添加新的模块需要手动注册,注册又得考虑模块化之间依赖顺序问题
  • 不能对模块注册进行监视,比如加载之前,加载失败,加载之后

3.2.2 先看一个例子

在一个大型的 .NET Core 项目中,会经常看到这样的代码:

using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace Furion.Web.Core;public sealed class FurWebCoreStartup : AppStartup{    public void ConfigureServices(IServiceCollection services)    {        services.AddCorsAccessor();        services.AddControllers().AddInject();        services.AddRemoteRequest();        services.AddEventBus();        services.AddAppLocalization();        services.AddViewEngine();        services.AddSensitiveDetection();        services.AddVirtualFileServer();        services.AddX();        services.AddXX();        services.AddXXX();        services.AddXXXX();        services.AddXXXXX();        services.AddXXXXXX();        // .....    }    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    {        if (env.IsDevelopment())        {            app.UseDeveloperExceptionPage();        }        app.UseHttpsRedirection();        app.UseRouting();        app.UseCorsAccessor();        app.UseAuthentication();        app.UseAuthorization();        app.UseInject();        app.UseX();        app.UseXX();        app.UseXXX();        app.UseXXXX();        app.UseXXXXX();        app.UseXXXXXX();        app.UseEndpoints(endpoints =>        {            endpoints.MapControllers();        });    }}

可能对于大部分 .NET 开发者来说貌似没有任何问题,但是仔细瞧瞧,这里充斥着大量的 .AddXXXX().UseXXXX()真的美观,真的好吗?而且稍有不慎移动了它们的注册顺序可能会引发灾难,还有可能多个服务之间相互依赖,要么全部移除,要么全部保留,未来替代你开发岗位的人知道吗?

试问,这个问题是无解吗?

3.2.3 当然有解

Furion 3.7.3+ 版本之后,借助 Docker-Compose 的设计理念,推出了全新的 Component 组件化 模式,通过组件化开发可以实现组件之间相互依赖,相互链接,还可以共享参数,你仅仅需要编写一个入口组件即可。

先看一个例子:

  • 创建 EntryServiceComponent 入口服务组件
// 创建入口服务组件实现 IServeComponent 接口public sealed class EntryServiceComponent : IServiceComponent{    public void Load(IServiceCollection services, ComponentContext componentContext)    {        // 做任何你想做的事情,如 service.AddYourInitService(); 如添加你的模块初始化配置    }}
  • 通过 AddComponent<> 注册入口组件
// 通过 .AddComponent 注册一个入口服务组件Serve.Run(RunOptions.Default.AddComponent<EntryServiceComponent>());

接下来,我们模拟实际项目的开发需求:

  1. 需要添加跨域服务,创建 CorsServiceComponent 组件
public sealed class CorsServiceComponent : IServiceComponent{    public void Load(IServiceCollection services, ComponentContext componentContext)    {        services.AddCorsAccessor();    }}
  1. 需要添加动态 WebAPI 服务,创建 DynamicApiServiceComponent 组件
public sealed class DynamicApiServiceComponent : IServiceComponent{    public void Load(IServiceCollection services, ComponentContext componentContext)    {        services.AddDynamicApiControllers();    }}
  1. 需要添加 XXX 第三方服务,创建 XXXServiceComponent 组件
public sealed class XXXServiceComponent : IServiceComponent{    public void Load(IServiceCollection services, ComponentContext componentContext)    {        services.AddXXX();    }}

有了这么多服务组件,那怎么将它们关联起来呢,而且能够正确的处理它们的顺序呢?比如 AddXXX() 必须等 AddDynamicApiControllers() 注册才能注册,这时候只需要为 XXXServiceComponent 添加依赖即可,如:

[DependsOn(    typeof(DynamicApiServiceComponent))]public sealed class XXXServiceComponent : IServiceComponent{    // ....}

这样表示 XXXServiceComponent 依赖 DynamicApiServiceComponent 组件,只有 DynamicApiServiceComponent 完成注册才会注册 XXXServiceComponent

那么最后的 EntryServiceComponent 的代码将会是:

[DependsOn(    typeof(CorsServiceComponent),    typeof(XXXServiceComponent))]public sealed class EntryServiceComponent : IServiceComponent{   // ....}

最后生成的调用顺序为:AddCorsAccessor() -> AddDynamicApiControllers() -> AddXXX() -> AddEntry()

看到这里,是否已找到答案:每一个项目只有一个入口组件,每个组件只做一件事,组件之间可以通过 DependsOn 配置依赖,组件之间还能共享上下文数据 ComponentContext

没错,这就是 Furion 目前能够想到的最优解决方案。

3.2.4 IComponent

Furion 3.7.3+ 版本,新增了 Components 模块,该模块的根接口为 IComponent,含有两个派生接口 IServiceComponentIApplicationComponent

3.2.4.1 IServiceComponent

IServiceComponent 接口简称服务组件对应的是 Startup.cs 中的 ConfigureService,接口签名为:

namespace System;/// <summary>/// 服务组件依赖接口/// </summary>public interface IServiceComponent : IComponent{    /// <summary>    /// 装载服务    /// </summary>    /// <param name="services"><see cref="IServiceCollection"/></param>    /// <param name="componentContext">组件上下文</param>    void Load(IServiceCollection services, ComponentContext componentContext);}

需要注册服务可在 Load 方法中注册即可。

3.2.4.2 IApplicationComponent

IApplicationComponent 接口简称中间件组件对应的是 Startup.cs 中的 Configure,接口签名为:

namespace System;/// <summary>/// 应用中间件接口/// </summary>public interface IApplicationComponent : IComponent{    /// <summary>    /// 装置中间件    /// </summary>    /// <param name="app"><see cref="IApplicationBuilder"/></param>    /// <param name="env"><see cref="IWebHostEnvironment"/></param>    /// <param name="componentContext">组件上下文</param>    void Load(IApplicationBuilder app, IWebHostEnvironment env, ComponentContext componentContext);}

需要注册中间件可在 Load 方法中注册即可。

3.2.4.3 IWebComponent

IWebComponent 接口简称 Web 组件对应的是 Program.cs 中的 WebApplicationBuilder,接口签名为:

namespace System;/// <summary>/// WebApplicationBuilder 组件依赖接口/// </summary>public interface IWebComponent : IComponent{    /// <summary>    /// 装置 Web 应用构建器    /// </summary>    /// <param name="app"><see cref="WebApplicationBuilder"/></param>    /// <param name="componentContext">组件上下文</param>    void Load(WebApplicationBuilder builder, ComponentContext componentContext);}

需要注册中间件可在 Load 方法中注册即可。

3.2.4.3 注册组件

Furion 提供了多种注册组件的方式:

  • 方式一

通过 RunOptionsLegacyRunOptionsGenericRunOptions 方式:

Serve.Run(RunOptions.Default    .AddComponent<TComponent>()    .UseComponent<TComponent>());// .NET6+ 还支持 AddWebComponent<TComponent>();Serve.Run(RunOptions.Default    .AddWebComponent<TComponent>());
  • 方式二

通过 services.AddComponentapp.UseComponent 方式

// 服务组件service.AddComponent<TComponent>();// 中间件组件app.UseComponent<TComponent>();// .NET6+ 还支持 AddWebComponent<TComponent>();builder.AddWebComponent<TComponent>();
  • 方式三

组件注册可以传递参数,通过最后的参数指定。

// 服务组件service.AddComponent<TComponent>(options);// 中间件组件app.UseComponent<TComponent>(options);// .NET6+ 还支持 AddWebComponent<TComponent>();builder.AddWebComponent<TComponent>(options);
类型 Type 注册方式

除了提供泛型注册组件的方式,还提供了 .AddComponent(typeof(XXXComponent)).UseComponent(typeof(XXXComponent)) 方式。

3.2.5 组件设计原则

3.2.5.1 职责单一性

组件的设计理应遵循职责单一性原则,具有单一性又有职责明确性,通俗点说每一个组件尽可能的只做一件事,如果组件之间有依赖,通过 [DependsOn] 声明配置,如:

[DependsOn(    typeof(OtherServiceComponent),    "Other.Assembly;Other.Assembly.OtherServiceComponent")]public sealed class YourServiceComponent : IServiceComponent{    public void Load(IServiceCollection services, ComponentContext componentContext)    {        services.AddXXX();    }}

3.2.5.2 约定大于配置

由于组件通常包含服务和中间件两个注册,所以推荐组件类的命名统一为:XXXComponent.cs,然后在 XXXComponent.cs 中分别写 IServiceComponentIApplicationComponent 组件。

尽可能每一个服务组件(IServiceComponent)以 ServiceComponent 结尾,每一个中间件组件(IApplicationComponent)以 ApplicationComponent 结尾。如:

XXXComponent.cs
namespace Your.Components;// 服务组件public sealed class XXXServiceComponent : IServiceComponent{    // ....}// 中间件组件public sealed class XXXApplicationComponent : IApplicationComponent{    // ....}// WebApplicationBuilder 组件public sealed class XXXWebComponent : IWebComponent{    // ....}
小知识

如果没有 IServiceComponentIApplicationComponent,则写其一即可。

3.2.6 [DependsOn] 详解

由于组件和组件之间存在依赖方式,甚至没有依赖关系但支持唤醒其他组件功能,所以 Furion 提供了 [DependsOn] 特性。

3.2.6.1 配置介绍

  • DependsOn
    • DependComponents:配置组件依赖关系,Type[] 类型,一旦配置了依赖关系,那么被依赖的组件会先于当前组件注册
    • Links:配置组件链接关系,Type[] 类型,该配置主要解决一些组件并不是从 根组件 进行配置,而是处于和 根组件 平行的情况,类似多入口组件
构造函数说明

DependComponentsDependsOnAttribute 特性的默认构造函数,支持 TypeString 类型,如:

[DependsOn(    typeof(XXXComponent),    typeof(XXXXComponent),    "程序集;类型完整限定名" // 会自动加载程序集中特定的组件,后续模块化开发非常方便)]

如需配置 Links,只需要这样接口:

[DependsOn(    typeof(XXXComponent),    Links = new object[]{        typeof(XXXComponent),        typeof(XXXXComponent)    })]

3.2.6.2 重复依赖问题

Furion 框架中已经处理了组件重复依赖问题,会自动生成好最佳的注册顺序并去除重复依赖注册问题。

3.2.6.3 循环依赖问题

循环依赖实际上是一种错误注册组件的方式,会导致出现内存溢出情况,早期组件化版本框架处理了循环依赖问题,也就是主动忽略或报错,但是考虑此行为本身带有潜在的安全问题,所以移除了循环依赖处理,而是选择在开发阶段抛出异常方式。

3.2.7 ComponentContext 详解

ComponentContext 是组件注册 Load 方法的最后参数,该参数提供了组件之间的一些元数据。

3.2.7.1 属性介绍

  • ComponentContext
    • ComponentType:组件类型,Type 类型
    • CalledContext:上级组件,ComponentContext 类型,也就是 DependsOn 中的组件上下文,如果没有则是前一个组件的上下文
    • RootContext:根组件/入口组件,ComponentContext 类型
    • DependComponents:组件依赖的所有组件列表,Type[] 类型
    • LinkComponents:组件链接的所有组件列表,Type[] 类型

3.2.7.2 参数配置/获取

在注册组件小节中,我们可以通过 .AddComponent.UseComponent 最后的参数来指定组件的参数,那么如何在组件中获取你传递的参数呢?

ComponentContext 提供了多种方法:

  • GetProperty<TComponent, TComponentOptions>():获取组件的参数
  • GetProperty<TComponentOptions>(Type):通过类型获取组件参数
  • GetProperty<TComponentOptions>(string):通过指定 key 获取
  • GetProperties():获取组件所有参数列表(包括依赖,链接等)
  • SetProperty<TComponent>(object):设置特定组件参数
  • SetProperty(Type, object):设置特定类型组件的参数
  • SetProperty(string, object):设置指定 key 的参数值

例子说明

注册时传入 EntryOption 参数

service.AddComponent<EntryServiceComponent>(new EntryOption {});

在组件内部获取:

public sealed class EntryServiceComponent : IServiceComponent{    public void Load(IServiceCollection services, ComponentContext componentContext)    {        var options = componentContext.GetProperty<EntryServiceComponent, EntryOption>();        services.AddXXXX(options);    }}

除此之外,还可以通过 componentContext.SetProperty<XXXServiceComponent>(new xxxOptions{}) 来设置下游组件的参数。

3.2.8 实现 Startup.cs 模式

组件模式是非常强大且灵活的,我们也可以通过组件的模式模拟出传统的 Startup.cs,如:

StartupComponent
// 模拟 ConfigureServicepublic sealed class StartupServiceComponent : IServiceComponent{    public void Load(IServiceCollection services, ComponentContext componentContext)    {         services.AddControllers()                        .AddInject();    }}// 模拟 Configurepublic sealed class StartupApplicationComponent : IApplicationComponent{    public void Load(IApplicationBuilder app, IWebHostEnvironment env, ComponentContext componentContext)    {        app.UseRouting();        app.UseInject(string.Empty);        app.UseEndpoints(endpoints =>        {            endpoints.MapControllers();        });    }}

只需要通过 service.AddComponent<StartupComponent>() 注册即可,如果使用 Serve.Run() 模式将更简单,如:

Serve.Run(RunOptions.Default            .AddComponent<StartupServiceComponent>()            .UseComponent<StartupApplicationComponent>());

是不是很灵活啊~

3.2.9 最佳实践?

在写最佳实践时是最痛苦的,因为最佳实践应该是把微软底层所有的 service.AddXXXapp.AddXXX 独立成一个个组件,比如 servers.AddControllers() 对应一个 ControllersServiceComponent

这样做的话工作量是非常大的,但如果不这样做,组件化就无法彻底。

所以现阶段暂时采用自由定制组件方式,比如自己在项目中编写 ControllersServiceComponent 这类组件。

3.2.10 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/configuration/index.html b/handbook/build/docs/configuration/index.html index 158ff76b01..a76cc96bbe 100644 --- a/handbook/build/docs/configuration/index.html +++ b/handbook/build/docs/configuration/index.html @@ -2,22 +2,21 @@ - - - + +4.1 配置 | Furion -4.1 配置 | Furion - - + + +
-

4.1 配置

温馨提示

推荐使用 《4.2 选项》代替本章节功能。(为什么)?

自定义配置特别注意

如:xxxx.json,必须在 VS Studio 中右键属性设置 复制输出目录为如果较新则复制,生成操作为:内容

如果 .json 文件配置在多个项目层,也必须保证命名唯一,不然编译后出现相互覆盖的情况。

中文乱码问题

默认情况下,.json 文件并未采用 utf-8 编码,所以如果存在中文读取后就会出现乱码情况,这时候,只需要修改 .json 文件编码为 utf-8 即可。

4.1.1 什么是配置

简单来说,配置将系统应用可动态调配的选项放在统一地方管理,通过不同的配置让系统做出动态调整。

ASP.NET Core 应用程序启动时默认加载 启动项目 下的 appsettings.json 作为应用配置。同时还支持不同的运行环境加载对应的配置文件,如:

  • Development:加载 appsettings.Development.json
  • Staging:加载 appsettings.Staging.json
  • {Environment}appsettings.{Environment}.json

4.1.2 配置的使用

假设我们需要在系统运行时获取系统名称、版本号及版权信息,这些信息可能随时变化而且需要在多个地方使用。这时就需要将这些信息配置起来。具体步骤如下:

4.1.2.1 配置 appsettings.json 信息

{  "AppInfo": {    "Name": "Furion",    "Version": "1.0.0",    "Company": "Baiqian"  }}
特别注意

appsettings.json 复制输出目录为如果较新则复制,生成操作为:内容

另外,某些 linux 系统不支持读取带 注释 的 json 文件,直接读取将会报错。需要将 json 内的注释全部 删除 才能正常读取。

4.1.2.2 读取 appsettings.json 信息

Furion 框架中,提供了两种读取方式:

  • 依赖注入 IConfiguration 对象读取
  • 通过 App.Configuration[path] 读取
using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    [Route("api/[controller]")]    public class DefaultController : ControllerBase    {        [HttpGet]        public string Get()        {            return $@"名称:{App.Configuration["AppInfo:Name"]}                      版本:{App.Configuration["AppInfo:Version"]}                      公司:{App.Configuration["AppInfo:Company"]}";        }    }}
依赖注入的方式

通过依赖注入注入实例有几种方式:

  • 构造函数注入方式
private readonly IConfiguration _configuration;public DefaultController(IConfiguration configuration){    _configuration = configuration;}
  • 参数注入方式 [FromServices]
public string Get([FromServices] IConfiguration configuration){}
  • 属性注入方式
public IConfiguration Configuration { get; set; }

想了解更多关于《ASP.NET Core - 依赖注入》 知识

4.1.2.3 如何选择读取方式

  • 在可依赖注入类中,依赖注入 IConfiguration 读取
  • 在静态类/非依赖注入类中,选择 App.Configuration[path] 读取

4.1.2.4 读取配置并转换成特定类型

ASP.NET CoreFurion 提供了多种配置类型读取并转换成特定类型,包括基础类型,对象类型,数组,集合,字典等等,如:

// ASP.NET Corevar data = Configuration.GetSection("配置节点").Get<类型>();// Furion,推荐!!!var data = App.GetConfig<类型>("配置节点");

4.1.3 路径符 查找节点

ASP.NET Core 中,配置采用 : 分隔符来读取分层配置数据。如上述例子中的 AppInfo:Name。如有更多层级数据则只需要通过 : 进入下一层节点即可。

假设我们有以下配置信息:

{  "AppInfo": {    "Name": "Furion",    "Version": "1.0.0",    "Company": {      "Name": "Baiqian",      "Address": {        "City": "中国",        "Province": "广东省",        "Detail": "中山市东区紫马公园西门"      }    }  }}
var companyName = App.Configuration["AppInfo:Name"]; // => Furion

4.1.3.1 查找数组节点

有些时候我们需要或者数组特定的某些,可以通过 App.Configuration["array:0"] 获取,0 是索引数字。

4.1.4 自定义配置文件

XML 配置说明

Furion v2.8.0 版本移除了 .xml 文件自动扫描配置了,改为手动添加配置。

大多情况下,我们的配置只需要在 appsettings.json 中配置即可,但一些特殊情况下,我们希望某些组件或功能拥有独立的配置,这个时候就需要用到自定义配置,Furion 目前支持 .json.xml 两种方式配置,如:

Furion.Web.Entry/emailsetting.json
{  "outlook": {    "smtp": {      "server": "smtp.office365.com",      "port": "587",      "ssl": "STARTTLS"    },    "pop": {      "server": "outlook.office365.com",      "port": "995",      "ssl": "TLS"    }  }}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<MyKey>MyXMLFile Value</MyKey>
<Position>
<Title>Title from MyXMLFile</Title>
<Name>Name from MyXMLFile</Name>
</Position>
<Logging>
<LogLevel>
<Default>Information</Default>
<Microsoft>Warning</Microsoft>
</LogLevel>
</Logging>
</configuration>
xml 配置事项

如果采用 xml 配置,那么文件名必须以 .config.xml 结尾(不区分大小写)。

特别说明

Furion 框架会在启动时自动扫描每一个项目层根目录下的 *.json 文件加入配置中,所以无需手工配置。

新增 *.json 文件的属性 复制到输出目录 设置为始终复制或较新复制,否则不会载入。另外配置文件不能出现重名,也就是保证整个项目中配置文件名字唯一。比如不能在非 Web 其他层定义 appsettings.json 文件。

v2.16.7+ 版本版本之后,支持自定义配置扫描目录:

{  "ConfigurationScanDirectories": ["目录1名称", "目录1名称/子目录名称"]}

同时 Furion 提供了非常灵活的方式支持自定义配置文件读取,如:

4.1.4.1 读取 emailsetting.json 配置

读取自定义配置文件和读取 appsettings.json 一致,系统会自动从多个配置文件中读取输入,如:

var smtpServer = App.Configuration["outlook:smtp:server"]; // => smtp.office365.com

4.1.4.2 排除特定配置文件

有些时候,我们不需要 .json.xml 自动载入配置中,我们只需要在启动层 appsettings.json 中添加 IgnoreConfigurationFiles 节点即可:

{  "IgnoreConfigurationFiles": ["runtime.json"]}

4.1.5 不同环境读取

在实际应用开发中,我们可能会根据不同的环境加载不同的配置文件,如 数据库连接字符串

这时我们只需要遵循特定命名规范 {name}.{Environment}.json 即可。如:

  • appsettings.Development.json
  • appsettings.Staging.json
  • appsettings.Production.json
  • emailsetting.Development.json
  • emailsetting.Staging.json
  • emailsetting.Production.json

这时,ASP.NET Core 会在应用启动时自动加载不同环境的配置文件。

4.1.6 配置更改通知(热更新

.NET Core 应用程序中,配置支持更改通知,也就是热更新操作。一旦监听到 appsetting.json 或自定义配置文件发生变动,就会触发 OnChange 方法。代码如下:

var appInfoConfiguration = App.Configuration.GetSection("AppInfo");ChangeToken.OnChange(() => App.Configuration.GetReloadToken(), () =>{  var name = appInfoConfiguration["Name"];  // 实时的最新值  var version = appInfoConfiguration["Version"];  // 实时的最新值});
监听对象

如果监听全局配置文件传入 App.Configuration.GetReloadToken(),如果只需要监听特定节点,传入 App.Configuration.GetSection("AppInfo")

4.1.7 手动添加配置文件

获取路径说明
  • 获取项目目录:AppContext.BaseDirectory
  • 获取网站根目录:Directory.GetCurrentDirectory()

有些时候,我们的配置文件没有放在项目的根目录下,这时候我们需要手动载入自定义配置文件,有以下几种方式:

  • 方式一:appsettings.json 中 (推荐)
支持版本

v2.16.7+ 版本有效

{  "ConfigurationScanDirectories": ["目录1名称", "目录1名称/子目录名称"]}
  • 方式二:.NET5Program.cs 中配置
public class Program{    public static void Main(string[] args)    {        CreateHostBuilder(args).Build().Run();    }    public static IHostBuilder CreateHostBuilder(string[] args) =>        Host.CreateDefaultBuilder(args)            .ConfigureAppConfiguration((hostingContext, config) =>            {                // 加载自定义配置                config.AddJsonFile("MyConfig.json", optional: true, reloadOnChange: true);            })            .ConfigureWebHostDefaults(webBuilder =>            {                webBuilder.UseStartup<Startup>();            });}
  • 方式三:.NET6Program.cs 中配置
var builder = WebApplication.CreateBuilder(args)builder.Configuration.AddJsonFile("MyConfig.json", optional: true, reloadOnChange: true);// 注意先添加配置再初始化 Furionbuilder.Inject();var app = builder.Build();app.Run();

如果使用 Serve.Run() 模式可使用下列代码配置:

Serve.Run(RunOptions.Default.ConfigureConfiguration(configuration => {  configuration.AddJsonFile("MyConfig.json", optional: true, reloadOnChange: true);}));

4.1.8 配置的优缺点

  • 优点

    • 能够在系统运行时快速读取
    • 无需额外配置
  • 缺点

    • 存在重复读取
    • 通过硬编码字符串读取,容易出错
    • 不能设置默认值
    • 不能在运行环境中动态配置
    • 不能验证配置有效性
    • 不支持更改通知

4.1.9 配置使用场景

如果只需要一次性读取配置信息,则使用配置,否则应该使用 《4.2 选项》代替。

4.1.10 实现配置中心

ASP.NET Core 除了通过配置文件读取配置信息外,还支持自定义 配置提供程序,通过 配置提供程序 可以实现配置中心,比如通过数据库提供配置。

具体实现查看微软官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/?view=aspnetcore-5.0#custom-configuration-provider

采用该方式后,如果数据发生改变可调用 App.Configuration.Reload() 刷新即可。

4.1.11 重载配置

Furion 会在应用启动的时候对 IConfiguration 进行静态缓存,如果使用了 App.Configuration 静态属性且配置数据已发生变更,则调用以下方法刷新即可:

App.Configuration.Reload();

4.1.12 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 配置 知识可查阅 ASP.NET Core - 配置 章节。

演练场
- - +

4.1 配置

温馨提示

推荐使用 《4.2 选项》代替本章节功能。(为什么)?

自定义配置特别注意

如:xxxx.json,必须在 VS Studio 中右键属性设置 复制输出目录为如果较新则复制,生成操作为:内容

如果 .json 文件配置在多个项目层,也必须保证命名唯一,不然编译后出现相互覆盖的情况。

中文乱码问题

默认情况下,.json 文件并未采用 utf-8 编码,所以如果存在中文读取后就会出现乱码情况,这时候,只需要修改 .json 文件编码为 utf-8 即可。

4.1.1 什么是配置

简单来说,配置将系统应用可动态调配的选项放在统一地方管理,通过不同的配置让系统做出动态调整。

ASP.NET Core 应用程序启动时默认加载 启动项目 下的 appsettings.json 作为应用配置。同时还支持不同的运行环境加载对应的配置文件,如:

  • Development:加载 appsettings.Development.json
  • Staging:加载 appsettings.Staging.json
  • {Environment}appsettings.{Environment}.json

4.1.2 配置的使用

假设我们需要在系统运行时获取系统名称、版本号及版权信息,这些信息可能随时变化而且需要在多个地方使用。这时就需要将这些信息配置起来。具体步骤如下:

4.1.2.1 配置 appsettings.json 信息

{  "AppInfo": {    "Name": "Furion",    "Version": "1.0.0",    "Company": "Baiqian"  }}
特别注意

appsettings.json 复制输出目录为如果较新则复制,生成操作为:内容

另外,某些 linux 系统不支持读取带 注释 的 json 文件,直接读取将会报错。需要将 json 内的注释全部 删除 才能正常读取。

4.1.2.2 读取 appsettings.json 信息

Furion 框架中,提供了两种读取方式:

  • 依赖注入 IConfiguration 对象读取
  • 通过 App.Configuration[path] 读取
using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    [Route("api/[controller]")]    public class DefaultController : ControllerBase    {        [HttpGet]        public string Get()        {            return $@"名称:{App.Configuration["AppInfo:Name"]}                      版本:{App.Configuration["AppInfo:Version"]}                      公司:{App.Configuration["AppInfo:Company"]}";        }    }}
依赖注入的方式

通过依赖注入注入实例有几种方式:

  • 构造函数注入方式
private readonly IConfiguration _configuration;public DefaultController(IConfiguration configuration){    _configuration = configuration;}
  • 参数注入方式 [FromServices]
public string Get([FromServices] IConfiguration configuration){}
  • 属性注入方式
public IConfiguration Configuration { get; set; }

想了解更多关于《ASP.NET Core - 依赖注入》 知识

4.1.2.3 如何选择读取方式

  • 在可依赖注入类中,依赖注入 IConfiguration 读取
  • 在静态类/非依赖注入类中,选择 App.Configuration[path] 读取

4.1.2.4 读取配置并转换成特定类型

ASP.NET CoreFurion 提供了多种配置类型读取并转换成特定类型,包括基础类型,对象类型,数组,集合,字典等等,如:

// ASP.NET Corevar data = Configuration.GetSection("配置节点").Get<类型>();// Furion,推荐!!!var data = App.GetConfig<类型>("配置节点");

4.1.3 路径符 查找节点

ASP.NET Core 中,配置采用 : 分隔符来读取分层配置数据。如上述例子中的 AppInfo:Name。如有更多层级数据则只需要通过 : 进入下一层节点即可。

假设我们有以下配置信息:

{  "AppInfo": {    "Name": "Furion",    "Version": "1.0.0",    "Company": {      "Name": "Baiqian",      "Address": {        "City": "中国",        "Province": "广东省",        "Detail": "中山市东区紫马公园西门"      }    }  }}
var companyName = App.Configuration["AppInfo:Name"]; // => Furion

4.1.3.1 查找数组节点

有些时候我们需要或者数组特定的某些,可以通过 App.Configuration["array:0"] 获取,0 是索引数字。

4.1.4 自定义配置文件

XML 配置说明

Furion v2.8.0 版本移除了 .xml 文件自动扫描配置了,改为手动添加配置。

大多情况下,我们的配置只需要在 appsettings.json 中配置即可,但一些特殊情况下,我们希望某些组件或功能拥有独立的配置,这个时候就需要用到自定义配置,Furion 目前支持 .json.xml 两种方式配置,如:

Furion.Web.Entry/emailsetting.json
{  "outlook": {    "smtp": {      "server": "smtp.office365.com",      "port": "587",      "ssl": "STARTTLS"    },    "pop": {      "server": "outlook.office365.com",      "port": "995",      "ssl": "TLS"    }  }}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<MyKey>MyXMLFile Value</MyKey>
<Position>
<Title>Title from MyXMLFile</Title>
<Name>Name from MyXMLFile</Name>
</Position>
<Logging>
<LogLevel>
<Default>Information</Default>
<Microsoft>Warning</Microsoft>
</LogLevel>
</Logging>
</configuration>
xml 配置事项

如果采用 xml 配置,那么文件名必须以 .config.xml 结尾(不区分大小写)。

特别说明

Furion 框架会在启动时自动扫描每一个项目层根目录下的 *.json 文件加入配置中,所以无需手工配置。

新增 *.json 文件的属性 复制到输出目录 设置为始终复制或较新复制,否则不会载入。另外配置文件不能出现重名,也就是保证整个项目中配置文件名字唯一。比如不能在非 Web 其他层定义 appsettings.json 文件。

v2.16.7+ 版本版本之后,支持自定义配置扫描目录:

{  "ConfigurationScanDirectories": ["目录1名称", "目录1名称/子目录名称"]}

同时 Furion 提供了非常灵活的方式支持自定义配置文件读取,如:

4.1.4.1 读取 emailsetting.json 配置

读取自定义配置文件和读取 appsettings.json 一致,系统会自动从多个配置文件中读取输入,如:

var smtpServer = App.Configuration["outlook:smtp:server"]; // => smtp.office365.com

4.1.4.2 排除特定配置文件

有些时候,我们不需要 .json.xml 自动载入配置中,我们只需要在启动层 appsettings.json 中添加 IgnoreConfigurationFiles 节点即可:

{  "IgnoreConfigurationFiles": ["runtime.json"]}

4.1.5 不同环境读取

在实际应用开发中,我们可能会根据不同的环境加载不同的配置文件,如 数据库连接字符串

这时我们只需要遵循特定命名规范 {name}.{Environment}.json 即可。如:

  • appsettings.Development.json
  • appsettings.Staging.json
  • appsettings.Production.json
  • emailsetting.Development.json
  • emailsetting.Staging.json
  • emailsetting.Production.json

这时,ASP.NET Core 会在应用启动时自动加载不同环境的配置文件。

4.1.6 配置更改通知(热更新

.NET Core 应用程序中,配置支持更改通知,也就是热更新操作。一旦监听到 appsetting.json 或自定义配置文件发生变动,就会触发 OnChange 方法。代码如下:

var appInfoConfiguration = App.Configuration.GetSection("AppInfo");ChangeToken.OnChange(() => App.Configuration.GetReloadToken(), () =>{  var name = appInfoConfiguration["Name"];  // 实时的最新值  var version = appInfoConfiguration["Version"];  // 实时的最新值});
监听对象

如果监听全局配置文件传入 App.Configuration.GetReloadToken(),如果只需要监听特定节点,传入 App.Configuration.GetSection("AppInfo")

4.1.7 手动添加配置文件

获取路径说明
  • 获取项目目录:AppContext.BaseDirectory
  • 获取网站根目录:Directory.GetCurrentDirectory()

有些时候,我们的配置文件没有放在项目的根目录下,这时候我们需要手动载入自定义配置文件,有以下几种方式:

  • 方式一:appsettings.json 中 (推荐)
支持版本

v2.16.7+ 版本有效

{  "ConfigurationScanDirectories": ["目录1名称", "目录1名称/子目录名称"]}
  • 方式二:.NET5Program.cs 中配置
public class Program{    public static void Main(string[] args)    {        CreateHostBuilder(args).Build().Run();    }    public static IHostBuilder CreateHostBuilder(string[] args) =>        Host.CreateDefaultBuilder(args)            .ConfigureAppConfiguration((hostingContext, config) =>            {                // 加载自定义配置                config.AddJsonFile("MyConfig.json", optional: true, reloadOnChange: true);            })            .ConfigureWebHostDefaults(webBuilder =>            {                webBuilder.UseStartup<Startup>();            });}
  • 方式三:.NET6Program.cs 中配置
var builder = WebApplication.CreateBuilder(args)builder.Configuration.AddJsonFile("MyConfig.json", optional: true, reloadOnChange: true);// 注意先添加配置再初始化 Furionbuilder.Inject();var app = builder.Build();app.Run();

如果使用 Serve.Run() 模式可使用下列代码配置:

Serve.Run(RunOptions.Default.ConfigureConfiguration(configuration => {  configuration.AddJsonFile("MyConfig.json", optional: true, reloadOnChange: true);}));

4.1.8 配置的优缺点

  • 优点

    • 能够在系统运行时快速读取
    • 无需额外配置
  • 缺点

    • 存在重复读取
    • 通过硬编码字符串读取,容易出错
    • 不能设置默认值
    • 不能在运行环境中动态配置
    • 不能验证配置有效性
    • 不支持更改通知

4.1.9 配置使用场景

如果只需要一次性读取配置信息,则使用配置,否则应该使用 《4.2 选项》代替。

4.1.10 实现配置中心

ASP.NET Core 除了通过配置文件读取配置信息外,还支持自定义 配置提供程序,通过 配置提供程序 可以实现配置中心,比如通过数据库提供配置。

具体实现查看微软官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/?view=aspnetcore-5.0#custom-configuration-provider

采用该方式后,如果数据发生改变可调用 App.Configuration.Reload() 刷新即可。

4.1.11 重载配置

Furion 会在应用启动的时候对 IConfiguration 进行静态缓存,如果使用了 App.Configuration 静态属性且配置数据已发生变更,则调用以下方法刷新即可:

App.Configuration.Reload();

4.1.12 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 配置 知识可查阅 ASP.NET Core - 配置 章节。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/contribute/index.html b/handbook/build/docs/contribute/index.html index db71e9a6cb..b883c4dc1b 100644 --- a/handbook/build/docs/contribute/index.html +++ b/handbook/build/docs/contribute/index.html @@ -2,22 +2,21 @@ - - - + +38. 贡献指南 | Furion -38. 贡献指南 | Furion - - + + +
-

38. 贡献指南

38.1 提交错误报告

如果您在 Furion 中发现了一个不存在安全问题的漏洞,请在 Furion 仓库中的 Issues 中搜索,以防该漏洞已被提交,如果找不到漏洞可以创建一个新的 Issues,如果发现了一个安全问题请不要将其公开,请参阅安全问题处理方式,提交错误报告时应该详尽。

38.2 安全问题处理

本项目中对安全问题处理的形式,项目核心人员确认编辑,该部分内容可以根据项目情况添加。

38.3 解决现有问题

通过查看仓库的 Issues 列表可以发现需要处理的问题信息,可以尝试解决其中的某个问题。

38.4 如何提出新功能

提出新功能有些项目使用 Issues 的 Feature 标签进行管理,有些则通过邮件的形式统一收集,在收集后项目内人员会进行确认开发,一般将确认开发的功能会放入下一个版本的任务列表。

38.5 如何设置开发环境并运行测试

如果是通过 Git 管理可以从 git clone https://gitee.com/dotnetchina/Furion.git 开始编写,将开发环境的配置信息,IDE 的设置等信息配置文档编写。

38.6 变更日志填写规则

  1. 使用现在时态
  2. 第一行字数限制
  3. 提交内容的约束

38.7 编码约定

  • 项目内编码约定文件:.editorconfig

38.8 分支处理约定

  • 分支处理形式,如 gitFlow

38.9 合并 PR 的形式

在什么情况下可以合并到 master/main:

  1. 通过 CI
  2. 两个及以上的维护者通过.
  3. 最新版本
演练场
- - +

38. 贡献指南

38.1 提交错误报告

如果您在 Furion 中发现了一个不存在安全问题的漏洞,请在 Furion 仓库中的 Issues 中搜索,以防该漏洞已被提交,如果找不到漏洞可以创建一个新的 Issues,如果发现了一个安全问题请不要将其公开,请参阅安全问题处理方式,提交错误报告时应该详尽。

38.2 安全问题处理

本项目中对安全问题处理的形式,项目核心人员确认编辑,该部分内容可以根据项目情况添加。

38.3 解决现有问题

通过查看仓库的 Issues 列表可以发现需要处理的问题信息,可以尝试解决其中的某个问题。

38.4 如何提出新功能

提出新功能有些项目使用 Issues 的 Feature 标签进行管理,有些则通过邮件的形式统一收集,在收集后项目内人员会进行确认开发,一般将确认开发的功能会放入下一个版本的任务列表。

38.5 如何设置开发环境并运行测试

如果是通过 Git 管理可以从 git clone https://gitee.com/dotnetchina/Furion.git 开始编写,将开发环境的配置信息,IDE 的设置等信息配置文档编写。

38.6 变更日志填写规则

  1. 使用现在时态
  2. 第一行字数限制
  3. 提交内容的约束

38.7 编码约定

  • 项目内编码约定文件:.editorconfig

38.8 分支处理约定

  • 分支处理形式,如 gitFlow

38.9 合并 PR 的形式

在什么情况下可以合并到 master/main:

  1. 通过 CI
  2. 两个及以上的维护者通过.
  3. 最新版本
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/cors/index.html b/handbook/build/docs/cors/index.html index fbbee94f2f..6c63837d30 100644 --- a/handbook/build/docs/cors/index.html +++ b/handbook/build/docs/cors/index.html @@ -2,22 +2,21 @@ - - - + +16. CORS 跨域 | Furion -16. CORS 跨域 | Furion - - + + +
-

16. CORS 跨域

16.1 什么是跨域

简单来说,当一个请求 url 的协议、域名、端口三者之间任意一个与当前页面 url 不同即为跨域。那为什么会出现跨域问题呢?

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的 javascript 脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

16.2 有跨域行为示例

当前页面 url被请求页面 url是否跨域原因
http://www.furion.icu/http://www.furion.icu/index.html同源(协议、域名、端口号相同)
http://www.furion.icu/https://www.furion.icu/index.html跨域协议不同(http/https)
http://www.furion.icu/http://www.baidu.com/跨域主域名不同(chinadot/baidu)
http://www.furion.icu/http://blog.furion.icu/跨域子域名不同(www/blog)
http://www.furion.icu:8080/http://www.furion.icu:7001/跨域端口号不同(8080/7001)

16.3 什么是 CORS

跨源资源共享 (CORS) :

  • 是一种 W3C 标准,可让服务器放宽相同的源策略。
  • 不是一项安全功能,CORS 放宽 securityAPI 不能通过允许 CORS 来更安全。 有关详细信息,请参阅 CORS 工作原理
  • 允许服务器明确允许一些跨源请求,同时拒绝其他请求。
  • 比早期的技术(如 JSONP)更安全且更灵活。

16.4 如何使用

16.4.1 添加 CORS 服务

启用跨域 Cors 支持首先添加 CorsAccessor 服务,如:

using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace Furion.Web.Core{    [AppStartup(700)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddCorsAccessor();            // ...        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            //...            app.UseCorsAccessor();            // ...        }    }}
特别注意

services.AddCorsAccessor(); 需在 services.AddControllers() 之前注册。

app.UseCorsAccessor(); 需在 app.UseRouting();app.UseAuthentication(); 之间注册。

16.4.2 配置允许跨域域名

小提醒

默认情况下,Furion 允许所有域名来源访问,也就是无需配置任何来源域名,另外前端也需要设置请求参数:withCredentials:false

如果需要指定特定域名,则添加以下配置即可:

{  "CorsAccessorSettings": {    "PolicyName": "自定义跨域策略名",    "WithOrigins": ["http://localhost:4200", "https://furion.icu"]  }}

16.5 CorsAccessorSettings 配置

  • CorsAccessorSettings
    • PolicyName:跨域策略名,string 类型,必填,默认 App.Cors.Policy
    • WithOrigins:允许跨域的域名列表,string[] 类型,默认 *
    • WithHeaders:请求表头,没有配置则允许所有表头,string[] 类型
    • WithExposedHeaders:设置客户端可获取的响应标头,string[] 类型,默认 ["access-token", "x-access-token"]
    • WithMethods:设置跨域允许请求谓词,没有配置则允许所有,string[] 类型
    • AllowCredentials:是否允许跨域请求中的凭据,bool 类型,默认值 true
    • SetPreflightMaxAge:设置预检过期时间,int 类型,默认值 24小时
    • FixedClientToken:是否默认配置 WithExposedHeadersbool 类型,默认 true
    • SignalRSupport:是否启用 SignalR 跨域支持,bool 类型,默认 false

16.6 前端不能读取响应头注意事项

有时候,我们通过 ajax 或者 axios 第三方库无法读取响应头自定义信息,这时需要响应报文中公开特定 Header 才能放行,如:Access-Control-Expose-Headers: xxxxx,所以,需要添加以下配置:

appsettings.json
{  "CorsAccessorSettings": {    "WithExposedHeaders": ["access-token","x-access-token"]  }}

需要获取哪个头,就在 WithExposedHeaders 数组中配置即可。如果使用 ajax 可以通过 xhr.getResponseHeader(key)xhr.getAllResponseHeaders() 获取配置的 key

特别情况下不能请求,可以考虑设置 withCredentials: false

16.7 使用 $.ajax 前端注意事项

使用 Jquery 前端请求可以参考以下配置:

$.ajax({        url: "https://localhost:5001/api/system/getdata",        type: "GET",        xhrFields: {            withCredentials: false  // 如果是https请求,可以试试 true        },        crossDomain: true,        success: function (res) {            render(res);        }});
特别注意

在本地开发阶段,请求如果出现 Access to XMLHttpRequest...has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header... 错误,请确保 ajaxurl 参数是正确的,通常错误的做法是:

  • 使用了 127.0.0.1 而不是 localhost 主机地址
  • 使用 http 而不是 https 主机协议
  • 使用了 5000 而不是 5001 主机端口

16.8 禁用跨域

有时候,我们希望某个方法不检查跨域请求,可以在 Action 中贴 [DisableCors] 特性即可。

16.9 SignalR 跨域问题

SignalR 实现跨域需要满足下面几个条件:

  • 允许特定的预期来源,允许任何来源是可行的,但不安全或不推荐使用
  • 必须允许使用 HTTP 方法 GETPOST
  • 为了使基于 cookie 的粘滞会话正常工作,必须允许使用凭据,即使未使用身份验证,也必须启用它们。

官方文档说明 https://docs.microsoft.com/zh-cn/aspnet/core/signalr/security?view=aspnetcore-6.0

Furion 4.1.4+ 版本已修正 SignalR 跨域问题,只需要启用 SignalRSupport 配置即可,如:

{  "CorsAccessorSettings": {    "SignalRSupport": true  }}

16.10 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 跨域请求 知识可查阅 ASP.NET Core - 启用跨域请求 章节。

演练场
- - +

16. CORS 跨域

16.1 什么是跨域

简单来说,当一个请求 url 的协议、域名、端口三者之间任意一个与当前页面 url 不同即为跨域。那为什么会出现跨域问题呢?

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的 javascript 脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

16.2 有跨域行为示例

当前页面 url被请求页面 url是否跨域原因
http://www.furion.icu/http://www.furion.icu/index.html同源(协议、域名、端口号相同)
http://www.furion.icu/https://www.furion.icu/index.html跨域协议不同(http/https)
http://www.furion.icu/http://www.baidu.com/跨域主域名不同(chinadot/baidu)
http://www.furion.icu/http://blog.furion.icu/跨域子域名不同(www/blog)
http://www.furion.icu:8080/http://www.furion.icu:7001/跨域端口号不同(8080/7001)

16.3 什么是 CORS

跨源资源共享 (CORS) :

  • 是一种 W3C 标准,可让服务器放宽相同的源策略。
  • 不是一项安全功能,CORS 放宽 securityAPI 不能通过允许 CORS 来更安全。 有关详细信息,请参阅 CORS 工作原理
  • 允许服务器明确允许一些跨源请求,同时拒绝其他请求。
  • 比早期的技术(如 JSONP)更安全且更灵活。

16.4 如何使用

16.4.1 添加 CORS 服务

启用跨域 Cors 支持首先添加 CorsAccessor 服务,如:

using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace Furion.Web.Core{    [AppStartup(700)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddCorsAccessor();            // ...        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            //...            app.UseCorsAccessor();            // ...        }    }}
特别注意

services.AddCorsAccessor(); 需在 services.AddControllers() 之前注册。

app.UseCorsAccessor(); 需在 app.UseRouting();app.UseAuthentication(); 之间注册。

16.4.2 配置允许跨域域名

小提醒

默认情况下,Furion 允许所有域名来源访问,也就是无需配置任何来源域名,另外前端也需要设置请求参数:withCredentials:false

如果需要指定特定域名,则添加以下配置即可:

{  "CorsAccessorSettings": {    "PolicyName": "自定义跨域策略名",    "WithOrigins": ["http://localhost:4200", "https://furion.icu"]  }}

16.5 CorsAccessorSettings 配置

  • CorsAccessorSettings
    • PolicyName:跨域策略名,string 类型,必填,默认 App.Cors.Policy
    • WithOrigins:允许跨域的域名列表,string[] 类型,默认 *
    • WithHeaders:请求表头,没有配置则允许所有表头,string[] 类型
    • WithExposedHeaders:设置客户端可获取的响应标头,string[] 类型,默认 ["access-token", "x-access-token"]
    • WithMethods:设置跨域允许请求谓词,没有配置则允许所有,string[] 类型
    • AllowCredentials:是否允许跨域请求中的凭据,bool 类型,默认值 true
    • SetPreflightMaxAge:设置预检过期时间,int 类型,默认值 24小时
    • FixedClientToken:是否默认配置 WithExposedHeadersbool 类型,默认 true
    • SignalRSupport:是否启用 SignalR 跨域支持,bool 类型,默认 false

16.6 前端不能读取响应头注意事项

有时候,我们通过 ajax 或者 axios 第三方库无法读取响应头自定义信息,这时需要响应报文中公开特定 Header 才能放行,如:Access-Control-Expose-Headers: xxxxx,所以,需要添加以下配置:

appsettings.json
{  "CorsAccessorSettings": {    "WithExposedHeaders": ["access-token","x-access-token"]  }}

需要获取哪个头,就在 WithExposedHeaders 数组中配置即可。如果使用 ajax 可以通过 xhr.getResponseHeader(key)xhr.getAllResponseHeaders() 获取配置的 key

特别情况下不能请求,可以考虑设置 withCredentials: false

16.7 使用 $.ajax 前端注意事项

使用 Jquery 前端请求可以参考以下配置:

$.ajax({        url: "https://localhost:5001/api/system/getdata",        type: "GET",        xhrFields: {            withCredentials: false  // 如果是https请求,可以试试 true        },        crossDomain: true,        success: function (res) {            render(res);        }});
特别注意

在本地开发阶段,请求如果出现 Access to XMLHttpRequest...has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header... 错误,请确保 ajaxurl 参数是正确的,通常错误的做法是:

  • 使用了 127.0.0.1 而不是 localhost 主机地址
  • 使用 http 而不是 https 主机协议
  • 使用了 5000 而不是 5001 主机端口

16.8 禁用跨域

有时候,我们希望某个方法不检查跨域请求,可以在 Action 中贴 [DisableCors] 特性即可。

16.9 SignalR 跨域问题

SignalR 实现跨域需要满足下面几个条件:

  • 允许特定的预期来源,允许任何来源是可行的,但不安全或不推荐使用
  • 必须允许使用 HTTP 方法 GETPOST
  • 为了使基于 cookie 的粘滞会话正常工作,必须允许使用凭据,即使未使用身份验证,也必须启用它们。

官方文档说明 https://docs.microsoft.com/zh-cn/aspnet/core/signalr/security?view=aspnetcore-6.0

Furion 4.1.4+ 版本已修正 SignalR 跨域问题,只需要启用 SignalRSupport 配置即可,如:

{  "CorsAccessorSettings": {    "SignalRSupport": true  }}

16.10 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 跨域请求 知识可查阅 ASP.NET Core - 启用跨域请求 章节。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/course/index.html b/handbook/build/docs/course/index.html index 5008d26ecc..5ef10b0c58 100644 --- a/handbook/build/docs/course/index.html +++ b/handbook/build/docs/course/index.html @@ -2,22 +2,21 @@ - - - + +1.7 发展大事记 | Furion -1.7 发展大事记 | Furion - - + + +
-

1.7 发展大事记

2020 年

  • 2020 年 06 月 29 日,在 Gitee 平台创建了 Fur 仓库。
  • 2020 年 09 月 01 日,正式写下第一行代码。
  • 2020 年 10 月 22 日Fur 在 Gitee 平台获得 1000 stars.
  • 2020 年 11 月 11 日,单身节当天发布了 1.0.0 正式版。
  • 2020 年 11 月 20 日Fur 改名为 Furion
  • 2020 年 11 月 23 日Furion Logo 由之前的 奶牛 更换为 袋鼠
  • 2020 年 12 月 22 日Furion 在 Gitee 平台获得 2000 stars。

2021 年

  • 2021 年 03 月 01 日Furion 捐赠项目到 dotNET China 组织。
  • 2021 年 03 月 05 日Furion 在 Gitee 平台获得 3000 stars。
  • 2021 年 04 月 01 日Furion 所在群 dotNET China 突破 5000 人。
  • 2021 年 04 月 06 日Furion 在 Gitee 平台获得 4000 stars。
  • 2021 年 04 月 19 日Furion 正式发布 2.0.0 版本,并支持控制台应用开发。
  • 2021 年 04 月 29 日Furion 所在群 dotNET China 突破 6000 人。
  • 2021 年 05 月 13 日Furion 在 Gitee 平台获得 5000 stars。
  • 2021 年 06 月 01 日Furion 所在群 dotNET China 突破 7000 人。
  • 2021 年 06 月 22 日Furion 在 Gitee 平台获得 6000 stars。
  • 2021 年 07 月 04 日Furion 登顶 Gitee 平台 C# 语言板块第一名。
  • 2021 年 07 月 16 日Furion 采用 百小僧 头像作为 Logo
  • 2021 年 07 月 20 日FurionApache 2.0 开源协议修改为 MulanPSL-2.0 (木兰宽松许可证)
  • 2021 年 07 月 27 日Furion 正式支持全平台、.NET 全平台项目开发。
  • 2021 年 08 月 11 日Furion 加入 木兰开源社区 重点孵化。
  • 2021 年 08 月 21 日FurionNuget 平台突破 100万 安装量。
  • 2021 年 08 月 30 日Furion 在 Gitee 平台获得 7000 stars。
  • 2021 年 09 月 01 日Furion 诞生一周年。
  • 2021 年 11 月 09 日Furion 正式发布 3.0.0 版本,全新的 .NET6 架构。

2022 年

  • 2022 年 05 月 20 日Furion 在 Gitee 平台获得 8000 Stars。
  • 2022 年 06 月 18 日Furion 有了自己的入口函数 Serve.Run() 和错误页。
  • 2022 年 06 月 20 日Furion 项目贡献者突破 200 人。
  • 2022 年 07 月 25 日Furion 正式发布 4.0.0 版本,彻底实现大一统(.NET5-.NET N)都可以升级。
  • 2022 年 08 月 01 日FurionMulanPSL-2.0 开源协议修改为 MIT
  • 2022 年 08 月 18 日FurionNuget 平台突破 300万 安装量。
  • 2022 年 09 月 01 日Furion 诞生两周年。
演练场
- - +

1.7 发展大事记

2020 年

  • 2020 年 06 月 29 日,在 Gitee 平台创建了 Fur 仓库。
  • 2020 年 09 月 01 日,正式写下第一行代码。
  • 2020 年 10 月 22 日Fur 在 Gitee 平台获得 1000 stars.
  • 2020 年 11 月 11 日,单身节当天发布了 1.0.0 正式版。
  • 2020 年 11 月 20 日Fur 改名为 Furion
  • 2020 年 11 月 23 日Furion Logo 由之前的 奶牛 更换为 袋鼠
  • 2020 年 12 月 22 日Furion 在 Gitee 平台获得 2000 stars。

2021 年

  • 2021 年 03 月 01 日Furion 捐赠项目到 dotNET China 组织。
  • 2021 年 03 月 05 日Furion 在 Gitee 平台获得 3000 stars。
  • 2021 年 04 月 01 日Furion 所在群 dotNET China 突破 5000 人。
  • 2021 年 04 月 06 日Furion 在 Gitee 平台获得 4000 stars。
  • 2021 年 04 月 19 日Furion 正式发布 2.0.0 版本,并支持控制台应用开发。
  • 2021 年 04 月 29 日Furion 所在群 dotNET China 突破 6000 人。
  • 2021 年 05 月 13 日Furion 在 Gitee 平台获得 5000 stars。
  • 2021 年 06 月 01 日Furion 所在群 dotNET China 突破 7000 人。
  • 2021 年 06 月 22 日Furion 在 Gitee 平台获得 6000 stars。
  • 2021 年 07 月 04 日Furion 登顶 Gitee 平台 C# 语言板块第一名。
  • 2021 年 07 月 16 日Furion 采用 百小僧 头像作为 Logo
  • 2021 年 07 月 20 日FurionApache 2.0 开源协议修改为 MulanPSL-2.0 (木兰宽松许可证)
  • 2021 年 07 月 27 日Furion 正式支持全平台、.NET 全平台项目开发。
  • 2021 年 08 月 11 日Furion 加入 木兰开源社区 重点孵化。
  • 2021 年 08 月 21 日FurionNuget 平台突破 100万 安装量。
  • 2021 年 08 月 30 日Furion 在 Gitee 平台获得 7000 stars。
  • 2021 年 09 月 01 日Furion 诞生一周年。
  • 2021 年 11 月 09 日Furion 正式发布 3.0.0 版本,全新的 .NET6 架构。

2022 年

  • 2022 年 05 月 20 日Furion 在 Gitee 平台获得 8000 Stars。
  • 2022 年 06 月 18 日Furion 有了自己的入口函数 Serve.Run() 和错误页。
  • 2022 年 06 月 20 日Furion 项目贡献者突破 200 人。
  • 2022 年 07 月 25 日Furion 正式发布 4.0.0 版本,彻底实现大一统(.NET5-.NET N)都可以升级。
  • 2022 年 08 月 01 日FurionMulanPSL-2.0 开源协议修改为 MIT
  • 2022 年 08 月 18 日FurionNuget 平台突破 300万 安装量。
  • 2022 年 09 月 01 日Furion 诞生两周年。
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dapper/index.html b/handbook/build/docs/dapper/index.html index 2996e81d73..ac797f941f 100644 --- a/handbook/build/docs/dapper/index.html +++ b/handbook/build/docs/dapper/index.html @@ -2,22 +2,21 @@ - - - + +10.2 Dapper 集成 | Furion -10.2 Dapper 集成 | Furion - - + + +
-

10.2 Dapper 集成

温馨提醒

Furion 包中默认集成了 EFCore如果不使用 EFCore,可安装纯净版 Furion.Pure 代替 Furion

10.2.1 关于 Dapper

Dapper 是 .NET/C# 平台非常优秀的 微型 ORM 框架,主要是为 ADO.NET 操作对象提供拓展能力,推崇原生 sql 操作法。

Dapper 官方仓库地址:https://github.com/StackExchange/Dapper

10.2.2 如何集成

Furion 框架中,已经推出 Dapper 拓展包 Furion.Extras.DatabaseAccessor.Dapper

10.2.2.1 注册 Dapper 服务

使用非常简单,只需要在 Startup.cs 中添加 services.AddDapper(connStr, SqlProvider) 即可。如:

services.AddDapper("Data Source=./Furion.db", SqlProvider.Sqlite);// 更多配置,仅 v3.4.3+ 版本有效servers.AddDapper("Data Source=./Furion.db", SqlProvider.Sqlite, () => {  DefaultTypeMap.MatchNamesWithUnderscores = true;})

10.2.2.2 安装对应的数据库提供器

  • SqlServerMicrosoft.Data.SqlClient
  • SqliteMicrosoft.Data.Sqlite
  • MySqlMySql.Data
  • NpgsqlNpgsql
  • OracleOracle.ManagedDataAccess.Core
  • FirebirdFirebirdSql.Data.FirebirdClient
安装拓展包位置

Furion 框架中,推荐将拓展包 Furion.Extras.DatabaseAccessor.Dapper 安装到 Furion.Core 层中。

10.2.3 基本使用

在使用之前,我们可以通过构造函数注入 IDapperRepositoryIDapperRepository<TEntity> 接口,如:

  • 非泛型版本
private readonly IDapperRepository _dapperRepository;public PersonService(IDapperRepository dapperRepository){    _dapperRepository = dapperRepository;}
  • 泛型版本
private readonly IDapperRepository<Person> _personRepository;public PersonService(IDapperRepository<Person> personRepository){    _personRepository = personRepository;}

10.2.3.1 sql 操作

var data = _dapperRepository.Query("select * from person");var data = await _dapperRepository.QueryAsync("select * from person");var data = _dapperRepository.Query<Person>("select * from person");var guid = Guid.NewGuid();var dog = _dapperRepository.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });
var count = _dapperRepository.Execute(@"insert MyTable(colA, colB) values (@a, @b)",    new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }  );var user = _dapperRepository.Query<User>("spGetUser", new {Id = 1},        commandType: CommandType.StoredProcedure).SingleOrDefault();

用法和官方一致,此处不再举更多例子。

10.2.3.2 <TEntity> 操作

Furion 框架提供了 IDapperRepositoryIDapperRepository<TEntity> 两个操作仓储,后者继承前者。使用如下:

var person = personRepository.Get(1);var persons = personRepository.GetAll();var effects = personRepository.Insert(person);var effects = personRepository.Update(person);var effects = personRepository.Delete(person);var effects = personRepository.Insert(persons); // 插入多个var effects = personRepository.Update(persons); // 更新多个var effects = personRepository.Delete(persons); // 删除多个var effects = await personRepository.InsertAsync(person);

10.2.4 高级使用

IDapperRepositoryIDapperRepository<TEntity> 仓储提供了 ContextDynamicContext 属性,该属性返回 IDbConnection 对象。

拿到该对象后,我们就可以操作 Dapper 提供的所有操作了,如:

10.2.4.1 查询一对一

var sql =@"select * from #Posts pleft join #Users u on u.Id = p.OwnerIdOrder by p.Id";var data = dapperRepository.Context.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post;});var post = data.First();

10.2.4.2 查询多个结果

var sql =@"select * from Customers where CustomerId = @idselect * from Orders where CustomerId = @idselect * from Returns where CustomerId = @id";using (var multi = dapperRepository.Context.QueryMultiple(sql, new {id=selectedId})){  var customer = multi.Read<Customer>().Single();  var orders = multi.Read<Order>().ToList();  var returns = multi.Read<Return>().ToList();  // ...}

10.2.4.3 更多操作

var shapes = new List<IShape>();using (var reader = dapperRepository.Context.ExecuteReader("select * from Shapes")){   var circleParser = reader.GetRowParser<IShape>(typeof(Circle));   var squareParser = reader.GetRowParser<IShape>(typeof(Square));   var triangleParser = reader.GetRowParser<IShape>(typeof(Triangle));   var typeColumnIndex = reader.GetOrdinal("Type");   while (reader.Read())   {       IShape shape;       var type = (ShapeType)reader.GetInt32(typeColumnIndex);       switch (type)       {           case ShapeType.Circle:            shape = circleParser(reader);            break;           case ShapeType.Square:            shape = squareParser(reader);            break;           case ShapeType.Triangle:            shape = triangleParser(reader);            break;           default:            throw new NotImplementedException();       }        shapes.Add(shape);   }}

10.2.5 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 Dapper 知识可查阅 Dapper 官网

演练场
- - +

10.2 Dapper 集成

温馨提醒

Furion 包中默认集成了 EFCore如果不使用 EFCore,可安装纯净版 Furion.Pure 代替 Furion

10.2.1 关于 Dapper

Dapper 是 .NET/C# 平台非常优秀的 微型 ORM 框架,主要是为 ADO.NET 操作对象提供拓展能力,推崇原生 sql 操作法。

Dapper 官方仓库地址:https://github.com/StackExchange/Dapper

10.2.2 如何集成

Furion 框架中,已经推出 Dapper 拓展包 Furion.Extras.DatabaseAccessor.Dapper

10.2.2.1 注册 Dapper 服务

使用非常简单,只需要在 Startup.cs 中添加 services.AddDapper(connStr, SqlProvider) 即可。如:

services.AddDapper("Data Source=./Furion.db", SqlProvider.Sqlite);// 更多配置,仅 v3.4.3+ 版本有效servers.AddDapper("Data Source=./Furion.db", SqlProvider.Sqlite, () => {  DefaultTypeMap.MatchNamesWithUnderscores = true;})

10.2.2.2 安装对应的数据库提供器

  • SqlServerMicrosoft.Data.SqlClient
  • SqliteMicrosoft.Data.Sqlite
  • MySqlMySql.Data
  • NpgsqlNpgsql
  • OracleOracle.ManagedDataAccess.Core
  • FirebirdFirebirdSql.Data.FirebirdClient
安装拓展包位置

Furion 框架中,推荐将拓展包 Furion.Extras.DatabaseAccessor.Dapper 安装到 Furion.Core 层中。

10.2.3 基本使用

在使用之前,我们可以通过构造函数注入 IDapperRepositoryIDapperRepository<TEntity> 接口,如:

  • 非泛型版本
private readonly IDapperRepository _dapperRepository;public PersonService(IDapperRepository dapperRepository){    _dapperRepository = dapperRepository;}
  • 泛型版本
private readonly IDapperRepository<Person> _personRepository;public PersonService(IDapperRepository<Person> personRepository){    _personRepository = personRepository;}

10.2.3.1 sql 操作

var data = _dapperRepository.Query("select * from person");var data = await _dapperRepository.QueryAsync("select * from person");var data = _dapperRepository.Query<Person>("select * from person");var guid = Guid.NewGuid();var dog = _dapperRepository.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });
var count = _dapperRepository.Execute(@"insert MyTable(colA, colB) values (@a, @b)",    new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }  );var user = _dapperRepository.Query<User>("spGetUser", new {Id = 1},        commandType: CommandType.StoredProcedure).SingleOrDefault();

用法和官方一致,此处不再举更多例子。

10.2.3.2 <TEntity> 操作

Furion 框架提供了 IDapperRepositoryIDapperRepository<TEntity> 两个操作仓储,后者继承前者。使用如下:

var person = personRepository.Get(1);var persons = personRepository.GetAll();var effects = personRepository.Insert(person);var effects = personRepository.Update(person);var effects = personRepository.Delete(person);var effects = personRepository.Insert(persons); // 插入多个var effects = personRepository.Update(persons); // 更新多个var effects = personRepository.Delete(persons); // 删除多个var effects = await personRepository.InsertAsync(person);

10.2.4 高级使用

IDapperRepositoryIDapperRepository<TEntity> 仓储提供了 ContextDynamicContext 属性,该属性返回 IDbConnection 对象。

拿到该对象后,我们就可以操作 Dapper 提供的所有操作了,如:

10.2.4.1 查询一对一

var sql =@"select * from #Posts pleft join #Users u on u.Id = p.OwnerIdOrder by p.Id";var data = dapperRepository.Context.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post;});var post = data.First();

10.2.4.2 查询多个结果

var sql =@"select * from Customers where CustomerId = @idselect * from Orders where CustomerId = @idselect * from Returns where CustomerId = @id";using (var multi = dapperRepository.Context.QueryMultiple(sql, new {id=selectedId})){  var customer = multi.Read<Customer>().Single();  var orders = multi.Read<Order>().ToList();  var returns = multi.Read<Return>().ToList();  // ...}

10.2.4.3 更多操作

var shapes = new List<IShape>();using (var reader = dapperRepository.Context.ExecuteReader("select * from Shapes")){   var circleParser = reader.GetRowParser<IShape>(typeof(Circle));   var squareParser = reader.GetRowParser<IShape>(typeof(Square));   var triangleParser = reader.GetRowParser<IShape>(typeof(Triangle));   var typeColumnIndex = reader.GetOrdinal("Type");   while (reader.Read())   {       IShape shape;       var type = (ShapeType)reader.GetInt32(typeColumnIndex);       switch (type)       {           case ShapeType.Circle:            shape = circleParser(reader);            break;           case ShapeType.Square:            shape = squareParser(reader);            break;           case ShapeType.Triangle:            shape = triangleParser(reader);            break;           default:            throw new NotImplementedException();       }        shapes.Add(shape);   }}

10.2.5 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 Dapper 知识可查阅 Dapper 官网

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/data-validation/index.html b/handbook/build/docs/data-validation/index.html index 0a7d5d6999..7f88dbf12a 100644 --- a/handbook/build/docs/data-validation/index.html +++ b/handbook/build/docs/data-validation/index.html @@ -2,22 +2,21 @@ - - - + +8. 数据校验 | Furion -8. 数据校验 | Furion - - + + +
-

8. 数据校验

8.1 关于数据校验

数据校验字面上的意思就是对使用者提交过来的数据进行合法性验证。在一套完善的应用系统中,数据有效性校验是必不可少的业务处理第一道关卡。

8.2 数据校验的好处

  • 过滤不安全数据,提高系统的安全性
  • 减少不必要的业务异常处理,提高系统的响应速度
  • 大大提高系统稳定性
  • 大数据并发时起着一定的缓冲作用

8.3 数据校验方式

  • 传统方式,在业务代码之前手动验证
  • Mvc 特性方式,Mvc 内置的 DataAnnotations 方式
  • 推荐方式Furion 框架内置的 DataValidation 验证
  • 其他方式,使用第三方验证库,如 FluentValidation

8.3.1 传统方式

在很多老项目中,我们经常看到这样的代码:

public bool Insert(Person person){    // 验证参数    if(string.IsNullOrEmty(person.Name))    {        throw new System.Exception("名字不能为空");    }    if(person.Age < 18)    {        throw new System.Exception("年龄不能小于 18 岁");    }    if(!person.Password.Equals(person.ConfirmPassword)    {        throw new System.Exception("两次密码不一致");    }    // 业务代码    _repository.Insert(person.Adapt<PersonEntity>());    // ...}

从上面的代码看起来,似乎没有什么不妥,但是从一个程序可维护性来说,这是一个糟糕的代码,因为该业务代码中包含了太多与业务无关的数据验证

试想一下,如果这个 Person 有 几十个参数都需要验证呢?可想而知,这是一个庞大的业务代码。

再者,如果其他地方也需要用到这个 Person 类验证呢?那代码好比老鼠啃过的面包屑一样,到处都是。

如此得知,这样的方式是极其不推荐的,不但污染了业务代码,也破坏了业务职责单一性原理,也让验证逻辑无法实现通用,后续维护难度大大升级

8.3.2 Mvc 特性方式

ASP.NET Core 中,微软为我们提供了全新的 特性 验证方式,可通过对对象贴特性实现数据验证。这种方式有效的将数据校验和业务代码剥离开来,而且容易使用和拓展。

  • 在模型中验证
using System.ComponentModel.DataAnnotations;namespace Hoa.Application.Authorization.Dtos{    public class SignInInput    {        [Required]  // 必填验证        [MinLength(4)]  // 最小长度验证        public string Account { get; set; }        [Required]    // 必填验证        [MaxLength(32)]    // 最大长度验证        public string Password { get; set; }    }}
  • 在参数中验证
public void CheckMethodParameterValid(    [Required]    // 必填验证    [MinLength(4)]    // 最小长度验证    string name,    int age,    [Required]    // 必填验证    [RegularExpression("[a-zA-Z0-9_]{8,30}")    // 正则表达式验证    string password,    [Required]    // 必填验证    [RegularExpression("[a-zA-Z0-9_]{8,30}")    // 正则表达式验证    string confirmPassword){    // TODO}
小提醒

如果函数的参数大于或等于 3 个,建议抽离出模型类,也就是不建议上面的方式。

  • Mvc 内置特性

    • [ValidateNever]:指示熟悉或参数从验证中排除
    • [CreditCard]:信用卡格式验证
    • [Compare]:验证两个属性值是否匹配
    • [EmailAddress]:验证电子邮箱
    • [Phone]:验证电话号码
    • [Range]:验证指定范围
    • [RegularExpression]:验证属性值是否匹配正则表达式
    • [Required]:验证不为 null
    • [StringLength]:验证字符串长度
    • [URL]:验证是否有效的 URL 格式
    • [Remote]:调用远程服务地址进行客户端验证
Mvc 内置特性

想了解 Mvc 内置特性列表可查看官方文档 ASP.NET Core - 模型验证

  • 自定义特性验证
public class ClassicMovieAttribute : ValidationAttribute{    public ClassicMovieAttribute(int year)    {        Year = year;    }    public int Year { get; }    public string GetErrorMessage() =>        $"Classic movies must have a release year no later than {Year}.";    protected override ValidationResult IsValid(object value, ValidationContext validationContext)    {        var movie = (Movie)validationContext.ObjectInstance;        var releaseYear = ((DateTime)value).Year;        if (movie.Genre == Genre.Classic && releaseYear > Year)        {            return new ValidationResult(GetErrorMessage());        }        return ValidationResult.Success;    }}
  • IValidatableObject 复杂验证
using System.Collections.Generic;public class DtoModel : IValidatableObject{    [Required]    [StringLength(100)]    public string Title { get; set; }    // 你的验证逻辑    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)    {        // 还可以解析服务        var service = validationContext.GetService(typeof(类型));        if (你的逻辑代码)        {            yield return new ValidationResult(                "错误消息"                ,new[] { nameof(Title) }  // 验证失败的属性            );        }    }}

Mvc 特性方式极大的将业务逻辑和验证进行了剥离和解耦,而且还能实现自定义复杂验证。

但是 Mvc 特性验证方式有几个明显的缺点

  • 只能在 控制器 中的 Action(动作方法)中使用
  • 无法在任意类、任意方法中使用
  • 内置的验证类型非常有限,且不易拓展
  • 不支持验证消息后期配置

所以,Furion 提供了新的验证引擎 DataValidation,在完全兼容 Mvc 内置验证的同时提供了大量常见验证、复杂验证、自定义验证等能力。

8.4 DataValidation 验证 🤗

DataValidationFurion 框架提供了全新的验证方式,完全兼容 Mvc 内置验证,并且赋予了超能。

8.4.1 DataValidation 优点

  • 完全兼容 Mvc 内置验证引擎
  • 内置常见验证类型及可自定义验证类型功能
  • 提供全局对象拓展验证方式
  • 支持验证消息后期配置,支持实时更新
  • 支持在任何类,任何方法、任何位置实现手动验证、特性方式验证等
  • 支持设置验证结果模型

8.5 DataValidation 使用

备注

.AddDataValidation() 默认已经集成在 AddInject() 中了,无需再次注册。也就是 8.5.1 章节可不配置。

8.5.1 注册验证服务

Furion.Web.Core\FurWebCoreStartup.cs
using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Core{    [AppStartup(800)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddControllers()                    .AddDataValidation();        }    }}
特别注意

.AddDataValidation() 需在 services.AddControllers() 之后注册。

8.5.2 兼容 Mvc 特性验证

using System.ComponentModel.DataAnnotations;namespace Furion.Application{    public class TestDto    {        [Range(10, 20, ErrorMessage = "Id 只能在 10-20 区间取值")]        public int Id { get; set; }        [Required(ErrorMessage = "必填"), MinLength(3, ErrorMessage = "字符串长度不能少于3位")]        public string Name { get; set; }    }}

如下图所示:

8.5.3 兼容 Mvc 复杂验证

using System.Collections.Generic;using System.ComponentModel.DataAnnotations;namespace Furion.Application{    public class TestDto : IValidatableObject    {        [Range(10, 20, ErrorMessage = "Id 只能在 10-20 区间取值")]        public int Id { get; set; }        [Required(ErrorMessage = "必填"), MinLength(3, ErrorMessage = "字符串长度不能少于3位")]        public string Name { get; set; }        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)        {            // 还可以解析服务            var service = validationContext.GetService(typeof(类型));            if (Name.StartsWith("Furion"))            {                yield return new ValidationResult(                    "不能以 Furion 开头"                    , new[] { nameof(Name) }                );            }        }    }}

如下图所示:

8.6 手动验证

8.6.1 验证模型

using Furion.DataValidation;using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [NonValidation] // 跳过全局验证        public DataValidationResult Post(TestDto testDto)        {            return testDto.TryValidate();        }    }}

如下图所示:

note

支持 Mvc 内置的特性验证、属性验证及复杂的 IValidatableObject 验证。

8.6.2 TryValidateValidate

Furion 提供了 TryValidate()Validate() 两个验证拓展方法,唯一的区别就是后者验证失败将自动抛出异常消息。

8.6.3 ValidationTypes 常见验证

Furion 内置了很多常用类型的数据验证,包括:

  • Numeric:数值类型
  • PositiveNumber:正数类型
  • NegativeNumber:负数类型
  • Integer:整数类型
  • Money:金钱类型
  • Date:日期类型
  • Time:时间类型
  • IDCard:身份证类型
  • PostCode:邮编类型
  • PhoneNumber:手机号类型
  • Telephone:固话类型
  • PhoneOrTelNumber:手机或固话类型
  • EmailAddress:邮件地址类型
  • Url:网址类型
  • Color:颜色值类型
  • Chinese:中文类型
  • IPv4:IPv4 地址类型
  • IPv6:IPv6 地址类型
  • Age:年龄类型
  • ChineseName:中文名类型
  • EnglishName:英文名类型
  • Capital:纯大写英文类型
  • Lowercase:纯小写英文类型
  • Ascii:Ascii 类型
  • Md5:Md5 字符串类型
  • Zip:压缩包格式类型
  • Image:图片格式类型
  • Document:文档格式类型
  • MP3:Mp3 格式类型
  • Flash:Flash 格式类型
  • Video:视频文件格式类型
  • HtmlHtml 标签格式

使用示例

// 验证中文"我叫 MonK".TryValidate(ValidationTypes.Chinese); // => false// 验证数值2.TryValidate(ValidationTypes.Numeric); // => true// 验证整数true.TryValidate(ValidationTypes.Integer); // => false// 验证邮箱"monksoul@outlook.com".TryValidate(ValidationTypes.EmailAddress); // => true// 验证负数2.0m.TryValidate(ValidationTypes.NegativeNumber); // => false// 自定义正则表达式验证"Furion".TryValidate("/^Furion$"); // => true
小知识

可通过设置 TryValidate([ValidationPattern], params object[] validationTypes) 方法的 ValidationPattern 参数配置验证逻辑,如:同时成立只要一个成立 即可验证通过

8.6.4 [DataValidation] 特性

Furion 还提供了 [DataValidation] 特性方便在模型参数中使用 ValidationTypes 常见验证或自定义验证。

using Furion.DataValidation;namespace Furion.Application{    public class TestDto    {        [DataValidation(ValidationTypes.Integer)]        public int Id { get; set; }        [DataValidation(ValidationTypes.Numeric, ValidationTypes.Integer)]        public int Cost { get; set; }        [DataValidation(ValidationPattern.AtLeastOne, ValidationTypes.Chinese, ValidationTypes.Date)]        public string Name { get; set; }        // 可以和Mvc特性共存        [Required, DataValidation(ValidationTypes.Age)]        public int Age { get; set; }        [DataValidation(ValidationTypes.IDCard, ErrorMessage = "自定义身份证提示消息")]        public string IDCard { get; set; }    }}

[DataValidation] 特性具备 ValidationAttribute 特性的所有配置以外还提供了以下配置:

  • ValidationTypes:验证类型,Enum[] 类型,
  • ValidationPattern:验证逻辑,ValidationPattern 类型,可选 AllOfThem(全部验证通过)AtleastOne(至少一个验证通过)
  • AllowNullValue:是否允许空值,bool 类型,默认 false
  • AllowEmptyStrings:是否允许空字符串,bool 类型,默认 false

8.6.5 [ModelBinder] 特性

默认情况下,验证失败信息会根据属性名进行序列化,但是如果属性序列化自定义了 [JsonPropertyName] 特性,那么验证失败的消息就不匹配了,这时我们需要添加 [ModelBinder(Name = "序列化对应名字")] 进行纠正。如下图所示:

[JsonPropertyName("phone_number"), ModelBinder(Name = "phone_number")]public string PhoneNumber { get; set; }

8.7 [NonValidation] 跳过验证

Furion 框架提供了对象模型跳过验证特性 [NonValidation],支持在 控制器动作方法 中使用。

一旦贴了此特性,那么将不会执行验证操作。

note

[NonValidation] 只对对象类型有效,值类型无效。

8.8 高级自定义操作

8.8.1 自定义 ValidationTypes 类型

除了 Furion 内置的验证类型以外,Furion 还提供了非常灵活的自定义验证类型机制。

实现自定义验证类型必须遵循以下配置:

  • 验证类型必须是公开且是 Enum 枚举类型
  • 枚举类型必须贴有 [ValidationType] 特性
  • 枚举中每一项必须贴有 [ValidationItemMetadata] 特性

using Furion.DataValidation;using System.Text.RegularExpressions;namespace Furion.Application{    [ValidationType]    public enum MyValidationTypes    {        /// <summary>        /// 强密码类型        /// </summary>        [ValidationItemMetadata(@"^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$", "必须须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间")]        StrongPassword,        /// <summary>        /// 以 Furion 字符串开头,忽略大小写        /// </summary>        [ValidationItemMetadata(@"^(furion).*", "默认提示:必须以Fur字符串开头,忽略大小写", RegexOptions.IgnoreCase)]        StartWithFurString    }}
小知识

Any-Rule 是国人记录的正则表达式大全,如需查找正则表达式可查阅 https://any86.github.io/any-rule/

使用

  • 手动使用
"q1w2e3".TryValidate(MyValidationTypes.StrongPassword); // => false"furos".TryValidate(MyValidationTypes.StartWithFurString); // => true
  • [DataValidation] 中使用
[DataValidation(MyValidationTypes.StrongPassword)]public string Password { get; set; }
  • 多个自定义类型混用
"Q1w2e3r4t5!*".TryValidate(MyValidationTypes.StrongPassword, ValidationTypes.EmailAddress); // => true
特别注意

自定义的验证类型也要保证名称全局唯一,也就是多个验证类型不能出现一样的名字。

8.8.2 自定义 ValidationTypes 失败消息

Furion 内置的 ValidationTypes 已有默认的失败消息:

  • NumericThe value is not a numeric type.
  • PositiveNumberThe value is not a positive number type.
  • NegativeNumberThe value is not a negative number type.
  • IntegerThe value is not a integer type.
  • MoneyThe value is not a money type.
  • DateThe value is not a date type.
  • TimeThe value is not a time type.
  • IDCardThe value is not a idcard type.
  • PostCodeThe value is not a postcode type.
  • PhoneNumberThe value is not a phone number type.
  • TelephoneThe value is not a telephone type.
  • PhoneOrTelNumberThe value is not a phone number or telephone type.
  • EmailAddressThe value is not a email address type.
  • UrlThe value is not a url address type.
  • ColorThe value is not a color type.
  • ChineseThe value is not a chinese type.
  • IPv4The value is not a IPv4 type.
  • IPv6The value is not a IPv6 type.
  • AgeThe value is not a age type.
  • ChineseNameThe value is not a chinese name type.
  • EnglishNameThe value is not a english name type.
  • CapitalThe value is not a capital type.
  • LowercaseThe value is not a lowercase type.
  • AsciiThe value is not a ascii type.
  • Md5The value is not a md5 type.
  • ZipThe value is not a zip type.
  • ImageThe value is not a image type.
  • DocumentThe value is not a document type.
  • MP3The value is not a mp3 type.
  • FlashThe value is not a flash type.
  • VideoThe value is not a video type.
  • HtmlThe value is not a html type.

我们可以通过创建继承 IValidationMessageTypeProvider 验证消息提供器类型,或通过 appsettings.json 配置。

  • [ValidationMessageType] 方式
using Furion.DataValidation;namespace Furion.Application{    [ValidationMessageType]    public enum MyValidationMessageType    {        [ValidationMessage("必须是数值类型")]        Numeric,        [ValidationMessage("必须是正数")]        PositiveNumber,        // 修改自定义类型验证失败消息        [ValidationMessage("密码太简单了")]        StrongPassword,        [ValidationMessage("必须以 Furion 开头")]        StartWithFurString    }}
小知识

除了贴 [ValidationMessageType] 特性外,Furion 框架还提供了 IValidationMessageTypeProvider 方式查找验证消息类型,如下图所示:

using Furion.DataValidation;using System;namespace Furion.Application{    public class MyValidationTypeMessageProvider : IValidationMessageTypeProvider    {        public Type[] Definitions => new[]        {            typeof(MyValidationMessageType),            typeof(MyValidationMessageType2)        };    }}

注册验证消息提供器

Furion.Web.Core\FurWebCoreStartup.cs
using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Core{    [AppStartup(800)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddControllers()                    .AddDataValidation<MyValidationTypeMessageProvider>();        }    }}

如下图所示:

  • appsettings.json 方式
Furion.Web.Entry/appsettings.json
{  "ValidationTypeMessageSettings": {    "Definitions": [      ["Numeric", "必须是数值类型"],      ["StrongPassword", "密码太简单了!!!"]    ]  }}
info

appsettings.json 中相同的 Key 会覆盖 IValidationMessageTypeProvider 提供相同 Key 的值。

错误消息查找优先级

DefaultErrorMessage -> IValidationMessageTypeProvider -> appsettings.json (低 -> 高)

8.9 模型验证范围

Furion 提供多种模型验证范围设置:

  • 全局验证(默认)
  • [NonValidation] 跳过验证
  • [TypeFilter(typeof(DataValidationFilter))] 局部验证
  • [ApiController] 控制器范围验证

8.9.1 全局验证

默认情况下,通过 .AddDataValidation() 注册数据验证服务已经启用了全局验证,如若不想启用全局验证,则传入 false 即可,如:.AddDataValidation(false)

8.9.2 [NonValidation] 跳过验证

可通过 [NonValidation] 贴在 控制器动作方法 中跳过全局验证或不需要验证

8.9.3 [TypeFilter(typeof(DataValidationFilter))] 局部验证

我们也可以无需注册 .AddDataValidation() 服务,直接在 动作方法 上贴 [TypeFilter(typeof(DataValidationFilter))] 可启用局部验证。如:

using Furion.DataValidation;using Furion.DynamicApiController;using Microsoft.AspNetCore.Mvc;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [TypeFilter(typeof(DataValidationFilter))]        public TestDto Post(TestDto testDto)        {            return testDto;        }    }}

8.9.4 [ApiController] 控制器范围验证

[ApiController]Mvc 提供的控制器范围(含所有动作方法)的验证。

using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    [ApiController]    public class MvcController : Controller    {        public IActionResult Index()        {            return View();        }    }}

8.10 MiniProfiler 查看

如下图所示:

8.11 多语言支持

参见 【全球化和本地化(多语言)】 章节

8.12 集成 FluentValidation 第三方校验

Furion 内置的验证已经可以满足绝大多数校验情况,但是对于 场景 验证目前暂未支持。这里推荐集成 FluentValidation 第三方校验组件。

8.12.1 安装 FluentValidation.AspNetCore 拓展包

dotnet add package FluentValidation.AspNetCore

8.12.2 在 Startup.cs 中注册

services.AddControllers()        .AddFluentValidation(fv => {            fv.RegisterValidatorsFromAssemblies(App.Assemblies);        });

8.12.3 使用例子

public class Person {    public int Id { get; set; }    public string Name { get; set; }    public string Email { get; set; }    public int Age { get; set; }}public class PersonValidator : AbstractValidator<Person> {    public PersonValidator() {        RuleFor(x => x.Id).NotNull();        RuleFor(x => x.Name).Length(0, 10);        RuleFor(x => x.Email).EmailAddress();        RuleFor(x => x.Age).InclusiveBetween(18, 60);    }}

在控制器中使用无需手动调用 ModelState.IsValid 进行判断,Furion 会自动执行该操作。

如需了解更多 FluentValidation 知识可查阅官方文档:https://fluentvalidation.net/

8.13 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

8. 数据校验

8.1 关于数据校验

数据校验字面上的意思就是对使用者提交过来的数据进行合法性验证。在一套完善的应用系统中,数据有效性校验是必不可少的业务处理第一道关卡。

8.2 数据校验的好处

  • 过滤不安全数据,提高系统的安全性
  • 减少不必要的业务异常处理,提高系统的响应速度
  • 大大提高系统稳定性
  • 大数据并发时起着一定的缓冲作用

8.3 数据校验方式

  • 传统方式,在业务代码之前手动验证
  • Mvc 特性方式,Mvc 内置的 DataAnnotations 方式
  • 推荐方式Furion 框架内置的 DataValidation 验证
  • 其他方式,使用第三方验证库,如 FluentValidation

8.3.1 传统方式

在很多老项目中,我们经常看到这样的代码:

public bool Insert(Person person){    // 验证参数    if(string.IsNullOrEmty(person.Name))    {        throw new System.Exception("名字不能为空");    }    if(person.Age < 18)    {        throw new System.Exception("年龄不能小于 18 岁");    }    if(!person.Password.Equals(person.ConfirmPassword)    {        throw new System.Exception("两次密码不一致");    }    // 业务代码    _repository.Insert(person.Adapt<PersonEntity>());    // ...}

从上面的代码看起来,似乎没有什么不妥,但是从一个程序可维护性来说,这是一个糟糕的代码,因为该业务代码中包含了太多与业务无关的数据验证

试想一下,如果这个 Person 有 几十个参数都需要验证呢?可想而知,这是一个庞大的业务代码。

再者,如果其他地方也需要用到这个 Person 类验证呢?那代码好比老鼠啃过的面包屑一样,到处都是。

如此得知,这样的方式是极其不推荐的,不但污染了业务代码,也破坏了业务职责单一性原理,也让验证逻辑无法实现通用,后续维护难度大大升级

8.3.2 Mvc 特性方式

ASP.NET Core 中,微软为我们提供了全新的 特性 验证方式,可通过对对象贴特性实现数据验证。这种方式有效的将数据校验和业务代码剥离开来,而且容易使用和拓展。

  • 在模型中验证
using System.ComponentModel.DataAnnotations;namespace Hoa.Application.Authorization.Dtos{    public class SignInInput    {        [Required]  // 必填验证        [MinLength(4)]  // 最小长度验证        public string Account { get; set; }        [Required]    // 必填验证        [MaxLength(32)]    // 最大长度验证        public string Password { get; set; }    }}
  • 在参数中验证
public void CheckMethodParameterValid(    [Required]    // 必填验证    [MinLength(4)]    // 最小长度验证    string name,    int age,    [Required]    // 必填验证    [RegularExpression("[a-zA-Z0-9_]{8,30}")    // 正则表达式验证    string password,    [Required]    // 必填验证    [RegularExpression("[a-zA-Z0-9_]{8,30}")    // 正则表达式验证    string confirmPassword){    // TODO}
小提醒

如果函数的参数大于或等于 3 个,建议抽离出模型类,也就是不建议上面的方式。

  • Mvc 内置特性

    • [ValidateNever]:指示熟悉或参数从验证中排除
    • [CreditCard]:信用卡格式验证
    • [Compare]:验证两个属性值是否匹配
    • [EmailAddress]:验证电子邮箱
    • [Phone]:验证电话号码
    • [Range]:验证指定范围
    • [RegularExpression]:验证属性值是否匹配正则表达式
    • [Required]:验证不为 null
    • [StringLength]:验证字符串长度
    • [URL]:验证是否有效的 URL 格式
    • [Remote]:调用远程服务地址进行客户端验证
Mvc 内置特性

想了解 Mvc 内置特性列表可查看官方文档 ASP.NET Core - 模型验证

  • 自定义特性验证
public class ClassicMovieAttribute : ValidationAttribute{    public ClassicMovieAttribute(int year)    {        Year = year;    }    public int Year { get; }    public string GetErrorMessage() =>        $"Classic movies must have a release year no later than {Year}.";    protected override ValidationResult IsValid(object value, ValidationContext validationContext)    {        var movie = (Movie)validationContext.ObjectInstance;        var releaseYear = ((DateTime)value).Year;        if (movie.Genre == Genre.Classic && releaseYear > Year)        {            return new ValidationResult(GetErrorMessage());        }        return ValidationResult.Success;    }}
  • IValidatableObject 复杂验证
using System.Collections.Generic;public class DtoModel : IValidatableObject{    [Required]    [StringLength(100)]    public string Title { get; set; }    // 你的验证逻辑    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)    {        // 还可以解析服务        var service = validationContext.GetService(typeof(类型));        if (你的逻辑代码)        {            yield return new ValidationResult(                "错误消息"                ,new[] { nameof(Title) }  // 验证失败的属性            );        }    }}

Mvc 特性方式极大的将业务逻辑和验证进行了剥离和解耦,而且还能实现自定义复杂验证。

但是 Mvc 特性验证方式有几个明显的缺点

  • 只能在 控制器 中的 Action(动作方法)中使用
  • 无法在任意类、任意方法中使用
  • 内置的验证类型非常有限,且不易拓展
  • 不支持验证消息后期配置

所以,Furion 提供了新的验证引擎 DataValidation,在完全兼容 Mvc 内置验证的同时提供了大量常见验证、复杂验证、自定义验证等能力。

8.4 DataValidation 验证 🤗

DataValidationFurion 框架提供了全新的验证方式,完全兼容 Mvc 内置验证,并且赋予了超能。

8.4.1 DataValidation 优点

  • 完全兼容 Mvc 内置验证引擎
  • 内置常见验证类型及可自定义验证类型功能
  • 提供全局对象拓展验证方式
  • 支持验证消息后期配置,支持实时更新
  • 支持在任何类,任何方法、任何位置实现手动验证、特性方式验证等
  • 支持设置验证结果模型

8.5 DataValidation 使用

备注

.AddDataValidation() 默认已经集成在 AddInject() 中了,无需再次注册。也就是 8.5.1 章节可不配置。

8.5.1 注册验证服务

Furion.Web.Core\FurWebCoreStartup.cs
using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Core{    [AppStartup(800)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddControllers()                    .AddDataValidation();        }    }}
特别注意

.AddDataValidation() 需在 services.AddControllers() 之后注册。

8.5.2 兼容 Mvc 特性验证

using System.ComponentModel.DataAnnotations;namespace Furion.Application{    public class TestDto    {        [Range(10, 20, ErrorMessage = "Id 只能在 10-20 区间取值")]        public int Id { get; set; }        [Required(ErrorMessage = "必填"), MinLength(3, ErrorMessage = "字符串长度不能少于3位")]        public string Name { get; set; }    }}

如下图所示:

8.5.3 兼容 Mvc 复杂验证

using System.Collections.Generic;using System.ComponentModel.DataAnnotations;namespace Furion.Application{    public class TestDto : IValidatableObject    {        [Range(10, 20, ErrorMessage = "Id 只能在 10-20 区间取值")]        public int Id { get; set; }        [Required(ErrorMessage = "必填"), MinLength(3, ErrorMessage = "字符串长度不能少于3位")]        public string Name { get; set; }        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)        {            // 还可以解析服务            var service = validationContext.GetService(typeof(类型));            if (Name.StartsWith("Furion"))            {                yield return new ValidationResult(                    "不能以 Furion 开头"                    , new[] { nameof(Name) }                );            }        }    }}

如下图所示:

8.6 手动验证

8.6.1 验证模型

using Furion.DataValidation;using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [NonValidation] // 跳过全局验证        public DataValidationResult Post(TestDto testDto)        {            return testDto.TryValidate();        }    }}

如下图所示:

note

支持 Mvc 内置的特性验证、属性验证及复杂的 IValidatableObject 验证。

8.6.2 TryValidateValidate

Furion 提供了 TryValidate()Validate() 两个验证拓展方法,唯一的区别就是后者验证失败将自动抛出异常消息。

8.6.3 ValidationTypes 常见验证

Furion 内置了很多常用类型的数据验证,包括:

  • Numeric:数值类型
  • PositiveNumber:正数类型
  • NegativeNumber:负数类型
  • Integer:整数类型
  • Money:金钱类型
  • Date:日期类型
  • Time:时间类型
  • IDCard:身份证类型
  • PostCode:邮编类型
  • PhoneNumber:手机号类型
  • Telephone:固话类型
  • PhoneOrTelNumber:手机或固话类型
  • EmailAddress:邮件地址类型
  • Url:网址类型
  • Color:颜色值类型
  • Chinese:中文类型
  • IPv4:IPv4 地址类型
  • IPv6:IPv6 地址类型
  • Age:年龄类型
  • ChineseName:中文名类型
  • EnglishName:英文名类型
  • Capital:纯大写英文类型
  • Lowercase:纯小写英文类型
  • Ascii:Ascii 类型
  • Md5:Md5 字符串类型
  • Zip:压缩包格式类型
  • Image:图片格式类型
  • Document:文档格式类型
  • MP3:Mp3 格式类型
  • Flash:Flash 格式类型
  • Video:视频文件格式类型
  • HtmlHtml 标签格式

使用示例

// 验证中文"我叫 MonK".TryValidate(ValidationTypes.Chinese); // => false// 验证数值2.TryValidate(ValidationTypes.Numeric); // => true// 验证整数true.TryValidate(ValidationTypes.Integer); // => false// 验证邮箱"monksoul@outlook.com".TryValidate(ValidationTypes.EmailAddress); // => true// 验证负数2.0m.TryValidate(ValidationTypes.NegativeNumber); // => false// 自定义正则表达式验证"Furion".TryValidate("/^Furion$"); // => true
小知识

可通过设置 TryValidate([ValidationPattern], params object[] validationTypes) 方法的 ValidationPattern 参数配置验证逻辑,如:同时成立只要一个成立 即可验证通过

8.6.4 [DataValidation] 特性

Furion 还提供了 [DataValidation] 特性方便在模型参数中使用 ValidationTypes 常见验证或自定义验证。

using Furion.DataValidation;namespace Furion.Application{    public class TestDto    {        [DataValidation(ValidationTypes.Integer)]        public int Id { get; set; }        [DataValidation(ValidationTypes.Numeric, ValidationTypes.Integer)]        public int Cost { get; set; }        [DataValidation(ValidationPattern.AtLeastOne, ValidationTypes.Chinese, ValidationTypes.Date)]        public string Name { get; set; }        // 可以和Mvc特性共存        [Required, DataValidation(ValidationTypes.Age)]        public int Age { get; set; }        [DataValidation(ValidationTypes.IDCard, ErrorMessage = "自定义身份证提示消息")]        public string IDCard { get; set; }    }}

[DataValidation] 特性具备 ValidationAttribute 特性的所有配置以外还提供了以下配置:

  • ValidationTypes:验证类型,Enum[] 类型,
  • ValidationPattern:验证逻辑,ValidationPattern 类型,可选 AllOfThem(全部验证通过)AtleastOne(至少一个验证通过)
  • AllowNullValue:是否允许空值,bool 类型,默认 false
  • AllowEmptyStrings:是否允许空字符串,bool 类型,默认 false

8.6.5 [ModelBinder] 特性

默认情况下,验证失败信息会根据属性名进行序列化,但是如果属性序列化自定义了 [JsonPropertyName] 特性,那么验证失败的消息就不匹配了,这时我们需要添加 [ModelBinder(Name = "序列化对应名字")] 进行纠正。如下图所示:

[JsonPropertyName("phone_number"), ModelBinder(Name = "phone_number")]public string PhoneNumber { get; set; }

8.7 [NonValidation] 跳过验证

Furion 框架提供了对象模型跳过验证特性 [NonValidation],支持在 控制器动作方法 中使用。

一旦贴了此特性,那么将不会执行验证操作。

note

[NonValidation] 只对对象类型有效,值类型无效。

8.8 高级自定义操作

8.8.1 自定义 ValidationTypes 类型

除了 Furion 内置的验证类型以外,Furion 还提供了非常灵活的自定义验证类型机制。

实现自定义验证类型必须遵循以下配置:

  • 验证类型必须是公开且是 Enum 枚举类型
  • 枚举类型必须贴有 [ValidationType] 特性
  • 枚举中每一项必须贴有 [ValidationItemMetadata] 特性

using Furion.DataValidation;using System.Text.RegularExpressions;namespace Furion.Application{    [ValidationType]    public enum MyValidationTypes    {        /// <summary>        /// 强密码类型        /// </summary>        [ValidationItemMetadata(@"^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$", "必须须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间")]        StrongPassword,        /// <summary>        /// 以 Furion 字符串开头,忽略大小写        /// </summary>        [ValidationItemMetadata(@"^(furion).*", "默认提示:必须以Fur字符串开头,忽略大小写", RegexOptions.IgnoreCase)]        StartWithFurString    }}
小知识

Any-Rule 是国人记录的正则表达式大全,如需查找正则表达式可查阅 https://any86.github.io/any-rule/

使用

  • 手动使用
"q1w2e3".TryValidate(MyValidationTypes.StrongPassword); // => false"furos".TryValidate(MyValidationTypes.StartWithFurString); // => true
  • [DataValidation] 中使用
[DataValidation(MyValidationTypes.StrongPassword)]public string Password { get; set; }
  • 多个自定义类型混用
"Q1w2e3r4t5!*".TryValidate(MyValidationTypes.StrongPassword, ValidationTypes.EmailAddress); // => true
特别注意

自定义的验证类型也要保证名称全局唯一,也就是多个验证类型不能出现一样的名字。

8.8.2 自定义 ValidationTypes 失败消息

Furion 内置的 ValidationTypes 已有默认的失败消息:

  • NumericThe value is not a numeric type.
  • PositiveNumberThe value is not a positive number type.
  • NegativeNumberThe value is not a negative number type.
  • IntegerThe value is not a integer type.
  • MoneyThe value is not a money type.
  • DateThe value is not a date type.
  • TimeThe value is not a time type.
  • IDCardThe value is not a idcard type.
  • PostCodeThe value is not a postcode type.
  • PhoneNumberThe value is not a phone number type.
  • TelephoneThe value is not a telephone type.
  • PhoneOrTelNumberThe value is not a phone number or telephone type.
  • EmailAddressThe value is not a email address type.
  • UrlThe value is not a url address type.
  • ColorThe value is not a color type.
  • ChineseThe value is not a chinese type.
  • IPv4The value is not a IPv4 type.
  • IPv6The value is not a IPv6 type.
  • AgeThe value is not a age type.
  • ChineseNameThe value is not a chinese name type.
  • EnglishNameThe value is not a english name type.
  • CapitalThe value is not a capital type.
  • LowercaseThe value is not a lowercase type.
  • AsciiThe value is not a ascii type.
  • Md5The value is not a md5 type.
  • ZipThe value is not a zip type.
  • ImageThe value is not a image type.
  • DocumentThe value is not a document type.
  • MP3The value is not a mp3 type.
  • FlashThe value is not a flash type.
  • VideoThe value is not a video type.
  • HtmlThe value is not a html type.

我们可以通过创建继承 IValidationMessageTypeProvider 验证消息提供器类型,或通过 appsettings.json 配置。

  • [ValidationMessageType] 方式
using Furion.DataValidation;namespace Furion.Application{    [ValidationMessageType]    public enum MyValidationMessageType    {        [ValidationMessage("必须是数值类型")]        Numeric,        [ValidationMessage("必须是正数")]        PositiveNumber,        // 修改自定义类型验证失败消息        [ValidationMessage("密码太简单了")]        StrongPassword,        [ValidationMessage("必须以 Furion 开头")]        StartWithFurString    }}
小知识

除了贴 [ValidationMessageType] 特性外,Furion 框架还提供了 IValidationMessageTypeProvider 方式查找验证消息类型,如下图所示:

using Furion.DataValidation;using System;namespace Furion.Application{    public class MyValidationTypeMessageProvider : IValidationMessageTypeProvider    {        public Type[] Definitions => new[]        {            typeof(MyValidationMessageType),            typeof(MyValidationMessageType2)        };    }}

注册验证消息提供器

Furion.Web.Core\FurWebCoreStartup.cs
using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Core{    [AppStartup(800)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddControllers()                    .AddDataValidation<MyValidationTypeMessageProvider>();        }    }}

如下图所示:

  • appsettings.json 方式
Furion.Web.Entry/appsettings.json
{  "ValidationTypeMessageSettings": {    "Definitions": [      ["Numeric", "必须是数值类型"],      ["StrongPassword", "密码太简单了!!!"]    ]  }}
info

appsettings.json 中相同的 Key 会覆盖 IValidationMessageTypeProvider 提供相同 Key 的值。

错误消息查找优先级

DefaultErrorMessage -> IValidationMessageTypeProvider -> appsettings.json (低 -> 高)

8.9 模型验证范围

Furion 提供多种模型验证范围设置:

  • 全局验证(默认)
  • [NonValidation] 跳过验证
  • [TypeFilter(typeof(DataValidationFilter))] 局部验证
  • [ApiController] 控制器范围验证

8.9.1 全局验证

默认情况下,通过 .AddDataValidation() 注册数据验证服务已经启用了全局验证,如若不想启用全局验证,则传入 false 即可,如:.AddDataValidation(false)

8.9.2 [NonValidation] 跳过验证

可通过 [NonValidation] 贴在 控制器动作方法 中跳过全局验证或不需要验证

8.9.3 [TypeFilter(typeof(DataValidationFilter))] 局部验证

我们也可以无需注册 .AddDataValidation() 服务,直接在 动作方法 上贴 [TypeFilter(typeof(DataValidationFilter))] 可启用局部验证。如:

using Furion.DataValidation;using Furion.DynamicApiController;using Microsoft.AspNetCore.Mvc;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [TypeFilter(typeof(DataValidationFilter))]        public TestDto Post(TestDto testDto)        {            return testDto;        }    }}

8.9.4 [ApiController] 控制器范围验证

[ApiController]Mvc 提供的控制器范围(含所有动作方法)的验证。

using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    [ApiController]    public class MvcController : Controller    {        public IActionResult Index()        {            return View();        }    }}

8.10 MiniProfiler 查看

如下图所示:

8.11 多语言支持

参见 【全球化和本地化(多语言)】 章节

8.12 集成 FluentValidation 第三方校验

Furion 内置的验证已经可以满足绝大多数校验情况,但是对于 场景 验证目前暂未支持。这里推荐集成 FluentValidation 第三方校验组件。

8.12.1 安装 FluentValidation.AspNetCore 拓展包

dotnet add package FluentValidation.AspNetCore

8.12.2 在 Startup.cs 中注册

services.AddControllers()        .AddFluentValidation(fv => {            fv.RegisterValidatorsFromAssemblies(App.Assemblies);        });

8.12.3 使用例子

public class Person {    public int Id { get; set; }    public string Name { get; set; }    public string Email { get; set; }    public int Age { get; set; }}public class PersonValidator : AbstractValidator<Person> {    public PersonValidator() {        RuleFor(x => x.Id).NotNull();        RuleFor(x => x.Name).Length(0, 10);        RuleFor(x => x.Email).EmailAddress();        RuleFor(x => x.Age).InclusiveBetween(18, 60);    }}

在控制器中使用无需手动调用 ModelState.IsValid 进行判断,Furion 会自动执行该操作。

如需了解更多 FluentValidation 知识可查阅官方文档:https://fluentvalidation.net/

8.13 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-Interceptor/index.html b/handbook/build/docs/dbcontext-Interceptor/index.html index 9dbf58e56d..cf9d4af024 100644 --- a/handbook/build/docs/dbcontext-Interceptor/index.html +++ b/handbook/build/docs/dbcontext-Interceptor/index.html @@ -2,22 +2,21 @@ - - - + +9.24 数据库操作拦截器 | Furion -9.24 数据库操作拦截器 | Furion - - + + +
-

9.24 数据库操作拦截器

9.24.1 数据库拦截器

Furion 框架提供四种数据库操作拦截器,可以通过拦截器动态修改数据库连接字符串,动态修改 sql,动态更改参数等操作。

Furion 支持这四种拦截器:

  • DbConnectionInterceptor:数据库连接拦截器
  • DbCommandInterceptor:数据库执行 Sql 拦截器
  • SaveChangesInterceptor:提交到数据库拦截器
  • 在数据库上下文中重写 SavedChangesEvent 相关事件

9.24.2 支持拦截类型

9.24.2.1 DbConnectionInterceptor

using Microsoft.EntityFrameworkCore.Diagnostics;using System.Data.Common;using System.Threading;using System.Threading.Tasks;namespace Furion.DatabaseAccessor.Interceptors{    public class SqlConnectionInterceptor : DbConnectionInterceptor    {        // 数据库连接之前        public override InterceptionResult ConnectionOpening(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)        {            return base.ConnectionOpening(connection, eventData, result);        }        // 数据库连接之前(异步)        public override ValueTask<InterceptionResult> ConnectionOpeningAsync(DbConnection connection, ConnectionEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)        {            return base.ConnectionOpeningAsync(connection, eventData, result, cancellationToken);        }        // 数据库连接成功        public override void ConnectionOpened(DbConnection connection, ConnectionEndEventData eventData)        {            base.ConnectionOpened(connection, eventData);        }        // 数据库连接成功(异步)        public override Task ConnectionOpenedAsync(DbConnection connection, ConnectionEndEventData eventData, CancellationToken cancellationToken = default)        {            return base.ConnectionOpenedAsync(connection, eventData, cancellationToken);        }        // 数据库连接关闭之前        public override InterceptionResult ConnectionClosing(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)        {            return base.ConnectionClosing(connection, eventData, result);        }        // 数据库连接关闭之前(异步)        public override ValueTask<InterceptionResult> ConnectionClosingAsync(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)        {            return base.ConnectionClosingAsync(connection, eventData, result);        }        // 数据库连接关闭成功        public override void ConnectionClosed(DbConnection connection, ConnectionEndEventData eventData)        {            base.ConnectionClosed(connection, eventData);        }        // 数据库连接关闭成功(异步)        public override Task ConnectionClosedAsync(DbConnection connection, ConnectionEndEventData eventData)        {            return base.ConnectionClosedAsync(connection, eventData);        }        // 数据库连接失败        public override void ConnectionFailed(DbConnection connection, ConnectionErrorEventData eventData)        {            base.ConnectionFailed(connection, eventData);        }        // 数据库连接失败(异步)        public override Task ConnectionFailedAsync(DbConnection connection, ConnectionErrorEventData eventData, CancellationToken cancellationToken = default)        {            return base.ConnectionFailedAsync(connection, eventData, cancellationToken);        }    }}

9.24.2.2 DbCommandInterceptor

using Microsoft.EntityFrameworkCore.Diagnostics;using System.Data.Common;using System.Threading;using System.Threading.Tasks;namespace Furion.DatabaseAccessor{    internal sealed class SqlCommandProfilerInterceptor : DbCommandInterceptor    {        // 创建命令对象之前        public override InterceptionResult<DbCommand> CommandCreating(CommandCorrelatedEventData eventData, InterceptionResult<DbCommand> result)        {            return base.CommandCreating(eventData, result);        }        // 创建命令对象之后        public override DbCommand CommandCreated(CommandEndEventData eventData, DbCommand result)        {            return base.CommandCreated(eventData, result);        }        // 创建命令对象失败        public override void CommandFailed(DbCommand command, CommandErrorEventData eventData)        {            base.CommandFailed(command, eventData);        }         // 创建命令对象失败(异步)        public override Task CommandFailedAsync(DbCommand command, CommandErrorEventData eventData, CancellationToken cancellationToken = default)        {            return base.CommandFailedAsync(command, eventData, cancellationToken);        }        // 读取数据之前        public override InterceptionResult<DbDataReader> ReaderExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result)        {            return base.ReaderExecuting(command, eventData, result);        }        // 读取数据之前(异步)        public override ValueTask<InterceptionResult<DbDataReader>> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result, CancellationToken cancellationToken = default)        {            return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);        }        // 读取数据之后        public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result)        {            return base.ReaderExecuted(command, eventData, result);        }        // 读取数据之后(异步)        public override ValueTask<DbDataReader> ReaderExecutedAsync(DbCommand command, CommandExecutedEventData eventData, DbDataReader result, CancellationToken cancellationToken = default)        {            return base.ReaderExecutedAsync(command, eventData, result, cancellationToken);        }        // DataReader 对象释放之前        public override InterceptionResult DataReaderDisposing(DbCommand command, DataReaderDisposingEventData eventData, InterceptionResult result)        {            return base.DataReaderDisposing(command, eventData, result);        }        // 无查询执行 sql 之前        public override InterceptionResult<int> NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<int> result)        {            return base.NonQueryExecuting(command, eventData, result);        }        // 无查询执行 sql 之前(异步)        public override ValueTask<InterceptionResult<int>> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)        {            return base.NonQueryExecutingAsync(command, eventData, result, cancellationToken);        }        // 无查询执行 sql 之后        public override int NonQueryExecuted(DbCommand command, CommandExecutedEventData eventData, int result)        {            return base.NonQueryExecuted(command, eventData, result);        }        // 无查询执行 sql 之后(异步)        public override ValueTask<int> NonQueryExecutedAsync(DbCommand command, CommandExecutedEventData eventData, int result, CancellationToken cancellationToken = default)        {            return base.NonQueryExecutedAsync(command, eventData, result, cancellationToken);        }        // 执行 sql 返回单行单列之前        public override InterceptionResult<object> ScalarExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<object> result)        {            return base.ScalarExecuting(command, eventData, result);        }        // 执行 sql 返回单行单列之前(异步)        public override ValueTask<InterceptionResult<object>> ScalarExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<object> result, CancellationToken cancellationToken = default)        {            return base.ScalarExecutingAsync(command, eventData, result, cancellationToken);        }        // 执行 sql 返回单行单列之后        public override object ScalarExecuted(DbCommand command, CommandExecutedEventData eventData, object result)        {            return base.ScalarExecuted(command, eventData, result);        }        // 执行 sql 返回单行单列之后(异步)        public override ValueTask<object> ScalarExecutedAsync(DbCommand command, CommandExecutedEventData eventData, object result, CancellationToken cancellationToken = default)        {            return base.ScalarExecutedAsync(command, eventData, result, cancellationToken);        }    }}

9.24.2.3 SaveChangesInterceptor

using Microsoft.EntityFrameworkCore.Diagnostics;using System.Threading;using System.Threading.Tasks;namespace Furion.DatabaseAccessor{    public class DbContextSaveChangesInterceptor : SaveChangesInterceptor    {        // 提交到数据库之前        public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)        {            return base.SavingChanges(eventData, result);        }        // 提交到数据库之前(异步)        public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)        {            return base.SavingChangesAsync(eventData, result, cancellationToken);        }        // 提交到数据库之后        public override int SavedChanges(SaveChangesCompletedEventData eventData, int result)        {            return base.SavedChanges(eventData, result);        }        // 提交到数据库之后(异步)        public override ValueTask<int> SavedChangesAsync(SaveChangesCompletedEventData eventData, int result, CancellationToken cancellationToken = default)        {            return base.SavedChangesAsync(eventData, result, cancellationToken);        }        // 提交数据库失败        public override void SaveChangesFailed(DbContextErrorEventData eventData)        {            base.SaveChangesFailed(eventData);        }        // 提交数据库失败(异步)        public override Task SaveChangesFailedAsync(DbContextErrorEventData eventData, CancellationToken cancellationToken = default)        {            return base.SaveChangesFailedAsync(eventData, cancellationToken);        }    }}

9.24.2.4 SavedChangesEvent 拦截

Furion 框架中为所有 AppDbContext 子类都提供了三个可重写的方法,这三个方法分别由三个事件触发:

  • 提交更改之前 SavingChanges 事件:触发 void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result) 方法
  • 提交更改之后 SavedChanges 事件:触发 void SavedChangesEvent(SaveChangesCompletedEventData eventData, int result) 方法
  • 提交更改失败 SaveChangesFailed 事件:触发 void SaveChangesFailedEvent(DbContextErrorEventData eventData) 方法

通过这三个事件我们可以在数据库做增、删、改时候做拦截,比如设置创建时间、更新时间或其他默认操作

如自动添加租户 Id:

protected override void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result){    // 获取当前事件对应上下文    var dbContext = eventData.Context;    // 获取所有新增和更新的实体    var entities = dbContext.ChangeTracker.Entries()                .Where(u => u.State == EntityState.Added || u.State == EntityState.Modified);    foreach (var entity in entities)    {        switch (entity.State)        {            // 自动设置租户Id            case EntityState.Added:                entity.Property(nameof(Entity.TenantId)).CurrentValue = GetTenantId();                break;            // 排除租户Id            case EntityState.Modified:                entity.Property(nameof(Entity.TenantId)).IsModified = false;                break;        }    }}

9.24.3 注册自定义筛选器

定义好过滤器之后,我们需要在数据库上下文中注册:

// services.AddDb 也是一样用法services.AddDbPool<FurionDbContext>(interceptors: new IInterceptor[] {    new YourSqlConnectionProfilerInterceptor(),    new YourDbContextSaveChangesInterceptor(),    new YourSqlCommandProfilerInterceptor()});

9.24.4 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.24 数据库操作拦截器

9.24.1 数据库拦截器

Furion 框架提供四种数据库操作拦截器,可以通过拦截器动态修改数据库连接字符串,动态修改 sql,动态更改参数等操作。

Furion 支持这四种拦截器:

  • DbConnectionInterceptor:数据库连接拦截器
  • DbCommandInterceptor:数据库执行 Sql 拦截器
  • SaveChangesInterceptor:提交到数据库拦截器
  • 在数据库上下文中重写 SavedChangesEvent 相关事件

9.24.2 支持拦截类型

9.24.2.1 DbConnectionInterceptor

using Microsoft.EntityFrameworkCore.Diagnostics;using System.Data.Common;using System.Threading;using System.Threading.Tasks;namespace Furion.DatabaseAccessor.Interceptors{    public class SqlConnectionInterceptor : DbConnectionInterceptor    {        // 数据库连接之前        public override InterceptionResult ConnectionOpening(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)        {            return base.ConnectionOpening(connection, eventData, result);        }        // 数据库连接之前(异步)        public override ValueTask<InterceptionResult> ConnectionOpeningAsync(DbConnection connection, ConnectionEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)        {            return base.ConnectionOpeningAsync(connection, eventData, result, cancellationToken);        }        // 数据库连接成功        public override void ConnectionOpened(DbConnection connection, ConnectionEndEventData eventData)        {            base.ConnectionOpened(connection, eventData);        }        // 数据库连接成功(异步)        public override Task ConnectionOpenedAsync(DbConnection connection, ConnectionEndEventData eventData, CancellationToken cancellationToken = default)        {            return base.ConnectionOpenedAsync(connection, eventData, cancellationToken);        }        // 数据库连接关闭之前        public override InterceptionResult ConnectionClosing(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)        {            return base.ConnectionClosing(connection, eventData, result);        }        // 数据库连接关闭之前(异步)        public override ValueTask<InterceptionResult> ConnectionClosingAsync(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)        {            return base.ConnectionClosingAsync(connection, eventData, result);        }        // 数据库连接关闭成功        public override void ConnectionClosed(DbConnection connection, ConnectionEndEventData eventData)        {            base.ConnectionClosed(connection, eventData);        }        // 数据库连接关闭成功(异步)        public override Task ConnectionClosedAsync(DbConnection connection, ConnectionEndEventData eventData)        {            return base.ConnectionClosedAsync(connection, eventData);        }        // 数据库连接失败        public override void ConnectionFailed(DbConnection connection, ConnectionErrorEventData eventData)        {            base.ConnectionFailed(connection, eventData);        }        // 数据库连接失败(异步)        public override Task ConnectionFailedAsync(DbConnection connection, ConnectionErrorEventData eventData, CancellationToken cancellationToken = default)        {            return base.ConnectionFailedAsync(connection, eventData, cancellationToken);        }    }}

9.24.2.2 DbCommandInterceptor

using Microsoft.EntityFrameworkCore.Diagnostics;using System.Data.Common;using System.Threading;using System.Threading.Tasks;namespace Furion.DatabaseAccessor{    internal sealed class SqlCommandProfilerInterceptor : DbCommandInterceptor    {        // 创建命令对象之前        public override InterceptionResult<DbCommand> CommandCreating(CommandCorrelatedEventData eventData, InterceptionResult<DbCommand> result)        {            return base.CommandCreating(eventData, result);        }        // 创建命令对象之后        public override DbCommand CommandCreated(CommandEndEventData eventData, DbCommand result)        {            return base.CommandCreated(eventData, result);        }        // 创建命令对象失败        public override void CommandFailed(DbCommand command, CommandErrorEventData eventData)        {            base.CommandFailed(command, eventData);        }         // 创建命令对象失败(异步)        public override Task CommandFailedAsync(DbCommand command, CommandErrorEventData eventData, CancellationToken cancellationToken = default)        {            return base.CommandFailedAsync(command, eventData, cancellationToken);        }        // 读取数据之前        public override InterceptionResult<DbDataReader> ReaderExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result)        {            return base.ReaderExecuting(command, eventData, result);        }        // 读取数据之前(异步)        public override ValueTask<InterceptionResult<DbDataReader>> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result, CancellationToken cancellationToken = default)        {            return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);        }        // 读取数据之后        public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result)        {            return base.ReaderExecuted(command, eventData, result);        }        // 读取数据之后(异步)        public override ValueTask<DbDataReader> ReaderExecutedAsync(DbCommand command, CommandExecutedEventData eventData, DbDataReader result, CancellationToken cancellationToken = default)        {            return base.ReaderExecutedAsync(command, eventData, result, cancellationToken);        }        // DataReader 对象释放之前        public override InterceptionResult DataReaderDisposing(DbCommand command, DataReaderDisposingEventData eventData, InterceptionResult result)        {            return base.DataReaderDisposing(command, eventData, result);        }        // 无查询执行 sql 之前        public override InterceptionResult<int> NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<int> result)        {            return base.NonQueryExecuting(command, eventData, result);        }        // 无查询执行 sql 之前(异步)        public override ValueTask<InterceptionResult<int>> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)        {            return base.NonQueryExecutingAsync(command, eventData, result, cancellationToken);        }        // 无查询执行 sql 之后        public override int NonQueryExecuted(DbCommand command, CommandExecutedEventData eventData, int result)        {            return base.NonQueryExecuted(command, eventData, result);        }        // 无查询执行 sql 之后(异步)        public override ValueTask<int> NonQueryExecutedAsync(DbCommand command, CommandExecutedEventData eventData, int result, CancellationToken cancellationToken = default)        {            return base.NonQueryExecutedAsync(command, eventData, result, cancellationToken);        }        // 执行 sql 返回单行单列之前        public override InterceptionResult<object> ScalarExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<object> result)        {            return base.ScalarExecuting(command, eventData, result);        }        // 执行 sql 返回单行单列之前(异步)        public override ValueTask<InterceptionResult<object>> ScalarExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<object> result, CancellationToken cancellationToken = default)        {            return base.ScalarExecutingAsync(command, eventData, result, cancellationToken);        }        // 执行 sql 返回单行单列之后        public override object ScalarExecuted(DbCommand command, CommandExecutedEventData eventData, object result)        {            return base.ScalarExecuted(command, eventData, result);        }        // 执行 sql 返回单行单列之后(异步)        public override ValueTask<object> ScalarExecutedAsync(DbCommand command, CommandExecutedEventData eventData, object result, CancellationToken cancellationToken = default)        {            return base.ScalarExecutedAsync(command, eventData, result, cancellationToken);        }    }}

9.24.2.3 SaveChangesInterceptor

using Microsoft.EntityFrameworkCore.Diagnostics;using System.Threading;using System.Threading.Tasks;namespace Furion.DatabaseAccessor{    public class DbContextSaveChangesInterceptor : SaveChangesInterceptor    {        // 提交到数据库之前        public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)        {            return base.SavingChanges(eventData, result);        }        // 提交到数据库之前(异步)        public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)        {            return base.SavingChangesAsync(eventData, result, cancellationToken);        }        // 提交到数据库之后        public override int SavedChanges(SaveChangesCompletedEventData eventData, int result)        {            return base.SavedChanges(eventData, result);        }        // 提交到数据库之后(异步)        public override ValueTask<int> SavedChangesAsync(SaveChangesCompletedEventData eventData, int result, CancellationToken cancellationToken = default)        {            return base.SavedChangesAsync(eventData, result, cancellationToken);        }        // 提交数据库失败        public override void SaveChangesFailed(DbContextErrorEventData eventData)        {            base.SaveChangesFailed(eventData);        }        // 提交数据库失败(异步)        public override Task SaveChangesFailedAsync(DbContextErrorEventData eventData, CancellationToken cancellationToken = default)        {            return base.SaveChangesFailedAsync(eventData, cancellationToken);        }    }}

9.24.2.4 SavedChangesEvent 拦截

Furion 框架中为所有 AppDbContext 子类都提供了三个可重写的方法,这三个方法分别由三个事件触发:

  • 提交更改之前 SavingChanges 事件:触发 void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result) 方法
  • 提交更改之后 SavedChanges 事件:触发 void SavedChangesEvent(SaveChangesCompletedEventData eventData, int result) 方法
  • 提交更改失败 SaveChangesFailed 事件:触发 void SaveChangesFailedEvent(DbContextErrorEventData eventData) 方法

通过这三个事件我们可以在数据库做增、删、改时候做拦截,比如设置创建时间、更新时间或其他默认操作

如自动添加租户 Id:

protected override void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result){    // 获取当前事件对应上下文    var dbContext = eventData.Context;    // 获取所有新增和更新的实体    var entities = dbContext.ChangeTracker.Entries()                .Where(u => u.State == EntityState.Added || u.State == EntityState.Modified);    foreach (var entity in entities)    {        switch (entity.State)        {            // 自动设置租户Id            case EntityState.Added:                entity.Property(nameof(Entity.TenantId)).CurrentValue = GetTenantId();                break;            // 排除租户Id            case EntityState.Modified:                entity.Property(nameof(Entity.TenantId)).IsModified = false;                break;        }    }}

9.24.3 注册自定义筛选器

定义好过滤器之后,我们需要在数据库上下文中注册:

// services.AddDb 也是一样用法services.AddDbPool<FurionDbContext>(interceptors: new IInterceptor[] {    new YourSqlConnectionProfilerInterceptor(),    new YourDbContextSaveChangesInterceptor(),    new YourSqlCommandProfilerInterceptor()});

9.24.4 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-add-or-update/index.html b/handbook/build/docs/dbcontext-add-or-update/index.html index eaae2e21cb..22828cdc57 100644 --- a/handbook/build/docs/dbcontext-add-or-update/index.html +++ b/handbook/build/docs/dbcontext-add-or-update/index.html @@ -2,22 +2,21 @@ - - - + +9.7 新增或更新操作 | Furion -9.7 新增或更新操作 | Furion - - + + +
-

9.7 新增或更新操作

功能移除声明

以下内容在 Furion 2.5.1 + 版本中已移除。此操作让很多不了解 EFCore 的开发者产生了很大的误解,不知何时新增或何时更新,故移除此功能。

9.7.1 新增或更新(不立即提交)

// ==== 同步操作 ====// 示例一repository.InsertOrUpdate(user);// 示例二user.InsertOrUpdate();// ==== 异步操作 ====// 示例一await repository.InsertOrUpdateAsync(user);// 示例二await user.InsertOrUpdateAsync();

9.7.2 新增或更新(立即提交)

// ==== 同步操作 ====// 示例一repository.InsertOrUpdateNow(user);// 示例二user.InsertOrUpdateNow();// ==== 异步操作 ====// 示例一await repository.InsertOrUpdateNowAsync(user);// 示例二await user.InsertOrUpdateNowAsync();

9.7.3 新增或更新部分列(不立即提交)

// ==== 同步操作 ====// 示例一repository.InsertOrUpdateInclude(user, u=>u.Name, u=>u.Age);// 示例二repository.InsertOrUpdateInclude(user, "Age", "Name");// 示例三repository.InsertOrUpdateInclude(user, new[] { u=>u.Name, u=>u.Age});// 示例四repository.InsertOrUpdateInclude(user, new[] {"Age", "Name"});// 示例五user.InsertOrUpdateInclude(u=>u.Name, u=>u.Age);// 示例六user.InsertOrUpdateInclude("Age", "Name");// 示例七user.InsertOrUpdateInclude(new[] { u=>u.Name, u=>u.Age});// 示例八user.InsertOrUpdateInclude(new[] {"Age", "Name"});// ==== 异步操作 ====// 示例一await repository.InsertOrUpdateIncludeAsync(user, u=>u.Name, u=>u.Age);// 示例二await repository.InsertOrUpdateIncludeAsync(user, "Age", "Name");// 示例三await repository.InsertOrUpdateIncludeAsync(user, new[] { u=>u.Name, u=>u.Age});// 示例四await repository.InsertOrUpdateIncludeAsync(user, new[] {"Age", "Name"});// 示例五await user.InsertOrUpdateIncludeAsync(u=>u.Name, u=>u.Age);// 示例六await user.InsertOrUpdateIncludeAsync("Age", "Name");// 示例七await user.InsertOrUpdateIncludeAsync(new[] { u=>u.Name, u=>u.Age});// 示例八await user.InsertOrUpdateIncludeAsync(new[] {"Age", "Name"});

9.7.4 新增或更新部分列(立即提交)

// ==== 同步操作 ====// 示例一repository.InsertOrUpdateIncludeNow(user, u=>u.Name, u=>u.Age);// 示例二repository.InsertOrUpdateIncludeNow(user, "Age", "Name");// 示例三repository.InsertOrUpdateIncludeNow(user, new[] { u=>u.Name, u=>u.Age});// 示例四repository.InsertOrUpdateIncludeNow(user, new[] {"Age", "Name"});// 示例五user.InsertOrUpdateIncludeNow(u=>u.Name, u=>u.Age);// 示例六user.InsertOrUpdateIncludeNow("Age", "Name");// 示例七user.InsertOrUpdateIncludeNow(new[] { u=>u.Name, u=>u.Age});// 示例八user.InsertOrUpdateIncludeNow(new[] {"Age", "Name"});// ==== 异步操作 ====// 示例一await repository.InsertOrUpdateIncludeNowAsync(user, u=>u.Name, u=>u.Age);// 示例二await repository.InsertOrUpdateIncludeNowAsync(user, "Age", "Name");// 示例三await repository.InsertOrUpdateIncludeNowAsync(user, new[] { u=>u.Name, u=>u.Age});// 示例四await repository.InsertOrUpdateIncludeNowAsync(user, new[] {"Age", "Name"});// 示例五await user.InsertOrUpdateIncludeNowAsync(u=>u.Name, u=>u.Age);// 示例六await user.InsertOrUpdateIncludeNowAsync("Age", "Name");// 示例七await user.InsertOrUpdateIncludeNowAsync(new[] { u=>u.Name, u=>u.Age});// 示例八await user.InsertOrUpdateIncludeNowAsync(new[] {"Age", "Name"});

9.7.5 新增或更新排除特定列(不立即提交)

// ==== 同步操作 ====// 示例一repository.InsertOrUpdateExclude(user, u=>u.Name, u=>u.Age);// 示例二repository.InsertOrUpdateExclude(user, "Age", "Name");// 示例三repository.InsertOrUpdateExclude(user, new[] { u=>u.Name, u=>u.Age});// 示例四repository.InsertOrUpdateExclude(user, new[] {"Age", "Name"});// 示例五user.InsertOrUpdateExclude(u=>u.Name, u=>u.Age);// 示例六user.InsertOrUpdateExclude("Age", "Name");// 示例七user.InsertOrUpdateExclude(new[] { u=>u.Name, u=>u.Age});// 示例八user.InsertOrUpdateExclude(new[] {"Age", "Name"});// ==== 异步操作 ====// 示例一await repository.InsertOrUpdateExcludeAsync(user, u=>u.Name, u=>u.Age);// 示例二await repository.InsertOrUpdateExcludeAsync(user, "Age", "Name");// 示例三await repository.InsertOrUpdateExcludeAsync(user, new[] { u=>u.Name, u=>u.Age});// 示例四await repository.InsertOrUpdateExcludeAsync(user, new[] {"Age", "Name"});// 示例五await user.InsertOrUpdateExcludeAsync(u=>u.Name, u=>u.Age);// 示例六await user.InsertOrUpdateExcludeAsync("Age", "Name");// 示例七await user.InsertOrUpdateExcludeAsync(new[] { u=>u.Name, u=>u.Age});// 示例八await user.InsertOrUpdateExcludeAsync(new[] {"Age", "Name"});

9.7.6 新增或更新排除特定列(立即提交)

// ==== 同步操作 ====// 示例一repository.InsertOrUpdateExcludeNow(user, u=>u.Name, u=>u.Age);// 示例二repository.InsertOrUpdateExcludeNow(user, "Age", "Name");// 示例三repository.InsertOrUpdateExcludeNow(user, new[] { u=>u.Name, u=>u.Age});// 示例四repository.InsertOrUpdateExcludeNow(user, new[] {"Age", "Name"});// 示例五user.InsertOrUpdateExcludeNow(u=>u.Name, u=>u.Age);// 示例六user.InsertOrUpdateExcludeNow("Age", "Name");// 示例七user.InsertOrUpdateExcludeNow(new[] { u=>u.Name, u=>u.Age});// 示例八user.InsertOrUpdateExcludeNow(new[] {"Age", "Name"});// ==== 异步操作 ====// 示例一await repository.InsertOrUpdateExcludeNowAsync(user, u=>u.Name, u=>u.Age);// 示例二await repository.InsertOrUpdateExcludeNowAsync(user, "Age", "Name");// 示例三await repository.InsertOrUpdateExcludeNowAsync(user, new[] { u=>u.Name, u=>u.Age});// 示例四await repository.InsertOrUpdateExcludeNowAsync(user, new[] {"Age", "Name"});// 示例五await user.InsertOrUpdateExcludeNowAsync(u=>u.Name, u=>u.Age);// 示例六await user.InsertOrUpdateExcludeNowAsync("Age", "Name");// 示例七await user.InsertOrUpdateExcludeNowAsync(new[] { u=>u.Name, u=>u.Age});// 示例八await user.InsertOrUpdateExcludeNowAsync(new[] {"Age", "Name"});

9.7.7 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.7 新增或更新操作

功能移除声明

以下内容在 Furion 2.5.1 + 版本中已移除。此操作让很多不了解 EFCore 的开发者产生了很大的误解,不知何时新增或何时更新,故移除此功能。

9.7.1 新增或更新(不立即提交)

// ==== 同步操作 ====// 示例一repository.InsertOrUpdate(user);// 示例二user.InsertOrUpdate();// ==== 异步操作 ====// 示例一await repository.InsertOrUpdateAsync(user);// 示例二await user.InsertOrUpdateAsync();

9.7.2 新增或更新(立即提交)

// ==== 同步操作 ====// 示例一repository.InsertOrUpdateNow(user);// 示例二user.InsertOrUpdateNow();// ==== 异步操作 ====// 示例一await repository.InsertOrUpdateNowAsync(user);// 示例二await user.InsertOrUpdateNowAsync();

9.7.3 新增或更新部分列(不立即提交)

// ==== 同步操作 ====// 示例一repository.InsertOrUpdateInclude(user, u=>u.Name, u=>u.Age);// 示例二repository.InsertOrUpdateInclude(user, "Age", "Name");// 示例三repository.InsertOrUpdateInclude(user, new[] { u=>u.Name, u=>u.Age});// 示例四repository.InsertOrUpdateInclude(user, new[] {"Age", "Name"});// 示例五user.InsertOrUpdateInclude(u=>u.Name, u=>u.Age);// 示例六user.InsertOrUpdateInclude("Age", "Name");// 示例七user.InsertOrUpdateInclude(new[] { u=>u.Name, u=>u.Age});// 示例八user.InsertOrUpdateInclude(new[] {"Age", "Name"});// ==== 异步操作 ====// 示例一await repository.InsertOrUpdateIncludeAsync(user, u=>u.Name, u=>u.Age);// 示例二await repository.InsertOrUpdateIncludeAsync(user, "Age", "Name");// 示例三await repository.InsertOrUpdateIncludeAsync(user, new[] { u=>u.Name, u=>u.Age});// 示例四await repository.InsertOrUpdateIncludeAsync(user, new[] {"Age", "Name"});// 示例五await user.InsertOrUpdateIncludeAsync(u=>u.Name, u=>u.Age);// 示例六await user.InsertOrUpdateIncludeAsync("Age", "Name");// 示例七await user.InsertOrUpdateIncludeAsync(new[] { u=>u.Name, u=>u.Age});// 示例八await user.InsertOrUpdateIncludeAsync(new[] {"Age", "Name"});

9.7.4 新增或更新部分列(立即提交)

// ==== 同步操作 ====// 示例一repository.InsertOrUpdateIncludeNow(user, u=>u.Name, u=>u.Age);// 示例二repository.InsertOrUpdateIncludeNow(user, "Age", "Name");// 示例三repository.InsertOrUpdateIncludeNow(user, new[] { u=>u.Name, u=>u.Age});// 示例四repository.InsertOrUpdateIncludeNow(user, new[] {"Age", "Name"});// 示例五user.InsertOrUpdateIncludeNow(u=>u.Name, u=>u.Age);// 示例六user.InsertOrUpdateIncludeNow("Age", "Name");// 示例七user.InsertOrUpdateIncludeNow(new[] { u=>u.Name, u=>u.Age});// 示例八user.InsertOrUpdateIncludeNow(new[] {"Age", "Name"});// ==== 异步操作 ====// 示例一await repository.InsertOrUpdateIncludeNowAsync(user, u=>u.Name, u=>u.Age);// 示例二await repository.InsertOrUpdateIncludeNowAsync(user, "Age", "Name");// 示例三await repository.InsertOrUpdateIncludeNowAsync(user, new[] { u=>u.Name, u=>u.Age});// 示例四await repository.InsertOrUpdateIncludeNowAsync(user, new[] {"Age", "Name"});// 示例五await user.InsertOrUpdateIncludeNowAsync(u=>u.Name, u=>u.Age);// 示例六await user.InsertOrUpdateIncludeNowAsync("Age", "Name");// 示例七await user.InsertOrUpdateIncludeNowAsync(new[] { u=>u.Name, u=>u.Age});// 示例八await user.InsertOrUpdateIncludeNowAsync(new[] {"Age", "Name"});

9.7.5 新增或更新排除特定列(不立即提交)

// ==== 同步操作 ====// 示例一repository.InsertOrUpdateExclude(user, u=>u.Name, u=>u.Age);// 示例二repository.InsertOrUpdateExclude(user, "Age", "Name");// 示例三repository.InsertOrUpdateExclude(user, new[] { u=>u.Name, u=>u.Age});// 示例四repository.InsertOrUpdateExclude(user, new[] {"Age", "Name"});// 示例五user.InsertOrUpdateExclude(u=>u.Name, u=>u.Age);// 示例六user.InsertOrUpdateExclude("Age", "Name");// 示例七user.InsertOrUpdateExclude(new[] { u=>u.Name, u=>u.Age});// 示例八user.InsertOrUpdateExclude(new[] {"Age", "Name"});// ==== 异步操作 ====// 示例一await repository.InsertOrUpdateExcludeAsync(user, u=>u.Name, u=>u.Age);// 示例二await repository.InsertOrUpdateExcludeAsync(user, "Age", "Name");// 示例三await repository.InsertOrUpdateExcludeAsync(user, new[] { u=>u.Name, u=>u.Age});// 示例四await repository.InsertOrUpdateExcludeAsync(user, new[] {"Age", "Name"});// 示例五await user.InsertOrUpdateExcludeAsync(u=>u.Name, u=>u.Age);// 示例六await user.InsertOrUpdateExcludeAsync("Age", "Name");// 示例七await user.InsertOrUpdateExcludeAsync(new[] { u=>u.Name, u=>u.Age});// 示例八await user.InsertOrUpdateExcludeAsync(new[] {"Age", "Name"});

9.7.6 新增或更新排除特定列(立即提交)

// ==== 同步操作 ====// 示例一repository.InsertOrUpdateExcludeNow(user, u=>u.Name, u=>u.Age);// 示例二repository.InsertOrUpdateExcludeNow(user, "Age", "Name");// 示例三repository.InsertOrUpdateExcludeNow(user, new[] { u=>u.Name, u=>u.Age});// 示例四repository.InsertOrUpdateExcludeNow(user, new[] {"Age", "Name"});// 示例五user.InsertOrUpdateExcludeNow(u=>u.Name, u=>u.Age);// 示例六user.InsertOrUpdateExcludeNow("Age", "Name");// 示例七user.InsertOrUpdateExcludeNow(new[] { u=>u.Name, u=>u.Age});// 示例八user.InsertOrUpdateExcludeNow(new[] {"Age", "Name"});// ==== 异步操作 ====// 示例一await repository.InsertOrUpdateExcludeNowAsync(user, u=>u.Name, u=>u.Age);// 示例二await repository.InsertOrUpdateExcludeNowAsync(user, "Age", "Name");// 示例三await repository.InsertOrUpdateExcludeNowAsync(user, new[] { u=>u.Name, u=>u.Age});// 示例四await repository.InsertOrUpdateExcludeNowAsync(user, new[] {"Age", "Name"});// 示例五await user.InsertOrUpdateExcludeNowAsync(u=>u.Name, u=>u.Age);// 示例六await user.InsertOrUpdateExcludeNowAsync("Age", "Name");// 示例七await user.InsertOrUpdateExcludeNowAsync(new[] { u=>u.Name, u=>u.Age});// 示例八await user.InsertOrUpdateExcludeNowAsync(new[] {"Age", "Name"});

9.7.7 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-add/index.html b/handbook/build/docs/dbcontext-add/index.html index 21ed925f07..920abdaeb9 100644 --- a/handbook/build/docs/dbcontext-add/index.html +++ b/handbook/build/docs/dbcontext-add/index.html @@ -2,22 +2,21 @@ - - - + +9.5 新增操作 | Furion -9.5 新增操作 | Furion - - + + +
-

9.5 新增操作

Furion 框架提供非常多的语法糖进行数据库操作。

9.5.1 新增一条,无返回值

var user = new User { Name = "百小僧", Age = 27 };// ==== 同步操作 ====// 示例一repository.Insert(user);// 示例二user.Insert();// 示例三repository.Entities.Add(user);// 示例四repository.ChangeEntityState(user, EntityState.Added);// ==== 异步操作 ====// 示例一await repository.InsertAsync(user);// 示例二await user.InsertAsync();// 示例三await repository.Entities.AddAsync(user);

9.5.2 新增一条,返回最新数据

// ==== 同步操作 ====// 示例一var newEntity = repository.InsertNow(user);// 示例三var newEntity = user.InsertNow();// ==== 异步操作 ====// 示例二var newEntity = await repository.InsertNowAsync(user); // 有三个重载// 示例四var newEntity = await user.InsertNowAsync();  // 有三个重载

9.5.3 新增多条(不立即提交)

// ==== 同步操作 ====// 示例一repository.Insert(user, user2);// 示例二repository.Insert(new List<User> { user, user2 });// 示例三repository.Insert(new[] {user, user2 });// ==== 异步操作 ====// 示例一await repository.InsertAsync(user, user2);// 示例二await repository.InsertAsync(new List<User> { user, user2 });// 示例三await repository.InsertAsync(new[] {user, user2 });

9.5.4 新增多条(立即提交)

// ==== 同步操作 ====// 示例一repository.InsertNow(user, user2);// 示例二repository.InsertNow(new List<User> { user, user2 });// 示例三repository.InsertNow(new[] {user, user2 });// ==== 异步操作 ====// 示例一await repository.InsertNowAsync(user, user2);// 示例二await repository.InsertNowAsync(new List<User> { user, user2 });// 示例三await repository.InsertNowAsync(new[] {user, user2 });
小知识

所有带 Now 结尾的表示立即提交到数据库,也就是立即调用 SaveChangesSaveChangesAsync

9.5.5 忽略空值新增

默认情况下,EFCore 新增会插入全部列(除实体跟踪方式以外),有些时候我们希望 Null 值无需插入,这是我们只需要在更新时候配置 ignoreNullValues 参数即可,如:

repository.Insert(entity, ignoreNullValues: true);

也可以全局配置,在 AppDbContext 的派生类的构造函数中启用即可:

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class DefaultDbContext : AppDbContext<DefaultDbContext>    {        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)        {            InsertOrUpdateIgnoreNullValues = true;        }    }}

9.5.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.5 新增操作

Furion 框架提供非常多的语法糖进行数据库操作。

9.5.1 新增一条,无返回值

var user = new User { Name = "百小僧", Age = 27 };// ==== 同步操作 ====// 示例一repository.Insert(user);// 示例二user.Insert();// 示例三repository.Entities.Add(user);// 示例四repository.ChangeEntityState(user, EntityState.Added);// ==== 异步操作 ====// 示例一await repository.InsertAsync(user);// 示例二await user.InsertAsync();// 示例三await repository.Entities.AddAsync(user);

9.5.2 新增一条,返回最新数据

// ==== 同步操作 ====// 示例一var newEntity = repository.InsertNow(user);// 示例三var newEntity = user.InsertNow();// ==== 异步操作 ====// 示例二var newEntity = await repository.InsertNowAsync(user); // 有三个重载// 示例四var newEntity = await user.InsertNowAsync();  // 有三个重载

9.5.3 新增多条(不立即提交)

// ==== 同步操作 ====// 示例一repository.Insert(user, user2);// 示例二repository.Insert(new List<User> { user, user2 });// 示例三repository.Insert(new[] {user, user2 });// ==== 异步操作 ====// 示例一await repository.InsertAsync(user, user2);// 示例二await repository.InsertAsync(new List<User> { user, user2 });// 示例三await repository.InsertAsync(new[] {user, user2 });

9.5.4 新增多条(立即提交)

// ==== 同步操作 ====// 示例一repository.InsertNow(user, user2);// 示例二repository.InsertNow(new List<User> { user, user2 });// 示例三repository.InsertNow(new[] {user, user2 });// ==== 异步操作 ====// 示例一await repository.InsertNowAsync(user, user2);// 示例二await repository.InsertNowAsync(new List<User> { user, user2 });// 示例三await repository.InsertNowAsync(new[] {user, user2 });
小知识

所有带 Now 结尾的表示立即提交到数据库,也就是立即调用 SaveChangesSaveChangesAsync

9.5.5 忽略空值新增

默认情况下,EFCore 新增会插入全部列(除实体跟踪方式以外),有些时候我们希望 Null 值无需插入,这是我们只需要在更新时候配置 ignoreNullValues 参数即可,如:

repository.Insert(entity, ignoreNullValues: true);

也可以全局配置,在 AppDbContext 的派生类的构造函数中启用即可:

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class DefaultDbContext : AppDbContext<DefaultDbContext>    {        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)        {            InsertOrUpdateIgnoreNullValues = true;        }    }}

9.5.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-audit/index.html b/handbook/build/docs/dbcontext-audit/index.html index 63bdf3b5cf..f9579fe3fb 100644 --- a/handbook/build/docs/dbcontext-audit/index.html +++ b/handbook/build/docs/dbcontext-audit/index.html @@ -2,22 +2,21 @@ - - - + +9.22 审计日志 | Furion -9.22 审计日志 | Furion - - + + +
-

9.22 审计日志

9.22.1 审计日志

在一个企业应用系统中,用户对系统所有的操作包括请求、数据库操作等等都应该记录起来,那么这些日志我们称为操作日志,也可以说审计日志。

通常来说,我们审计日志更多指的是数据库的操作记录

审计日志一般会记录以下三个操作:

  • 新增操作:记录某某人在某某时间对哪个表新增了什么数据
  • 更新操作:记录某某人在某某时间对哪个表的哪些数据做了更改,记录更改前的值和更改后的值
  • 删除操作:记录某某人在某某时间对哪个表删除了什么数据

9.22.2 关于 SaveChanges 事件

Furion 框架中为所有 AppDbContext 子类都提供了三个可重写的方法,这三个方法分别由三个事件触发:

  • 提交更改之前 SavingChanges 事件:触发 void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result) 方法
  • 提交更改之后 SavedChanges 事件:触发 void SavedChangesEvent(SaveChangesCompletedEventData eventData, int result) 方法
  • 提交更改失败 SaveChangesFailed 事件:触发 void SaveChangesFailedEvent(DbContextErrorEventData eventData) 方法

通过这三个事件我们就可以捕获所有更改的实体然后保存到数据库审计日志中。

9.22.3 如何实现

9.22.3.1 数据库审计日志

我们只需要在 AppDbContext 子类中重写 SavingChanges 事件对应方法即可:

using Furion.DatabaseAccessor;using Microsoft.AspNetCore.Http;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Infrastructure;using System;using System.Linq;using System.Security.AccessControl;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString")]    public class FurionDbContext : AppDbContext<FurionDbContext>    {        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }        /// <summary>        /// 重写保存之前事件        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        protected override void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result)        {            // 获取当前事件对应上下文            var dbContext = eventData.Context;            // 强制重新检查一边实体更改信息            // dbContext.ChangeTracker.DetectChanges();            // 获取所有更改,删除,新增的实体,但排除审计实体(避免死循环)            var entities = dbContext.ChangeTracker.Entries()                .Where(u => u.Entity.GetType() != typeof(Audit) && (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added))                .ToList();            // 通过请求中获取当前操作人            var userId = App.GetService<IHttpContextAccessor>().HttpContext.Items["UserId"];            // 获取所有已更改的实体            foreach (var entity in entities)            {                // 获取实体类型                var entityType = entity.Entity.GetType();                // 获取所有实体有效属性,排除 [NotMapper] 属性                var props = entity.OriginalValues.Properties;                // 获取实体当前(现在)的值                var currentValues = entity.CurrentValues;                // 获取数据库中实体的值                var databaseValues = entity.GetDatabaseValues();                // 遍历所有属性                foreach (var prop in props)                {                    // 获取属性名                    var propName = prop.Name;                    // 获取现在的实体值                    var newValue = currentValues[propName];                    object oldValue = null;                    // 如果是新增数据,则 databaseValues 为空,所以需要判断一下                    if (databaseValues != null)                    {                        oldValue = databaseValues[propName];                    }                    // 插入审计日志表,Audit 是你自定义的实体                    dbContext.Set<Audit>().Add(new Audit                    {                        Table = entityType.Name,    // 表名                        Column = propName,  // 更新的列                        NewValue = newValue,    // 新值                        OldValue = oldValue,    // 旧值                        CreatedTime = DateTime.Now, // 操作时间                        UserId = userId,    // 操作人                        Operate = entity.State.ToString()  // 操作方式:新增、更新、删除                    });                }            }        }    }}
小知识

如果对性能有所要求,那么建议审计日志通过 日志组件 写入数据库,如通过 Nlog、Log4Net 这些等:

// 插入审计日志表dbContext.Set<Audit>().Add(new Audit{    Table = entityType.Name,    // 表名    Column = propName,  // 更新的列    newValue = newValue,    // 新值    OldValue = oldValue,    // 旧值    CreatedTime = DateTime.Now, // 操作时间    UserId = userId,    // 操作人    Operate = entity.State.ToString()  // 操作方式:新增、更新、删除});

替换为:

logger.Information(JsonConvert.SerializeObject(new Audit{    Table = entityType.Name,    // 表名    Column = propName,  // 更新的列    newValue = newValue,    // 新值    OldValue = oldValue,    // 旧值    CreatedTime = DateTime.Now, // 操作时间    UserId = userId,    // 操作人    Operate = entity.State.ToString()  // 操作方式:新增、更新、删除}));

通过上面的例子,我们就可以对数据库所有的新增、更新、删除进行监控了。

9.22.3.2 执行 sql 审计日志

主要通过 DbCommandInterceptor 拦截实现,具体使用可查看 数据库拦截器 - DbCommandInterceptor,如:

using Microsoft.EntityFrameworkCore.Diagnostics;using System.Data.Common;using System.Threading;using System.Threading.Tasks;namespace Furion.Web.Core{    /// <summary>    /// 执行 sql 审计    /// </summary>    public sealed class SqlCommandAuditInterceptor : DbCommandInterceptor    {        public override InterceptionResult<int> NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<int> result)        {            // 获取执行的 sql 语句            var sql = command.CommandText;            // 获取执行的 sql 类型,是 sql 语句,还是存储过程,还是其他            var type = command.CommandType;            // 获取 sql 传递的命令参数            var parameters = command.Parameters;            // 写日志~~~~            return base.NonQueryExecuting(command, eventData, result);        }        public override ValueTask<InterceptionResult<int>> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)        {            // 获取执行的 sql 语句            var sql = command.CommandText;            // 获取执行的 sql 类型,是 sql 语句,还是存储过程,还是其他            var type = command.CommandType;            // 获取 sql 传递的命令参数            var parameters = command.Parameters;            // 写日志~~~~            return base.NonQueryExecutingAsync(command, eventData, result, cancellationToken);        }        // 其他 override    }}
  • 注册审计日志

只需要在注册数据库上下文中指定 interceptors 参数即可

// services.AddDb 一样services.AddDbPool<FurionDbContext>(interceptors: new IInterceptor[] {    new SqlCommandAuditInterceptor()});

9.22.3.3 请求审计日志

关于请求审计日志

如需实现请求审计日志可查阅 【5.4 请求审计日志章节

9.22.4 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.22 审计日志

9.22.1 审计日志

在一个企业应用系统中,用户对系统所有的操作包括请求、数据库操作等等都应该记录起来,那么这些日志我们称为操作日志,也可以说审计日志。

通常来说,我们审计日志更多指的是数据库的操作记录

审计日志一般会记录以下三个操作:

  • 新增操作:记录某某人在某某时间对哪个表新增了什么数据
  • 更新操作:记录某某人在某某时间对哪个表的哪些数据做了更改,记录更改前的值和更改后的值
  • 删除操作:记录某某人在某某时间对哪个表删除了什么数据

9.22.2 关于 SaveChanges 事件

Furion 框架中为所有 AppDbContext 子类都提供了三个可重写的方法,这三个方法分别由三个事件触发:

  • 提交更改之前 SavingChanges 事件:触发 void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result) 方法
  • 提交更改之后 SavedChanges 事件:触发 void SavedChangesEvent(SaveChangesCompletedEventData eventData, int result) 方法
  • 提交更改失败 SaveChangesFailed 事件:触发 void SaveChangesFailedEvent(DbContextErrorEventData eventData) 方法

通过这三个事件我们就可以捕获所有更改的实体然后保存到数据库审计日志中。

9.22.3 如何实现

9.22.3.1 数据库审计日志

我们只需要在 AppDbContext 子类中重写 SavingChanges 事件对应方法即可:

using Furion.DatabaseAccessor;using Microsoft.AspNetCore.Http;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Infrastructure;using System;using System.Linq;using System.Security.AccessControl;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString")]    public class FurionDbContext : AppDbContext<FurionDbContext>    {        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }        /// <summary>        /// 重写保存之前事件        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        protected override void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result)        {            // 获取当前事件对应上下文            var dbContext = eventData.Context;            // 强制重新检查一边实体更改信息            // dbContext.ChangeTracker.DetectChanges();            // 获取所有更改,删除,新增的实体,但排除审计实体(避免死循环)            var entities = dbContext.ChangeTracker.Entries()                .Where(u => u.Entity.GetType() != typeof(Audit) && (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added))                .ToList();            // 通过请求中获取当前操作人            var userId = App.GetService<IHttpContextAccessor>().HttpContext.Items["UserId"];            // 获取所有已更改的实体            foreach (var entity in entities)            {                // 获取实体类型                var entityType = entity.Entity.GetType();                // 获取所有实体有效属性,排除 [NotMapper] 属性                var props = entity.OriginalValues.Properties;                // 获取实体当前(现在)的值                var currentValues = entity.CurrentValues;                // 获取数据库中实体的值                var databaseValues = entity.GetDatabaseValues();                // 遍历所有属性                foreach (var prop in props)                {                    // 获取属性名                    var propName = prop.Name;                    // 获取现在的实体值                    var newValue = currentValues[propName];                    object oldValue = null;                    // 如果是新增数据,则 databaseValues 为空,所以需要判断一下                    if (databaseValues != null)                    {                        oldValue = databaseValues[propName];                    }                    // 插入审计日志表,Audit 是你自定义的实体                    dbContext.Set<Audit>().Add(new Audit                    {                        Table = entityType.Name,    // 表名                        Column = propName,  // 更新的列                        NewValue = newValue,    // 新值                        OldValue = oldValue,    // 旧值                        CreatedTime = DateTime.Now, // 操作时间                        UserId = userId,    // 操作人                        Operate = entity.State.ToString()  // 操作方式:新增、更新、删除                    });                }            }        }    }}
小知识

如果对性能有所要求,那么建议审计日志通过 日志组件 写入数据库,如通过 Nlog、Log4Net 这些等:

// 插入审计日志表dbContext.Set<Audit>().Add(new Audit{    Table = entityType.Name,    // 表名    Column = propName,  // 更新的列    newValue = newValue,    // 新值    OldValue = oldValue,    // 旧值    CreatedTime = DateTime.Now, // 操作时间    UserId = userId,    // 操作人    Operate = entity.State.ToString()  // 操作方式:新增、更新、删除});

替换为:

logger.Information(JsonConvert.SerializeObject(new Audit{    Table = entityType.Name,    // 表名    Column = propName,  // 更新的列    newValue = newValue,    // 新值    OldValue = oldValue,    // 旧值    CreatedTime = DateTime.Now, // 操作时间    UserId = userId,    // 操作人    Operate = entity.State.ToString()  // 操作方式:新增、更新、删除}));

通过上面的例子,我们就可以对数据库所有的新增、更新、删除进行监控了。

9.22.3.2 执行 sql 审计日志

主要通过 DbCommandInterceptor 拦截实现,具体使用可查看 数据库拦截器 - DbCommandInterceptor,如:

using Microsoft.EntityFrameworkCore.Diagnostics;using System.Data.Common;using System.Threading;using System.Threading.Tasks;namespace Furion.Web.Core{    /// <summary>    /// 执行 sql 审计    /// </summary>    public sealed class SqlCommandAuditInterceptor : DbCommandInterceptor    {        public override InterceptionResult<int> NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<int> result)        {            // 获取执行的 sql 语句            var sql = command.CommandText;            // 获取执行的 sql 类型,是 sql 语句,还是存储过程,还是其他            var type = command.CommandType;            // 获取 sql 传递的命令参数            var parameters = command.Parameters;            // 写日志~~~~            return base.NonQueryExecuting(command, eventData, result);        }        public override ValueTask<InterceptionResult<int>> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)        {            // 获取执行的 sql 语句            var sql = command.CommandText;            // 获取执行的 sql 类型,是 sql 语句,还是存储过程,还是其他            var type = command.CommandType;            // 获取 sql 传递的命令参数            var parameters = command.Parameters;            // 写日志~~~~            return base.NonQueryExecutingAsync(command, eventData, result, cancellationToken);        }        // 其他 override    }}
  • 注册审计日志

只需要在注册数据库上下文中指定 interceptors 参数即可

// services.AddDb 一样services.AddDbPool<FurionDbContext>(interceptors: new IInterceptor[] {    new SqlCommandAuditInterceptor()});

9.22.3.3 请求审计日志

关于请求审计日志

如需实现请求审计日志可查阅 【5.4 请求审计日志章节

9.22.4 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-batch/index.html b/handbook/build/docs/dbcontext-batch/index.html index f1f2bc2017..a8f9df15db 100644 --- a/handbook/build/docs/dbcontext-batch/index.html +++ b/handbook/build/docs/dbcontext-batch/index.html @@ -2,22 +2,21 @@ - - - + +9.9 批量操作 | Furion -9.9 批量操作 | Furion - - + + +
-

9.9 批量操作

9.9.1 关于批量操作

Furion 框架中,默认只提供小数据(100 条 以内)批量数据操作,如果需要更大的数据批量处理,推荐使用第三方包 Zack.EFCore.Batch,支持和 Furion 无缝衔接。

9.9.2 Zack.EFCore.Batch 使用

9.9.2.1 安装对应的数据库 Nuget

  • MSSQLZack.EFCore.Batch.MSSQL
  • MySqlZack.EFCore.Batch.MySQL.Pomelo
  • NpgsqlZack.EFCore.Batch.Npgsql
  • OracleZack.EFCore.Batch.Oracle
  • SqliteZack.EFCore.Batch.Sqlite

9.9.2.2 注册并配置服务

services.AddDatabaseAccessor(options =>{    options.AddDbPool<DefaultDbContext>(providerName: default, optionBuilder: (services, opt) => // 如果是 v3.7.11 之前,使用 opt =>    {        opt.UseBatchEF_Sqlite();    // SQlite 数据库包    });});

9.9.2.3 基本使用

// 批量更新await repository.Context.BatchUpdate<Book>()    .Set(b => b.Price, b => b.Price + 3)    .Set(b => b.Title, b => s)    .Set(b => b.AuthorName,b=>b.Title.Substring(3,2)+b.AuthorName.ToUpper())    .Set(b => b.PubTime, b => DateTime.Now)    .Where(b => b.Id > n || b.AuthorName.StartsWith("Zack"))    .ExecuteAsync();// 批量删除await repository.Context.DeleteRangeAsync<Book>(b => b.Price > n || b.AuthorName == "zack yang");

9.9.3 EFCore.BulkExtensions 使用

通过 Nuget 安装 EFCore.BulkExtensions 包即可。

9.9.3.1 常见批量操作

// 批量插入repository.Context.BulkInsert(entitiesList);repository.Context.BulkInsertAsync(entitiesList);// 批量更新repository.Context.BulkUpdate(entitiesList);repository.Context.BulkUpdateAsync(entitiesList);// 批量删除repository.Context.BulkDelete(entitiesList);repository.Context.BulkDeleteAsync(entitiesList);// 批量插入或更新repository.Context.BulkInsertOrUpdate(entitiesList);repository.Context.BulkInsertOrUpdateAsync(entitiesList);// 批量插入或更新或删除repository.Context.BulkInsertOrUpdateOrDelete(entitiesList);repository.Context.BulkInsertOrUpdateOrDeleteAsync(entitiesList);// 批量读取多个实体repository.Context.BulkRead(entitiesList);repository.Context.BulkReadAsync(entitiesList);// 批量清空表(慎用!!!!!)repository.Context.Truncate<Entity>();repository.Context.TruncateAsync<Entity>();

9.9.3.2 查询后批量操作

// 根据条件批量删除repository.Where(a => a.ItemId >  500).BatchDelete();await repository.Where(a => a.ItemId >  500).BatchDeleteAsync();// 根据条件批量更新repository.Where(a => a.ItemId <= 500).BatchUpdate(a => new Item { Quantity = a.Quantity + 100 });repository.Where(a => a.ItemId <= 500).BatchUpdate(new Item { Description = "Updated" });await repository.Where(a => a.ItemId <= 500).BatchUpdateAsync(new Item { Description = "Updated" });// 批量更新指定列var updateColumns = new List<string> { nameof(Item.Quantity) };var q = repository.Where(a => a.ItemId <= 500);int affected = q.BatchUpdate(new Item { Description = "Updated" }, updateColumns);

9.9.3.3 批量操作性能

Operations\Rows100,000 EF100,000 EFBulk1,000,000 EFBulk
Insert38.98 s2.10 s17.99 s
Update109.25 s3.96 s31.45 s
Delete7.26 s2.04 s12.18 s
---------------------------------------------------------------
Together70.70 s5.88 s56.84 s

9.9.4 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 EFCore.BulkExtensions 知识可查阅 EFCore.BulkExtensions 开源仓库

演练场
- - +

9.9 批量操作

9.9.1 关于批量操作

Furion 框架中,默认只提供小数据(100 条 以内)批量数据操作,如果需要更大的数据批量处理,推荐使用第三方包 Zack.EFCore.Batch,支持和 Furion 无缝衔接。

9.9.2 Zack.EFCore.Batch 使用

9.9.2.1 安装对应的数据库 Nuget

  • MSSQLZack.EFCore.Batch.MSSQL
  • MySqlZack.EFCore.Batch.MySQL.Pomelo
  • NpgsqlZack.EFCore.Batch.Npgsql
  • OracleZack.EFCore.Batch.Oracle
  • SqliteZack.EFCore.Batch.Sqlite

9.9.2.2 注册并配置服务

services.AddDatabaseAccessor(options =>{    options.AddDbPool<DefaultDbContext>(providerName: default, optionBuilder: (services, opt) => // 如果是 v3.7.11 之前,使用 opt =>    {        opt.UseBatchEF_Sqlite();    // SQlite 数据库包    });});

9.9.2.3 基本使用

// 批量更新await repository.Context.BatchUpdate<Book>()    .Set(b => b.Price, b => b.Price + 3)    .Set(b => b.Title, b => s)    .Set(b => b.AuthorName,b=>b.Title.Substring(3,2)+b.AuthorName.ToUpper())    .Set(b => b.PubTime, b => DateTime.Now)    .Where(b => b.Id > n || b.AuthorName.StartsWith("Zack"))    .ExecuteAsync();// 批量删除await repository.Context.DeleteRangeAsync<Book>(b => b.Price > n || b.AuthorName == "zack yang");

9.9.3 EFCore.BulkExtensions 使用

通过 Nuget 安装 EFCore.BulkExtensions 包即可。

9.9.3.1 常见批量操作

// 批量插入repository.Context.BulkInsert(entitiesList);repository.Context.BulkInsertAsync(entitiesList);// 批量更新repository.Context.BulkUpdate(entitiesList);repository.Context.BulkUpdateAsync(entitiesList);// 批量删除repository.Context.BulkDelete(entitiesList);repository.Context.BulkDeleteAsync(entitiesList);// 批量插入或更新repository.Context.BulkInsertOrUpdate(entitiesList);repository.Context.BulkInsertOrUpdateAsync(entitiesList);// 批量插入或更新或删除repository.Context.BulkInsertOrUpdateOrDelete(entitiesList);repository.Context.BulkInsertOrUpdateOrDeleteAsync(entitiesList);// 批量读取多个实体repository.Context.BulkRead(entitiesList);repository.Context.BulkReadAsync(entitiesList);// 批量清空表(慎用!!!!!)repository.Context.Truncate<Entity>();repository.Context.TruncateAsync<Entity>();

9.9.3.2 查询后批量操作

// 根据条件批量删除repository.Where(a => a.ItemId >  500).BatchDelete();await repository.Where(a => a.ItemId >  500).BatchDeleteAsync();// 根据条件批量更新repository.Where(a => a.ItemId <= 500).BatchUpdate(a => new Item { Quantity = a.Quantity + 100 });repository.Where(a => a.ItemId <= 500).BatchUpdate(new Item { Description = "Updated" });await repository.Where(a => a.ItemId <= 500).BatchUpdateAsync(new Item { Description = "Updated" });// 批量更新指定列var updateColumns = new List<string> { nameof(Item.Quantity) };var q = repository.Where(a => a.ItemId <= 500);int affected = q.BatchUpdate(new Item { Description = "Updated" }, updateColumns);

9.9.3.3 批量操作性能

Operations\Rows100,000 EF100,000 EFBulk1,000,000 EFBulk
Insert38.98 s2.10 s17.99 s
Update109.25 s3.96 s31.45 s
Delete7.26 s2.04 s12.18 s
---------------------------------------------------------------
Together70.70 s5.88 s56.84 s

9.9.4 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 EFCore.BulkExtensions 知识可查阅 EFCore.BulkExtensions 开源仓库

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-code-first/index.html b/handbook/build/docs/dbcontext-code-first/index.html index 68606d7aa2..1fa01c1c82 100644 --- a/handbook/build/docs/dbcontext-code-first/index.html +++ b/handbook/build/docs/dbcontext-code-first/index.html @@ -2,22 +2,21 @@ - - - + +9.20 模型生成数据库 | Furion -9.20 模型生成数据库 | Furion - - + + +
-

9.20 模型生成数据库

开始之前

Fur.Web.Entry 层需要安装 Microsoft.EntityFrameworkCore.Tools 包。

9.20.1 数据库开发方式

Furion 提供两种主要方法来 保持实体模型和数据库架构同步

至于我们应该选用哪个方法,请确定你是希望以实体模型为准还是以数据库为准:

  • 如果希望 以实体模型为准,请使用正向工程(Code First)。 对实体模型进行更改时,此方法会以增量方式将相应架构更改应用到数据库,以使数据库保持与实体模型兼容。

  • 如果希望 以数据库架构为准,请使用反向工程(Database First)。 使用此方法,可通过将数据库架构反向工程到实体模型来生成相应的实体类型。

本章节是 正向工程(Code First) 的相关内容。

9.20.2 操作指南

特别注意

Furion 框架默认数据迁移的程序集为:Furion.Database.Migrations,所以如果您改了程序集名称或通过 Nuget 方式安装的 Furion 包,则需要配置迁移程序集名称:

services.AddDatabaseAccessor(options =>{    options.AddDbPool<FurionDbContext>(DbProvider.Sqlite);}, "存放迁移文件的项目名称");

另外,如果应用中配置了多个数据库上下文,那么所有的 迁移命令 都需要指定 -Context 数据库上下文名称 参数。如:

Add-Migration v1.0.0 -Context FurionDbContext

9.20.2.1 创建实体模型 Person

using Furion.DatabaseAccessor;using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;namespace Furion.Core{    public class Person : Entity    {        /// <summary>        /// 构造函数        /// </summary>        public Person()        {            CreatedTime = DateTime.Now;            IsDeleted = false;        }        /// <summary>        /// 姓名        /// </summary>        [MaxLength(32)]        public string Name { get; set; }        /// <summary>        /// 年龄        /// </summary>        public int Age { get; set; }        /// <summary>        /// 住址        /// </summary>        public string Address { get; set; }    }}
实体约定

所有数据库实体必须直接或间接继承 IEntity 接口。

9.20.2.2 打开 程序包管理控制台

9.20.2.3 切换默认项目

程序包管理控制台 默认项目设置为 Furion.Database.Migrations

9.20.2.4 创建模型版本

Add-Migration v1.0.0
特别说明

v1.0.0 是此处数据库更改的版本号,可以写任何字符串,但推荐写版本号,每次 +1

最终命令如下:

PM> Add-Migration v1.0.0Build started...Build succeeded.Microsoft.EntityFrameworkCore.Model.Validation[10400]      Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data, this mode should only be enabled during development.Microsoft.EntityFrameworkCore.Infrastructure[10403]      Entity Framework Core 5.0.0-rc.1.20451.13 initialized 'FurionDbContext' using provider 'Microsoft.EntityFrameworkCore.Sqlite' with options: SensitiveDataLoggingEnabled DetailedErrorsEnabled MaxPoolSize=100 MigrationsAssembly=Furion.Database.MigrationsTo undo this action, use Remove-Migration.PM>

生成成功后,Furion.Database.Migrations 项目下会新增 Migrations 文件夹(如果没有),同时本次的架构生成文件,如:

9.20.2.5 更新到数据库

Update-Database

执行该命令后,数据库就会自动根据模型生成对应的表。

小知识

如果 Update-Database 后面带字符串参数,则会自动还原数据库到指定版本,如:

Update-Database v0.0.3

将数据库还原到 v0.0.3 版本

9.20.3 更新模型

如果模型改变了,重复上面操作即可,如:

Add-Migration v1.0.1
Update-Database

9.20.4 导出 Sql

有些时候,我们没有直接更新数据库的权限,或者怕出问题,我们都会先生成 Sql 看看,这时候只需要通过 Script-Migration 导出即可,如:

Script-Migration

9.20.5 VS Code/Rider/任何IDE/操作系统 方式

9.20.5.1 安装 dotnet ef

dotnet tool install --global dotnet-ef --version 5.0.0-rc.2.20475.6

9.20.5.2 cd 目录

通过 VS Code 打开 .sln 所在的目录,如:framework

之后进入 Furion.Database.Migrations 目录

cd Furion.Database.Migrations

9.20.5.3 执行命令

dotnet ef migrations add v1.0.0 -s "../Furion.Web.Entry"
dotnet ef database update -s "../Furion.Web.Entry"

9.20.6 应用启动时自动生成数据库

Furion 框架建议大家使用命令方式操作数据库,完全不推荐自动化生成数据库,但是有些特殊情况下,有这个必要,故将此功能写出:

9.20.6.1 对已经生成 Migrations 文件情况

如果已经生成 Migrations 文件,那么可以直接在 Startup.cs 代码中实现程序启动时自动执行 update-database 命令,如:

public void Configure(IApplicationBuilder app, IHostingEnvironment env){    // 判断开发环境!!!必须!!!!    if (env.IsDevelopment())    {        Scoped.Create((_, scope) =>        {            var context = scope.ServiceProvider.GetRequiredService<FurionDbContext>();            context.Database.Migrate();        });    }    // 其他代码}

9.20.6.2 如果没有生成过 Migrations 文件情况

public void Configure(IApplicationBuilder app, IHostingEnvironment env){    // 判断开发环境!!!必须!!!!    if (env.IsDevelopment())    {        Scoped.Create((_, scope) =>        {            var context = scope.ServiceProvider.GetRequiredService<FurionDbContext>();            context.Database.EnsureCreated();        });    }    // 其他代码}

如果需要在创建数据库之前先删除旧的,可先调用 context.Database.EnsureDeleted(); 代码。慎重!!!!!!!!!!!!

9.20.7 MySql.EntityFrameworkCore.NET 6.0.8+ 问题

.NET 6.0.8+ 版本,微软底层修改了 IDesignTimeServices 逻辑导致 MySql.EntityFrameworkCore 版本没有及时更新导致一下错误:

PM> Add-Migration v0.0.1Build started...Build succeeded.Microsoft.EntityFrameworkCore.Model.Validation[10400]      Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data; this mode should only be enabled during development.Microsoft.EntityFrameworkCore.Infrastructure[10403]      Entity Framework Core 6.0.8 initialized 'DefaultDbContext' using provider 'MySql.EntityFrameworkCore:6.0.4+MySQL8.0.30' with options: SensitiveDataLoggingEnabled DetailedErrorsEnabled MaxPoolSize=100 MigrationsAssembly=Furion.TestMS.Database.Migrations System.InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.Storage.TypeMappingSourceDependencies' while attempting to activate 'MySql.EntityFrameworkCore.Storage.Internal.MySQLTypeMappingSource'.   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateEnumerable(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType)   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)Unable to resolve service for type 'Microsoft.EntityFrameworkCore.Storage.TypeMappingSourceDependencies' while attempting to activate 'MySql.EntityFrameworkCore.Storage.Internal.MySQLTypeMappingSource'.PM> 

解决办法也很简单,只需要在启动层添加 MysqlEntityFrameworkDesignTimeServices.cs 并写入以下内容即可:

using Microsoft.EntityFrameworkCore.Design;using MySql.EntityFrameworkCore.Extensions;namespace YourProject.Web.Entry;public class MysqlEntityFrameworkDesignTimeServices : IDesignTimeServices{    public void ConfigureDesignTimeServices(IServiceCollection serviceCollection)    {        serviceCollection.AddEntityFrameworkMySQL();        new EntityFrameworkRelationalDesignServicesBuilder(serviceCollection)            .TryAddCoreServices();    }}

相关 Issue 讨论:https://gitee.com/dotnetchina/Furion/issues/I5O5ER

9.20.8 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 正向工厂 知识可查阅 EF Core - 管理数据库架构 章节。

演练场
- - +

9.20 模型生成数据库

开始之前

Fur.Web.Entry 层需要安装 Microsoft.EntityFrameworkCore.Tools 包。

9.20.1 数据库开发方式

Furion 提供两种主要方法来 保持实体模型和数据库架构同步

至于我们应该选用哪个方法,请确定你是希望以实体模型为准还是以数据库为准:

  • 如果希望 以实体模型为准,请使用正向工程(Code First)。 对实体模型进行更改时,此方法会以增量方式将相应架构更改应用到数据库,以使数据库保持与实体模型兼容。

  • 如果希望 以数据库架构为准,请使用反向工程(Database First)。 使用此方法,可通过将数据库架构反向工程到实体模型来生成相应的实体类型。

本章节是 正向工程(Code First) 的相关内容。

9.20.2 操作指南

特别注意

Furion 框架默认数据迁移的程序集为:Furion.Database.Migrations,所以如果您改了程序集名称或通过 Nuget 方式安装的 Furion 包,则需要配置迁移程序集名称:

services.AddDatabaseAccessor(options =>{    options.AddDbPool<FurionDbContext>(DbProvider.Sqlite);}, "存放迁移文件的项目名称");

另外,如果应用中配置了多个数据库上下文,那么所有的 迁移命令 都需要指定 -Context 数据库上下文名称 参数。如:

Add-Migration v1.0.0 -Context FurionDbContext

9.20.2.1 创建实体模型 Person

using Furion.DatabaseAccessor;using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;namespace Furion.Core{    public class Person : Entity    {        /// <summary>        /// 构造函数        /// </summary>        public Person()        {            CreatedTime = DateTime.Now;            IsDeleted = false;        }        /// <summary>        /// 姓名        /// </summary>        [MaxLength(32)]        public string Name { get; set; }        /// <summary>        /// 年龄        /// </summary>        public int Age { get; set; }        /// <summary>        /// 住址        /// </summary>        public string Address { get; set; }    }}
实体约定

所有数据库实体必须直接或间接继承 IEntity 接口。

9.20.2.2 打开 程序包管理控制台

9.20.2.3 切换默认项目

程序包管理控制台 默认项目设置为 Furion.Database.Migrations

9.20.2.4 创建模型版本

Add-Migration v1.0.0
特别说明

v1.0.0 是此处数据库更改的版本号,可以写任何字符串,但推荐写版本号,每次 +1

最终命令如下:

PM> Add-Migration v1.0.0Build started...Build succeeded.Microsoft.EntityFrameworkCore.Model.Validation[10400]      Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data, this mode should only be enabled during development.Microsoft.EntityFrameworkCore.Infrastructure[10403]      Entity Framework Core 5.0.0-rc.1.20451.13 initialized 'FurionDbContext' using provider 'Microsoft.EntityFrameworkCore.Sqlite' with options: SensitiveDataLoggingEnabled DetailedErrorsEnabled MaxPoolSize=100 MigrationsAssembly=Furion.Database.MigrationsTo undo this action, use Remove-Migration.PM>

生成成功后,Furion.Database.Migrations 项目下会新增 Migrations 文件夹(如果没有),同时本次的架构生成文件,如:

9.20.2.5 更新到数据库

Update-Database

执行该命令后,数据库就会自动根据模型生成对应的表。

小知识

如果 Update-Database 后面带字符串参数,则会自动还原数据库到指定版本,如:

Update-Database v0.0.3

将数据库还原到 v0.0.3 版本

9.20.3 更新模型

如果模型改变了,重复上面操作即可,如:

Add-Migration v1.0.1
Update-Database

9.20.4 导出 Sql

有些时候,我们没有直接更新数据库的权限,或者怕出问题,我们都会先生成 Sql 看看,这时候只需要通过 Script-Migration 导出即可,如:

Script-Migration

9.20.5 VS Code/Rider/任何IDE/操作系统 方式

9.20.5.1 安装 dotnet ef

dotnet tool install --global dotnet-ef --version 5.0.0-rc.2.20475.6

9.20.5.2 cd 目录

通过 VS Code 打开 .sln 所在的目录,如:framework

之后进入 Furion.Database.Migrations 目录

cd Furion.Database.Migrations

9.20.5.3 执行命令

dotnet ef migrations add v1.0.0 -s "../Furion.Web.Entry"
dotnet ef database update -s "../Furion.Web.Entry"

9.20.6 应用启动时自动生成数据库

Furion 框架建议大家使用命令方式操作数据库,完全不推荐自动化生成数据库,但是有些特殊情况下,有这个必要,故将此功能写出:

9.20.6.1 对已经生成 Migrations 文件情况

如果已经生成 Migrations 文件,那么可以直接在 Startup.cs 代码中实现程序启动时自动执行 update-database 命令,如:

public void Configure(IApplicationBuilder app, IHostingEnvironment env){    // 判断开发环境!!!必须!!!!    if (env.IsDevelopment())    {        Scoped.Create((_, scope) =>        {            var context = scope.ServiceProvider.GetRequiredService<FurionDbContext>();            context.Database.Migrate();        });    }    // 其他代码}

9.20.6.2 如果没有生成过 Migrations 文件情况

public void Configure(IApplicationBuilder app, IHostingEnvironment env){    // 判断开发环境!!!必须!!!!    if (env.IsDevelopment())    {        Scoped.Create((_, scope) =>        {            var context = scope.ServiceProvider.GetRequiredService<FurionDbContext>();            context.Database.EnsureCreated();        });    }    // 其他代码}

如果需要在创建数据库之前先删除旧的,可先调用 context.Database.EnsureDeleted(); 代码。慎重!!!!!!!!!!!!

9.20.7 MySql.EntityFrameworkCore.NET 6.0.8+ 问题

.NET 6.0.8+ 版本,微软底层修改了 IDesignTimeServices 逻辑导致 MySql.EntityFrameworkCore 版本没有及时更新导致一下错误:

PM> Add-Migration v0.0.1Build started...Build succeeded.Microsoft.EntityFrameworkCore.Model.Validation[10400]      Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data; this mode should only be enabled during development.Microsoft.EntityFrameworkCore.Infrastructure[10403]      Entity Framework Core 6.0.8 initialized 'DefaultDbContext' using provider 'MySql.EntityFrameworkCore:6.0.4+MySQL8.0.30' with options: SensitiveDataLoggingEnabled DetailedErrorsEnabled MaxPoolSize=100 MigrationsAssembly=Furion.TestMS.Database.Migrations System.InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.Storage.TypeMappingSourceDependencies' while attempting to activate 'MySql.EntityFrameworkCore.Storage.Internal.MySQLTypeMappingSource'.   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateEnumerable(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Type serviceType, CallSiteChain callSiteChain)   at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType)   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)Unable to resolve service for type 'Microsoft.EntityFrameworkCore.Storage.TypeMappingSourceDependencies' while attempting to activate 'MySql.EntityFrameworkCore.Storage.Internal.MySQLTypeMappingSource'.PM> 

解决办法也很简单,只需要在启动层添加 MysqlEntityFrameworkDesignTimeServices.cs 并写入以下内容即可:

using Microsoft.EntityFrameworkCore.Design;using MySql.EntityFrameworkCore.Extensions;namespace YourProject.Web.Entry;public class MysqlEntityFrameworkDesignTimeServices : IDesignTimeServices{    public void ConfigureDesignTimeServices(IServiceCollection serviceCollection)    {        serviceCollection.AddEntityFrameworkMySQL();        new EntityFrameworkRelationalDesignServicesBuilder(serviceCollection)            .TryAddCoreServices();    }}

相关 Issue 讨论:https://gitee.com/dotnetchina/Furion/issues/I5O5ER

9.20.8 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 正向工厂 知识可查阅 EF Core - 管理数据库架构 章节。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-db-first/index.html b/handbook/build/docs/dbcontext-db-first/index.html index 293b4ba3f3..2e6272dc64 100644 --- a/handbook/build/docs/dbcontext-db-first/index.html +++ b/handbook/build/docs/dbcontext-db-first/index.html @@ -2,22 +2,21 @@ - - - + +9.19 数据库生成模型 | Furion -9.19 数据库生成模型 | Furion - - + + +
-

9.19 数据库生成模型

关于脚本

在阅读下面文档之前,必须把Furion 源码文件夹下的 tools/cli.ps1 文件拷贝到本地中。而且 Fur.Web.Entry 层需要安装 Microsoft.EntityFrameworkCore.Tools 包。

系统提示禁止运行脚本解决

如果出现 cli.ps1 无法运行的情况,如提示:“因为在此系统上禁止运行脚本”,只需要打开系统管理员 CMD/Powershell 执行:set-ExecutionPolicy RemoteSigned 命令并根据操作提示输入 A 即可。

之后重启 Visual Studio 工具。

9.19.1 数据库开发方式

Furion 提供两种主要方法来 保持实体模型和数据库架构同步

至于我们应该选用哪个方法,请确定你是希望以实体模型为准还是以数据库为准:

  • 如果希望 以实体模型为准,请使用正向工程(Code First)。 对实体模型进行更改时,此方法会以增量方式将相应架构更改应用到数据库,以使数据库保持与实体模型兼容。

  • 如果希望 以数据库架构为准,请使用反向工程(Database First)。 使用此方法,可通过将数据库架构反向工程到实体模型来生成相应的实体类型。

本章节是 反向工程(Database First) 的相关内容。

9.19.2 操作指南

操作之前注意事项

目前 Furion Tools 生成工具默认不支持任何数据库生成,所以如需生成特定数据库的代码,只需要在 Furion.EntityFrameworkCore.Core 安装对应的数据库包即可:

各个数据库的包可查阅:多数据库操作-数据库提供器对应包

另外,只有 SqlServer 数据库支持可视化 GUI 操作,其他的只能命令行操作。

9.19.2.1 打开 程序包管理控制台

注意:开始之前先把 Furion.Web.Entry 设为启动项目。

9.19.2.2 切换默认项目

程序包管理控制台 默认项目设置为 Furion.Core,如果您是其他名字,则切换对应即可。

9.19.2.3 输入 cli.ps1 命令

PM> Show-Command ../tools/cli.ps1
全命令方式(推荐)❤️

除了采用 Show-Command 方式以外,还可以直接执行命令,如:

&"./tools/cli.ps1" -DbProvider "Microsoft.EntityFrameworkCore.SqlServer" -CoreProject "XXX.Core" -EntryProject "XXX.Web.Entry" -ConnectionName "Default"
小提示

如果使用的是 SqlServer 数据库,则默认不需要指定 -DbProvider 参数。

如果不清楚当前运行环境的路径,可以输入 pwd 查看。

关于数据库命名

如果需要保持和数据库一模一样的命名,则使用 -UseDatabaseNames 参数指定,如:

 &"../tools/cli.ps1" -UseDatabaseNames
等待输入

执行上面命令后,此时 Cli 有一个等待输入提示:

Furion Tools v1.0.0 请键入操作类型:[G] 界面操作,[任意字符] 命令行操作Furion Tools v1.0.0 您的输入是:

输入大写 G 进入界面操作模式,其他任意字符进入命令行操作模式。

注意事项

目前只有 Sql Server 数据库才支持 GUI 界面操作模式,其他数据库请使用命令行模式。

9.19.3 界面操作模式

9.19.3.1 启动界面操作

当我们输入 G 时,将打开 GUI 界面操作模式,如:

这时,Furion Tools 会自动查找所有数据库配置连接字符串的 .json 文件:

注意事项

数据库连接字符串配置项需写到 json 配置文件中,且根节点需要写为 ConnectionStrings

{  "Logging": {    "LogLevel": {      "Default": "Information",      "Microsoft": "Warning",      "Microsoft.Hosting.Lifetime": "Information",      "Microsoft.EntityFrameworkCore": "Information"    }  },  "AllowedHosts": "*",  "ConnectionStrings": {    "DbConnectionString": "Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;",    "Sqlite3ConnectionString": "Data Source=./Furion.db"  }}

9.19.3.2 加载数据库表

选择连接字符串之后,点击 加载数据库表和视图 按钮加载。

9.19.3.3 选择表或视图生成

加载表完成后,可以选择您要生成的表或视图,支持多选

点击底部按钮 立即生成

9.19.3.4 选择保存目录

点击 立即生成 按钮后,会弹出实体保存选择目录资源管理器,默认实体只能保存在 Furion.Core 层:

点击确定后就可完成所有生成操作。

9.19.3.5 生成最终实体代码

最终脚本如下:

PM> &"../tools/cli.ps1"// -----------------------------------------------------------------------------//   ______            _______          _//  |  ____|          |__   __|        | |//  | |__ _   _ _ __     | | ___   ___ | |___//  |  __| | | | '__|    | |/ _ \ / _ \| / __|//  | |  | |_| | |       | | (_) | (_) | \__ \//  |_|   \__,_|_|       |_|\___/ \___/|_|___///// -----------------------------------------------------------------------------Furion Tools v1.0.0 启动中......Furion Tools v1.0.0 启动成功!Furion Tools v1.0.0 请键入操作类型:[G] 界面操作,[任意字符] 命令行操作Furion Tools v1.0.0 您的输入是: GFurion Tools v1.0.0 正在加载数据库表和视图......Furion Tools v1.0.0 加载成功!Furion Tools v1.0.0 正在编译解决方案代码......Build started...Build succeeded.For foreign key FK_PersonDetail_Person_PersonId on table dbo.PersonDetail, unable to model the end of the foreign key on principal table dbo.Person. This is usually because the principal table was not included in the selection set.Furion Tools v1.0.0 编译成功!Furion Tools v1.0.0 开始生成实体文件......Furion Tools v1.0.0 正在生成 City.cs 实体代码......Furion Tools v1.0.0 成功生成 City.cs 实体代码// -----------------------------------------------------------------------------// 以下代码由 Furion Tools v1.0.0 生成// -----------------------------------------------------------------------------using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Collections.Generic;#nullable disablenamespace Furion.Core{    public partial class City : IEntity, IEntityTypeBuilder<City>    {        public City()        {            InverseParent = new HashSet<City>();        }        public int Id { get; set; }        public string Name { get; set; }        public int? ParentId { get; set; }        public DateTime CreatedTime { get; set; }        public DateTime? UpdatedTime { get; set; }        public bool IsDeleted { get; set; }        public virtual City Parent { get; set; }        public virtual ICollection<City> InverseParent { get; set; }        public void Configure(EntityTypeBuilder<City> entityBuilder, DbContext dbContext, Type dbContextLocator)        {                entityBuilder.HasIndex(e => e.ParentId, "IX_City_ParentId");                entityBuilder.HasOne(d => d.Parent)                    .WithMany(p => p.InverseParent)                    .HasForeignKey(d => d.ParentId);        }    }}Furion Tools v1.0.0 正在生成 PersonDetail.cs 实体代码......Furion Tools v1.0.0 成功生成 PersonDetail.cs 实体代码// -----------------------------------------------------------------------------// 以下代码由 Furion Tools v1.0.0 生成// -----------------------------------------------------------------------------using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Collections.Generic;#nullable disablenamespace Furion.Core{    public partial class PersonDetail : IEntity, IEntityTypeBuilder<PersonDetail>    {        public int Id { get; set; }        public string PhoneNumber { get; set; }        public string Qq { get; set; }        public int PersonId { get; set; }        public void Configure(EntityTypeBuilder<PersonDetail> entityBuilder, DbContext dbContext, Type dbContextLocator)        {                entityBuilder.HasIndex(e => e.PersonId, "IX_PersonDetail_PersonId")                    .IsUnique();                entityBuilder.Property(e => e.Qq).HasColumnName("QQ");        }    }}Furion Tools v1.0.0 正在生成 Post.cs 实体代码......Furion Tools v1.0.0 成功生成 Post.cs 实体代码// -----------------------------------------------------------------------------// 以下代码由 Furion Tools v1.0.0 生成// -----------------------------------------------------------------------------using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Collections.Generic;#nullable disablenamespace Furion.Core{    public partial class Post : IEntity    {        public int Id { get; set; }        public string Name { get; set; }        public DateTime CreatedTime { get; set; }        public DateTime? UpdatedTime { get; set; }        public bool IsDeleted { get; set; }    }}Furion Tools v1.0.0 正在生成 VPerson.cs 实体代码......Furion Tools v1.0.0 成功生成 VPerson.cs 实体代码// -----------------------------------------------------------------------------// 以下代码由 Furion Tools v1.0.0 生成// -----------------------------------------------------------------------------using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Collections.Generic;#nullable disablenamespace Furion.Core{    public partial class VPerson : IEntity, IEntityTypeBuilder<VPerson>    {        public int Id { get; set; }        public string Name { get; set; }        public int Age { get; set; }        public string Address { get; set; }        public void Configure(EntityTypeBuilder<VPerson> entityBuilder, DbContext dbContext, Type dbContextLocator)        {                entityBuilder.HasNoKey();                entityBuilder.ToView("V_Person");                entityBuilder.Property(e => e.Id).ValueGeneratedOnAdd();                entityBuilder.Property(e => e.Name).HasMaxLength(32);        }    }}Furion Tools v1.0.0 全部实体生成成功!PM>

9.19.4 命令参数配置

Furion Tools Cli 支持多个参数配置,使用方法只需要在命令后面添加即可,如:

 &"../tools/cli.ps1" -Context 数据库上下文名 -ConnectionName 连接字符串Key

支持参数如下:

  • -Tables:配置要生成的数据库表,数组类型,如果为空,则生成数据库所有表和视图。如:-Tables Person,PersonDetails
  • -Context:配置数据库上下文,默认 FurionDbContext,如果有多个数据库上下文,则此参数必须配置
  • -ConnectionName:配置数据库连接字符串,对应 appsetting.json 中的 ConnectionStrings 定义的 Key
  • -OutputDir:生成实体代码输出目录,默认为:./Furion.Core/Entities/
  • -DbProvider:数据库提供器,默认是 Microsoft.EntityFrameworkCore.SqlServer,其他数据库请指定对应程序集
    • SqlServerMicrosoft.EntityFrameworkCore.SqlServer
    • SqliteMicrosoft.EntityFrameworkCore.Sqlite
    • CosmosMicrosoft.EntityFrameworkCore.Cosmos
    • InMemoryDatabaseMicrosoft.EntityFrameworkCore.InMemory
    • MySqlPomelo.EntityFrameworkCore.MySqlMySql.EntityFrameworkCore
    • PostgreSQLNpgsql.EntityFrameworkCore.PostgreSQL
    • OracleOracle.EntityFrameworkCore
    • DmMicrosoft.EntityFrameworkCore.Dm
  • -EntryProject:Web 启用项目层名,默认 Furion.Web.Entry
  • -CoreProject:实体项目层名,默认 Furion.Core
  • -DbContextLocators:多数据库上下文定位器,默认 MasterDbContextLocator,支持多个,如:MasterDbContextLocator,MySqlDbContextLocator
  • -Product:解决方案默认前缀,如 Furion
  • -UseDatabaseNames:是否保持生成和数据库、表一致的名称
  • -Namespace:指定实体命名空间

9.19.5 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.19 数据库生成模型

关于脚本

在阅读下面文档之前,必须把Furion 源码文件夹下的 tools/cli.ps1 文件拷贝到本地中。而且 Fur.Web.Entry 层需要安装 Microsoft.EntityFrameworkCore.Tools 包。

系统提示禁止运行脚本解决

如果出现 cli.ps1 无法运行的情况,如提示:“因为在此系统上禁止运行脚本”,只需要打开系统管理员 CMD/Powershell 执行:set-ExecutionPolicy RemoteSigned 命令并根据操作提示输入 A 即可。

之后重启 Visual Studio 工具。

9.19.1 数据库开发方式

Furion 提供两种主要方法来 保持实体模型和数据库架构同步

至于我们应该选用哪个方法,请确定你是希望以实体模型为准还是以数据库为准:

  • 如果希望 以实体模型为准,请使用正向工程(Code First)。 对实体模型进行更改时,此方法会以增量方式将相应架构更改应用到数据库,以使数据库保持与实体模型兼容。

  • 如果希望 以数据库架构为准,请使用反向工程(Database First)。 使用此方法,可通过将数据库架构反向工程到实体模型来生成相应的实体类型。

本章节是 反向工程(Database First) 的相关内容。

9.19.2 操作指南

操作之前注意事项

目前 Furion Tools 生成工具默认不支持任何数据库生成,所以如需生成特定数据库的代码,只需要在 Furion.EntityFrameworkCore.Core 安装对应的数据库包即可:

各个数据库的包可查阅:多数据库操作-数据库提供器对应包

另外,只有 SqlServer 数据库支持可视化 GUI 操作,其他的只能命令行操作。

9.19.2.1 打开 程序包管理控制台

注意:开始之前先把 Furion.Web.Entry 设为启动项目。

9.19.2.2 切换默认项目

程序包管理控制台 默认项目设置为 Furion.Core,如果您是其他名字,则切换对应即可。

9.19.2.3 输入 cli.ps1 命令

PM> Show-Command ../tools/cli.ps1
全命令方式(推荐)❤️

除了采用 Show-Command 方式以外,还可以直接执行命令,如:

&"./tools/cli.ps1" -DbProvider "Microsoft.EntityFrameworkCore.SqlServer" -CoreProject "XXX.Core" -EntryProject "XXX.Web.Entry" -ConnectionName "Default"
小提示

如果使用的是 SqlServer 数据库,则默认不需要指定 -DbProvider 参数。

如果不清楚当前运行环境的路径,可以输入 pwd 查看。

关于数据库命名

如果需要保持和数据库一模一样的命名,则使用 -UseDatabaseNames 参数指定,如:

 &"../tools/cli.ps1" -UseDatabaseNames
等待输入

执行上面命令后,此时 Cli 有一个等待输入提示:

Furion Tools v1.0.0 请键入操作类型:[G] 界面操作,[任意字符] 命令行操作Furion Tools v1.0.0 您的输入是:

输入大写 G 进入界面操作模式,其他任意字符进入命令行操作模式。

注意事项

目前只有 Sql Server 数据库才支持 GUI 界面操作模式,其他数据库请使用命令行模式。

9.19.3 界面操作模式

9.19.3.1 启动界面操作

当我们输入 G 时,将打开 GUI 界面操作模式,如:

这时,Furion Tools 会自动查找所有数据库配置连接字符串的 .json 文件:

注意事项

数据库连接字符串配置项需写到 json 配置文件中,且根节点需要写为 ConnectionStrings

{  "Logging": {    "LogLevel": {      "Default": "Information",      "Microsoft": "Warning",      "Microsoft.Hosting.Lifetime": "Information",      "Microsoft.EntityFrameworkCore": "Information"    }  },  "AllowedHosts": "*",  "ConnectionStrings": {    "DbConnectionString": "Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;",    "Sqlite3ConnectionString": "Data Source=./Furion.db"  }}

9.19.3.2 加载数据库表

选择连接字符串之后,点击 加载数据库表和视图 按钮加载。

9.19.3.3 选择表或视图生成

加载表完成后,可以选择您要生成的表或视图,支持多选

点击底部按钮 立即生成

9.19.3.4 选择保存目录

点击 立即生成 按钮后,会弹出实体保存选择目录资源管理器,默认实体只能保存在 Furion.Core 层:

点击确定后就可完成所有生成操作。

9.19.3.5 生成最终实体代码

最终脚本如下:

PM> &"../tools/cli.ps1"// -----------------------------------------------------------------------------//   ______            _______          _//  |  ____|          |__   __|        | |//  | |__ _   _ _ __     | | ___   ___ | |___//  |  __| | | | '__|    | |/ _ \ / _ \| / __|//  | |  | |_| | |       | | (_) | (_) | \__ \//  |_|   \__,_|_|       |_|\___/ \___/|_|___///// -----------------------------------------------------------------------------Furion Tools v1.0.0 启动中......Furion Tools v1.0.0 启动成功!Furion Tools v1.0.0 请键入操作类型:[G] 界面操作,[任意字符] 命令行操作Furion Tools v1.0.0 您的输入是: GFurion Tools v1.0.0 正在加载数据库表和视图......Furion Tools v1.0.0 加载成功!Furion Tools v1.0.0 正在编译解决方案代码......Build started...Build succeeded.For foreign key FK_PersonDetail_Person_PersonId on table dbo.PersonDetail, unable to model the end of the foreign key on principal table dbo.Person. This is usually because the principal table was not included in the selection set.Furion Tools v1.0.0 编译成功!Furion Tools v1.0.0 开始生成实体文件......Furion Tools v1.0.0 正在生成 City.cs 实体代码......Furion Tools v1.0.0 成功生成 City.cs 实体代码// -----------------------------------------------------------------------------// 以下代码由 Furion Tools v1.0.0 生成// -----------------------------------------------------------------------------using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Collections.Generic;#nullable disablenamespace Furion.Core{    public partial class City : IEntity, IEntityTypeBuilder<City>    {        public City()        {            InverseParent = new HashSet<City>();        }        public int Id { get; set; }        public string Name { get; set; }        public int? ParentId { get; set; }        public DateTime CreatedTime { get; set; }        public DateTime? UpdatedTime { get; set; }        public bool IsDeleted { get; set; }        public virtual City Parent { get; set; }        public virtual ICollection<City> InverseParent { get; set; }        public void Configure(EntityTypeBuilder<City> entityBuilder, DbContext dbContext, Type dbContextLocator)        {                entityBuilder.HasIndex(e => e.ParentId, "IX_City_ParentId");                entityBuilder.HasOne(d => d.Parent)                    .WithMany(p => p.InverseParent)                    .HasForeignKey(d => d.ParentId);        }    }}Furion Tools v1.0.0 正在生成 PersonDetail.cs 实体代码......Furion Tools v1.0.0 成功生成 PersonDetail.cs 实体代码// -----------------------------------------------------------------------------// 以下代码由 Furion Tools v1.0.0 生成// -----------------------------------------------------------------------------using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Collections.Generic;#nullable disablenamespace Furion.Core{    public partial class PersonDetail : IEntity, IEntityTypeBuilder<PersonDetail>    {        public int Id { get; set; }        public string PhoneNumber { get; set; }        public string Qq { get; set; }        public int PersonId { get; set; }        public void Configure(EntityTypeBuilder<PersonDetail> entityBuilder, DbContext dbContext, Type dbContextLocator)        {                entityBuilder.HasIndex(e => e.PersonId, "IX_PersonDetail_PersonId")                    .IsUnique();                entityBuilder.Property(e => e.Qq).HasColumnName("QQ");        }    }}Furion Tools v1.0.0 正在生成 Post.cs 实体代码......Furion Tools v1.0.0 成功生成 Post.cs 实体代码// -----------------------------------------------------------------------------// 以下代码由 Furion Tools v1.0.0 生成// -----------------------------------------------------------------------------using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Collections.Generic;#nullable disablenamespace Furion.Core{    public partial class Post : IEntity    {        public int Id { get; set; }        public string Name { get; set; }        public DateTime CreatedTime { get; set; }        public DateTime? UpdatedTime { get; set; }        public bool IsDeleted { get; set; }    }}Furion Tools v1.0.0 正在生成 VPerson.cs 实体代码......Furion Tools v1.0.0 成功生成 VPerson.cs 实体代码// -----------------------------------------------------------------------------// 以下代码由 Furion Tools v1.0.0 生成// -----------------------------------------------------------------------------using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Collections.Generic;#nullable disablenamespace Furion.Core{    public partial class VPerson : IEntity, IEntityTypeBuilder<VPerson>    {        public int Id { get; set; }        public string Name { get; set; }        public int Age { get; set; }        public string Address { get; set; }        public void Configure(EntityTypeBuilder<VPerson> entityBuilder, DbContext dbContext, Type dbContextLocator)        {                entityBuilder.HasNoKey();                entityBuilder.ToView("V_Person");                entityBuilder.Property(e => e.Id).ValueGeneratedOnAdd();                entityBuilder.Property(e => e.Name).HasMaxLength(32);        }    }}Furion Tools v1.0.0 全部实体生成成功!PM>

9.19.4 命令参数配置

Furion Tools Cli 支持多个参数配置,使用方法只需要在命令后面添加即可,如:

 &"../tools/cli.ps1" -Context 数据库上下文名 -ConnectionName 连接字符串Key

支持参数如下:

  • -Tables:配置要生成的数据库表,数组类型,如果为空,则生成数据库所有表和视图。如:-Tables Person,PersonDetails
  • -Context:配置数据库上下文,默认 FurionDbContext,如果有多个数据库上下文,则此参数必须配置
  • -ConnectionName:配置数据库连接字符串,对应 appsetting.json 中的 ConnectionStrings 定义的 Key
  • -OutputDir:生成实体代码输出目录,默认为:./Furion.Core/Entities/
  • -DbProvider:数据库提供器,默认是 Microsoft.EntityFrameworkCore.SqlServer,其他数据库请指定对应程序集
    • SqlServerMicrosoft.EntityFrameworkCore.SqlServer
    • SqliteMicrosoft.EntityFrameworkCore.Sqlite
    • CosmosMicrosoft.EntityFrameworkCore.Cosmos
    • InMemoryDatabaseMicrosoft.EntityFrameworkCore.InMemory
    • MySqlPomelo.EntityFrameworkCore.MySqlMySql.EntityFrameworkCore
    • PostgreSQLNpgsql.EntityFrameworkCore.PostgreSQL
    • OracleOracle.EntityFrameworkCore
    • DmMicrosoft.EntityFrameworkCore.Dm
  • -EntryProject:Web 启用项目层名,默认 Furion.Web.Entry
  • -CoreProject:实体项目层名,默认 Furion.Core
  • -DbContextLocators:多数据库上下文定位器,默认 MasterDbContextLocator,支持多个,如:MasterDbContextLocator,MySqlDbContextLocator
  • -Product:解决方案默认前缀,如 Furion
  • -UseDatabaseNames:是否保持生成和数据库、表一致的名称
  • -Namespace:指定实体命名空间

9.19.5 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-delete/index.html b/handbook/build/docs/dbcontext-delete/index.html index af031d7673..88e8da8541 100644 --- a/handbook/build/docs/dbcontext-delete/index.html +++ b/handbook/build/docs/dbcontext-delete/index.html @@ -2,22 +2,21 @@ - - - + +9.8 删除操作 | Furion -9.8 删除操作 | Furion - - + + +
-

9.8 删除操作

功能移除声明

以下内容包含 Exists 单词的在 Furion 2.6.0 + 版本中已移除。

9.8.1 删除一个实体(不立即提交)

// ==== 同步操作 ====// 示例一repository.Delete(user);// 示例二user.Delete();// 示例三repository.ChangeEntityState(user, EntityState.Deleted);// 示例四repository.Entities.Remove(user);// ==== 异步操作 ====// 示例一await repository.DeleteAsync(user);// 示例二await user.DeleteAsync();

9.8.2 删除一个实体(立即提交)

// ==== 同步操作 ====// 示例一repository.DeleteNow(user);// 示例二user.DeleteNow();// ==== 异步操作 ====// 示例一await repository.DeleteNowAsync(user);// 示例二await user.DeleteNowAsync();

9.8.3 根据主键删除记录(不立即提交)

// ==== 同步操作 ====// 示例一repository.Delete(1);// 示例二user.Delete(1);// ==== 异步操作 ====// 示例一await repository.DeleteAsync(1);// 示例二await user.DeleteAsync(1);

9.8.4 根据主键删除记录(立即提交)

// ==== 同步操作 ====// 示例一repository.DeleteNow(1);// 示例二user.DeleteNow(1);// ==== 异步操作 ====// 示例一await repository.DeleteNowAsync(1);// 示例二await user.DeleteNowAsync(1);

9.8.5 数据存在才根据主键删除(不立即提交)

// ==== 同步操作 ====// 示例一repository.DeleteExists(1);// 示例二user.DeleteExists(1);// ==== 异步操作 ====// 示例一await repository.DeleteExistsAsync(1);// 示例二await user.DeleteExistsAsync(1);

9.8.6 数据存在才根据主键删除(立即提交)

// ==== 同步操作 ====// 示例一repository.DeleteExistsNow(1);// 示例二user.DeleteExistsNow(1);// ==== 异步操作 ====// 示例一await repository.DeleteExistsNowAsync(1);// 示例二await user.DeleteExistsNowAsync(1);
小知识

所有带 Now 结尾的表示立即提交到数据库,也就是立即调用 SaveChangesSaveChangesAsync

9.8.7 假删除/软删除

功能移除声明

以下内容在 Furion 2.10 + 版本中已移除。

Furion 框架中可以通过 [FakeDelete] 特性标记假删除特性,如:

9.8.7.1 添加 [FakeDelete] 标记

public class Model: IEntity{    [FakeDelete(true)]  // 设置假删除的值    public bool IsDeleted { get; set; }}
[FakeDelete]

[FakeDelete] 属性拥有带一个参数的构造函数,这个参数是假删除的值

9.8.7.2 假删除使用

// ==== 同步操作 ====// 示例一repository.FakeDelete(entity);// 示例二repository.FakeDeleteNow(entity);// 示例三repository.FakeDelete(1);// 示例四repository.FakeDeleteNow(1);// 示例五entity.FakeDelete();// 示例六repository.UpdateInclude(user, u => u.IsDeleted);// ==== 异步操作 ====// 示例一await repository.FakeDeleteAsync(entity);// 示例二await repository.FakeDeleteNowAsync(entity);// 示例三await repository.FakeDeleteAsync(1);// 示例四await repository.FakeDeleteNowAsync(1);// 示例五await entity.FakeDeleteAsync();// 示例六await repository.UpdateIncludeAsync(user, u => u.IsDeleted);

9.8.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.8 删除操作

功能移除声明

以下内容包含 Exists 单词的在 Furion 2.6.0 + 版本中已移除。

9.8.1 删除一个实体(不立即提交)

// ==== 同步操作 ====// 示例一repository.Delete(user);// 示例二user.Delete();// 示例三repository.ChangeEntityState(user, EntityState.Deleted);// 示例四repository.Entities.Remove(user);// ==== 异步操作 ====// 示例一await repository.DeleteAsync(user);// 示例二await user.DeleteAsync();

9.8.2 删除一个实体(立即提交)

// ==== 同步操作 ====// 示例一repository.DeleteNow(user);// 示例二user.DeleteNow();// ==== 异步操作 ====// 示例一await repository.DeleteNowAsync(user);// 示例二await user.DeleteNowAsync();

9.8.3 根据主键删除记录(不立即提交)

// ==== 同步操作 ====// 示例一repository.Delete(1);// 示例二user.Delete(1);// ==== 异步操作 ====// 示例一await repository.DeleteAsync(1);// 示例二await user.DeleteAsync(1);

9.8.4 根据主键删除记录(立即提交)

// ==== 同步操作 ====// 示例一repository.DeleteNow(1);// 示例二user.DeleteNow(1);// ==== 异步操作 ====// 示例一await repository.DeleteNowAsync(1);// 示例二await user.DeleteNowAsync(1);

9.8.5 数据存在才根据主键删除(不立即提交)

// ==== 同步操作 ====// 示例一repository.DeleteExists(1);// 示例二user.DeleteExists(1);// ==== 异步操作 ====// 示例一await repository.DeleteExistsAsync(1);// 示例二await user.DeleteExistsAsync(1);

9.8.6 数据存在才根据主键删除(立即提交)

// ==== 同步操作 ====// 示例一repository.DeleteExistsNow(1);// 示例二user.DeleteExistsNow(1);// ==== 异步操作 ====// 示例一await repository.DeleteExistsNowAsync(1);// 示例二await user.DeleteExistsNowAsync(1);
小知识

所有带 Now 结尾的表示立即提交到数据库,也就是立即调用 SaveChangesSaveChangesAsync

9.8.7 假删除/软删除

功能移除声明

以下内容在 Furion 2.10 + 版本中已移除。

Furion 框架中可以通过 [FakeDelete] 特性标记假删除特性,如:

9.8.7.1 添加 [FakeDelete] 标记

public class Model: IEntity{    [FakeDelete(true)]  // 设置假删除的值    public bool IsDeleted { get; set; }}
[FakeDelete]

[FakeDelete] 属性拥有带一个参数的构造函数,这个参数是假删除的值

9.8.7.2 假删除使用

// ==== 同步操作 ====// 示例一repository.FakeDelete(entity);// 示例二repository.FakeDeleteNow(entity);// 示例三repository.FakeDelete(1);// 示例四repository.FakeDeleteNow(1);// 示例五entity.FakeDelete();// 示例六repository.UpdateInclude(user, u => u.IsDeleted);// ==== 异步操作 ====// 示例一await repository.FakeDeleteAsync(entity);// 示例二await repository.FakeDeleteNowAsync(entity);// 示例三await repository.FakeDeleteAsync(1);// 示例四await repository.FakeDeleteNowAsync(1);// 示例五await entity.FakeDeleteAsync();// 示例六await repository.UpdateIncludeAsync(user, u => u.IsDeleted);

9.8.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-entitytrigger/index.html b/handbook/build/docs/dbcontext-entitytrigger/index.html index 47dc5c0e5a..fa943ce6f1 100644 --- a/handbook/build/docs/dbcontext-entitytrigger/index.html +++ b/handbook/build/docs/dbcontext-entitytrigger/index.html @@ -2,22 +2,21 @@ - - - + +9.25. 实体数据监听器 | Furion -9.25. 实体数据监听器 | Furion - - + + +
-

9.25. 实体数据监听器

9.25.1 实体数据监听器

在最新的 Furion1.1.6+ 版本中,新增了 IEntityChangedListener 实体数据监听接口,可以监听 EFCore 任何实体表 增删改 操作。

9.25.2 有何作用

  • 类似数据库 触发器 功能,可实现 增删改 监听
  • 可以实现特殊操作,比如刷新缓存,记录日志等

9.25.3 如何使用

Furion 框架中,默认不启用实体数据监听器,如想启用,只需要在 数据库上下文 构造函数中启用即可:

9.25.3.1 启用数据监听

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString")]    public class DefaultDbContext : AppDbContext<DefaultDbContext>    {        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)        {            EnabledEntityChangedListener = true;        }    }}

9.25.3.2 监听特定实体数据

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.Extensions.Caching.Memory;using System;using System.Collections.Generic;namespace Furion.Core{    public class Post : Entity, IEntityChangedListener<Post>    {        /// <summary>        /// 构造函数        /// </summary>        public Post()        {            CreatedTime = DateTimeOffset.UtcNow;            IsDeleted = false;        }        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }        /// <summary>        /// Person 集合        /// </summary>        public ICollection<Person> Persons { get; set; }        /// <summary>        /// 实体更改后触发        /// </summary>        /// <param name="entity">新数据</param>        /// <param name="oldEntity">旧数据</param>        /// <param name="dbContext">数据库上下文</param>        /// <param name="dbContextLocator">数据库上下文定位器</param>        /// <param name="state">实体状态</param>        public void OnChanged(Post entity, Post oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state)        {            // 刷新缓存            App.GetService<IMemoryCache>().Set("Key", "Value");        }    }}

9.25.4 IEntityChangedListener 定义

/// <summary>/// 实体数据改变监听依赖接口/// </summary>/// <typeparam name="TEntity"></typeparam>public interface IEntityChangedListener<TEntity>    where TEntity : class, IPrivateEntity, new(){    /// <summary>    /// 监听数据改变之前(仅支持EFCore操作)    /// </summary>    /// <param name="entity"></param>    /// <param name="dbContext"></param>    /// <param name="dbContextLocator"></param>    /// <param name="state"></param>    void OnChanging(TEntity entity, DbContext dbContext, Type dbContextLocator, EntityState state) { }    /// <summary>    /// 监听数据改变之后(仅支持EFCore操作)    /// </summary>    /// <param name="newEntity">新值</param>    /// <param name="oldEntity">旧值</param>    /// <param name="dbContext"></param>    /// <param name="dbContextLocator"></param>    /// <param name="state"></param>    void OnChanged(TEntity newEntity, TEntity oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state);    /// <summary>    /// 监听数据改变失败(仅支持EFCore操作)    /// </summary>    /// <param name="entity"></param>    /// <param name="dbContext"></param>    /// <param name="dbContextLocator"></param>    /// <param name="state"></param>    void OnChangeFailed(TEntity entity, DbContext dbContext, Type dbContextLocator, EntityState state) { }}

9.25.5 [SuppressChangedListener] 跳过监听

默认情况下,Furion 框架会对所有新增、更新、编辑的实体进行监听,有些时候我们无需监听特定实体,只需要在实体上贴 [SuppressChangedListener] 特性即可。

9.25.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.25. 实体数据监听器

9.25.1 实体数据监听器

在最新的 Furion1.1.6+ 版本中,新增了 IEntityChangedListener 实体数据监听接口,可以监听 EFCore 任何实体表 增删改 操作。

9.25.2 有何作用

  • 类似数据库 触发器 功能,可实现 增删改 监听
  • 可以实现特殊操作,比如刷新缓存,记录日志等

9.25.3 如何使用

Furion 框架中,默认不启用实体数据监听器,如想启用,只需要在 数据库上下文 构造函数中启用即可:

9.25.3.1 启用数据监听

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString")]    public class DefaultDbContext : AppDbContext<DefaultDbContext>    {        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)        {            EnabledEntityChangedListener = true;        }    }}

9.25.3.2 监听特定实体数据

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.Extensions.Caching.Memory;using System;using System.Collections.Generic;namespace Furion.Core{    public class Post : Entity, IEntityChangedListener<Post>    {        /// <summary>        /// 构造函数        /// </summary>        public Post()        {            CreatedTime = DateTimeOffset.UtcNow;            IsDeleted = false;        }        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }        /// <summary>        /// Person 集合        /// </summary>        public ICollection<Person> Persons { get; set; }        /// <summary>        /// 实体更改后触发        /// </summary>        /// <param name="entity">新数据</param>        /// <param name="oldEntity">旧数据</param>        /// <param name="dbContext">数据库上下文</param>        /// <param name="dbContextLocator">数据库上下文定位器</param>        /// <param name="state">实体状态</param>        public void OnChanged(Post entity, Post oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state)        {            // 刷新缓存            App.GetService<IMemoryCache>().Set("Key", "Value");        }    }}

9.25.4 IEntityChangedListener 定义

/// <summary>/// 实体数据改变监听依赖接口/// </summary>/// <typeparam name="TEntity"></typeparam>public interface IEntityChangedListener<TEntity>    where TEntity : class, IPrivateEntity, new(){    /// <summary>    /// 监听数据改变之前(仅支持EFCore操作)    /// </summary>    /// <param name="entity"></param>    /// <param name="dbContext"></param>    /// <param name="dbContextLocator"></param>    /// <param name="state"></param>    void OnChanging(TEntity entity, DbContext dbContext, Type dbContextLocator, EntityState state) { }    /// <summary>    /// 监听数据改变之后(仅支持EFCore操作)    /// </summary>    /// <param name="newEntity">新值</param>    /// <param name="oldEntity">旧值</param>    /// <param name="dbContext"></param>    /// <param name="dbContextLocator"></param>    /// <param name="state"></param>    void OnChanged(TEntity newEntity, TEntity oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state);    /// <summary>    /// 监听数据改变失败(仅支持EFCore操作)    /// </summary>    /// <param name="entity"></param>    /// <param name="dbContext"></param>    /// <param name="dbContextLocator"></param>    /// <param name="state"></param>    void OnChangeFailed(TEntity entity, DbContext dbContext, Type dbContextLocator, EntityState state) { }}

9.25.5 [SuppressChangedListener] 跳过监听

默认情况下,Furion 框架会对所有新增、更新、编辑的实体进行监听,有些时候我们无需监听特定实体,只需要在实体上贴 [SuppressChangedListener] 特性即可。

9.25.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-filter/index.html b/handbook/build/docs/dbcontext-filter/index.html index 58a0dc3be4..0a2168cde0 100644 --- a/handbook/build/docs/dbcontext-filter/index.html +++ b/handbook/build/docs/dbcontext-filter/index.html @@ -2,22 +2,21 @@ - - - + +9.23 实体/全局查询筛选器 | Furion -9.23 实体/全局查询筛选器 | Furion - - + + +
-

9.23 实体/全局查询筛选器

9.23.1 查询筛选器

通常,我们系统中有一些维护字段,如 IsDeleted 字段,这个字段用来标识用户已经删除的数据,那么我们需要每次查询数据的时候带上这个字段,避免查询出不该出现的数据。

Furion 提供非常灵活方便的全局查询筛选器,能够应用到每一次查询中。

9.23.2 多种筛选器配置

9.23.2.1 单表筛选器

单表筛选器就是只针对特定实体进行筛选操作,使用简单,只需要在继承 IEntityTypeBuilder<TEntity> 接口并实现即可,如:

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;namespace Furion.Core{    public class Person : Entity, IEntityTypeBuilder<Person>    {        public Person()        {            CreatedTime = DateTime.Now;            IsDeleted = false;        }        public string Name { get; set; }        public int Age { get; set; }        public string Address { get; set; }        public void Configure(EntityTypeBuilder<Person> entityBuilder, DbContext dbContext, Type dbContextLocator)        {            entityBuilder.HasQueryFilter(u => !u.IsDeleted);        }    }}

9.23.2.2 全局筛选器

全局筛选器可以配置所有实体应用筛选器中,无需一个一个去配置。使用方法稍微有些复杂,需要动态构建 Lambda 表达式。

实现全局筛选器依赖于 IModelBuilderFilter 接口,该接口提供两个方法:

  • OnCreating:实体构建之前
  • OnCreated:实体构建之后

通过实现这两个方法即可配置全局过滤器,如:

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Linq.Expressions;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString")]    public class FurionDbContext : AppDbContext<FurionDbContext>, IModelBuilderFilter    {        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }        public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)        {            // 设置软删除表达式            var fakeDeleteQueryFilterExpression = FakeDeleteQueryFilterExpression(entityBuilder, dbContext);            if (fakeDeleteQueryFilterExpression == null) return;            entityBuilder.HasQueryFilter(fakeDeleteQueryFilterExpression);        }    }}
小建议

如果对动态构建 LambdaExpression 不熟悉的朋友,可以使用 System.Linq.Dynamic.Corehttps://github.com/zzzprojects/System.Linq.Dynamic.Core

9.23.3 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.23 实体/全局查询筛选器

9.23.1 查询筛选器

通常,我们系统中有一些维护字段,如 IsDeleted 字段,这个字段用来标识用户已经删除的数据,那么我们需要每次查询数据的时候带上这个字段,避免查询出不该出现的数据。

Furion 提供非常灵活方便的全局查询筛选器,能够应用到每一次查询中。

9.23.2 多种筛选器配置

9.23.2.1 单表筛选器

单表筛选器就是只针对特定实体进行筛选操作,使用简单,只需要在继承 IEntityTypeBuilder<TEntity> 接口并实现即可,如:

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;namespace Furion.Core{    public class Person : Entity, IEntityTypeBuilder<Person>    {        public Person()        {            CreatedTime = DateTime.Now;            IsDeleted = false;        }        public string Name { get; set; }        public int Age { get; set; }        public string Address { get; set; }        public void Configure(EntityTypeBuilder<Person> entityBuilder, DbContext dbContext, Type dbContextLocator)        {            entityBuilder.HasQueryFilter(u => !u.IsDeleted);        }    }}

9.23.2.2 全局筛选器

全局筛选器可以配置所有实体应用筛选器中,无需一个一个去配置。使用方法稍微有些复杂,需要动态构建 Lambda 表达式。

实现全局筛选器依赖于 IModelBuilderFilter 接口,该接口提供两个方法:

  • OnCreating:实体构建之前
  • OnCreated:实体构建之后

通过实现这两个方法即可配置全局过滤器,如:

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Linq.Expressions;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString")]    public class FurionDbContext : AppDbContext<FurionDbContext>, IModelBuilderFilter    {        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }        public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)        {            // 设置软删除表达式            var fakeDeleteQueryFilterExpression = FakeDeleteQueryFilterExpression(entityBuilder, dbContext);            if (fakeDeleteQueryFilterExpression == null) return;            entityBuilder.HasQueryFilter(fakeDeleteQueryFilterExpression);        }    }}
小建议

如果对动态构建 LambdaExpression 不熟悉的朋友,可以使用 System.Linq.Dynamic.Corehttps://github.com/zzzprojects/System.Linq.Dynamic.Core

9.23.3 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-function/index.html b/handbook/build/docs/dbcontext-function/index.html index 388468f905..0036db5e42 100644 --- a/handbook/build/docs/dbcontext-function/index.html +++ b/handbook/build/docs/dbcontext-function/index.html @@ -2,22 +2,21 @@ - - - + +9.14 函数操作 | Furion -9.14 函数操作 | Furion - - + + +
-

9.14 函数操作

温馨提示

推荐使用 《9.17 Sql 高级代理》代替本章节功能。Sql 高级代理 能够提供更容易且更易维护的方式。

9.14.1 数据库函数

引用百度百科:

数据库函数是指当需要分析数据清单中的数值是否符合特定条件时,使用数据库工作表函数。

简单来说,数据库函数就是用于子计算的函数。其计算的结果可以用于构建 sql 语句。

9.14.1.1 支持标量函数的数据库

SqlServerSqliteCosmosInMemoryDatabaseMySqlPostgreSQLOracleFirebirdDm

9.14.1.2 支持表值函数的数据库

SqlServerSqliteCosmosInMemoryDatabaseMySqlPostgreSQLOracleFirebirdDm

9.14.2 数据库函数类型

在关系型数据库中,数据库函数有这两种类型:

  • 标量函数:只能返回单个值
  • 表值函数:只能返回一个结果集

9.14.3 函数的使用

9.14.3.1 标量函数返回 object

// ISqlRepository 方法var value = _sqlRepository.SqlFunctionScalar("func_GetValue");// ISqlDispatchProxy 方式var value = _sqlExecuteProxy.GetValue();  // 推荐方式// 实体仓储方式var value = _personRepository.SqlFunctionScalar("func_GetValue");// IRepository 非泛型方式var value = _repository.Sql().SqlFunctionScalar("func_GetValue");// 变态懒人方式,直接通过函数名执行var value = "func_GetValue".SqlFunctionScalar();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.14.3.2 标量函数返回 T

// ISqlRepository 方法var value = _sqlRepository.SqlFunctionScalar<string>("func_GetValue");// ISqlDispatchProxy 方式var value = _sqlExecuteProxy.GetValue();  // 推荐方式// 实体仓储方式var value = _personRepository.SqlFunctionScalar<string>("func_GetValue");// IRepository 非泛型方式var value = _repository.Sql().SqlFunctionScalar<string>("func_GetValue");// 变态懒人方式,直接通过函数名执行var value = "func_GetValue".SqlFunctionScalar<string>();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.14.3.3 表值函数返回 DataTable

// ISqlRepository 方法var value = _sqlRepository.SqlFunctionQuery("func_GetTable");// ISqlDispatchProxy 方式var value = _sqlExecuteProxy.GetTable();  // 推荐方式// 实体仓储方式var value = _personRepository.SqlFunctionQuery("func_GetTable");// IRepository 非泛型方式var value = _repository.Sql().SqlFunctionQuery("func_GetTable");// 变态懒人方式,直接通过函数名执行var value = "func_GetTable".SqlFunctionQuery();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.14.3.4 表值函数返回 List<T>

// ISqlRepository 方法var value = _sqlRepository.SqlFunctionQuery<Person>("func_GetTable");// ISqlDispatchProxy 方式var value = _sqlExecuteProxy.GetTable();  // 推荐方式// 实体仓储方式var value = _personRepository.SqlFunctionQuery<Person>("func_GetTable");// IRepository 非泛型方式var value = _repository.Sql().SqlFunctionQuery<Person>("func_GetTable");// 变态懒人方式,直接通过函数名执行var value = "func_GetTable".SqlFunctionQuery<Person>();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.14.4 在 Linq 中使用 标量函数

Furion 框架提供非常灵活的在 Linq 中使用标量函数的方法。如果像使用这样的方式,需要满足以下两个条件:

  • 标量函数必须定义在公开静态类中,且自己也是公开静态方法
  • 公开静态方法必须贴有 [QueryableFunction] 特性

示例如下:

9.14.4.1 创建标量函数

CREATE FUNCTION FN_GetId(    @id INT)RETURNS INTASBEGIN    RETURN @id + 1;END;

9.14.4.2 创建静态类和静态方法

创建静态类,如 QueryFunctions,将该 标量函数 放在静态类中:

using Furion.DatabaseAccessor;using System;namespace Furion.Application{    // 必须是公开静态的    public static class QueryFunctions    {        // 必须是静态方法        [QueryableFunction("FN_GetId", "dbo")]  // 配置标量函数        public static int GetId(int id) => throw new NotSupportedException();    }}

9.14.4.3 在 Linq 中使用

_personRepository.Where(u => u.Id > QueryFunctions.GetId(1)).ToList();
SELECT [p].[Id], [p].[Address], [p].[Age], [p].[CreatedTime], [p].[IsDeleted], [p].[Name], [p].[UpdatedTime]FROM [Person] AS [p]WHERE [p].[Id] > [dbo].[FN_GetId](1)    // 💥 注意这里

9.14.5 在 Linq 中使用 表值函数

EF Core 5.0 版本支持在 Linq 中操作 表值函数,操作有点类似 视图操作

示例如下:

9.14.5.1 创建表值函数

CREATE FUNCTION dbo.GetPersons(    @id INT)RETURNS TABLEASRETURN(    SELECT Id,           Name,           Age,           Address    FROM dbo.Person    WHERE Id > @id);

9.14.5.2 创建表值函数模型

namespace Furion.Core{    public class F_Person    {        /// <summary>        /// 主键Id        /// </summary>        public int Id { get; set; }        /// <summary>        /// 姓名        /// </summary>        public string Name { get; set; }        /// <summary>        /// 年龄        /// </summary>        public int Age { get; set; }        /// <summary>        /// 住址        /// </summary>        public string Address { get; set; }    }}

9.14.5.3 表值函数配置

DbContext 类中定义方法:

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using System.Linq;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString")]    public class FurionDbContext : AppDbContext<FurionDbContext>    {        public IQueryable<F_Person> GetPersons(int id) => FromExpression(() => GetPersons(id));        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }        protected override void OnModelCreating(ModelBuilder modelBuilder)        {            base.OnModelCreating(modelBuilder);            modelBuilder.Entity(typeof(F_Person)).HasNoKey();            modelBuilder.HasDbFunction(() => GetPersons(default));        }    }}

9.14.5.4 在 Linq 中使用

IQueryable<F_Person> query = _repository.DynamicDbContext.GetPersons(1);var result = query.Where(u => u.Name.Equals("Furion")).ToList();

最终生成 Sql

SELECT [g].Id, [g].Name, [g].Age, [g].AddressFROM dbo.GetPersons(1) AS [g]WHERE [g].Name == N'Furion';

9.14.6 在 EF Core 内置函数

EF Core 为我们提供了很多常用的内置函数,可以在 Lambda 条件中使用,主要是通过 EF.Functions 调用,如:

_repository.Where(u => EF.Functions.DateDiffHour(u.CreatedDt, DateTime.Now) > 8).FirstOrDefault();

这个语句使用了 EF.Functions.DateDiffHour 最终生成的 Sql 如下:

SELECT TOP(1) [a].*FROM [dbo].[TEST] AS [a]WHERE DATEDIFF(HOUR, [a].[CREATED_DT], GETDATE()) > 8

EF Core 内置函数就不一一列出了,可以通过 EF.Functions 查看更多,如果不能满足自己的需求,那么可以自定义 Linq 标量函数

9.14.7 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.14 函数操作

温馨提示

推荐使用 《9.17 Sql 高级代理》代替本章节功能。Sql 高级代理 能够提供更容易且更易维护的方式。

9.14.1 数据库函数

引用百度百科:

数据库函数是指当需要分析数据清单中的数值是否符合特定条件时,使用数据库工作表函数。

简单来说,数据库函数就是用于子计算的函数。其计算的结果可以用于构建 sql 语句。

9.14.1.1 支持标量函数的数据库

SqlServerSqliteCosmosInMemoryDatabaseMySqlPostgreSQLOracleFirebirdDm

9.14.1.2 支持表值函数的数据库

SqlServerSqliteCosmosInMemoryDatabaseMySqlPostgreSQLOracleFirebirdDm

9.14.2 数据库函数类型

在关系型数据库中,数据库函数有这两种类型:

  • 标量函数:只能返回单个值
  • 表值函数:只能返回一个结果集

9.14.3 函数的使用

9.14.3.1 标量函数返回 object

// ISqlRepository 方法var value = _sqlRepository.SqlFunctionScalar("func_GetValue");// ISqlDispatchProxy 方式var value = _sqlExecuteProxy.GetValue();  // 推荐方式// 实体仓储方式var value = _personRepository.SqlFunctionScalar("func_GetValue");// IRepository 非泛型方式var value = _repository.Sql().SqlFunctionScalar("func_GetValue");// 变态懒人方式,直接通过函数名执行var value = "func_GetValue".SqlFunctionScalar();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.14.3.2 标量函数返回 T

// ISqlRepository 方法var value = _sqlRepository.SqlFunctionScalar<string>("func_GetValue");// ISqlDispatchProxy 方式var value = _sqlExecuteProxy.GetValue();  // 推荐方式// 实体仓储方式var value = _personRepository.SqlFunctionScalar<string>("func_GetValue");// IRepository 非泛型方式var value = _repository.Sql().SqlFunctionScalar<string>("func_GetValue");// 变态懒人方式,直接通过函数名执行var value = "func_GetValue".SqlFunctionScalar<string>();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.14.3.3 表值函数返回 DataTable

// ISqlRepository 方法var value = _sqlRepository.SqlFunctionQuery("func_GetTable");// ISqlDispatchProxy 方式var value = _sqlExecuteProxy.GetTable();  // 推荐方式// 实体仓储方式var value = _personRepository.SqlFunctionQuery("func_GetTable");// IRepository 非泛型方式var value = _repository.Sql().SqlFunctionQuery("func_GetTable");// 变态懒人方式,直接通过函数名执行var value = "func_GetTable".SqlFunctionQuery();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.14.3.4 表值函数返回 List<T>

// ISqlRepository 方法var value = _sqlRepository.SqlFunctionQuery<Person>("func_GetTable");// ISqlDispatchProxy 方式var value = _sqlExecuteProxy.GetTable();  // 推荐方式// 实体仓储方式var value = _personRepository.SqlFunctionQuery<Person>("func_GetTable");// IRepository 非泛型方式var value = _repository.Sql().SqlFunctionQuery<Person>("func_GetTable");// 变态懒人方式,直接通过函数名执行var value = "func_GetTable".SqlFunctionQuery<Person>();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.14.4 在 Linq 中使用 标量函数

Furion 框架提供非常灵活的在 Linq 中使用标量函数的方法。如果像使用这样的方式,需要满足以下两个条件:

  • 标量函数必须定义在公开静态类中,且自己也是公开静态方法
  • 公开静态方法必须贴有 [QueryableFunction] 特性

示例如下:

9.14.4.1 创建标量函数

CREATE FUNCTION FN_GetId(    @id INT)RETURNS INTASBEGIN    RETURN @id + 1;END;

9.14.4.2 创建静态类和静态方法

创建静态类,如 QueryFunctions,将该 标量函数 放在静态类中:

using Furion.DatabaseAccessor;using System;namespace Furion.Application{    // 必须是公开静态的    public static class QueryFunctions    {        // 必须是静态方法        [QueryableFunction("FN_GetId", "dbo")]  // 配置标量函数        public static int GetId(int id) => throw new NotSupportedException();    }}

9.14.4.3 在 Linq 中使用

_personRepository.Where(u => u.Id > QueryFunctions.GetId(1)).ToList();
SELECT [p].[Id], [p].[Address], [p].[Age], [p].[CreatedTime], [p].[IsDeleted], [p].[Name], [p].[UpdatedTime]FROM [Person] AS [p]WHERE [p].[Id] > [dbo].[FN_GetId](1)    // 💥 注意这里

9.14.5 在 Linq 中使用 表值函数

EF Core 5.0 版本支持在 Linq 中操作 表值函数,操作有点类似 视图操作

示例如下:

9.14.5.1 创建表值函数

CREATE FUNCTION dbo.GetPersons(    @id INT)RETURNS TABLEASRETURN(    SELECT Id,           Name,           Age,           Address    FROM dbo.Person    WHERE Id > @id);

9.14.5.2 创建表值函数模型

namespace Furion.Core{    public class F_Person    {        /// <summary>        /// 主键Id        /// </summary>        public int Id { get; set; }        /// <summary>        /// 姓名        /// </summary>        public string Name { get; set; }        /// <summary>        /// 年龄        /// </summary>        public int Age { get; set; }        /// <summary>        /// 住址        /// </summary>        public string Address { get; set; }    }}

9.14.5.3 表值函数配置

DbContext 类中定义方法:

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using System.Linq;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString")]    public class FurionDbContext : AppDbContext<FurionDbContext>    {        public IQueryable<F_Person> GetPersons(int id) => FromExpression(() => GetPersons(id));        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }        protected override void OnModelCreating(ModelBuilder modelBuilder)        {            base.OnModelCreating(modelBuilder);            modelBuilder.Entity(typeof(F_Person)).HasNoKey();            modelBuilder.HasDbFunction(() => GetPersons(default));        }    }}

9.14.5.4 在 Linq 中使用

IQueryable<F_Person> query = _repository.DynamicDbContext.GetPersons(1);var result = query.Where(u => u.Name.Equals("Furion")).ToList();

最终生成 Sql

SELECT [g].Id, [g].Name, [g].Age, [g].AddressFROM dbo.GetPersons(1) AS [g]WHERE [g].Name == N'Furion';

9.14.6 在 EF Core 内置函数

EF Core 为我们提供了很多常用的内置函数,可以在 Lambda 条件中使用,主要是通过 EF.Functions 调用,如:

_repository.Where(u => EF.Functions.DateDiffHour(u.CreatedDt, DateTime.Now) > 8).FirstOrDefault();

这个语句使用了 EF.Functions.DateDiffHour 最终生成的 Sql 如下:

SELECT TOP(1) [a].*FROM [dbo].[TEST] AS [a]WHERE DATEDIFF(HOUR, [a].[CREATED_DT], GETDATE()) > 8

EF Core 内置函数就不一一列出了,可以通过 EF.Functions 查看更多,如果不能满足自己的需求,那么可以自定义 Linq 标量函数

9.14.7 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-hight-query/index.html b/handbook/build/docs/dbcontext-hight-query/index.html index 9aaead1651..fb5d23b58c 100644 --- a/handbook/build/docs/dbcontext-hight-query/index.html +++ b/handbook/build/docs/dbcontext-hight-query/index.html @@ -2,22 +2,21 @@ - - - + +9.11 高级查询操作 | Furion -9.11 高级查询操作 | Furion - - + + +
-

9.11 高级查询操作

9.11.1 关联数据模型

using Furion.DatabaseAccessor;using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;namespace Furion.Core{    public class Person : Entity    {        /// <summary>        /// 构造函数        /// </summary>        public Person()        {            CreatedTime = DateTime.Now;        }        /// <summary>        /// 姓名        /// </summary>        [MaxLength(32)]        public string Name { get; set; }        /// <summary>        /// 年龄        /// </summary>        public int Age { get; set; }        /// <summary>        /// 住址        /// </summary>        public string Address { get; set; }        /// <summary>        /// 从表        /// </summary>        public PersonDetail PersonDetail { get; set; }        /// <summary>        /// 一对多        /// </summary>        public ICollection<Children> Childrens { get; set; }        /// <summary>        /// 多对多        /// </summary>        public ICollection<Post> Posts { get; set; }    }}

9.11.2 一对一查询

// 示例一var person = repository.Include(u => u.Detail);// 示例二var person = repository.Include(u => u.Detail)                       .Include(u => u.Post);// 示例三var person = repository.Include(u => u.Detail)                            .ThenInclude(d => d.Review)                       .Include(u => u.Post);// 示例四var person = repository.Include(u => u.Detail.Where(d => d.Id > 10).OrderBy(d => d.Name))                            .ThenInclude(d => d.Review)                       .Include(u => u.Post);// 示例五var person = repository.Include(!string.IsNullOrEmpty(keyword), u => u.Detail);// 示例六var person = repository.Include(!string.IsNullOrEmpty(keyword), u => u.Detail)                       .Include(age > 18, u => u.Detail.Where(d => d.Id > 10).OrderBy(d => d.Name))                            .ThenInclude(d => d.Review)                       .Include(u => u.Post);

9.11.3 一对多查询

// 示例一var person = repository.Include(u => u.Childrens);// 参考 一对一 例子
特别说明

一对一一对多 查询方法一样,唯一的区别是:一对多 采用 ICollection<TEntity> 定义属性。

9.11.4 多对多查询

// 示例一var person = repository.Include(u => u.Posts);// 参考 一对一 例子
特别说明

一对一多对多 查询方法一样,唯一的区别是:多对多 采用 ICollection<TEntity> 定义属性。

9.11.5 联表查询

9.11.5.1 内连接 Inner Join

var query = from p in _personRepository.AsQueryable()            join d in _personDetailRepository.AsQueryable() on p.Id equals d.PersonId            select new PersonDto            {                PhoneNumber = p.PersonDetail.PhoneNumber,                Address = p.Address,                Age = p.Age,                Name = p.Name,                Id = p.Id,                QQ = p.PersonDetail.QQ            };

9.11.5.2 左连接 Left Join

var query = from p in _personRepository.AsQueryable()            join d in _personDetailRepository.AsQueryable() on p.Id equals d.PersonId into results            from d in results.DefaultIfEmpty()            select new PersonDto            {                PhoneNumber = p.PersonDetail.PhoneNumber,                Address = p.Address,                Age = p.Age,                Name = p.Name,                Id = p.Id,                QQ = p.PersonDetail.QQ            };
小提示

Left JoinInner Join 不同的是,Left Join 会先将结果 into 到新的结果集然后再查询,并调用 DefaultIfEmpty() 方法。

9.11.5.3 右连接 Right Join

Right Join 只需要将 Left Join 主从表位置更换即可。

9.11.6 分组查询

// 示例一var query = repository.AsQueryable().GroupBy(x => new { x.Column1, x.Column2 });// 示例二var query = from student in repository.AsQueryable()            group student by repository2.AsQueryable() into dateGroup            select new ResultData()            {                Key = dateGroup.Key,                Value = dateGroup.Count()            };// 示例三var query = from a in repository.AsQueryable()            join b in repository2.AsQueryable() on a.Id equals b.Aid            join c in repository3.AsQueryable() on c.id equals b.Bid            group a by new { a.Age, b.Sex } into g            select new {                Peo = g.Key,                Count = g.Count()            };

9.11.7 合并结果集

var query = repository.AsQueryable(u => u.Id > 10)                      .Union(                          repository2.AsQueryable(u => u.Id <= 10)                      );

9.11.8 查询排序

9.11.8.1 正序

// 示例一var query = repository.AsQueryable()                      .OrderBy(u => u.Id);// 示例二var query =repository.AsQueryable()                     .OrderBy(u => u.Id)                     .ThenBy(u => u.Name);

9.11.8.2 倒序

// 示例一var query = repository.AsQueryable()                      .OrderByDescending(u => u.Id);// 示例二var query =repository.AsQueryable()                     .OrderByDescending(u => u.Id)                     .ThenByDescending(u => u.Name);

9.11.8.3 混合倒序

// 示例一var query = repository.AsQueryable()                      .OrderBy(u => u.Id)                      .OrderByDescending(u => u.Name)                      .ThenBy(u => u.Age);

9.11.9 递归查询

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Collections.Generic;namespace Furion.Core{    /// <summary>    /// 城市    /// </summary>    public class City : Entity, IEntityTypeBuilder<City>, IEntitySeedData<City>    {        /// <summary>        /// 构造函数        /// </summary>        public City()        {            CreatedTime = DateTime.Now;                   }        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }        /// <summary>        /// 上级Id        /// </summary>        public int? ParentId { get; set; }        /// <summary>        /// 上级        /// </summary>        public virtual City Parent { get; set; }        /// <summary>        /// 子集        /// </summary>        public virtual ICollection<City> Childrens { get; set; }        /// <summary>        /// 配置实体关系        /// </summary>        /// <param name="entityBuilder"></param>        /// <param name="dbContext"></param>        /// <param name="dbContextLocator"></param>        public void Configure(EntityTypeBuilder<City> entityBuilder, DbContext dbContext, Type dbContextLocator)        {            entityBuilder                .HasMany(x => x.Childrens)                .WithOne(x => x.Parent)                .HasForeignKey(x => x.ParentId)                .OnDelete(DeleteBehavior.ClientSetNull); // 必须设置这一行        }        /// <summary>        /// 种子数据        /// </summary>        /// <param name="dbContext"></param>        /// <param name="dbContextLocator"></param>        /// <returns></returns>        public IEnumerable<City> HasData(DbContext dbContext, Type dbContextLocator)        {            return new List<City>            {                new City { Id=1,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="中国" },                new City { Id=2,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="广东省",ParentId=1 },                new City { Id=3,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="中山市",ParentId=2 },                new City { Id=4,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="珠海市",ParentId=2 },                new City { Id=5,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="浙江省",ParentId=1 },            };        }    }}
var cities = await repository.AsQueryable()                             .Include(u => u.Childrens)                             .Where(u => u.Id == 1)                             .ToListAsync();var dtos = cities.Adapt<List<CityDto>>();

9.11.10 动态 Sql 查询

Furion 默认不支持 动态 Sql 查询功能,不过可以通过第三方实现:

Furion 项目层安装 System.Linq.Dynamic.Corehttps://github.com/zzzprojects/System.Linq.Dynamic.Core

9.11.10.1 动态 Sql

// 示例一var query = repository.AsQueryable()                      .Where("City == @0 and Orders.Count >= @1", "China", 10)                      .OrderBy("CompanyName")                      .Select("new(CompanyName as Name, Phone)");// 示例二var list = repository.AsQueryable()                     .Where("Name.Contains(@0)","Furion")                     .ToList();// 示例三,支持 ? 语法var customers = repository.AsQueryable()                          .Include(c => c.Location)                          .Where(c => c.Location?.Name == "test") // 注意 Location?.Name                          .ToList();

9.11.10.2 动态 Lambda

// 示例一var x = Expression.Parameter(typeof(int), "x");var y = Expression.Parameter(typeof(int), "y");var e = DynamicExpressionParser            .ParseLambda(new ParameterExpression[] { x, y }, null, "(x + y) * 2");// 示例二var e = DynamicExpressionParser.ParseLambda(        typeof(Customer), typeof(bool),        "City = @0 and Orders.Count >= @1",        "London", 10);

9.11.11 时态查询

功能移除声明

以下内容在 Furion 2.13 + 版本中已移除。

Furion 框架还提供了时态查询功能,可以查询特定时间的数据,如:

var result = rep.Entities    .AsTemporalOf(DateTime.UtcNow.AddDays(-1))    .Include(i=> i.Company)    .FirstOrDefault(i => i.Name == "Furion");

另外提供了多个时态查询方法

  • AsTemporalAll()
  • AsTemporalAsOf(date)
  • AsTemporalFrom(startDate, endDate)
  • AsTemporalBetween(startDate, endDate)
  • AsTemporalContained(startDate, endDate)

9.11.12 性能优化

默认情况下,EF Core 会跟踪所有实体,也就是任何数据改变都会引起数据检查,所以如果只做查询操作,建议关闭实体跟踪功能。

Furion 框架提供了以下高性能实体集合:

  • DetachedEntities:脱轨/不追踪实体
  • AsQueryable(false):不追踪实体
  • Entities.AsNoTracking():手动关闭实体追踪

EF Core 中,复杂查询总是会生成一个 sql,也就是 AsSingleQuery(),我们也可以设置为 AsSplitQuery() 切割成多个查询。

9.11.13 分表查询小例子

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Collections.Generic;namespace Furion.Core{    public class Person : Entity, IEntityTypeBuilder<Person>    {        public string Name { get; set; }        /// <summary>        /// 配置实体关系        /// </summary>        /// <param name="entityBuilder"></param>        /// <param name="dbContext"></param>        /// <param name="dbContextLocator"></param>        public void Configure(EntityTypeBuilder<Person> entityBuilder, DbContext dbContext, Type dbContextLocator)        {            entityBuilder.ToSqlQuery(              @"select * from dbo.person.2020-09-19                union all                select * from dbo.person.2020-09-20");        }    }}
var posts = repository.Where(u => u.Id > 10).ToList();

9.11.14 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.11 高级查询操作

9.11.1 关联数据模型

using Furion.DatabaseAccessor;using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;namespace Furion.Core{    public class Person : Entity    {        /// <summary>        /// 构造函数        /// </summary>        public Person()        {            CreatedTime = DateTime.Now;        }        /// <summary>        /// 姓名        /// </summary>        [MaxLength(32)]        public string Name { get; set; }        /// <summary>        /// 年龄        /// </summary>        public int Age { get; set; }        /// <summary>        /// 住址        /// </summary>        public string Address { get; set; }        /// <summary>        /// 从表        /// </summary>        public PersonDetail PersonDetail { get; set; }        /// <summary>        /// 一对多        /// </summary>        public ICollection<Children> Childrens { get; set; }        /// <summary>        /// 多对多        /// </summary>        public ICollection<Post> Posts { get; set; }    }}

9.11.2 一对一查询

// 示例一var person = repository.Include(u => u.Detail);// 示例二var person = repository.Include(u => u.Detail)                       .Include(u => u.Post);// 示例三var person = repository.Include(u => u.Detail)                            .ThenInclude(d => d.Review)                       .Include(u => u.Post);// 示例四var person = repository.Include(u => u.Detail.Where(d => d.Id > 10).OrderBy(d => d.Name))                            .ThenInclude(d => d.Review)                       .Include(u => u.Post);// 示例五var person = repository.Include(!string.IsNullOrEmpty(keyword), u => u.Detail);// 示例六var person = repository.Include(!string.IsNullOrEmpty(keyword), u => u.Detail)                       .Include(age > 18, u => u.Detail.Where(d => d.Id > 10).OrderBy(d => d.Name))                            .ThenInclude(d => d.Review)                       .Include(u => u.Post);

9.11.3 一对多查询

// 示例一var person = repository.Include(u => u.Childrens);// 参考 一对一 例子
特别说明

一对一一对多 查询方法一样,唯一的区别是:一对多 采用 ICollection<TEntity> 定义属性。

9.11.4 多对多查询

// 示例一var person = repository.Include(u => u.Posts);// 参考 一对一 例子
特别说明

一对一多对多 查询方法一样,唯一的区别是:多对多 采用 ICollection<TEntity> 定义属性。

9.11.5 联表查询

9.11.5.1 内连接 Inner Join

var query = from p in _personRepository.AsQueryable()            join d in _personDetailRepository.AsQueryable() on p.Id equals d.PersonId            select new PersonDto            {                PhoneNumber = p.PersonDetail.PhoneNumber,                Address = p.Address,                Age = p.Age,                Name = p.Name,                Id = p.Id,                QQ = p.PersonDetail.QQ            };

9.11.5.2 左连接 Left Join

var query = from p in _personRepository.AsQueryable()            join d in _personDetailRepository.AsQueryable() on p.Id equals d.PersonId into results            from d in results.DefaultIfEmpty()            select new PersonDto            {                PhoneNumber = p.PersonDetail.PhoneNumber,                Address = p.Address,                Age = p.Age,                Name = p.Name,                Id = p.Id,                QQ = p.PersonDetail.QQ            };
小提示

Left JoinInner Join 不同的是,Left Join 会先将结果 into 到新的结果集然后再查询,并调用 DefaultIfEmpty() 方法。

9.11.5.3 右连接 Right Join

Right Join 只需要将 Left Join 主从表位置更换即可。

9.11.6 分组查询

// 示例一var query = repository.AsQueryable().GroupBy(x => new { x.Column1, x.Column2 });// 示例二var query = from student in repository.AsQueryable()            group student by repository2.AsQueryable() into dateGroup            select new ResultData()            {                Key = dateGroup.Key,                Value = dateGroup.Count()            };// 示例三var query = from a in repository.AsQueryable()            join b in repository2.AsQueryable() on a.Id equals b.Aid            join c in repository3.AsQueryable() on c.id equals b.Bid            group a by new { a.Age, b.Sex } into g            select new {                Peo = g.Key,                Count = g.Count()            };

9.11.7 合并结果集

var query = repository.AsQueryable(u => u.Id > 10)                      .Union(                          repository2.AsQueryable(u => u.Id <= 10)                      );

9.11.8 查询排序

9.11.8.1 正序

// 示例一var query = repository.AsQueryable()                      .OrderBy(u => u.Id);// 示例二var query =repository.AsQueryable()                     .OrderBy(u => u.Id)                     .ThenBy(u => u.Name);

9.11.8.2 倒序

// 示例一var query = repository.AsQueryable()                      .OrderByDescending(u => u.Id);// 示例二var query =repository.AsQueryable()                     .OrderByDescending(u => u.Id)                     .ThenByDescending(u => u.Name);

9.11.8.3 混合倒序

// 示例一var query = repository.AsQueryable()                      .OrderBy(u => u.Id)                      .OrderByDescending(u => u.Name)                      .ThenBy(u => u.Age);

9.11.9 递归查询

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Collections.Generic;namespace Furion.Core{    /// <summary>    /// 城市    /// </summary>    public class City : Entity, IEntityTypeBuilder<City>, IEntitySeedData<City>    {        /// <summary>        /// 构造函数        /// </summary>        public City()        {            CreatedTime = DateTime.Now;                   }        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }        /// <summary>        /// 上级Id        /// </summary>        public int? ParentId { get; set; }        /// <summary>        /// 上级        /// </summary>        public virtual City Parent { get; set; }        /// <summary>        /// 子集        /// </summary>        public virtual ICollection<City> Childrens { get; set; }        /// <summary>        /// 配置实体关系        /// </summary>        /// <param name="entityBuilder"></param>        /// <param name="dbContext"></param>        /// <param name="dbContextLocator"></param>        public void Configure(EntityTypeBuilder<City> entityBuilder, DbContext dbContext, Type dbContextLocator)        {            entityBuilder                .HasMany(x => x.Childrens)                .WithOne(x => x.Parent)                .HasForeignKey(x => x.ParentId)                .OnDelete(DeleteBehavior.ClientSetNull); // 必须设置这一行        }        /// <summary>        /// 种子数据        /// </summary>        /// <param name="dbContext"></param>        /// <param name="dbContextLocator"></param>        /// <returns></returns>        public IEnumerable<City> HasData(DbContext dbContext, Type dbContextLocator)        {            return new List<City>            {                new City { Id=1,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="中国" },                new City { Id=2,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="广东省",ParentId=1 },                new City { Id=3,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="中山市",ParentId=2 },                new City { Id=4,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="珠海市",ParentId=2 },                new City { Id=5,CreatedTime =DateTime.Parse("2020-08-20 15:30:20"),IsDeleted=false,Name="浙江省",ParentId=1 },            };        }    }}
var cities = await repository.AsQueryable()                             .Include(u => u.Childrens)                             .Where(u => u.Id == 1)                             .ToListAsync();var dtos = cities.Adapt<List<CityDto>>();

9.11.10 动态 Sql 查询

Furion 默认不支持 动态 Sql 查询功能,不过可以通过第三方实现:

Furion 项目层安装 System.Linq.Dynamic.Corehttps://github.com/zzzprojects/System.Linq.Dynamic.Core

9.11.10.1 动态 Sql

// 示例一var query = repository.AsQueryable()                      .Where("City == @0 and Orders.Count >= @1", "China", 10)                      .OrderBy("CompanyName")                      .Select("new(CompanyName as Name, Phone)");// 示例二var list = repository.AsQueryable()                     .Where("Name.Contains(@0)","Furion")                     .ToList();// 示例三,支持 ? 语法var customers = repository.AsQueryable()                          .Include(c => c.Location)                          .Where(c => c.Location?.Name == "test") // 注意 Location?.Name                          .ToList();

9.11.10.2 动态 Lambda

// 示例一var x = Expression.Parameter(typeof(int), "x");var y = Expression.Parameter(typeof(int), "y");var e = DynamicExpressionParser            .ParseLambda(new ParameterExpression[] { x, y }, null, "(x + y) * 2");// 示例二var e = DynamicExpressionParser.ParseLambda(        typeof(Customer), typeof(bool),        "City = @0 and Orders.Count >= @1",        "London", 10);

9.11.11 时态查询

功能移除声明

以下内容在 Furion 2.13 + 版本中已移除。

Furion 框架还提供了时态查询功能,可以查询特定时间的数据,如:

var result = rep.Entities    .AsTemporalOf(DateTime.UtcNow.AddDays(-1))    .Include(i=> i.Company)    .FirstOrDefault(i => i.Name == "Furion");

另外提供了多个时态查询方法

  • AsTemporalAll()
  • AsTemporalAsOf(date)
  • AsTemporalFrom(startDate, endDate)
  • AsTemporalBetween(startDate, endDate)
  • AsTemporalContained(startDate, endDate)

9.11.12 性能优化

默认情况下,EF Core 会跟踪所有实体,也就是任何数据改变都会引起数据检查,所以如果只做查询操作,建议关闭实体跟踪功能。

Furion 框架提供了以下高性能实体集合:

  • DetachedEntities:脱轨/不追踪实体
  • AsQueryable(false):不追踪实体
  • Entities.AsNoTracking():手动关闭实体追踪

EF Core 中,复杂查询总是会生成一个 sql,也就是 AsSingleQuery(),我们也可以设置为 AsSplitQuery() 切割成多个查询。

9.11.13 分表查询小例子

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Collections.Generic;namespace Furion.Core{    public class Person : Entity, IEntityTypeBuilder<Person>    {        public string Name { get; set; }        /// <summary>        /// 配置实体关系        /// </summary>        /// <param name="entityBuilder"></param>        /// <param name="dbContext"></param>        /// <param name="dbContextLocator"></param>        public void Configure(EntityTypeBuilder<Person> entityBuilder, DbContext dbContext, Type dbContextLocator)        {            entityBuilder.ToSqlQuery(              @"select * from dbo.person.2020-09-19                union all                select * from dbo.person.2020-09-20");        }    }}
var posts = repository.Where(u => u.Id > 10).ToList();

9.11.14 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-locator/index.html b/handbook/build/docs/dbcontext-locator/index.html index 542c049337..c4aed63d5c 100644 --- a/handbook/build/docs/dbcontext-locator/index.html +++ b/handbook/build/docs/dbcontext-locator/index.html @@ -2,22 +2,21 @@ - - - + +9.2 数据库上下文定位器 | Furion -9.2 数据库上下文定位器 | Furion - - + + +
-

9.2 数据库上下文定位器

小提醒

只要数据库上下文注册绑定了数据库上下文定位器,那么所有的仓储、实体、种子、配置、视图、函数等数据库相关的类、接口、方法都需要指定数据库上下文定位器,默认数据库上下文定位器除外。

如果改变了和数据库实体相关的所有配置接口的定位器,还需执行 Add-MigrationUpdate-Database 命令。

9.2.1 数据库上下文定位器

在了解数据库上下文定位器之前,我们先了解什么是 定位器定位器 就是给物体安装特殊配置,使其能够被实时追踪和定位。

那为什么需要 定位器

由于 EF Core 本身支持多个数据库上下文操作,但是通过 依赖注入 的方式默认只初始化一个数据库上下文,也就是如果我们想要操作多个数据库上下文,那么 构造函数 注入方式就会变得复杂。

所以,Furion 实现了一套 定位器 功能,通过这个 定位器 ,我们就能够通过 依赖注入 等多个方式定位到数据库上下文并初始化。

9.2.2 数据库上下文定位器作用

  • 能够实现构造函数初始化多个数据库上下文
  • 能够避免业务层直接引用 DbContext
  • 能够实现动态切换数据库、读写分离、主从库等复杂操作

9.2.3 如何定义数据库上下文定位器

定义数据库上下文定位器只需遵循三个原则即可:

  • 必须是公开 class 类型同时具备无参构造函数
  • 该类型必须继承 IDbContextLocator 接口
  • 数据库上下文定位器和数据库上下文必须是一对一关系,也就是不能同时被多个数据库上下文使用

数据库上下文定位器定义代码如下:

using Furion.DatabaseAccessor;namespace Furion.Core{    public sealed class FurionDbContextLocator : IDbContextLocator    {    }}

9.2.4 默认数据库上下文定位器

Furion 框架中已经提供了 MasterDbContextLocator 默认数据库上下文定位器,所以默认数据库上下文只需继承 AppDbContext<TDbContext> 即可。

如:只有一个数据库上下文定义:

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class DefaultDbContext : AppDbContext<DefaultDbContext>  // 无需指定定位器    {        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)        {        }    }}
关于多数据库定位器

默认数据库的定位器默认为 MasterDbContextLocator,所以无需显示指定定位器,但从第二个数据库开始,都必须指定数据库定位器。如:

  • 注册上下文:
options.AddDbPool<OtherDbContext, OtherDbContextLocator>();
  • 定义上下文
using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class OtherDbContext : AppDbContext<OtherDbContext, OtherDbContextLocator>   // 需指定定位器    {        public OtherDbContext(DbContextOptions<OtherDbContext> options) : base(options)        {        }    }}

另外,Entity/IEntityIRepository 等都需要指定定位器,如:IEntity<TKey, TLocator>IRepository<TEntity, TLocator> 操作。

9.2.5 数据库上下文定位器支持对象

目前数据库上下文支持以下多个对象:

  • AppDbContext<TEntity, TDbContextLocator>:数据上下文
  • IRepository<TEntity, TDbContextLocator>:实体仓储
  • ISqlRepository<TDbContextLocator>: Sql 操作仓储
  • IDbRepository<TDbContextLocator>: 特定数据库操作仓储
  • IMSRepository<TMasterDbContextLocator, TSlaveDbContextLocator1, ... TSlaveDbContextLocator7>: 读写分离仓储
  • Func<Type, DbContext>:依赖注入获取数据库上下文
  • Entity<Tkey, TDbContextLocator> :实体配置
  • EntityBase<Tkey, TDbContextLocator1, ... TDbContextLocator8>:实体配置
  • EntityNotKey<TDbContextLocator1, ... TDbContextLocator8>:无键实体配置
  • IEntity<TDbContextLocator1, ... TDbContextLocator8>:默认实体配置
  • IEntitySeedData<TEntity, TDbContextLocator1, ... TDbContextLocator8>:种子数据配置
  • IEntityTypeBuilder<TEntity, TDbContextLocator1, ... TDbContextLocator8>:实体类型构建器
  • IModelBuilderFilter<TDbContextLocator1, ... TDbContextLocator8>:模型构建筛选器
  • [QueryableFunction(DbContextLocators=Type[])]:查询函数

9.2.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.2 数据库上下文定位器

小提醒

只要数据库上下文注册绑定了数据库上下文定位器,那么所有的仓储、实体、种子、配置、视图、函数等数据库相关的类、接口、方法都需要指定数据库上下文定位器,默认数据库上下文定位器除外。

如果改变了和数据库实体相关的所有配置接口的定位器,还需执行 Add-MigrationUpdate-Database 命令。

9.2.1 数据库上下文定位器

在了解数据库上下文定位器之前,我们先了解什么是 定位器定位器 就是给物体安装特殊配置,使其能够被实时追踪和定位。

那为什么需要 定位器

由于 EF Core 本身支持多个数据库上下文操作,但是通过 依赖注入 的方式默认只初始化一个数据库上下文,也就是如果我们想要操作多个数据库上下文,那么 构造函数 注入方式就会变得复杂。

所以,Furion 实现了一套 定位器 功能,通过这个 定位器 ,我们就能够通过 依赖注入 等多个方式定位到数据库上下文并初始化。

9.2.2 数据库上下文定位器作用

  • 能够实现构造函数初始化多个数据库上下文
  • 能够避免业务层直接引用 DbContext
  • 能够实现动态切换数据库、读写分离、主从库等复杂操作

9.2.3 如何定义数据库上下文定位器

定义数据库上下文定位器只需遵循三个原则即可:

  • 必须是公开 class 类型同时具备无参构造函数
  • 该类型必须继承 IDbContextLocator 接口
  • 数据库上下文定位器和数据库上下文必须是一对一关系,也就是不能同时被多个数据库上下文使用

数据库上下文定位器定义代码如下:

using Furion.DatabaseAccessor;namespace Furion.Core{    public sealed class FurionDbContextLocator : IDbContextLocator    {    }}

9.2.4 默认数据库上下文定位器

Furion 框架中已经提供了 MasterDbContextLocator 默认数据库上下文定位器,所以默认数据库上下文只需继承 AppDbContext<TDbContext> 即可。

如:只有一个数据库上下文定义:

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class DefaultDbContext : AppDbContext<DefaultDbContext>  // 无需指定定位器    {        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)        {        }    }}
关于多数据库定位器

默认数据库的定位器默认为 MasterDbContextLocator,所以无需显示指定定位器,但从第二个数据库开始,都必须指定数据库定位器。如:

  • 注册上下文:
options.AddDbPool<OtherDbContext, OtherDbContextLocator>();
  • 定义上下文
using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class OtherDbContext : AppDbContext<OtherDbContext, OtherDbContextLocator>   // 需指定定位器    {        public OtherDbContext(DbContextOptions<OtherDbContext> options) : base(options)        {        }    }}

另外,Entity/IEntityIRepository 等都需要指定定位器,如:IEntity<TKey, TLocator>IRepository<TEntity, TLocator> 操作。

9.2.5 数据库上下文定位器支持对象

目前数据库上下文支持以下多个对象:

  • AppDbContext<TEntity, TDbContextLocator>:数据上下文
  • IRepository<TEntity, TDbContextLocator>:实体仓储
  • ISqlRepository<TDbContextLocator>: Sql 操作仓储
  • IDbRepository<TDbContextLocator>: 特定数据库操作仓储
  • IMSRepository<TMasterDbContextLocator, TSlaveDbContextLocator1, ... TSlaveDbContextLocator7>: 读写分离仓储
  • Func<Type, DbContext>:依赖注入获取数据库上下文
  • Entity<Tkey, TDbContextLocator> :实体配置
  • EntityBase<Tkey, TDbContextLocator1, ... TDbContextLocator8>:实体配置
  • EntityNotKey<TDbContextLocator1, ... TDbContextLocator8>:无键实体配置
  • IEntity<TDbContextLocator1, ... TDbContextLocator8>:默认实体配置
  • IEntitySeedData<TEntity, TDbContextLocator1, ... TDbContextLocator8>:种子数据配置
  • IEntityTypeBuilder<TEntity, TDbContextLocator1, ... TDbContextLocator8>:实体类型构建器
  • IModelBuilderFilter<TDbContextLocator1, ... TDbContextLocator8>:模型构建筛选器
  • [QueryableFunction(DbContextLocators=Type[])]:查询函数

9.2.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-multi-database/index.html b/handbook/build/docs/dbcontext-multi-database/index.html index 98fa909a90..87d9307258 100644 --- a/handbook/build/docs/dbcontext-multi-database/index.html +++ b/handbook/build/docs/dbcontext-multi-database/index.html @@ -2,22 +2,21 @@ - - - + +9.18 多种数据库操作 | Furion -9.18 多种数据库操作 | Furion - - + + +
-

9.18 多种数据库操作

连接字符串配置注意事项

如果连接字符串是配置在自定义的 .json 文件中,那么必须在 Visual Studio 中配置 .json 右键属性,设置 复制 输出目录为 如果较新则复制,生成操作为 内容

否则就会提示找不到配置或连接字符串的错误。

9.18.1 Furion 支持数据库提供器

SqlServerSqliteCosmosInMemoryDatabaseMySqlPostgreSQLOracleFirebirdDm

9.18.1.1 数据库提供器对应包

  • SqlServerMicrosoft.EntityFrameworkCore.SqlServer (支持 SqlServer 2005 +)
  • SqliteMicrosoft.EntityFrameworkCore.Sqlite
  • CosmosMicrosoft.EntityFrameworkCore.Cosmos
  • InMemoryDatabaseMicrosoft.EntityFrameworkCore.InMemory
  • MySql
    • Pomelo.EntityFrameworkCore.MySql:(支持 MySql 5.x +)
    • MySql.EntityFrameworkCore:支持 (MySql 8.x +)
  • PostgreSQLNpgsql.EntityFrameworkCore.PostgreSQL
  • OracleOracle.EntityFrameworkCore (支持 Oracle 10 +)
  • FirebirdFirebirdSql.EntityFrameworkCore.Firebird
  • DmMicrosoft.EntityFrameworkCore.Dm
小知识

这些数据库包应该安装在 Furion.EntityFramework.Core 层。特殊情况需安装在 Furion.Core 层中,如 Mysql HasCharset() 配置。

9.18.2 多数据库服务注册

// 注册 SqlServeroptions.AddDbPool<FurionDbContext>(DbProvider.SqlServer);options.AddDbPool<FurionDbContext>($"{DbProvider.SqlServer}@2005"); // 支持 2005 数据库options.AddDbPool<FurionDbContext>($"{DbProvider.SqlServer}@2008"); // 支持 2008 数据库// 注册 Sqliteoptions.AddDbPool<FurionDbContext>(DbProvider.Sqlite);// 注册 Cosmosoptions.AddDbPool<FurionDbContext>(DbProvider.Cosmos);// 注册 InMemoryDatabaseoptions.AddDbPool<FurionDbContext>(DbProvider.InMemoryDatabase);// 注册 MySqloptions.AddDbPool<FurionDbContext>(DbProvider.MySql);options.AddDbPool<FurionDbContext>($"{DbProvider.MySql}@8.0.22");  // 可以指定版本号options.AddDbPool<FurionDbContext>(DbProvider.MySqlOfficial);   // 使用 MySql 官方包(MySql.EntityFrameworkCore)// 注册 PostgreSQLoptions.AddDbPool<FurionDbContext>(DbProvider.Npgsql);// 注册 Oracleoptions.AddDbPool<FurionDbContext>(DbProvider.Oracle);options.AddDbPool<FurionDbContext>($"{DbProvider.Oracle}@11");  // 支持 Oracle 11 版本// 注册 Firebirdoptions.AddDbPool<FurionDbContext>(DbProvider.Firebird);// 注册 Dmoptions.AddDbPool<FurionDbContext>(DbProvider.Dm);
新版 SqlServer/MySQL/Oracle 注意

SqlServer 兼容 2005-2008 写法:

services.AddDatabaseAccessor(options =>{    options.AddDbPool<FurionDbContext>($"{DbProvider.SqlServer}@2005"); // 支持 2005 数据库    options.AddDbPool<FurionDbContext>($"{DbProvider.SqlServer}@2008"); // 支持 2008 数据库});

MySQL 兼容旧版本(带版本号)写法:

services.AddDatabaseAccessor(options =>{    options.AddDbPool<FurionDbContext>($"{DbProvider.MySql}@8.0.22");});

如果使用了 MySql.EntityFrameworkCore 包,则需改为以下注册:

services.AddDatabaseAccessor(options =>{    options.AddDbPool<FurionDbContext>(DbProvider.MySqlOfficial);});

Oracle 兼容 11 版本

services.AddDatabaseAccessor(options =>{    // 正常这样配置即可    options.AddDbPool<FurionDbContext>($"{DbProvider.Oracle}@11");    // 如果依然出现 ORA-00933: SQL 错误,可以尝试以下配置:    options.AddDbPool<FurionDbContext>($"{DbProvider.Oracle}@11", optionBuilder: (ses, opt) =>     {        opt.UseOracle(b => b.UseOracleSQLCompatibility("11"));    });});

9.18.3 各类数据库连接字符串配置示例

  • SqliteData Source=./Furion.db
  • MySqlData Source=localhost;Database=Furion;User ID=root;Password=000000;pooling=true;port=3306;sslmode=none;CharSet=utf8;
  • SqlServerServer=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;
  • OracleUser Id=orcl;Password=orcl;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl)))
  • PostgreSQLPORT=5432;DATABASE=postgres;HOST=127.0.0.1;PASSWORD=postgres;USER ID=postgres;

9.18.4 多数据库使用方式

Furion 通过独创的 数据库上下文定位器 实现多数据库灵活操作切换。只需要为每一种数据库绑定唯一的数据库上下文定位器即可。

以下是 Furion 支持多数据库操作的实例:

9.18.4.1 实体仓储方式

// 切换到 MSSQL 操作 Person表var mssqlRepository = personRepository.Change<Person, MsSqlDbContextLocator>();// 切换到 MySql 操作 Person表var mysqlRepository = personRepository.Change<Person, MySqlDbContextLocator>();// 切换到 Sqlite 操作 Person表var sqliteRepository = personRepository.Change<Person, SqliteDbContextLocator>();

9.18.4.2 非泛型仓储方式

// 切换到 MSSQL 操作 Person表var mssqlRepository = repository.Change<Person, MsSqlDbContextLocator>();// 切换到 MySql 操作 Person表var mysqlRepository = repository.Change<Person, MySqlDbContextLocator>();// 切换到 Sqlite 操作 Person表var sqliteRepository = repository.Change<Person, SqliteDbContextLocator>();

9.18.4.3 Sql 仓储方式

// 切换到 MSSQL 操作 Person表var mssqlRepository = sqlRepository.Change<MsSqlDbContextLocator>();// 切换到 MySql 操作 Person表var mysqlRepository = sqlRepository.Change<MySqlDbContextLocator>();// 切换到 Sqlite 操作 Person表var sqliteRepository = sqlRepository.Change<SqliteDbContextLocator>();

9.18.4.4 实体定义方式

// 支持一个数据库public class Person: IEntity<MySqlDbContextLocator>{    // ....}// 支持多个数据库public class Person: IEntity<MySqlDbContextLocator, SqliteDbContextLocator>{    // ....}
小知识

所有的 实体依赖接口或抽象类 都支持泛型方式 指定 数据库上下文定位器,最多支持 8 个。

9.18.4.5 Linq 函数方式

public static class QueryFunctions{    [QueryableFunction("FN_GetId", "dbo", typeof(MySqlDbContextLocator), typeof(SqliteDbContextLocator))]    public static int GetId(int id) => throw new NotSupportedException();}

9.18.5 SqlServer 低版本支持动态配置

正常情况下,只需要在注册的时候指定 @2008 数据库即可,有些时候我们可能需要在 DbContextOnConfigure 中配置,这个时候就需要添加以下代码:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){    optionsBuilder.UseSqlServer(DbProvider.GetConnectionString<TDbContext>())                  .ReplaceService<IQueryTranslationPostprocessorFactory, SqlServer2008QueryTranslationPostprocessorFactory>();    base.OnConfiguring(optionsBuilder);}
小知识

DbProvider.GetConnectionString<TDbContext>() 是获取对应上下文配置的数据库链接字符串。

9.18.6 MySql 时区问题/少 8 小时问题

可查阅相关 Issuehttps://gitee.com/dotnetchina/Furion/issues/I3RSCO

9.18.7 snake_case 风格表名和字段

默认情况下 EFCore 将使用和模型定义一致的方式定义表和字段,但可以通过 https://github.com/efcore/EFCore.NamingConventions 拓展插件改变此行为,如下图所示:

 builder.UseNpgsql()        .UseLowerCaseNamingConvention();

其他资料:https://www.npgsql.org/efcore/modeling/table-column-naming.html

9.18.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.18 多种数据库操作

连接字符串配置注意事项

如果连接字符串是配置在自定义的 .json 文件中,那么必须在 Visual Studio 中配置 .json 右键属性,设置 复制 输出目录为 如果较新则复制,生成操作为 内容

否则就会提示找不到配置或连接字符串的错误。

9.18.1 Furion 支持数据库提供器

SqlServerSqliteCosmosInMemoryDatabaseMySqlPostgreSQLOracleFirebirdDm

9.18.1.1 数据库提供器对应包

  • SqlServerMicrosoft.EntityFrameworkCore.SqlServer (支持 SqlServer 2005 +)
  • SqliteMicrosoft.EntityFrameworkCore.Sqlite
  • CosmosMicrosoft.EntityFrameworkCore.Cosmos
  • InMemoryDatabaseMicrosoft.EntityFrameworkCore.InMemory
  • MySql
    • Pomelo.EntityFrameworkCore.MySql:(支持 MySql 5.x +)
    • MySql.EntityFrameworkCore:支持 (MySql 8.x +)
  • PostgreSQLNpgsql.EntityFrameworkCore.PostgreSQL
  • OracleOracle.EntityFrameworkCore (支持 Oracle 10 +)
  • FirebirdFirebirdSql.EntityFrameworkCore.Firebird
  • DmMicrosoft.EntityFrameworkCore.Dm
小知识

这些数据库包应该安装在 Furion.EntityFramework.Core 层。特殊情况需安装在 Furion.Core 层中,如 Mysql HasCharset() 配置。

9.18.2 多数据库服务注册

// 注册 SqlServeroptions.AddDbPool<FurionDbContext>(DbProvider.SqlServer);options.AddDbPool<FurionDbContext>($"{DbProvider.SqlServer}@2005"); // 支持 2005 数据库options.AddDbPool<FurionDbContext>($"{DbProvider.SqlServer}@2008"); // 支持 2008 数据库// 注册 Sqliteoptions.AddDbPool<FurionDbContext>(DbProvider.Sqlite);// 注册 Cosmosoptions.AddDbPool<FurionDbContext>(DbProvider.Cosmos);// 注册 InMemoryDatabaseoptions.AddDbPool<FurionDbContext>(DbProvider.InMemoryDatabase);// 注册 MySqloptions.AddDbPool<FurionDbContext>(DbProvider.MySql);options.AddDbPool<FurionDbContext>($"{DbProvider.MySql}@8.0.22");  // 可以指定版本号options.AddDbPool<FurionDbContext>(DbProvider.MySqlOfficial);   // 使用 MySql 官方包(MySql.EntityFrameworkCore)// 注册 PostgreSQLoptions.AddDbPool<FurionDbContext>(DbProvider.Npgsql);// 注册 Oracleoptions.AddDbPool<FurionDbContext>(DbProvider.Oracle);options.AddDbPool<FurionDbContext>($"{DbProvider.Oracle}@11");  // 支持 Oracle 11 版本// 注册 Firebirdoptions.AddDbPool<FurionDbContext>(DbProvider.Firebird);// 注册 Dmoptions.AddDbPool<FurionDbContext>(DbProvider.Dm);
新版 SqlServer/MySQL/Oracle 注意

SqlServer 兼容 2005-2008 写法:

services.AddDatabaseAccessor(options =>{    options.AddDbPool<FurionDbContext>($"{DbProvider.SqlServer}@2005"); // 支持 2005 数据库    options.AddDbPool<FurionDbContext>($"{DbProvider.SqlServer}@2008"); // 支持 2008 数据库});

MySQL 兼容旧版本(带版本号)写法:

services.AddDatabaseAccessor(options =>{    options.AddDbPool<FurionDbContext>($"{DbProvider.MySql}@8.0.22");});

如果使用了 MySql.EntityFrameworkCore 包,则需改为以下注册:

services.AddDatabaseAccessor(options =>{    options.AddDbPool<FurionDbContext>(DbProvider.MySqlOfficial);});

Oracle 兼容 11 版本

services.AddDatabaseAccessor(options =>{    // 正常这样配置即可    options.AddDbPool<FurionDbContext>($"{DbProvider.Oracle}@11");    // 如果依然出现 ORA-00933: SQL 错误,可以尝试以下配置:    options.AddDbPool<FurionDbContext>($"{DbProvider.Oracle}@11", optionBuilder: (ses, opt) =>     {        opt.UseOracle(b => b.UseOracleSQLCompatibility("11"));    });});

9.18.3 各类数据库连接字符串配置示例

  • SqliteData Source=./Furion.db
  • MySqlData Source=localhost;Database=Furion;User ID=root;Password=000000;pooling=true;port=3306;sslmode=none;CharSet=utf8;
  • SqlServerServer=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;
  • OracleUser Id=orcl;Password=orcl;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl)))
  • PostgreSQLPORT=5432;DATABASE=postgres;HOST=127.0.0.1;PASSWORD=postgres;USER ID=postgres;

9.18.4 多数据库使用方式

Furion 通过独创的 数据库上下文定位器 实现多数据库灵活操作切换。只需要为每一种数据库绑定唯一的数据库上下文定位器即可。

以下是 Furion 支持多数据库操作的实例:

9.18.4.1 实体仓储方式

// 切换到 MSSQL 操作 Person表var mssqlRepository = personRepository.Change<Person, MsSqlDbContextLocator>();// 切换到 MySql 操作 Person表var mysqlRepository = personRepository.Change<Person, MySqlDbContextLocator>();// 切换到 Sqlite 操作 Person表var sqliteRepository = personRepository.Change<Person, SqliteDbContextLocator>();

9.18.4.2 非泛型仓储方式

// 切换到 MSSQL 操作 Person表var mssqlRepository = repository.Change<Person, MsSqlDbContextLocator>();// 切换到 MySql 操作 Person表var mysqlRepository = repository.Change<Person, MySqlDbContextLocator>();// 切换到 Sqlite 操作 Person表var sqliteRepository = repository.Change<Person, SqliteDbContextLocator>();

9.18.4.3 Sql 仓储方式

// 切换到 MSSQL 操作 Person表var mssqlRepository = sqlRepository.Change<MsSqlDbContextLocator>();// 切换到 MySql 操作 Person表var mysqlRepository = sqlRepository.Change<MySqlDbContextLocator>();// 切换到 Sqlite 操作 Person表var sqliteRepository = sqlRepository.Change<SqliteDbContextLocator>();

9.18.4.4 实体定义方式

// 支持一个数据库public class Person: IEntity<MySqlDbContextLocator>{    // ....}// 支持多个数据库public class Person: IEntity<MySqlDbContextLocator, SqliteDbContextLocator>{    // ....}
小知识

所有的 实体依赖接口或抽象类 都支持泛型方式 指定 数据库上下文定位器,最多支持 8 个。

9.18.4.5 Linq 函数方式

public static class QueryFunctions{    [QueryableFunction("FN_GetId", "dbo", typeof(MySqlDbContextLocator), typeof(SqliteDbContextLocator))]    public static int GetId(int id) => throw new NotSupportedException();}

9.18.5 SqlServer 低版本支持动态配置

正常情况下,只需要在注册的时候指定 @2008 数据库即可,有些时候我们可能需要在 DbContextOnConfigure 中配置,这个时候就需要添加以下代码:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){    optionsBuilder.UseSqlServer(DbProvider.GetConnectionString<TDbContext>())                  .ReplaceService<IQueryTranslationPostprocessorFactory, SqlServer2008QueryTranslationPostprocessorFactory>();    base.OnConfiguring(optionsBuilder);}
小知识

DbProvider.GetConnectionString<TDbContext>() 是获取对应上下文配置的数据库链接字符串。

9.18.6 MySql 时区问题/少 8 小时问题

可查阅相关 Issuehttps://gitee.com/dotnetchina/Furion/issues/I3RSCO

9.18.7 snake_case 风格表名和字段

默认情况下 EFCore 将使用和模型定义一致的方式定义表和字段,但可以通过 https://github.com/efcore/EFCore.NamingConventions 拓展插件改变此行为,如下图所示:

 builder.UseNpgsql()        .UseLowerCaseNamingConvention();

其他资料:https://www.npgsql.org/efcore/modeling/table-column-naming.html

9.18.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-proc/index.html b/handbook/build/docs/dbcontext-proc/index.html index 5e8453a52e..52c38fdd96 100644 --- a/handbook/build/docs/dbcontext-proc/index.html +++ b/handbook/build/docs/dbcontext-proc/index.html @@ -2,22 +2,21 @@ - - - + +9.13 存储过程操作 | Furion -9.13 存储过程操作 | Furion - - + + +
-

9.13 存储过程操作

温馨提示

推荐使用 《9.17 Sql 高级代理》代替本章节功能。Sql 高级代理 能够提供更容易且更易维护的方式。

9.13.1 关于存储过程

引用百度百科:

存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的 SQL 语句集,它存储在数据库中,一次编译后永久有效,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。

存储过程是数据库中的一个重要对象。在数据量特别庞大的情况下利用存储过程能达到倍速的效率提升。

简单来说,存储过程就是关系型数据库中(Sqlite 除外)中编写逻辑的函数/方法,通过这种方式,可以将 sql 编译缓存起来,大大提高存储过程的执行效率。

这里不讨论存储过程的优缺点。

9.13.2.0 支持存储过程的数据库

SqlServerSqliteCosmosInMemoryDatabaseMySqlPostgreSQLOracleFirebirdDm

9.13.2 存储过程使用

Furion 框架中提供了多种存储过程操作方式:

  • ISqlRepositorySql 操作仓储,可通过 依赖注入
  • ISqlDispatchProxySql 代理方式(高级用法,推荐)
  • 通过任意实体仓储操作:personRepository.SqlProcedureQuery(procName)
  • 通过字符串拓展方法:procName.SqlProcedureQuery()
  • 通过 repository.Sql().SqlProcedureQuery() 方式

9.13.2.1 初始化方式

using Furion.DatabaseAccessor;using Furion.DynamicApiController;namespace Furion.Application{    [DynamicApiController]    public class SqlService    {        private ISqlRepository _sqlRepository;        public SqlService(ISqlRepository sqlRepository)        {            _sqlRepository = sqlRepository;        }    }}

9.13.2.2 返回 DataTable

// ISqlRepository 方法var dataTable = _sqlRepository.SqlProcedureQuery("proc_GetPersons");// ISqlDispatchProxy 方式var dataTable = _sqlExecuteProxy.GetPersons();  // 推荐方式// 实体仓储方式var dataTable = _personRepository.SqlProcedureQuery("proc_GetPersons");// IRepository 非泛型方式var dataTable = _repository.Sql().SqlProcedureQuery("proc_GetPersons");// 变态懒人方式,直接通过存储过程名执行var dataTable = "proc_GetPersons".SqlProcedureQuery();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.2.3 返回 DataSet

// ISqlRepository 方法var dataSet = _sqlRepository.SqlProcedureQueries("proc_GetPersons");// ISqlDispatchProxy 方式var dataSet = _sqlExecuteProxy.GetPersons();  // 推荐方式// 实体仓储方式var dataSet = _personRepository.SqlProcedureQueries("proc_GetPersons");// IRepository 非泛型方式var dataSet = _repository.Sql().SqlProcedureQueries("proc_GetPersons");// 变态懒人方式,直接通过存储过程名执行var dataSet = "proc_GetPersons".SqlProcedureQueries();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.2.4 返回 List<T>

// ISqlRepository 方法var list = _sqlRepository.SqlProcedureQuery<Person>("proc_GetPersons");// ISqlDispatchProxy 方式var list = _sqlExecuteProxy.GetPersons();  // 推荐方式// 实体仓储方式var list = _personRepository.SqlProcedureQuery<Person>("proc_GetPersons");// IRepository 非泛型方式var list = _repository.Sql().SqlProcedureQuery<Person>("proc_GetPersons");// 变态懒人方式,直接通过存储过程名执行var list = "proc_GetPersons".SqlProcedureQuery<Person>();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.2.5 返回 Tuple<T1,...T8>

Furion 框架大大利用了 Tuple 的特性,将返回多个结果集转成 Tuple<T1,...T8> 类型

// ISqlRepository 方法// 返回一个结果集var list1 = _sqlRepository.SqlProcedureQueries<T1>("proc_GetPersons");// 返回两个结果集var (list1, list2) = _sqlRepository.SqlProcedureQueries<T1,T2>("proc_GetPersons");// 返回三个结果集var (list1, list2, list3) = _sqlRepository.SqlProcedureQueries<T1,T2,T3>("proc_GetPersons");// 返回四个结果集var (list1, list2, list3, list4) = _sqlRepository.SqlProcedureQueries<T1,T2,T3,T4>("proc_GetPersons");// 返回五个结果集var (list1, list2, list3, list4, list5) = _sqlRepository.SqlProcedureQueries<T1,T2,T3,T4,T5>("proc_GetPersons");// 返回六个结果集var (list1, list2, list3, list4, list5, list6) = _sqlRepository.SqlProcedureQueries<T1,T2,T3,T4,T5,T6>("proc_GetPersons");// 返回七个结果集var (list1, list2, list3, list4, list5, list6, list7) = _sqlRepository.SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7>("proc_GetPersons");// 返回八个结果集var (list1, list2, list3, list4, list5, list6, list7, list8) = _sqlRepository.SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7,T8>("proc_GetPersons");// ==================================// ISqlDispatchProxy 方式,推荐方式,自动处理多个结果集// 返回一个结果集var list1 = _sqlRepository.GetDatas();// 返回两个结果集var (list1, list2) = _sqlRepository.GetDatas();// 返回三个结果集var (list1, list2, list3) = _sqlRepository.GetDatas();// 返回四个结果集var (list1, list2, list3, list4) = _sqlRepository.GetDatas();// 返回五个结果集var (list1, list2, list3, list4, list5) = _sqlRepository.GetDatas();// 返回六个结果集var (list1, list2, list3, list4, list5, list6) = _sqlRepository.GetDatas();// 返回七个结果集var (list1, list2, list3, list4, list5, list6, list7) = _sqlRepository.GetDatas();// 返回八个结果集var (list1, list2, list3, list4, list5, list6, list7, list8) = _sqlRepository.GetDatas();// ==================================// 实体仓储方式// 返回一个结果集var list1 = _personRepository.SqlProcedureQueries<T1>("proc_GetPersons");// 返回两个结果集var (list1, list2) = _personRepository.SqlProcedureQueries<T1,T2>("proc_GetPersons");// 返回三个结果集var (list1, list2, list3) = _personRepository.SqlProcedureQueries<T1,T2,T3>("proc_GetPersons");// 返回四个结果集var (list1, list2, list3, list4) = _personRepository.SqlProcedureQueries<T1,T2,T3,T4>("proc_GetPersons");// 返回五个结果集var (list1, list2, list3, list4, list5) = _personRepository.SqlProcedureQueries<T1,T2,T3,T4,T5>("proc_GetPersons");// 返回六个结果集var (list1, list2, list3, list4, list5, list6) = _personRepository.SqlProcedureQueries<T1,T2,T3,T4,T5,T6>("proc_GetPersons");// 返回七个结果集var (list1, list2, list3, list4, list5, list6, list7) = _personRepository.SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7>("proc_GetPersons");// 返回八个结果集var (list1, list2, list3, list4, list5, list6, list7, list8) = _personRepository.SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7,T8>("proc_GetPersons");// ==================================// IRepository 非泛型方式// 返回一个结果集var list1 = _repository.Sql().SqlProcedureQueries<T1>("proc_GetPersons");// 返回两个结果集var (list1, list2) = _repository.Sql().SqlProcedureQueries<T1,T2>("proc_GetPersons");// 返回三个结果集var (list1, list2, list3) = _repository.Sql().SqlProcedureQueries<T1,T2,T3>("proc_GetPersons");// 返回四个结果集var (list1, list2, list3, list4) = _repository.Sql().SqlProcedureQueries<T1,T2,T3,T4>("proc_GetPersons");// 返回五个结果集var (list1, list2, list3, list4, list5) = _repository.Sql().SqlProcedureQueries<T1,T2,T3,T4,T5>("proc_GetPersons");// 返回六个结果集var (list1, list2, list3, list4, list5, list6) = _repository.Sql().SqlProcedureQueries<T1,T2,T3,T4,T5,T6>("proc_GetPersons");// 返回七个结果集var (list1, list2, list3, list4, list5, list6, list7) = _repository.Sql().SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7>("proc_GetPersons");// 返回八个结果集var (list1, list2, list3, list4, list5, list6, list7, list8) = _repository.Sql().SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7,T8>("proc_GetPersons");// ==================================// 变态懒人方式,直接通过存储过程名执行// 返回一个结果集var list1 = "proc_GetPersons".SqlProcedureQueries<T1>();// 返回两个结果集var (list1, list2) = "proc_GetPersons".SqlProcedureQueries<T1,T2>();// 返回三个结果集var (list1, list2, list3) = "proc_GetPersons".SqlProcedureQueries<T1,T2,T3>();// 返回四个结果集var (list1, list2, list3, list4) = "proc_GetPersons".SqlProcedureQueries<T1,T2,T3,T4>();// 返回五个结果集var (list1, list2, list3, list4, list5) = "proc_GetPersons".SqlProcedureQueries<T1,T2,T3,T4,T5>();// 返回六个结果集var (list1, list2, list3, list4, list5, list6) = "proc_GetPersons".SqlProcedureQueries<T1,T2,T3,T4,T5,T6>();// 返回七个结果集var (list1, list2, list3, list4, list5, list6, list7) = "proc_GetPersons".SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7>();// 返回八个结果集var (list1, list2, list3, list4, list5, list6, list7, list8) = "proc_GetPersons".SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7,T8>();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.2.6 返回 单行单列 object

// ISqlRepository 方法var value = _sqlRepository.SqlProcedureScalar("proc_GetName");// ISqlDispatchProxy 方式var value = _sqlExecuteProxy.GetName();  // 推荐方式// 实体仓储方式var value = _personRepository.SqlProcedureScalar("proc_GetName");// IRepository 非泛型方式var value = _repository.Sql().SqlProcedureScalar("proc_GetName");// 变态懒人方式,直接通过存储过程名执行var value = "proc_GetName".SqlProcedureScalar();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.2.7 返回 单行单列 <T>

// ISqlRepository 方法var value = _sqlRepository.SqlProcedureScalar<string>("proc_GetName");// ISqlDispatchProxy 方式var value = _sqlExecuteProxy.GetName();  // 推荐方式// 实体仓储方式var value = _personRepository.SqlProcedureScalar<string>("proc_GetName");// IRepository 非泛型方式var value = _repository.Sql().SqlProcedureScalar<string>("proc_GetName");// 变态懒人方式,直接通过存储过程名执行var value = "proc_GetName".SqlProcedureScalar<string>();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.2.8 执行但无返回

// ISqlRepository 方法_sqlRepository.SqlProcedureNonQuery("proc_UpdateData");// ISqlDispatchProxy 方式_sqlExecuteProxy.UpdateData();  // 推荐方式// 实体仓储方式_personRepository.SqlProcedureNonQuery("proc_UpdateData");// IRepository 非泛型方式_repository.Sql().SqlProcedureNonQuery("proc_UpdateData");// 变态懒人方式,直接通过存储过程名执行"proc_UpdateData".SqlProcedureNonQuery();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.3 执行复杂存储过程

在存储过程中,有一种例子非常复杂,那就是既有 INPUT 参数,又有 OUTPUT 参数,还有 RETURN 参数,同时还输出 结果集 💥,如:

CREATE PROC PROC_Output    @Id INT,    // 输入参数    @Name NVARCHAR(32) OUTPUT,  // 输出参数,还带长度    @Age INT OUTPUT // 输出参数ASBEGIN    SET @Name = 'Furion Output';    // 输出结果集    SELECT *    FROM dbo.Test    WHERE Id > @Id;    // 输出结果集    SELECT TOP 10           *    FROM dbo.Test;    SET @Age = 27;    // 带 RETURN 返回    RETURN 10;END;

9.13.3.1 创建参数模型

using Furion.DatabaseAccessor;using System.Data;namespace Furion.Application{    public class ProcOutputModel    {        public int Id { get; set; } // 输入参数        [DbParameter(ParameterDirection.Output, Size = 32)]        public string Name { get; set; }    // 输出参数        [DbParameter(ParameterDirection.Output)]        public int Age { get; set; }    // 输出参数        [DbParameter(ParameterDirection.ReturnValue)]        public int ReturnValue { get; set; }    // 返回值    }}

9.13.3.2 执行复杂存储过程

  • DataSet 方式
// ISqlRepository 方法ProcedureOutputResult result = _sqlRepository.SqlProcedureOutput("proc_Complex", new ProcOutputModel{});// ISqlDispatchProxy 方式ProcedureOutputResult result = _sqlExecuteProxy.Complex(new ProcOutputModel{});  // 推荐方式// 实体仓储方式ProcedureOutputResult result = _personRepository.SqlProcedureOutput("proc_Complex", new ProcOutputModel{});// IRepository 非泛型方式ProcedureOutputResult result = _repository.Sql().SqlProcedureOutput("proc_Complex", new ProcOutputModel{});// 变态懒人方式,直接通过存储过程名执行ProcedureOutputResult result = "proc_Complex".SqlProcedureOutput(new ProcOutputModel{});
// 获取 OUTPUT 参数值var outputs = result.OutputValues;// 获取 RETURN 返回值var reval = result.ReturnValue;// 获取返回结果集var dataSet = result.Result;
  • Tuple<T1,...T8> 方式
// ISqlRepository 方法ProcedureOutputResult<(List<Test>, List<Test>)> result = _sqlRepository.SqlProcedureOutput<(List<Test>, List<Test>)>("proc_Complex", new ProcOutputModel{});// ISqlDispatchProxy 方式ProcedureOutputResult<(List<Test>, List<Test>)> result = _sqlExecuteProxy.Complex(new ProcOutputModel{});  // 推荐方式// 实体仓储方式ProcedureOutputResult<(List<Test>, List<Test>)> result = _personRepository.SqlProcedureOutput<(List<Test>, List<Test>)>("proc_Complex", new ProcOutputModel{});// IRepository 非泛型方式ProcedureOutputResult<(List<Test>, List<Test>)> result = _repository.Sql().SqlProcedureOutput<(List<Test>, List<Test>)>("proc_Complex", new ProcOutputModel{});// 变态懒人方式,直接通过存储过程名执行ProcedureOutputResult<(List<Test>, List<Test>)> result = "proc_Complex".SqlProcedureOutput<(List<Test>, List<Test>)>(new ProcOutputModel{});
// 获取 OUTPUT 参数值var outputs = result.OutputValues;// 获取 RETURN 返回值var reval = result.ReturnValue;// 获取返回结果集var (list1,list2) = result.Result;
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.3 关于 [DbParameter]

[DbParameter] 特性是用来标注 Sql函数存储过程 参数的,可配置属性:

  • Direction:设置参数方向,ParameterDirection 枚举类型,默认 ParameterDirection.Input
  • DbType:设置参数类型,DbType 枚举类型,无默认
  • Size:设置参数长度的,int 类型

其中 Direction 属性是默认构造函数参数。

9.13.4 关于 ProcedureOutputResult

ProcedureOutputResultProcedureOutputResult<TResult> 是复杂存储过程执行返回模型类,有以下属性:

  • OutputValues:多个输出值,ProcedureOutputValue 类型
  • ReturnValue:返回值,object 类型
  • Result:结果集,非泛型版本是 DataSet类型,否则是 泛型类型

9.13.5 存储过程参数

所有 sql 参数都支持四种方式:

  • DbParameter[]:数组类型
  • new {}:匿名类型
  • new Class{}:强类型类型(支持复杂存储过程参数)
  • Dictionary<string,object> 类型

9.13.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.13 存储过程操作

温馨提示

推荐使用 《9.17 Sql 高级代理》代替本章节功能。Sql 高级代理 能够提供更容易且更易维护的方式。

9.13.1 关于存储过程

引用百度百科:

存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的 SQL 语句集,它存储在数据库中,一次编译后永久有效,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。

存储过程是数据库中的一个重要对象。在数据量特别庞大的情况下利用存储过程能达到倍速的效率提升。

简单来说,存储过程就是关系型数据库中(Sqlite 除外)中编写逻辑的函数/方法,通过这种方式,可以将 sql 编译缓存起来,大大提高存储过程的执行效率。

这里不讨论存储过程的优缺点。

9.13.2.0 支持存储过程的数据库

SqlServerSqliteCosmosInMemoryDatabaseMySqlPostgreSQLOracleFirebirdDm

9.13.2 存储过程使用

Furion 框架中提供了多种存储过程操作方式:

  • ISqlRepositorySql 操作仓储,可通过 依赖注入
  • ISqlDispatchProxySql 代理方式(高级用法,推荐)
  • 通过任意实体仓储操作:personRepository.SqlProcedureQuery(procName)
  • 通过字符串拓展方法:procName.SqlProcedureQuery()
  • 通过 repository.Sql().SqlProcedureQuery() 方式

9.13.2.1 初始化方式

using Furion.DatabaseAccessor;using Furion.DynamicApiController;namespace Furion.Application{    [DynamicApiController]    public class SqlService    {        private ISqlRepository _sqlRepository;        public SqlService(ISqlRepository sqlRepository)        {            _sqlRepository = sqlRepository;        }    }}

9.13.2.2 返回 DataTable

// ISqlRepository 方法var dataTable = _sqlRepository.SqlProcedureQuery("proc_GetPersons");// ISqlDispatchProxy 方式var dataTable = _sqlExecuteProxy.GetPersons();  // 推荐方式// 实体仓储方式var dataTable = _personRepository.SqlProcedureQuery("proc_GetPersons");// IRepository 非泛型方式var dataTable = _repository.Sql().SqlProcedureQuery("proc_GetPersons");// 变态懒人方式,直接通过存储过程名执行var dataTable = "proc_GetPersons".SqlProcedureQuery();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.2.3 返回 DataSet

// ISqlRepository 方法var dataSet = _sqlRepository.SqlProcedureQueries("proc_GetPersons");// ISqlDispatchProxy 方式var dataSet = _sqlExecuteProxy.GetPersons();  // 推荐方式// 实体仓储方式var dataSet = _personRepository.SqlProcedureQueries("proc_GetPersons");// IRepository 非泛型方式var dataSet = _repository.Sql().SqlProcedureQueries("proc_GetPersons");// 变态懒人方式,直接通过存储过程名执行var dataSet = "proc_GetPersons".SqlProcedureQueries();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.2.4 返回 List<T>

// ISqlRepository 方法var list = _sqlRepository.SqlProcedureQuery<Person>("proc_GetPersons");// ISqlDispatchProxy 方式var list = _sqlExecuteProxy.GetPersons();  // 推荐方式// 实体仓储方式var list = _personRepository.SqlProcedureQuery<Person>("proc_GetPersons");// IRepository 非泛型方式var list = _repository.Sql().SqlProcedureQuery<Person>("proc_GetPersons");// 变态懒人方式,直接通过存储过程名执行var list = "proc_GetPersons".SqlProcedureQuery<Person>();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.2.5 返回 Tuple<T1,...T8>

Furion 框架大大利用了 Tuple 的特性,将返回多个结果集转成 Tuple<T1,...T8> 类型

// ISqlRepository 方法// 返回一个结果集var list1 = _sqlRepository.SqlProcedureQueries<T1>("proc_GetPersons");// 返回两个结果集var (list1, list2) = _sqlRepository.SqlProcedureQueries<T1,T2>("proc_GetPersons");// 返回三个结果集var (list1, list2, list3) = _sqlRepository.SqlProcedureQueries<T1,T2,T3>("proc_GetPersons");// 返回四个结果集var (list1, list2, list3, list4) = _sqlRepository.SqlProcedureQueries<T1,T2,T3,T4>("proc_GetPersons");// 返回五个结果集var (list1, list2, list3, list4, list5) = _sqlRepository.SqlProcedureQueries<T1,T2,T3,T4,T5>("proc_GetPersons");// 返回六个结果集var (list1, list2, list3, list4, list5, list6) = _sqlRepository.SqlProcedureQueries<T1,T2,T3,T4,T5,T6>("proc_GetPersons");// 返回七个结果集var (list1, list2, list3, list4, list5, list6, list7) = _sqlRepository.SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7>("proc_GetPersons");// 返回八个结果集var (list1, list2, list3, list4, list5, list6, list7, list8) = _sqlRepository.SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7,T8>("proc_GetPersons");// ==================================// ISqlDispatchProxy 方式,推荐方式,自动处理多个结果集// 返回一个结果集var list1 = _sqlRepository.GetDatas();// 返回两个结果集var (list1, list2) = _sqlRepository.GetDatas();// 返回三个结果集var (list1, list2, list3) = _sqlRepository.GetDatas();// 返回四个结果集var (list1, list2, list3, list4) = _sqlRepository.GetDatas();// 返回五个结果集var (list1, list2, list3, list4, list5) = _sqlRepository.GetDatas();// 返回六个结果集var (list1, list2, list3, list4, list5, list6) = _sqlRepository.GetDatas();// 返回七个结果集var (list1, list2, list3, list4, list5, list6, list7) = _sqlRepository.GetDatas();// 返回八个结果集var (list1, list2, list3, list4, list5, list6, list7, list8) = _sqlRepository.GetDatas();// ==================================// 实体仓储方式// 返回一个结果集var list1 = _personRepository.SqlProcedureQueries<T1>("proc_GetPersons");// 返回两个结果集var (list1, list2) = _personRepository.SqlProcedureQueries<T1,T2>("proc_GetPersons");// 返回三个结果集var (list1, list2, list3) = _personRepository.SqlProcedureQueries<T1,T2,T3>("proc_GetPersons");// 返回四个结果集var (list1, list2, list3, list4) = _personRepository.SqlProcedureQueries<T1,T2,T3,T4>("proc_GetPersons");// 返回五个结果集var (list1, list2, list3, list4, list5) = _personRepository.SqlProcedureQueries<T1,T2,T3,T4,T5>("proc_GetPersons");// 返回六个结果集var (list1, list2, list3, list4, list5, list6) = _personRepository.SqlProcedureQueries<T1,T2,T3,T4,T5,T6>("proc_GetPersons");// 返回七个结果集var (list1, list2, list3, list4, list5, list6, list7) = _personRepository.SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7>("proc_GetPersons");// 返回八个结果集var (list1, list2, list3, list4, list5, list6, list7, list8) = _personRepository.SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7,T8>("proc_GetPersons");// ==================================// IRepository 非泛型方式// 返回一个结果集var list1 = _repository.Sql().SqlProcedureQueries<T1>("proc_GetPersons");// 返回两个结果集var (list1, list2) = _repository.Sql().SqlProcedureQueries<T1,T2>("proc_GetPersons");// 返回三个结果集var (list1, list2, list3) = _repository.Sql().SqlProcedureQueries<T1,T2,T3>("proc_GetPersons");// 返回四个结果集var (list1, list2, list3, list4) = _repository.Sql().SqlProcedureQueries<T1,T2,T3,T4>("proc_GetPersons");// 返回五个结果集var (list1, list2, list3, list4, list5) = _repository.Sql().SqlProcedureQueries<T1,T2,T3,T4,T5>("proc_GetPersons");// 返回六个结果集var (list1, list2, list3, list4, list5, list6) = _repository.Sql().SqlProcedureQueries<T1,T2,T3,T4,T5,T6>("proc_GetPersons");// 返回七个结果集var (list1, list2, list3, list4, list5, list6, list7) = _repository.Sql().SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7>("proc_GetPersons");// 返回八个结果集var (list1, list2, list3, list4, list5, list6, list7, list8) = _repository.Sql().SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7,T8>("proc_GetPersons");// ==================================// 变态懒人方式,直接通过存储过程名执行// 返回一个结果集var list1 = "proc_GetPersons".SqlProcedureQueries<T1>();// 返回两个结果集var (list1, list2) = "proc_GetPersons".SqlProcedureQueries<T1,T2>();// 返回三个结果集var (list1, list2, list3) = "proc_GetPersons".SqlProcedureQueries<T1,T2,T3>();// 返回四个结果集var (list1, list2, list3, list4) = "proc_GetPersons".SqlProcedureQueries<T1,T2,T3,T4>();// 返回五个结果集var (list1, list2, list3, list4, list5) = "proc_GetPersons".SqlProcedureQueries<T1,T2,T3,T4,T5>();// 返回六个结果集var (list1, list2, list3, list4, list5, list6) = "proc_GetPersons".SqlProcedureQueries<T1,T2,T3,T4,T5,T6>();// 返回七个结果集var (list1, list2, list3, list4, list5, list6, list7) = "proc_GetPersons".SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7>();// 返回八个结果集var (list1, list2, list3, list4, list5, list6, list7, list8) = "proc_GetPersons".SqlProcedureQueries<T1,T2,T3,T4,T5,T6,T7,T8>();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.2.6 返回 单行单列 object

// ISqlRepository 方法var value = _sqlRepository.SqlProcedureScalar("proc_GetName");// ISqlDispatchProxy 方式var value = _sqlExecuteProxy.GetName();  // 推荐方式// 实体仓储方式var value = _personRepository.SqlProcedureScalar("proc_GetName");// IRepository 非泛型方式var value = _repository.Sql().SqlProcedureScalar("proc_GetName");// 变态懒人方式,直接通过存储过程名执行var value = "proc_GetName".SqlProcedureScalar();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.2.7 返回 单行单列 <T>

// ISqlRepository 方法var value = _sqlRepository.SqlProcedureScalar<string>("proc_GetName");// ISqlDispatchProxy 方式var value = _sqlExecuteProxy.GetName();  // 推荐方式// 实体仓储方式var value = _personRepository.SqlProcedureScalar<string>("proc_GetName");// IRepository 非泛型方式var value = _repository.Sql().SqlProcedureScalar<string>("proc_GetName");// 变态懒人方式,直接通过存储过程名执行var value = "proc_GetName".SqlProcedureScalar<string>();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.2.8 执行但无返回

// ISqlRepository 方法_sqlRepository.SqlProcedureNonQuery("proc_UpdateData");// ISqlDispatchProxy 方式_sqlExecuteProxy.UpdateData();  // 推荐方式// 实体仓储方式_personRepository.SqlProcedureNonQuery("proc_UpdateData");// IRepository 非泛型方式_repository.Sql().SqlProcedureNonQuery("proc_UpdateData");// 变态懒人方式,直接通过存储过程名执行"proc_UpdateData".SqlProcedureNonQuery();
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.3 执行复杂存储过程

在存储过程中,有一种例子非常复杂,那就是既有 INPUT 参数,又有 OUTPUT 参数,还有 RETURN 参数,同时还输出 结果集 💥,如:

CREATE PROC PROC_Output    @Id INT,    // 输入参数    @Name NVARCHAR(32) OUTPUT,  // 输出参数,还带长度    @Age INT OUTPUT // 输出参数ASBEGIN    SET @Name = 'Furion Output';    // 输出结果集    SELECT *    FROM dbo.Test    WHERE Id > @Id;    // 输出结果集    SELECT TOP 10           *    FROM dbo.Test;    SET @Age = 27;    // 带 RETURN 返回    RETURN 10;END;

9.13.3.1 创建参数模型

using Furion.DatabaseAccessor;using System.Data;namespace Furion.Application{    public class ProcOutputModel    {        public int Id { get; set; } // 输入参数        [DbParameter(ParameterDirection.Output, Size = 32)]        public string Name { get; set; }    // 输出参数        [DbParameter(ParameterDirection.Output)]        public int Age { get; set; }    // 输出参数        [DbParameter(ParameterDirection.ReturnValue)]        public int ReturnValue { get; set; }    // 返回值    }}

9.13.3.2 执行复杂存储过程

  • DataSet 方式
// ISqlRepository 方法ProcedureOutputResult result = _sqlRepository.SqlProcedureOutput("proc_Complex", new ProcOutputModel{});// ISqlDispatchProxy 方式ProcedureOutputResult result = _sqlExecuteProxy.Complex(new ProcOutputModel{});  // 推荐方式// 实体仓储方式ProcedureOutputResult result = _personRepository.SqlProcedureOutput("proc_Complex", new ProcOutputModel{});// IRepository 非泛型方式ProcedureOutputResult result = _repository.Sql().SqlProcedureOutput("proc_Complex", new ProcOutputModel{});// 变态懒人方式,直接通过存储过程名执行ProcedureOutputResult result = "proc_Complex".SqlProcedureOutput(new ProcOutputModel{});
// 获取 OUTPUT 参数值var outputs = result.OutputValues;// 获取 RETURN 返回值var reval = result.ReturnValue;// 获取返回结果集var dataSet = result.Result;
  • Tuple<T1,...T8> 方式
// ISqlRepository 方法ProcedureOutputResult<(List<Test>, List<Test>)> result = _sqlRepository.SqlProcedureOutput<(List<Test>, List<Test>)>("proc_Complex", new ProcOutputModel{});// ISqlDispatchProxy 方式ProcedureOutputResult<(List<Test>, List<Test>)> result = _sqlExecuteProxy.Complex(new ProcOutputModel{});  // 推荐方式// 实体仓储方式ProcedureOutputResult<(List<Test>, List<Test>)> result = _personRepository.SqlProcedureOutput<(List<Test>, List<Test>)>("proc_Complex", new ProcOutputModel{});// IRepository 非泛型方式ProcedureOutputResult<(List<Test>, List<Test>)> result = _repository.Sql().SqlProcedureOutput<(List<Test>, List<Test>)>("proc_Complex", new ProcOutputModel{});// 变态懒人方式,直接通过存储过程名执行ProcedureOutputResult<(List<Test>, List<Test>)> result = "proc_Complex".SqlProcedureOutput<(List<Test>, List<Test>)>(new ProcOutputModel{});
// 获取 OUTPUT 参数值var outputs = result.OutputValues;// 获取 RETURN 返回值var reval = result.ReturnValue;// 获取返回结果集var (list1,list2) = result.Result;
关于异步

Furion 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

9.13.3 关于 [DbParameter]

[DbParameter] 特性是用来标注 Sql函数存储过程 参数的,可配置属性:

  • Direction:设置参数方向,ParameterDirection 枚举类型,默认 ParameterDirection.Input
  • DbType:设置参数类型,DbType 枚举类型,无默认
  • Size:设置参数长度的,int 类型

其中 Direction 属性是默认构造函数参数。

9.13.4 关于 ProcedureOutputResult

ProcedureOutputResultProcedureOutputResult<TResult> 是复杂存储过程执行返回模型类,有以下属性:

  • OutputValues:多个输出值,ProcedureOutputValue 类型
  • ReturnValue:返回值,object 类型
  • Result:结果集,非泛型版本是 DataSet类型,否则是 泛型类型

9.13.5 存储过程参数

所有 sql 参数都支持四种方式:

  • DbParameter[]:数组类型
  • new {}:匿名类型
  • new Class{}:强类型类型(支持复杂存储过程参数)
  • Dictionary<string,object> 类型

9.13.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-query/index.html b/handbook/build/docs/dbcontext-query/index.html index b2a81b0255..1f1a59adf6 100644 --- a/handbook/build/docs/dbcontext-query/index.html +++ b/handbook/build/docs/dbcontext-query/index.html @@ -2,22 +2,21 @@ - - - + +9.10 查询操作 | Furion -9.10 查询操作 | Furion - - + + +
-

9.10 查询操作

9.10.1 根据主键查询一条

// ==== 同步操作 ====// 示例一var person = repository.Find(1);// 示例二var person = repository.FindOrDefault(1);// 示例三var person = repository.Entities.Find(1);// ==== 异步操作 ====// 示例一var person = await repository.FindAsync(1);// 示例二var person = await repository.FindOrDefaultAsync(1);// 示例三var person = await repository.Entities.FindAsync(1);
小提示

可以支持多个键查询,如主键、联合键。repository.Find(1, "百小僧");

9.10.2 根据条件查询一条

// ==== 同步操作 ====// 示例一var person = repository.Single(u => u.Name == "Furion");// 示例二var person = repository.SingleOrDefault(u => u.Name == "Furion");// 示例三var person = repository.First(u => u.Name == "Furion");// 示例四var person = repository.FirstOrDefault(u => u.Name == "Furion");// 示例五var person = repository.Last(u => u.Name == "Furion");// 示例六var person = repository.LastOrDefault(u => u.Name == "Furion");// 示例七var person = repository.Entities.Single(u => u.Name == "Furion");// 示例八var person = repository.Entities.First(u => u.Name == "Furion");// 示例九var person = repository.Entities.FirstOrDefault(u => u.Name == "Furion");// 示例十var person = repository.Entities.Last(u => u.Name == "Furion");// 示例十一var person = repository.Entities.LastOrDefault(u => u.Name == "Furion");// ==== 异步操作 ====// 示例一var person = await repository.SingleAsync(u => u.Name == "Furion");// 示例二var person = await repository.SingleOrDefaultAsync(u => u.Name == "Furion");// 示例三var person = await repository.FirstAsync(u => u.Name == "Furion");// 示例四var person = await repository.FirstOrDefaultAsync(u => u.Name == "Furion");// 示例五var person = await repository.LastAsync(u => u.Name == "Furion");// 示例六var person = await repository.LastOrDefaultAsync(u => u.Name == "Furion");// 示例七var person = await repository.Entities.SingleAsync(u => u.Name == "Furion");// 示例八var person = await repository.Entities.FirstAsync(u => u.Name == "Furion");// 示例九var person = await repository.Entities.FirstOrDefaultAsync(u => u.Name == "Furion");// 示例十var person = await repository.Entities.LastAsync(u => u.Name == "Furion");// 示例十一var person = await repository.Entities.LastOrDefaultAsync(u => u.Name == "Furion");

9.10.3 查询所有数据

// ==== 同步操作 ====// 示例一var persons = repository.Entities;// 示例二var persons = repository.DetachedEntities;// 示例三var persons = repository.AsQueryable();// 示例四var persons = repository.AsEnumerable();// 示例五var persons = await repository.AsQueryable().ToListAsync();

9.10.4 根据条件查询所有数据

// 示例一var persons = repository.Where(u => u.Id > 10);// 示例二var persons = repository.Where(u => u.Id > 10 && u.Name.Equals("Furion"));// 示例三  (多个 where 里是 "并且",Id>10 and Name == "Furion")var persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"));// 示例四 (判断 name 是否有值,如果 name 是空的则不会执行 u => u.Id > 10 && u.Name.Equals("Furion"),如果 name 有值就会执行 u => u.Id > 10 && u.Name.Equals("Furion"))var persons = repository.Where(!string.IsNullOrEmpty(name), u => u.Id > 10 && u.Name.Equals("Furion"));// 示例五var persons = repository.Where(!string.IsNullOrEmpty(name), u => u.Id > 10)                        .Where(age > 18, u => u.Name.Contains("百小僧"))                        .Where(u => u.Age > 18);// 示例六 (在一个 where 里用逗号分隔是 "或者",Name=="Furion" or Name == "百小僧" or Name == "MonkSoul")var persons = repository.Where(u => u.Name == "Furion",                                 u => u.Name == "百小僧",                                 u => u.Name == "MonkSoul");// 示例七var persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"))                        .Where(age > 18, u => u.Name.Contains("百小僧"))                        .Where(u => u.Name == "Furion",                                 u => u.Name == "百小僧",                                 u => u.Name == "MonkSoul");// 示例八var persons = repository.Where((age > 18, u => u.Name == "Furion"),                                   (!string.IsNullOrEmpty(name), u => u.Id > 10));// 示例九var persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"))                        .Where(age > 18, u => u.Name.Contains("百小僧"))                        .Where(u => u.Name == "Furion",                                 u => u.Name == "百小僧",                                 u => u.Name == "MonkSoul")                        .Where((age > 18, u => u.Name == "Furion"),                                   (!string.IsNullOrEmpty(name), u => u.Id > 10));// 示例十var persons = repository.Entities.Where(u => u.Id > 10)                                 .Where(age > 18, u => u.Name.Contains("百小僧"));// 示例十一var persons = repository.DetachedEntities.Where(u => u.Id > 20);// 示例十二var persons = repository.AsQueryable(u => u.Id > 20).Where(u => u.Name == "Furion");

9.10.5 分页查询

// ==== 同步操作 ====// 示例一var persons = repository.Where(u => u.Id > 10).ToPagedList();// 示例二var persons = repository.Where(u => u.Id > 10).ToPagedList(1, 10);// ==== 异步操作 ====// 示例一var persons = await repository.Where(u => u.Id > 10).ToPagedListAsync();// 示例二var persons = await repository.Where(u => u.Id > 10).ToPagedListAsync(1, 10);

9.10.6 其他查询

9.10.6.1 查看记录是否存在

// ==== 同步操作 ====// 示例一var isExists = repository.Any();// 示例二var isExists = repository.Any(u => u.Id > 10);// 示例三var isExists = repository.Entities.Any();// 示例四var isExists = repository.DetachedEntities.Any(u => u.Id > 10);// 示例五var isExists = repository.Where(u => u.Id > 10).Any();// ==== 异步操作 ====// 示例一var isExists = await repository.AnyAsync();// 示例二var isExists = await repository.AnyAsync(u => u.Id > 10);// 示例三var isExists = await repository.Entities.AnyAsync();// 示例四var isExists = await repository.DetachedEntities.AnyAsync(u => u.Id > 10);// 示例五var isExists = await repository.Where(u => u.Id > 10).AnyAsync();

9.10.6.2 查询记录数

// ==== 同步操作 ====// 示例一var count = repository.Count();// 示例二var count = repository.Count(u => u.Id > 10);// 示例三var count = repository.Entities.Count(u => u.Id > 10);// 示例四var count = repository.Entities.DetachedEntities.Count();// 示例五var count = repository.Where(u => u.Id > 10).Count();// ==== 异步操作 ====// 示例一var count = await repository.CountAsync();// 示例二var count = await repository.CountAsync(u => u.Id > 10);// 示例三var count = await repository.Entities.CountAsync(u => u.Id > 10);// 示例四var count = await repository.Entities.DetachedEntities.CountAsync();// 示例五var count = await repository.Where(u => u.Id > 10).CountAsync();

9.10.6.3 查询最大值

// ==== 同步操作 ====// 示例一var entity = repository.Max();// 示例二var value = repository.Max(u => u.Id);// 示例三var entity = repository.Entities.Max();// 示例四var value = repository.Entities.DetachedEntities.Max(u => u.Age);// 示例五var value = repository.Where(u => u.Id > 10).Max(u => u.Age);// ==== 异步操作 ====// 示例一var entity = await repository.MaxAsync();// 示例二var value = await repository.MaxAsync(u => u.Id);// 示例三var entity = await repository.Entities.MaxAsync();// 示例四var value = await repository.Entities.DetachedEntities.MaxAsync(u => u.Age);// 示例五var value = await repository.Where(u => u.Id > 10).MaxAsync(u => u.Age);

9.10.6.4 查询最小值

// ==== 同步操作 ====// 示例一var entity = repository.Min();// 示例二var value = repository.Min(u => u.Id);// 示例三var entity = repository.Entities.Min();// 示例四var value = repository.Entities.DetachedEntities.Min(u => u.Age);// 示例五var value = repository.Where(u => u.Id > 10).Min(u => u.Age);// ==== 异步操作 ====// 示例一var entity = await repository.MinAsync();// 示例二var value = await repository.MinAsync(u => u.Id);// 示例三var entity = await repository.Entities.MinAsync();// 示例四var value = await repository.Entities.DetachedEntities.MinAsync(u => u.Age);// 示例五var value = await repository.Where(u => u.Id > 10).MinAsync(u => u.Age);

9.10.6.5 求和查询

// ==== 同步操作 ====// 示例一var sum = repository.Entities.Sum(u => u.Cost);// 示例二var sum = repository.AsQueryable().Sum(u => u.Cost);// 示例三var sum = repository.DetachedEntities.Sum(u => u.Cost);// ==== 异步操作 ====// 示例一var sum = await repository.Entities.SumAsync(u => u.Cost);// 示例二var sum = await repository.AsQueryable().SumAsync(u => u.Cost);// 示例三var sum = await repository.DetachedEntities.SumAsync(u => u.Cost);

9.10.6.6 求平均值查询

// ==== 同步操作 ====// 示例一var sum = repository.Entities.Average(u => u.Cost);// 示例二var sum = repository.AsQueryable().Average(u => u.Cost);// 示例三var sum = repository.DetachedEntities.Average(u => u.Cost);// ==== 异步操作 ====// 示例一var sum = await repository.Entities.AverageAsync(u => u.Cost);// 示例二var sum = await repository.AsQueryable().AverageAsync(u => u.Cost);// 示例三var sum = await repository.DetachedEntities.AverageAsync(u => u.Cost);

9.10.6.7 时间查询

var starDate = DateTime.Parse("2020-09-10");var endDate = DateTime.Parse("2020-09-10");var query = repository.Where(u => u.CreatedDt >= starDate && u.CreatedDt <= endDate);

9.10.6.8 模糊查询

// 示例一repository.Where(u => u.Name.StartsWith("Furion"));// 示例二_testRepository.Where(u => u.Name.EndsWith("Furion"));// 示例三_testRepository.Where(u => u.Name.Contains("Furion"));

9.10.6.9 Case When

数据库中的 Case When 实际上对应的是我们程序中的 三元表达式 ,也就是使用 三元表达式 即可自动生成 Case When 语句。

9.10.7 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.10 查询操作

9.10.1 根据主键查询一条

// ==== 同步操作 ====// 示例一var person = repository.Find(1);// 示例二var person = repository.FindOrDefault(1);// 示例三var person = repository.Entities.Find(1);// ==== 异步操作 ====// 示例一var person = await repository.FindAsync(1);// 示例二var person = await repository.FindOrDefaultAsync(1);// 示例三var person = await repository.Entities.FindAsync(1);
小提示

可以支持多个键查询,如主键、联合键。repository.Find(1, "百小僧");

9.10.2 根据条件查询一条

// ==== 同步操作 ====// 示例一var person = repository.Single(u => u.Name == "Furion");// 示例二var person = repository.SingleOrDefault(u => u.Name == "Furion");// 示例三var person = repository.First(u => u.Name == "Furion");// 示例四var person = repository.FirstOrDefault(u => u.Name == "Furion");// 示例五var person = repository.Last(u => u.Name == "Furion");// 示例六var person = repository.LastOrDefault(u => u.Name == "Furion");// 示例七var person = repository.Entities.Single(u => u.Name == "Furion");// 示例八var person = repository.Entities.First(u => u.Name == "Furion");// 示例九var person = repository.Entities.FirstOrDefault(u => u.Name == "Furion");// 示例十var person = repository.Entities.Last(u => u.Name == "Furion");// 示例十一var person = repository.Entities.LastOrDefault(u => u.Name == "Furion");// ==== 异步操作 ====// 示例一var person = await repository.SingleAsync(u => u.Name == "Furion");// 示例二var person = await repository.SingleOrDefaultAsync(u => u.Name == "Furion");// 示例三var person = await repository.FirstAsync(u => u.Name == "Furion");// 示例四var person = await repository.FirstOrDefaultAsync(u => u.Name == "Furion");// 示例五var person = await repository.LastAsync(u => u.Name == "Furion");// 示例六var person = await repository.LastOrDefaultAsync(u => u.Name == "Furion");// 示例七var person = await repository.Entities.SingleAsync(u => u.Name == "Furion");// 示例八var person = await repository.Entities.FirstAsync(u => u.Name == "Furion");// 示例九var person = await repository.Entities.FirstOrDefaultAsync(u => u.Name == "Furion");// 示例十var person = await repository.Entities.LastAsync(u => u.Name == "Furion");// 示例十一var person = await repository.Entities.LastOrDefaultAsync(u => u.Name == "Furion");

9.10.3 查询所有数据

// ==== 同步操作 ====// 示例一var persons = repository.Entities;// 示例二var persons = repository.DetachedEntities;// 示例三var persons = repository.AsQueryable();// 示例四var persons = repository.AsEnumerable();// 示例五var persons = await repository.AsQueryable().ToListAsync();

9.10.4 根据条件查询所有数据

// 示例一var persons = repository.Where(u => u.Id > 10);// 示例二var persons = repository.Where(u => u.Id > 10 && u.Name.Equals("Furion"));// 示例三  (多个 where 里是 "并且",Id>10 and Name == "Furion")var persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"));// 示例四 (判断 name 是否有值,如果 name 是空的则不会执行 u => u.Id > 10 && u.Name.Equals("Furion"),如果 name 有值就会执行 u => u.Id > 10 && u.Name.Equals("Furion"))var persons = repository.Where(!string.IsNullOrEmpty(name), u => u.Id > 10 && u.Name.Equals("Furion"));// 示例五var persons = repository.Where(!string.IsNullOrEmpty(name), u => u.Id > 10)                        .Where(age > 18, u => u.Name.Contains("百小僧"))                        .Where(u => u.Age > 18);// 示例六 (在一个 where 里用逗号分隔是 "或者",Name=="Furion" or Name == "百小僧" or Name == "MonkSoul")var persons = repository.Where(u => u.Name == "Furion",                                 u => u.Name == "百小僧",                                 u => u.Name == "MonkSoul");// 示例七var persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"))                        .Where(age > 18, u => u.Name.Contains("百小僧"))                        .Where(u => u.Name == "Furion",                                 u => u.Name == "百小僧",                                 u => u.Name == "MonkSoul");// 示例八var persons = repository.Where((age > 18, u => u.Name == "Furion"),                                   (!string.IsNullOrEmpty(name), u => u.Id > 10));// 示例九var persons = repository.Where(u => u.Id > 10).Where(u => u.Name.Equals("Furion"))                        .Where(age > 18, u => u.Name.Contains("百小僧"))                        .Where(u => u.Name == "Furion",                                 u => u.Name == "百小僧",                                 u => u.Name == "MonkSoul")                        .Where((age > 18, u => u.Name == "Furion"),                                   (!string.IsNullOrEmpty(name), u => u.Id > 10));// 示例十var persons = repository.Entities.Where(u => u.Id > 10)                                 .Where(age > 18, u => u.Name.Contains("百小僧"));// 示例十一var persons = repository.DetachedEntities.Where(u => u.Id > 20);// 示例十二var persons = repository.AsQueryable(u => u.Id > 20).Where(u => u.Name == "Furion");

9.10.5 分页查询

// ==== 同步操作 ====// 示例一var persons = repository.Where(u => u.Id > 10).ToPagedList();// 示例二var persons = repository.Where(u => u.Id > 10).ToPagedList(1, 10);// ==== 异步操作 ====// 示例一var persons = await repository.Where(u => u.Id > 10).ToPagedListAsync();// 示例二var persons = await repository.Where(u => u.Id > 10).ToPagedListAsync(1, 10);

9.10.6 其他查询

9.10.6.1 查看记录是否存在

// ==== 同步操作 ====// 示例一var isExists = repository.Any();// 示例二var isExists = repository.Any(u => u.Id > 10);// 示例三var isExists = repository.Entities.Any();// 示例四var isExists = repository.DetachedEntities.Any(u => u.Id > 10);// 示例五var isExists = repository.Where(u => u.Id > 10).Any();// ==== 异步操作 ====// 示例一var isExists = await repository.AnyAsync();// 示例二var isExists = await repository.AnyAsync(u => u.Id > 10);// 示例三var isExists = await repository.Entities.AnyAsync();// 示例四var isExists = await repository.DetachedEntities.AnyAsync(u => u.Id > 10);// 示例五var isExists = await repository.Where(u => u.Id > 10).AnyAsync();

9.10.6.2 查询记录数

// ==== 同步操作 ====// 示例一var count = repository.Count();// 示例二var count = repository.Count(u => u.Id > 10);// 示例三var count = repository.Entities.Count(u => u.Id > 10);// 示例四var count = repository.Entities.DetachedEntities.Count();// 示例五var count = repository.Where(u => u.Id > 10).Count();// ==== 异步操作 ====// 示例一var count = await repository.CountAsync();// 示例二var count = await repository.CountAsync(u => u.Id > 10);// 示例三var count = await repository.Entities.CountAsync(u => u.Id > 10);// 示例四var count = await repository.Entities.DetachedEntities.CountAsync();// 示例五var count = await repository.Where(u => u.Id > 10).CountAsync();

9.10.6.3 查询最大值

// ==== 同步操作 ====// 示例一var entity = repository.Max();// 示例二var value = repository.Max(u => u.Id);// 示例三var entity = repository.Entities.Max();// 示例四var value = repository.Entities.DetachedEntities.Max(u => u.Age);// 示例五var value = repository.Where(u => u.Id > 10).Max(u => u.Age);// ==== 异步操作 ====// 示例一var entity = await repository.MaxAsync();// 示例二var value = await repository.MaxAsync(u => u.Id);// 示例三var entity = await repository.Entities.MaxAsync();// 示例四var value = await repository.Entities.DetachedEntities.MaxAsync(u => u.Age);// 示例五var value = await repository.Where(u => u.Id > 10).MaxAsync(u => u.Age);

9.10.6.4 查询最小值

// ==== 同步操作 ====// 示例一var entity = repository.Min();// 示例二var value = repository.Min(u => u.Id);// 示例三var entity = repository.Entities.Min();// 示例四var value = repository.Entities.DetachedEntities.Min(u => u.Age);// 示例五var value = repository.Where(u => u.Id > 10).Min(u => u.Age);// ==== 异步操作 ====// 示例一var entity = await repository.MinAsync();// 示例二var value = await repository.MinAsync(u => u.Id);// 示例三var entity = await repository.Entities.MinAsync();// 示例四var value = await repository.Entities.DetachedEntities.MinAsync(u => u.Age);// 示例五var value = await repository.Where(u => u.Id > 10).MinAsync(u => u.Age);

9.10.6.5 求和查询

// ==== 同步操作 ====// 示例一var sum = repository.Entities.Sum(u => u.Cost);// 示例二var sum = repository.AsQueryable().Sum(u => u.Cost);// 示例三var sum = repository.DetachedEntities.Sum(u => u.Cost);// ==== 异步操作 ====// 示例一var sum = await repository.Entities.SumAsync(u => u.Cost);// 示例二var sum = await repository.AsQueryable().SumAsync(u => u.Cost);// 示例三var sum = await repository.DetachedEntities.SumAsync(u => u.Cost);

9.10.6.6 求平均值查询

// ==== 同步操作 ====// 示例一var sum = repository.Entities.Average(u => u.Cost);// 示例二var sum = repository.AsQueryable().Average(u => u.Cost);// 示例三var sum = repository.DetachedEntities.Average(u => u.Cost);// ==== 异步操作 ====// 示例一var sum = await repository.Entities.AverageAsync(u => u.Cost);// 示例二var sum = await repository.AsQueryable().AverageAsync(u => u.Cost);// 示例三var sum = await repository.DetachedEntities.AverageAsync(u => u.Cost);

9.10.6.7 时间查询

var starDate = DateTime.Parse("2020-09-10");var endDate = DateTime.Parse("2020-09-10");var query = repository.Where(u => u.CreatedDt >= starDate && u.CreatedDt <= endDate);

9.10.6.8 模糊查询

// 示例一repository.Where(u => u.Name.StartsWith("Furion"));// 示例二_testRepository.Where(u => u.Name.EndsWith("Furion"));// 示例三_testRepository.Where(u => u.Name.Contains("Furion"));

9.10.6.9 Case When

数据库中的 Case When 实际上对应的是我们程序中的 三元表达式 ,也就是使用 三元表达式 即可自动生成 Case When 语句。

9.10.7 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-read-write/index.html b/handbook/build/docs/dbcontext-read-write/index.html index 04fbcedc5c..521dee7c7d 100644 --- a/handbook/build/docs/dbcontext-read-write/index.html +++ b/handbook/build/docs/dbcontext-read-write/index.html @@ -2,23 +2,22 @@ - - - + +9.27 读写分离/主从复制 | Furion -9.27 读写分离/主从复制 | Furion - - + + +
-

9.27 读写分离/主从复制

9.27.1 读写分离

其实就是将数据库分为了主从库,一个主库用于写数据,多个从库完成读数据的操作,主从库之间通过某种机制进行数据的同步,是一种常见的数据库架构。

9.27.1.1 解决了什么问题

大多数互联网业务,往往读多写少,这时候,数据库的读会首先成为数据库的瓶颈,这时,如果我们希望能够线性的提升数据库的读性能,消除读写锁冲突从而提升数据库的写性能,那么就可以使用“分组架构”(读写分离架构)。

用一句话概括,读写分离是用来解决数据库的读性能瓶颈的。

9.27.1.2 注意事项

  • 数据库连接池要进行区分,哪些是读连接池,哪个是写连接池,研发的难度会增加;
  • 为了保证高可用,读连接池要能够实现故障自动转移;
  • 主从的一致性问题需要考虑。

9.27.2 如何实现

Furion 在数据库模块设计之初,就考虑了读写分离这种情况,所以从底层就支持动态切换数据库上下文及读写操作方法约束。

读写分离操作主要使用 IMSRepository 仓储,该仓储已经为开发者提供方便的操作调用。当然也可以不使用该仓储。

下面就给大家演示如何读写多库读写操作。

9.27.2.1 创建 主库 数据库上下文

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    /// <summary>    /// 主库数据库上下文    /// </summary>    [AppDbContext("MasterConnectionString")]    public class MasterDbContext : AppDbContext<MasterDbContext>    {        public MasterDbContext(DbContextOptions<MasterDbContext> options) : base(options)        {        }    }}

数据库连接字符串:

{  "ConnectionStrings": {    "MasterConnectionString": "Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;"  }}

9.27.2.2 创建 从库 数据库上下文

using Furion.Core;using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    /// <summary>    /// 从库数据库上下文    /// </summary>    [AppDbContext("SlaveConnectionString")]    public class SlaveDbContext : AppDbContext<SlaveDbContext, SlaveDbContextLocator>    {        public SlaveDbContext(DbContextOptions<SlaveDbContext> options) : base(options)        {        }    }}
特别注意

多数据库操作除了默认数据库无需自定义 数据库上下文定位器,其他数据库都需要有数据库上下文定位器。如 SlaveDbContextLocator

从库数据库上下文定位器:

using Furion.DatabaseAccessor;namespace Furion.Core{    /// <summary>    /// 从库数据库上下文定位器    /// </summary>    public class SlaveDbContextLocator : IDbContextLocator    {    }}

数据库连接字符串:

{  "ConnectionStrings": {    "SlaveConnectionString": "Server=localhost;Database=FurSlave;User=sa;Password=000000;MultipleActiveResultSets=True;"  }}

9.27.2.3 注册 主从库 数据库上下文

using Furion.Core;using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(600)]    public sealed class FurEntityFrameworkCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddDatabaseAccessor(options =>            {                services.AddDbPool<MasterDbContext>();                services.AddDbPool<SlaveDbContext, SlaveDbContextLocator>();            });        }    }}

9.27.2.4 创建 Person 实体

由于 主从库 具有相同的数据库结构,所以实体也必须声明 主从库

using Furion.DatabaseAccessor;using System.ComponentModel.DataAnnotations;using System.ComponentModel.DataAnnotations.Schema;namespace Furion.Core{    public class Person : IEntity<MasterDbContextLocator, SlaveDbContextLocator>    {        /// <summary>        /// 主键Id        /// </summary>        [Key]        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]        public int Id { get; set; }        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }        /// <summary>        /// 年龄        /// </summary>        public int Age { get; set; }    }}

9.27.2.5 将 Person 转换成数据库表

创建主库数据库表:

Add-Migration v0.0.1 -Context MasterDbContext
Update-Database -Context MasterDbContext

创建从库数据库表:

Add-Migration v0.0.1 -Context SlaveDbContext
Update-Database -Context SlaveDbContext

9.27.2.6 固定主从库使用例子

using Furion.Core;using Furion.DatabaseAccessor;using Furion.DynamicApiController;using System.Collections.Generic;namespace Furion.Application{    public class PersonService : IDynamicApiController    {        /// <summary>        /// 可调配仓储(读写分离)        /// </summary>        private readonly IMSRepository<MasterDbContextLocator, SlaveDbContextLocator> _msRepository;        /// <summary>        /// 构造函数初始化        /// </summary>        /// <param name="msRepository"></param>        public PersonService(IMSRepository<MasterDbContextLocator, SlaveDbContextLocator> msRepository)        {            _msRepository = msRepository;        }        /// <summary>        /// 新增走主库        /// </summary>        /// <param name="person"></param>        /// <returns></returns>        public void Insert(Person person)        {            _msRepository.Master<Person>().Insert(person);        }        /// <summary>        /// 查询走从库        /// </summary>        /// <returns></returns>        public List<Person> Get()        {            return _msRepository.Slave1<Person>().AsEnumerable().ToList();        }    }}

9.27.2.7 随机自定义返回从库 ✨

Furion 2.4.1 + 版本新增了 IMSRepositoryIMSRepository<TMasterDbContextLocator> 仓储类型,可以获取随机仓储或自定义仓储。使用例子如下:

  • 配置 主库 [AppDbContext] 特性的 SlaveDbContextLocators 属性,可通过构造函数最后参数传入,如:
using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite, typeof(从库定位器1), typeof(从库定位器2), typeof(从库定位器3))]    public class MasterDbContext : AppDbContext<MasterDbContext>    {        public MasterDbContext(DbContextOptions<MasterDbContext> options) : base(options)        {        }    }}
  • 使用 IMSRepositoryIMSRepository<TMasterDbContextLocator>
using Furion.Core;using Furion.DatabaseAccessor;using Furion.DynamicApiController;using System.Collections.Generic;namespace Furion.Application{    public class PersonService : IDynamicApiController    {        /// <summary>        /// 可调配仓储(读写分离)        /// </summary>        private readonly IMSRepository _msRepository;   // 不指定定位器,默认是 MasterDbContextLocator        /// <summary>        /// 构造函数初始化        /// </summary>        /// <param name="msRepository"></param>        public PersonService(IMSRepository msRepository)        {            _msRepository = msRepository;        }        /// <summary>        /// 新增走主库        /// </summary>        /// <param name="person"></param>        /// <returns></returns>        public void Insert(Person person)        {            _msRepository.Master<Person>().Insert(person);        }        /// <summary>        /// 随机从库        /// </summary>        /// <returns></returns>        public List<Person> Get()        {            return _msRepository.Slave<Person>().AsEnumerable().ToList();        }        /// <summary>        /// 自定义从库        /// </summary>        /// <returns></returns>        public List<Person> Get()        {            return _msRepository.Slave<Person>(() => {                // 这里写你的逻辑返回从库定位器                return 你的从库定位器;            }).AsEnumerable().ToList();        }    }}
特别说明

IMSRepository 不带泛型默认指的是 IMSRepository<TMasterDbContextLocator>,如需泛型版本,则使用 IMSRepository<定位器>

9.27.3 主从复制

主从复制:是一种数据备份的方案。

简单来说,是使用两个或两个以上相同的数据库,将一个数据库当做主数据库,而另一个数据库当做从数据库。在主数据库中进行相应操作时,从数据库记录下所有主数据库的操作,使其二者一模一样。

9.27.4 主从复制几种方式

9.27.4.1 同步复制

所谓的同步复制,意思是 Master 的变化,必须等待 Slave-1,Slave-2,...,Slave-n 完成后才能返回。 +

9.27 读写分离/主从复制

9.27.1 读写分离

其实就是将数据库分为了主从库,一个主库用于写数据,多个从库完成读数据的操作,主从库之间通过某种机制进行数据的同步,是一种常见的数据库架构。

9.27.1.1 解决了什么问题

大多数互联网业务,往往读多写少,这时候,数据库的读会首先成为数据库的瓶颈,这时,如果我们希望能够线性的提升数据库的读性能,消除读写锁冲突从而提升数据库的写性能,那么就可以使用“分组架构”(读写分离架构)。

用一句话概括,读写分离是用来解决数据库的读性能瓶颈的。

9.27.1.2 注意事项

  • 数据库连接池要进行区分,哪些是读连接池,哪个是写连接池,研发的难度会增加;
  • 为了保证高可用,读连接池要能够实现故障自动转移;
  • 主从的一致性问题需要考虑。

9.27.2 如何实现

Furion 在数据库模块设计之初,就考虑了读写分离这种情况,所以从底层就支持动态切换数据库上下文及读写操作方法约束。

读写分离操作主要使用 IMSRepository 仓储,该仓储已经为开发者提供方便的操作调用。当然也可以不使用该仓储。

下面就给大家演示如何读写多库读写操作。

9.27.2.1 创建 主库 数据库上下文

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    /// <summary>    /// 主库数据库上下文    /// </summary>    [AppDbContext("MasterConnectionString")]    public class MasterDbContext : AppDbContext<MasterDbContext>    {        public MasterDbContext(DbContextOptions<MasterDbContext> options) : base(options)        {        }    }}

数据库连接字符串:

{  "ConnectionStrings": {    "MasterConnectionString": "Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;"  }}

9.27.2.2 创建 从库 数据库上下文

using Furion.Core;using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    /// <summary>    /// 从库数据库上下文    /// </summary>    [AppDbContext("SlaveConnectionString")]    public class SlaveDbContext : AppDbContext<SlaveDbContext, SlaveDbContextLocator>    {        public SlaveDbContext(DbContextOptions<SlaveDbContext> options) : base(options)        {        }    }}
特别注意

多数据库操作除了默认数据库无需自定义 数据库上下文定位器,其他数据库都需要有数据库上下文定位器。如 SlaveDbContextLocator

从库数据库上下文定位器:

using Furion.DatabaseAccessor;namespace Furion.Core{    /// <summary>    /// 从库数据库上下文定位器    /// </summary>    public class SlaveDbContextLocator : IDbContextLocator    {    }}

数据库连接字符串:

{  "ConnectionStrings": {    "SlaveConnectionString": "Server=localhost;Database=FurSlave;User=sa;Password=000000;MultipleActiveResultSets=True;"  }}

9.27.2.3 注册 主从库 数据库上下文

using Furion.Core;using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(600)]    public sealed class FurEntityFrameworkCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddDatabaseAccessor(options =>            {                services.AddDbPool<MasterDbContext>();                services.AddDbPool<SlaveDbContext, SlaveDbContextLocator>();            });        }    }}

9.27.2.4 创建 Person 实体

由于 主从库 具有相同的数据库结构,所以实体也必须声明 主从库

using Furion.DatabaseAccessor;using System.ComponentModel.DataAnnotations;using System.ComponentModel.DataAnnotations.Schema;namespace Furion.Core{    public class Person : IEntity<MasterDbContextLocator, SlaveDbContextLocator>    {        /// <summary>        /// 主键Id        /// </summary>        [Key]        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]        public int Id { get; set; }        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }        /// <summary>        /// 年龄        /// </summary>        public int Age { get; set; }    }}

9.27.2.5 将 Person 转换成数据库表

创建主库数据库表:

Add-Migration v0.0.1 -Context MasterDbContext
Update-Database -Context MasterDbContext

创建从库数据库表:

Add-Migration v0.0.1 -Context SlaveDbContext
Update-Database -Context SlaveDbContext

9.27.2.6 固定主从库使用例子

using Furion.Core;using Furion.DatabaseAccessor;using Furion.DynamicApiController;using System.Collections.Generic;namespace Furion.Application{    public class PersonService : IDynamicApiController    {        /// <summary>        /// 可调配仓储(读写分离)        /// </summary>        private readonly IMSRepository<MasterDbContextLocator, SlaveDbContextLocator> _msRepository;        /// <summary>        /// 构造函数初始化        /// </summary>        /// <param name="msRepository"></param>        public PersonService(IMSRepository<MasterDbContextLocator, SlaveDbContextLocator> msRepository)        {            _msRepository = msRepository;        }        /// <summary>        /// 新增走主库        /// </summary>        /// <param name="person"></param>        /// <returns></returns>        public void Insert(Person person)        {            _msRepository.Master<Person>().Insert(person);        }        /// <summary>        /// 查询走从库        /// </summary>        /// <returns></returns>        public List<Person> Get()        {            return _msRepository.Slave1<Person>().AsEnumerable().ToList();        }    }}

9.27.2.7 随机自定义返回从库 ✨

Furion 2.4.1 + 版本新增了 IMSRepositoryIMSRepository<TMasterDbContextLocator> 仓储类型,可以获取随机仓储或自定义仓储。使用例子如下:

  • 配置 主库 [AppDbContext] 特性的 SlaveDbContextLocators 属性,可通过构造函数最后参数传入,如:
using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite, typeof(从库定位器1), typeof(从库定位器2), typeof(从库定位器3))]    public class MasterDbContext : AppDbContext<MasterDbContext>    {        public MasterDbContext(DbContextOptions<MasterDbContext> options) : base(options)        {        }    }}
  • 使用 IMSRepositoryIMSRepository<TMasterDbContextLocator>
using Furion.Core;using Furion.DatabaseAccessor;using Furion.DynamicApiController;using System.Collections.Generic;namespace Furion.Application{    public class PersonService : IDynamicApiController    {        /// <summary>        /// 可调配仓储(读写分离)        /// </summary>        private readonly IMSRepository _msRepository;   // 不指定定位器,默认是 MasterDbContextLocator        /// <summary>        /// 构造函数初始化        /// </summary>        /// <param name="msRepository"></param>        public PersonService(IMSRepository msRepository)        {            _msRepository = msRepository;        }        /// <summary>        /// 新增走主库        /// </summary>        /// <param name="person"></param>        /// <returns></returns>        public void Insert(Person person)        {            _msRepository.Master<Person>().Insert(person);        }        /// <summary>        /// 随机从库        /// </summary>        /// <returns></returns>        public List<Person> Get()        {            return _msRepository.Slave<Person>().AsEnumerable().ToList();        }        /// <summary>        /// 自定义从库        /// </summary>        /// <returns></returns>        public List<Person> Get()        {            return _msRepository.Slave<Person>(() => {                // 这里写你的逻辑返回从库定位器                return 你的从库定位器;            }).AsEnumerable().ToList();        }    }}
特别说明

IMSRepository 不带泛型默认指的是 IMSRepository<TMasterDbContextLocator>,如需泛型版本,则使用 IMSRepository<定位器>

9.27.3 主从复制

主从复制:是一种数据备份的方案。

简单来说,是使用两个或两个以上相同的数据库,将一个数据库当做主数据库,而另一个数据库当做从数据库。在主数据库中进行相应操作时,从数据库记录下所有主数据库的操作,使其二者一模一样。

9.27.4 主从复制几种方式

9.27.4.1 同步复制

所谓的同步复制,意思是 Master 的变化,必须等待 Slave-1,Slave-2,...,Slave-n 完成后才能返回。 这样,显然不可取,比如,在 Web 前端页面上,用户增加了条记录,需要等待很长时间。

9.27.4.2 异步复制

如同 AJAX 请求一样。Master 只需要完成自己的数据库操作即可。至于 Slaves 是否收到二进制日志,是否完成操作,不用关心。(推荐方式)

9.27.4.3 半同步复制

Master 只保证 Slaves 中的一个操作成功,就返回,其他 Slave 不管。

下面将使用 SqlServer 简单配置主从复制功能。

9.27.5 SqlServer 主库配置

9.27.5.1 添加 本地发布

9.27.5.2 选择 分发服务器

9.27.5.3 启用 代理

9.27.5.4 发布数据库

9.27.5.5 快照发布

具体选择何种发布类型,视具体业务场景而定。

9.27.5.6 选择发布项目

9.27.5.7 配置分发计划

9.27.5.8 配置安全设置

9.27.5.9 完成配置

9.27.6 SqlServer 从库配置

9.27.6.1 添加 本地订阅

9.27.6.2 选择 分发服务器

9.27.6.3 选择 分发代理位置

9.27.6.4 选择 订阅数据库

9.27.6.5 选择 分发安全设置

9.27.6.6 选择 同步计划

9.27.6.7 完成订阅

9.27.7 分发定义监视

9.27.8 查看主从复制结果

特别特性

主从复制有一定迟延性,所以系统设计要有一定“容忍性"。

9.27.9 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - + + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-repository/index.html b/handbook/build/docs/dbcontext-repository/index.html index 4f8181519d..845c8cae73 100644 --- a/handbook/build/docs/dbcontext-repository/index.html +++ b/handbook/build/docs/dbcontext-repository/index.html @@ -2,22 +2,21 @@ - - - + +9.4 仓储模式 | Furion -9.4 仓储模式 | Furion - - + + +
-

9.4 仓储模式

9.4.1 什么是仓储

在领域层和数据映射层的中介,使用类似集合的接口来存取领域对象,实际上,仓储被用于领域对象在数据库上的操作(实体 Entity 和值对象 Value types)。一般来说,我们针对不同的实体(或聚合根 Aggregate Root)会创建相对应的仓储。

简单来说,仓储就是数据存取操作的载体,但不限定于数据库。

9.4.2 内置仓储

Furion 框架内置了一个数据库操作的仓储,方便大家拓展和集成:

关于依赖注入说明

目前能够被依赖注入解析服务的仓储有:

  • IRepository
  • IRepository<TEntity>
  • IRepository<TEntity, TDbContextLocator>
  • ISqlRepository
  • ISqlRepository<TDbContextLocator>
  • IMSRepository
  • IMSRepository<TMasterDbContextLocator>
  • IMSRepository<TMasterDbContextLocator,...TSlaveDbContextLocator8>
  • IDbRepository<TDbContextLocator>

还有两个私有仓储,也是所有仓储的基类(用于高级自定义开发)

  • IPrivateRepository<TEntity>:所有实体仓储的基类
  • IPrivateSqlRepository:所有数据库操作的基类

除此之后的所有仓储只能通过 rep.Constraint<TRepository>() 进行约束创建,如,只读仓储:

var readRepository = rep.Constraint<IReadableRepository<TEntity>>();

9.4.2.1 非泛型超级仓储

  • IRepository:默认非泛型仓储接口,支持切换到任何仓储
  • EFCoreRepository:默认非泛型仓储实现

9.4.2.2 泛型实体仓储

  • IRepository<TEntity>:默认数据库实体仓储接口
  • EFCoreRepository<TEntity>:默认数据库实体仓储实现

9.4.2.3 泛型多数据库实体仓储

  • IRepository<TEntity, TDbContextLocator>:任意数据库的实体仓储接口
  • EFCoreRepository<TEntity, TDbContextLocator>:任意数据库的实体仓储实现

9.4.2.4 Sql 操作仓储

  • ISqlRepository:默认数据库 Sql 操作仓储接口
  • SqlRepository:默认数据库 Sql 操作仓储实现

9.4.2.5 多数据库 Sql 操作仓储

  • ISqlRepository<TDbContextLocator>:任意数据库的 Sql 操作仓储接口
  • SqlRepository<TDbContextLocator>:任意数据库的 Sql 操作仓储实现

9.4.2.6 只读实体仓储(支持多库)

  • IReadableRepository<TEntity>:默认数据库只读实体仓储接口
  • IReadableRepository<TEntity, TDbContextLocator>:多数据库只读实体仓储实现

9.4.2.7 只写实体仓储(支持多库)

  • IWritableRepository<TEntity>:默认数据库只写实体仓储接口
  • IWritableRepository<TEntity, TDbContextLocator>:多数据库只写实体仓储实现

9.4.2.8 只允许新增实体仓储(支持多库)

  • IInsertableRepository<TEntity>:默认数据库只允许新增的实体仓储接口
  • IInsertableRepository<TEntity, TDbContextLocator>:多数据库只允许新增的实体仓储实现

9.4.2.9 只允许更新实体仓储(支持多库)

  • IUpdateableRepository<TEntity>:默认数据库只允许更新的实体仓储接口
  • IUpdateableRepository<TEntity, TDbContextLocator>:多数据库只允许更新的实体仓储实现

9.4.2.10 只允许删除实体仓储(支持多库)

  • IDeletableRepository<TEntity>:默认数据库只允许删除的实体仓储接口
  • IDeletableRepository<TEntity, TDbContextLocator>:多数据库只允许删除的实体仓储实现

9.4.2.11 只允许拓展操作实体仓储(支持多库)

功能移除声明

该功能在 Furion 2.5.1 + 版本中已移除。此操作让很多不了解 EFCore 的开发者产生了很大的误解,不知何时新增或何时更新,故移除此功能。

  • IOperableRepository<TEntity>:默认数据库只允许拓展操作实体仓储接口
  • IOperableRepository<TEntity, TDbContextLocator>:多数据库只允许拓展操作实体仓储实现

9.4.2.12 只允许 Sql 查询仓储(支持多库)

  • ISqlReaderRepository:默认数据库只允许 Sql 查询仓储接口
  • ISqlReaderRepository<TDbContextLocator>:多数据库只允许 Sql 查询仓储实现

9.4.2.13 只允许 Sql 非查询仓储(支持多库)

  • ISqlExecutableRepository:默认数据库只允许 Sql 非查询仓储接口
  • ISqlExecutableRepository<TDbContextLocator>:多数据库只允许 Sql 非查询仓储实现

9.4.2.14 读写分离仓储

  • IMSRepository:最多支持 一主 7 从 仓储

9.4.2.15 定位器仓储

  • IDbRepository<TDbContextLocator>:初始化特定数据库仓储

9.4.3 仓储使用

Furion 提供了非常多的方式创建仓储,目的是为了让大家可以在不同的场景中使用。

9.4.3.1 构造函数注入

private readonly IRepository<Person> _personRepository;public FurionService(IRepository<Person> personRepository){    _personRepository = personRepository;}

9.4.3.2 方法参数注入

public async Task<List<PersonDto>> GetAll([FromServices] IRepository<Person> repository, string keyword){    var persons = await repository.AsQueryable().ToListAsync();    return persons.Adapt<List<PersonDto>>();}

9.4.3.3 Db.GetRepository 获取

// 非泛型仓储var repository = Db.GetRepository();// 泛型仓储var repository = Db.GetRepository<Person>();// Sql 仓储var sqlRepository = Db.GetSqlRepository();
特别说明

不管采用哪种方式,Furion 都保证了仓储一次请求唯一性。同时 Db.GetRepository<TEntity>() 方式支持任何静态类中使用。

9.4.4 仓储高级用法

9.4.4.1 动态切换实体仓储

var userRepository = personRepository.Change<User>();

9.4.4.2 动态切换仓储类型

比如,读写分离/主从库仓储:

// 只读仓储var readRepository = personRepository.Constraint<IReadableRepository<User>>();// 只写仓储var writeRepository = personRepository.Constraint<IWritableRepository<User>>();
小知识

.Constraint 支持切换任何仓储类型。

9.4.4.3 获取 Sql 操作仓储

var sqlRepository = repository.Sql();

9.4.5 多数据库操作

Furion 通过 DbContextLocator 数据库上下文定位器实现多种数据库操作,可以随意切换数据库

9.4.5.1 动态切换多个数据库

动态切换数据库

// 切换到 MSSQL 操作 Person表var mssqlRepository = repository.Change<Person, MsSqlDbContextLocator>();// 切换到 MySql 操作 Person表var mysqlRepository = repository.Change<Person, MySqlDbContextLocator>();// 切换到 Sqlite 操作 Person表var sqliteRepository = repository.Change<Person, SqliteDbContextLocator>();// 其他更多数据库一样的操作

另外任何仓储或实体配置都支持多个数据库同时操作

仓储方式

IRepository<Person, MsSqlDbContextLocator> mssqlRepositoryISqlRepository<MsSqlDbContextLocator> mssqlRepository;

动态 sql 方式

"select * from person".Change<MsSqlDbContextLocator>().SqlQuery();

实体配置方式

public class User:Entity<int, MsSqlDbContextLocator, MySqlDbContextLocator>{}

Sql 代理方式

[SqlFunction("funcName", DbContextLocator = typeof(MySqlDbContextLocator))]int GetAge(int id);

Linq 中方式

[QueryableFunction("funcName","dbo", DbContextLocator = typeof(MySqlDbContextLocator))]string GetName()=> throw Oops.Oh("不支持该数据库操作");

9.4.6 在后台任务中使用

由于 DbContext 默认注册为 Scoped 生存周期,所以在后台任务中使用 IServiceScopeFactory 获取所有服务,如:

public class JobService : BackgroundService{    // 日志对象    private readonly ILogger<JobService> _logger;    // 服务工厂    private readonly IServiceScopeFactory _scopeFactory;    public JobService(ILogger<JobService> logger        , IServiceScopeFactory scopeFactory)    {        _logger = logger;        _scopeFactory = scopeFactory;    }    protected override Task ExecuteAsync(CancellationToken stoppingToken)    {        _logger.LogInformation("写日志~~");        using (var scope = _scopeFactory.CreateScope())        {            var services = scope.ServiceProvider;            // 获取数据库上下文            var dbContext = Db.GetDbContext(services);            // 获取仓储            var respository = Db.GetRepository<Person>(services);            // 解析其他服务            var otherService = services.GetService<XXX>();        }        return Task.CompletedTask;    }}
数据库操作注意

如果作用域中对数据库有任何变更操作,需手动调用 SaveChanges 或带 Now 结尾的方法。也可以使用 Scoped.CreateUow(handler) 代替。

9.4.7 自定义仓储

有些时候我们需要自定义仓储,拓展现有的仓储功能,可参考以下代码(含定位器仓储和默认仓储实现)

/// <summary>/// 自定义仓储接口/// </summary>/// <typeparam name="TEntity"></typeparam>/// <typeparam name="TDbContextLocator"></typeparam>public interface IMyRepository<TEntity, TDbContextLocator> : IPrivateRepository<TEntity>    where TEntity : class, IPrivateEntity, new()    where TDbContextLocator : class, IDbContextLocator{    /// <summary>    /// 自定义方法    /// </summary>    void MyMethod();}/// <summary>/// 自定义仓储实现类/// </summary>/// <typeparam name="TEntity"></typeparam>/// <typeparam name="TDbContextLocator"></typeparam>public class MyRepository<TEntity, TDbContextLocator> : PrivateRepository<TEntity>, IMyRepository<TEntity, TDbContextLocator>, IScoped    where TEntity : class, IPrivateEntity, new()    where TDbContextLocator : class, IDbContextLocator{    /// <summary>    /// 实现基类构造函数    /// </summary>    /// <param name="serviceProvider"></param>    public MyRepository(IServiceProvider serviceProvider)        : base(typeof(TDbContextLocator), serviceProvider)    {    }    /// <summary>    /// 自定义方法    /// </summary>    public void MyMethod()    {        throw new System.NotImplementedException();    }}/// <summary>/// 默认数据库自定义仓储接口/// </summary>/// <typeparam name="TEntity"></typeparam>public interface IMyRepository<TEntity> : IMyRepository<TEntity, MasterDbContextLocator>    where TEntity : class, IPrivateEntity, new(){}/// <summary>/// 默认数据库自定义仓储实现/// </summary>/// <typeparam name="TEntity"></typeparam>public class MyRepository<TEntity> : MyRepository<TEntity, MasterDbContextLocator>, IMyRepository<TEntity>, IScoped    where TEntity : class, IPrivateEntity, new(){    public MyRepository(IServiceProvider serviceProvider) : base(serviceProvider)    {    }}

9.4.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.4 仓储模式

9.4.1 什么是仓储

在领域层和数据映射层的中介,使用类似集合的接口来存取领域对象,实际上,仓储被用于领域对象在数据库上的操作(实体 Entity 和值对象 Value types)。一般来说,我们针对不同的实体(或聚合根 Aggregate Root)会创建相对应的仓储。

简单来说,仓储就是数据存取操作的载体,但不限定于数据库。

9.4.2 内置仓储

Furion 框架内置了一个数据库操作的仓储,方便大家拓展和集成:

关于依赖注入说明

目前能够被依赖注入解析服务的仓储有:

  • IRepository
  • IRepository<TEntity>
  • IRepository<TEntity, TDbContextLocator>
  • ISqlRepository
  • ISqlRepository<TDbContextLocator>
  • IMSRepository
  • IMSRepository<TMasterDbContextLocator>
  • IMSRepository<TMasterDbContextLocator,...TSlaveDbContextLocator8>
  • IDbRepository<TDbContextLocator>

还有两个私有仓储,也是所有仓储的基类(用于高级自定义开发)

  • IPrivateRepository<TEntity>:所有实体仓储的基类
  • IPrivateSqlRepository:所有数据库操作的基类

除此之后的所有仓储只能通过 rep.Constraint<TRepository>() 进行约束创建,如,只读仓储:

var readRepository = rep.Constraint<IReadableRepository<TEntity>>();

9.4.2.1 非泛型超级仓储

  • IRepository:默认非泛型仓储接口,支持切换到任何仓储
  • EFCoreRepository:默认非泛型仓储实现

9.4.2.2 泛型实体仓储

  • IRepository<TEntity>:默认数据库实体仓储接口
  • EFCoreRepository<TEntity>:默认数据库实体仓储实现

9.4.2.3 泛型多数据库实体仓储

  • IRepository<TEntity, TDbContextLocator>:任意数据库的实体仓储接口
  • EFCoreRepository<TEntity, TDbContextLocator>:任意数据库的实体仓储实现

9.4.2.4 Sql 操作仓储

  • ISqlRepository:默认数据库 Sql 操作仓储接口
  • SqlRepository:默认数据库 Sql 操作仓储实现

9.4.2.5 多数据库 Sql 操作仓储

  • ISqlRepository<TDbContextLocator>:任意数据库的 Sql 操作仓储接口
  • SqlRepository<TDbContextLocator>:任意数据库的 Sql 操作仓储实现

9.4.2.6 只读实体仓储(支持多库)

  • IReadableRepository<TEntity>:默认数据库只读实体仓储接口
  • IReadableRepository<TEntity, TDbContextLocator>:多数据库只读实体仓储实现

9.4.2.7 只写实体仓储(支持多库)

  • IWritableRepository<TEntity>:默认数据库只写实体仓储接口
  • IWritableRepository<TEntity, TDbContextLocator>:多数据库只写实体仓储实现

9.4.2.8 只允许新增实体仓储(支持多库)

  • IInsertableRepository<TEntity>:默认数据库只允许新增的实体仓储接口
  • IInsertableRepository<TEntity, TDbContextLocator>:多数据库只允许新增的实体仓储实现

9.4.2.9 只允许更新实体仓储(支持多库)

  • IUpdateableRepository<TEntity>:默认数据库只允许更新的实体仓储接口
  • IUpdateableRepository<TEntity, TDbContextLocator>:多数据库只允许更新的实体仓储实现

9.4.2.10 只允许删除实体仓储(支持多库)

  • IDeletableRepository<TEntity>:默认数据库只允许删除的实体仓储接口
  • IDeletableRepository<TEntity, TDbContextLocator>:多数据库只允许删除的实体仓储实现

9.4.2.11 只允许拓展操作实体仓储(支持多库)

功能移除声明

该功能在 Furion 2.5.1 + 版本中已移除。此操作让很多不了解 EFCore 的开发者产生了很大的误解,不知何时新增或何时更新,故移除此功能。

  • IOperableRepository<TEntity>:默认数据库只允许拓展操作实体仓储接口
  • IOperableRepository<TEntity, TDbContextLocator>:多数据库只允许拓展操作实体仓储实现

9.4.2.12 只允许 Sql 查询仓储(支持多库)

  • ISqlReaderRepository:默认数据库只允许 Sql 查询仓储接口
  • ISqlReaderRepository<TDbContextLocator>:多数据库只允许 Sql 查询仓储实现

9.4.2.13 只允许 Sql 非查询仓储(支持多库)

  • ISqlExecutableRepository:默认数据库只允许 Sql 非查询仓储接口
  • ISqlExecutableRepository<TDbContextLocator>:多数据库只允许 Sql 非查询仓储实现

9.4.2.14 读写分离仓储

  • IMSRepository:最多支持 一主 7 从 仓储

9.4.2.15 定位器仓储

  • IDbRepository<TDbContextLocator>:初始化特定数据库仓储

9.4.3 仓储使用

Furion 提供了非常多的方式创建仓储,目的是为了让大家可以在不同的场景中使用。

9.4.3.1 构造函数注入

private readonly IRepository<Person> _personRepository;public FurionService(IRepository<Person> personRepository){    _personRepository = personRepository;}

9.4.3.2 方法参数注入

public async Task<List<PersonDto>> GetAll([FromServices] IRepository<Person> repository, string keyword){    var persons = await repository.AsQueryable().ToListAsync();    return persons.Adapt<List<PersonDto>>();}

9.4.3.3 Db.GetRepository 获取

// 非泛型仓储var repository = Db.GetRepository();// 泛型仓储var repository = Db.GetRepository<Person>();// Sql 仓储var sqlRepository = Db.GetSqlRepository();
特别说明

不管采用哪种方式,Furion 都保证了仓储一次请求唯一性。同时 Db.GetRepository<TEntity>() 方式支持任何静态类中使用。

9.4.4 仓储高级用法

9.4.4.1 动态切换实体仓储

var userRepository = personRepository.Change<User>();

9.4.4.2 动态切换仓储类型

比如,读写分离/主从库仓储:

// 只读仓储var readRepository = personRepository.Constraint<IReadableRepository<User>>();// 只写仓储var writeRepository = personRepository.Constraint<IWritableRepository<User>>();
小知识

.Constraint 支持切换任何仓储类型。

9.4.4.3 获取 Sql 操作仓储

var sqlRepository = repository.Sql();

9.4.5 多数据库操作

Furion 通过 DbContextLocator 数据库上下文定位器实现多种数据库操作,可以随意切换数据库

9.4.5.1 动态切换多个数据库

动态切换数据库

// 切换到 MSSQL 操作 Person表var mssqlRepository = repository.Change<Person, MsSqlDbContextLocator>();// 切换到 MySql 操作 Person表var mysqlRepository = repository.Change<Person, MySqlDbContextLocator>();// 切换到 Sqlite 操作 Person表var sqliteRepository = repository.Change<Person, SqliteDbContextLocator>();// 其他更多数据库一样的操作

另外任何仓储或实体配置都支持多个数据库同时操作

仓储方式

IRepository<Person, MsSqlDbContextLocator> mssqlRepositoryISqlRepository<MsSqlDbContextLocator> mssqlRepository;

动态 sql 方式

"select * from person".Change<MsSqlDbContextLocator>().SqlQuery();

实体配置方式

public class User:Entity<int, MsSqlDbContextLocator, MySqlDbContextLocator>{}

Sql 代理方式

[SqlFunction("funcName", DbContextLocator = typeof(MySqlDbContextLocator))]int GetAge(int id);

Linq 中方式

[QueryableFunction("funcName","dbo", DbContextLocator = typeof(MySqlDbContextLocator))]string GetName()=> throw Oops.Oh("不支持该数据库操作");

9.4.6 在后台任务中使用

由于 DbContext 默认注册为 Scoped 生存周期,所以在后台任务中使用 IServiceScopeFactory 获取所有服务,如:

public class JobService : BackgroundService{    // 日志对象    private readonly ILogger<JobService> _logger;    // 服务工厂    private readonly IServiceScopeFactory _scopeFactory;    public JobService(ILogger<JobService> logger        , IServiceScopeFactory scopeFactory)    {        _logger = logger;        _scopeFactory = scopeFactory;    }    protected override Task ExecuteAsync(CancellationToken stoppingToken)    {        _logger.LogInformation("写日志~~");        using (var scope = _scopeFactory.CreateScope())        {            var services = scope.ServiceProvider;            // 获取数据库上下文            var dbContext = Db.GetDbContext(services);            // 获取仓储            var respository = Db.GetRepository<Person>(services);            // 解析其他服务            var otherService = services.GetService<XXX>();        }        return Task.CompletedTask;    }}
数据库操作注意

如果作用域中对数据库有任何变更操作,需手动调用 SaveChanges 或带 Now 结尾的方法。也可以使用 Scoped.CreateUow(handler) 代替。

9.4.7 自定义仓储

有些时候我们需要自定义仓储,拓展现有的仓储功能,可参考以下代码(含定位器仓储和默认仓储实现)

/// <summary>/// 自定义仓储接口/// </summary>/// <typeparam name="TEntity"></typeparam>/// <typeparam name="TDbContextLocator"></typeparam>public interface IMyRepository<TEntity, TDbContextLocator> : IPrivateRepository<TEntity>    where TEntity : class, IPrivateEntity, new()    where TDbContextLocator : class, IDbContextLocator{    /// <summary>    /// 自定义方法    /// </summary>    void MyMethod();}/// <summary>/// 自定义仓储实现类/// </summary>/// <typeparam name="TEntity"></typeparam>/// <typeparam name="TDbContextLocator"></typeparam>public class MyRepository<TEntity, TDbContextLocator> : PrivateRepository<TEntity>, IMyRepository<TEntity, TDbContextLocator>, IScoped    where TEntity : class, IPrivateEntity, new()    where TDbContextLocator : class, IDbContextLocator{    /// <summary>    /// 实现基类构造函数    /// </summary>    /// <param name="serviceProvider"></param>    public MyRepository(IServiceProvider serviceProvider)        : base(typeof(TDbContextLocator), serviceProvider)    {    }    /// <summary>    /// 自定义方法    /// </summary>    public void MyMethod()    {        throw new System.NotImplementedException();    }}/// <summary>/// 默认数据库自定义仓储接口/// </summary>/// <typeparam name="TEntity"></typeparam>public interface IMyRepository<TEntity> : IMyRepository<TEntity, MasterDbContextLocator>    where TEntity : class, IPrivateEntity, new(){}/// <summary>/// 默认数据库自定义仓储实现/// </summary>/// <typeparam name="TEntity"></typeparam>public class MyRepository<TEntity> : MyRepository<TEntity, MasterDbContextLocator>, IMyRepository<TEntity>, IScoped    where TEntity : class, IPrivateEntity, new(){    public MyRepository(IServiceProvider serviceProvider) : base(serviceProvider)    {    }}

9.4.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-seed-data/index.html b/handbook/build/docs/dbcontext-seed-data/index.html index 67e626afb4..a9665e2e78 100644 --- a/handbook/build/docs/dbcontext-seed-data/index.html +++ b/handbook/build/docs/dbcontext-seed-data/index.html @@ -2,22 +2,21 @@ - - - + +9.21 实体种子数据 | Furion -9.21 实体种子数据 | Furion - - + + +
-

9.21 实体种子数据

特别提醒

一旦定义了种子数据或改变了种子数据,需要重新执行 Add-MigrationUpdate-Database 命令。

9.21.1 什么是种子数据

Furion 框架中,种子数据通常指的是通过程序为数据库预先设置一些初始化数据,比如我们的数据字典表,我们可能希望在系统构建初期就自动将一些规范化数据保存到数据库中。

如性别:男/女,地区,行业信息等等。

9.21.2 如何配置

Furion 提供非常灵活方便的 IEntitySeedData<TEntity> 依赖接口可以快速的构建种子数据,支持任何无参构造函数对象类中使用。如我们需要为 Person 表插入初始化数据:

9.21.2.1 在实体定义中使用

using Furion.DatabaseAccessor;using System;using System.Collections.Generic;namespace Furion.Core{    public class Person : EntityBase, IEntitySeedData<Person>    {        public string Name { get; set; }        public int Age { get; set; }        public string Address { get; set; }        // 配置种子数据        public IEnumerable<Person> HasData(DbContext dbContext, Type dbContextLocator)        {            return new List<Person>            {                new Person { Id = 1, Name = "百小僧", Address = "广东省中山市" },                new Person { Id = 2, Name = "新生帝", Address = "广东省珠海市" }            };        }    }}
特别注意

主键 值必须手动插入,因为会自动关闭主键或自增标识检查。

9.21.2.2 在任意对象类中使用

using Furion.DatabaseAccessor;using System.Collections.Generic;namespace Furion.Application{    public class PersonSeedData : IEntitySeedData<Person>    {        // 配置种子数据        public IEnumerable<Person> HasData(DbContext dbContext, Type dbContextLocator)        {            return new List<Person>            {                new Person { Id = 1, Name = "百小僧", Address = "广东省中山市" },                new Person { Id = 2, Name = "新生帝", Address = "广东省珠海市" }            };        }    }}

9.21.3 导航属性

通常我们的实体有 一对多多对多等外键关系,那么我们需要单独为每一个实体添加数据种子,而不是直接写在主表中。

9.21.4 多个数据库种子数据

Furion 提供泛型的方式支持多个数据库种子数据设定,如:

using Furion.DatabaseAccessor;using System.Collections.Generic;namespace Furion.Application{    public class PersonSeedData : IEntitySeedData<Person, MySqlDbContextLocator, SqliteDbContextLocator>    {        // 配置种子数据        public IEnumerable<Person> HasData(DbContext dbContext, Type dbContextLocator)        {            return new List<Person>            {                new Person { Id = 1, Name = "百小僧", Address = "广东省中山市" },                new Person { Id = 2, Name = "新生帝", Address = "广东省珠海市" }            };        }    }}

上面的例子表示同时为 MySqlDbContextSqliteDbContext 创建种子数据。

9.21.5 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 数据种子 知识可查阅 EF Core - 数据种子设定 章节。

演练场
- - +

9.21 实体种子数据

特别提醒

一旦定义了种子数据或改变了种子数据,需要重新执行 Add-MigrationUpdate-Database 命令。

9.21.1 什么是种子数据

Furion 框架中,种子数据通常指的是通过程序为数据库预先设置一些初始化数据,比如我们的数据字典表,我们可能希望在系统构建初期就自动将一些规范化数据保存到数据库中。

如性别:男/女,地区,行业信息等等。

9.21.2 如何配置

Furion 提供非常灵活方便的 IEntitySeedData<TEntity> 依赖接口可以快速的构建种子数据,支持任何无参构造函数对象类中使用。如我们需要为 Person 表插入初始化数据:

9.21.2.1 在实体定义中使用

using Furion.DatabaseAccessor;using System;using System.Collections.Generic;namespace Furion.Core{    public class Person : EntityBase, IEntitySeedData<Person>    {        public string Name { get; set; }        public int Age { get; set; }        public string Address { get; set; }        // 配置种子数据        public IEnumerable<Person> HasData(DbContext dbContext, Type dbContextLocator)        {            return new List<Person>            {                new Person { Id = 1, Name = "百小僧", Address = "广东省中山市" },                new Person { Id = 2, Name = "新生帝", Address = "广东省珠海市" }            };        }    }}
特别注意

主键 值必须手动插入,因为会自动关闭主键或自增标识检查。

9.21.2.2 在任意对象类中使用

using Furion.DatabaseAccessor;using System.Collections.Generic;namespace Furion.Application{    public class PersonSeedData : IEntitySeedData<Person>    {        // 配置种子数据        public IEnumerable<Person> HasData(DbContext dbContext, Type dbContextLocator)        {            return new List<Person>            {                new Person { Id = 1, Name = "百小僧", Address = "广东省中山市" },                new Person { Id = 2, Name = "新生帝", Address = "广东省珠海市" }            };        }    }}

9.21.3 导航属性

通常我们的实体有 一对多多对多等外键关系,那么我们需要单独为每一个实体添加数据种子,而不是直接写在主表中。

9.21.4 多个数据库种子数据

Furion 提供泛型的方式支持多个数据库种子数据设定,如:

using Furion.DatabaseAccessor;using System.Collections.Generic;namespace Furion.Application{    public class PersonSeedData : IEntitySeedData<Person, MySqlDbContextLocator, SqliteDbContextLocator>    {        // 配置种子数据        public IEnumerable<Person> HasData(DbContext dbContext, Type dbContextLocator)        {            return new List<Person>            {                new Person { Id = 1, Name = "百小僧", Address = "广东省中山市" },                new Person { Id = 2, Name = "新生帝", Address = "广东省珠海市" }            };        }    }}

上面的例子表示同时为 MySqlDbContextSqliteDbContext 创建种子数据。

9.21.5 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 数据种子 知识可查阅 EF Core - 数据种子设定 章节。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-sql-proxy/index.html b/handbook/build/docs/dbcontext-sql-proxy/index.html index b84eb02118..8c22dc233c 100644 --- a/handbook/build/docs/dbcontext-sql-proxy/index.html +++ b/handbook/build/docs/dbcontext-sql-proxy/index.html @@ -2,22 +2,21 @@ - - - + +9.17 Sql 高级代理 | Furion -9.17 Sql 高级代理 | Furion - - + + +
-

9.17 Sql 高级代理

9.17.1 关于 Sql 代理

Sql 代理是 Furion 框架中对 Sql 操作一个非常重要的概念,通过这种方式可以大大提高 Sql 书写效率,而且后期极易维护。

Sql 代理属于 Furion 框架中一个高级功能。

9.17.2 了解 ISqlDispatchProxy

ISqlDispatchProxy 接口是 Furion 实现被代理接口的唯一依赖,任何公开的接口一旦集成了 ISqlDispatchProxy 接口,那么这个接口就是被托管拦截Sql 操作接口。

简单定义一个 Sql 代理接口

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {    }}

一旦这个接口继承了 ISqlDispatchProxy,那么它就会动态创建接口实例,而且支持依赖注入/控制反转获取实例

9.17.3 开始领略 Sql 代理

下面我将通过多个例子来演示 Sql 代理的用法,为什么推荐这种方式操作 Sql

支持各种方式获取实例:

9.17.3.1 构造函数方式

private readonly ISql _sql;public FurionService(ISql sql){    _sql = sql;}

9.17.3.2 方法参数注入

public async Task<List<PersonDto>> GetAll([FromServices] ISql, string keyword){}

9.17.3.3 Db.GetSqlDispatchProxy<ISql>()

var sql = Db.GetSqlDispatchProxy<ISql>();

9.17.4 Sql 操作

9.17.4.1 返回 DataTable

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        // 执行sql并传入参数,基元类型        [SqlExecute("select * from person where id >@id and name like @name")]        DataTable GetPerson(int id, string name);        // 执行sql并传入参数,对象类型        [SqlExecute("select * from person where id >@id and name like @name")]        DataTable GetPerson(MyParam paras);        // 执行存储过程 sql,支持设置参数类型        [SqlExecute("exec PROP_NAME @id", CommandType = CommandType.StoredProcedure)]        DataTable GetPerson(int id);        // 支持多数据库操作        [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator))]        DataTable GetPerson();        // 异步方式        [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator))]        Task<DataTable> GetPersonAsync();    }}
关于参数

Sql 代理参数查找规则:

如果方法的参数是 基元类型(或 string值类型),则自动将这些类型组合成 Dictionary<string, object> 作为 Sql 参数。命令参数可使用方法同名参数加 @ 符号。

如果方法的参数是 类类型,那么自动遍历该类公开实例属性生成 DbParameter[] 数组,每一个属性名都将是命令参数,大部分数据库是不区分大小写,个别数据库除外,如 Sqlite,如:

public class MyModel{    public int Id {get;set;}    public string Name {get; set;}}

那么 sql 语句可以直接使用属性名作为参数:

select * from person where id > @id and name = @name;

9.17.4.2 返回 List<T>

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        // 执行sql并传入参数,基元类型        [SqlExecute("select * from person where id >@id and name like @name")]        List<Person> GetPerson(int id, string name);        // 执行sql并传入参数,对象类型        [SqlExecute("select * from person where id >@id and name like @name")]        List<Person> GetPerson(MyParam paras);        // 执行存储过程 sql,支持设置参数类型        [SqlExecute("exec PROP_NAME @id", CommandType = CommandType.StoredProcedure)]        List<Person> GetPerson(int id);        // 支持多数据库操作        [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]        List<Person> GetPerson();        // 异步方式        [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]        Task<List<Person>> GetPersonAsync();    }}

9.17.4.3 返回 DataSet

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        // 执行sql并传入参数,基元类型        [SqlExecute(@"            select * from person where id >@id and name like @name;            select top 10 * from student where Id >@id;")]        DataSet GetData(int id, string name);        // 执行sql并传入参数,对象类型        [SqlExecute(@"            select * from person where id >@id and name like @name;            select top 10 * from student where Id >@id;")]        DataSet GetData(MyParam paras);        // 执行存储过程 sql,支持设置参数类型        [SqlExecute(@"            exec PROP_NAME @id;            select * from person;", CommandType = CommandType.StoredProcedure)]        DataSet GetData(int id);        // 支持多数据库操作        [SqlExecute(@"            select * from person;            select * from student;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]        DataSet GetData();        // 异步方式        [SqlExecute(@"            select * from person;            select * from student;            select 1;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]        Task<DataSet> GetDataAsync());    }}

9.17.4.4 返回 Tuple<T1,...T8>

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        // 执行sql并传入参数,基元类型        [SqlExecute(@"            select * from person where id >@id and name like @name;            select top 10 * from student where Id >@id;")]        (List<Person>,List<Student>) GetData(int id, string name);        // 执行sql并传入参数,对象类型        [SqlExecute(@"            select * from person where id >@id and name like @name;            select top 10 * from student where Id >@id;")]        (List<Person>,List<Student>) GetData(MyParam paras);        // 执行存储过程 sql,支持设置参数类型        [SqlExecute(@"            exec PROP_NAME @id;            select * from person;", CommandType = CommandType.StoredProcedure)]        (List<Person>,List<Student>) GetData(int id);        // 支持多数据库操作        [SqlExecute(@"            select * from person;            select * from student;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]        (List<Person>,List<Student>) GetData();        // 异步方式        [SqlExecute(@"            select * from person;            select * from student;            select 1;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]        Task<(List<Person>,List<Student>,List<int>)> GetDataAsync();        // 自 v3.7.3+ 版本支持返回单个类类型参数        [SqlExecute(@"            select * from person where id =@id;            select * from person")]        (Person, List<Person>) GetData(int id); // 注意返回值是 `(Person, List<Person>)` 组合}

9.17.4.5 返回 单行单列

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlExecute("select Name from person where id = @id")]        string GetValue(int id);        [SqlExecute("select age from person where id = @id")]        int GetValue(int id);        [SqlExecute("select Name from person where id = @id")]        Task<string> GetValueAsync(int id);    }}

9.17.4.6 无返回值

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlExecute("insert into person(Name,Age) values(@name,@age)")]        void Insert(MyParam dto);        [SqlExecute("delete from person where id = @id")]        void Delete(int id);        [SqlExecute("update person set name=@name where id=@id")]        void Update(int id, string name);    }}

9.17.4.7 返回单个类类型参数

版本说明

以下内容仅限 Furion 3.7.1 + 版本使用。

public interface ISql : ISqlDispatchProxy{    // 自 v3.7.3+ 版本支持返回单个类类型参数    [SqlExecute("select * from person where id=@id")]    Person GetPerson(int id);}

9.17.5 存储过程 操作

9.17.5.1 返回 DataTable

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlProcedure("PROC_Name")]        DataTable GetPersons(MyParam dto);        [SqlProcedure("PROC_Name")]        DataTable GetPersons(int id);        [SqlProcedure("PROC_Name")]        DataTable GetPersons(int id, string name);    }}

9.17.5.2 返回 List<T>

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlProcedure("PROC_Name")]        List<Person> GetPersons(MyParam dto);        [SqlProcedure("PROC_Name")]        List<Person> GetPersons(int id);        [SqlProcedure("PROC_Name")]        List<Person> GetPersons(int id, string name);    }}

9.17.5.3 返回 DataSet

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlProcedure("PROC_Name")]        DataSet GetData(MyParam dto);        [SqlProcedure("PROC_Name")]        DataSet GetData(int id);        [SqlProcedure("PROC_Name")]        DataSet GetData(int id, string name);    }}

9.17.5.4 返回 Tuple(T1,...T8)

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlProcedure("PROC_Name")]        (List<Person>, List<Student>) GetData(MyParam dto);        [SqlProcedure("PROC_Name")]        (List<Person>, List<Student>) GetData(int id);        [SqlProcedure("PROC_Name")]        (List<Person>, List<Student>, Person, int) GetData(int id, string name);        // 自 v3.7.3+ 版本支持返回单个类类型参数        [SqlProcedure(@"PROC_Name)]        (Person, List<Person>) GetData(int id); // 注意返回值是 `(Person, List<Person>)` 组合    }}

9.17.5.5 返回 单行单列

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlProcedure("PROC_Name")]        object GetValue(MyParam dto);        [SqlProcedure("PROC_Name")]        string GetValue(int id);        [SqlProcedure("PROC_Name")]        int GetValue(int id, string name);    }}

9.17.5.6 无返回值

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlProcedure("PROC_Name")]        void GetValue(MyParam dto);        [SqlProcedure("PROC_Name")]        void GetValue(int id);        [SqlProcedure("PROC_Name")]        void GetValue(int id, string name);    }}

9.17.5.7 带 OUTPUT/RETURN 返回

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlProcedure("PROC_Name")]        ProcedureOutputResult GetOutput(ProcOutputModel pams);        [SqlProcedure("PROC_Name")]        ProcedureOutputResult GetOutput(ProcOutputModel pams);        [SqlProcedure("PROC_Name")]        ProcedureOutputResult<(List<Person>, List<Student>)> GetOutput(ProcOutputModel pams);    }}

9.17.5.8 返回单个类类型参数

版本说明

以下内容仅限 Furion 3.7.1 + 版本使用。

public interface ISql : ISqlDispatchProxy{    // 自 v3.7.3+ 版本支持返回单个类类型参数    [SqlProcedure("PROC_Name")]    Person GetPerson(int id);}

9.17.6 函数 操作

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlFunction("FN_Name")]    // 标量函数        string GetValue(MyParam dto);        [SqlProcedure("FN_Name")]   // 表值函数        List<Person> GetPersons(int id);    }}
补充说明

Sql 代理会自动判断返回值然后自动执行特定函数类型。

9.17.7 Sql 模板替换

在最新的 1.18.3 版本中提供了模板替换功能,如:

[SqlExecute("select * from person where id > {id} and name like {name} and age > {user.Age}")]List<Person> GetPerson(int id, string name, User user);
两者区别

模板字符串有别于命令参数替换,模板字符串采用 { } 方式,运行时直接替换为实际的内容, @ 而是转换成 DbParameter 参数。

9.17.8 切换数据库

Sql 代理方式的支持三种切换数据库的方式:

9.17.8.1 单个方法方式

主要通过在方法上贴 [SqlDbContextLocator] 特性

[SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]List<Person> GetPerson();

9.17.8.2 接口方式

在接口中贴 [SqlDbContextLocator] 特性,此方式下,接口所有方法将采用指定的数据库执行。

[SqlDbContextLocator(typeof(MySqlDbContextLocator)]public interface ISql : ISqlDispatchProxy{    [SqlFunction("FN_Name")]    // 标量函数    string GetValue(MyParam dto);    [SqlProcedure("FN_Name")]   // 表值函数    List<Person> GetPersons(int id);}

9.17.8.3 运行时 .Change 方法切换

除了以上两种 静态 配置方式,Furion 框架还提供 动态 方式,如:

// 将 sql 代理数据库切换成特定数据库_sql.Change<MySqlDbContextLocator>();_sql.GetPerson();// 多次切换_sql.Change<OracleDbContextLocator>();_sql.GetPerson();// 还支持重置数据库上下文定位器为初始状态_sql.ResetIt();_sql.GetPerson();
关于优先级问题

.Change<> 优先级大于 方法贴 [SqlDbContextLocator] 大于 接口贴 [SqlDbContextLocator]

默认情况下,不指定 DbContextLocator 属性,则为 MasterDbContextLocator

9.17.9 Sql 代理拦截

Furion v2.13 + 版本新增了 Sql 代理拦截功能,可以篡改特定方法或所有代理方法实际执行的参数,如 sql语句、参数、执行对象等等

若在 Sql 代理中实现拦截功能,必须满足两个条件

  • 方法必须是 static 静态方法且返回值为 void 且只有一个 SqlProxyMethod 参数
  • 方法必须贴 [Interceptor] 特性

如:

public interface ISql : ISqlDispatchProxy{    [SqlFunction("FN_Name")]    string GetValue(MyParam dto);    [SqlProcedure("FN_Name")]    List<Person> GetPersons(int id);    [SqlExecute("select name from person", InterceptorId = "GetPersonsByName")] // 通过 InterceptorId 解决方法名重载问题    Task<List<string>> GetPersons();    // 只拦截 GetValue 方法    [Interceptor(nameof(GetValue))]    static void 拦截1(SqlProxyMethod method)    {        method.FinalSql += " where id > 1"; // 篡改最终执行 sql    }    // 拦截 GetValue 和 GetPersons 方法    [Interceptor(nameof(GetValue), nameof(GetPersons))]    static void 拦截2(SqlProxyMethod method)    {        method.FinalSql += " where id > 1"; // 篡改最终执行 sql    }    [Interceptor("GetPersonsByName")]   // 对应上面的 InterceptorId 配置    static void 解决方法名重载拦截(SqlProxyMethod method)    {        // 。。。    }    [Interceptor]    static void 全局拦截(SqlProxyMethod method)    {        // 这里会拦截所有的方法    }}

9.17.10 设置超时时间

[Timeout(1000)]public interface ISql : ISqlDispatchProxy{    [SqlFunction("FN_Name"), Timeout(500)]   // 单位秒    string GetValue(MyParam dto);}

9.17.11 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.17 Sql 高级代理

9.17.1 关于 Sql 代理

Sql 代理是 Furion 框架中对 Sql 操作一个非常重要的概念,通过这种方式可以大大提高 Sql 书写效率,而且后期极易维护。

Sql 代理属于 Furion 框架中一个高级功能。

9.17.2 了解 ISqlDispatchProxy

ISqlDispatchProxy 接口是 Furion 实现被代理接口的唯一依赖,任何公开的接口一旦集成了 ISqlDispatchProxy 接口,那么这个接口就是被托管拦截Sql 操作接口。

简单定义一个 Sql 代理接口

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {    }}

一旦这个接口继承了 ISqlDispatchProxy,那么它就会动态创建接口实例,而且支持依赖注入/控制反转获取实例

9.17.3 开始领略 Sql 代理

下面我将通过多个例子来演示 Sql 代理的用法,为什么推荐这种方式操作 Sql

支持各种方式获取实例:

9.17.3.1 构造函数方式

private readonly ISql _sql;public FurionService(ISql sql){    _sql = sql;}

9.17.3.2 方法参数注入

public async Task<List<PersonDto>> GetAll([FromServices] ISql, string keyword){}

9.17.3.3 Db.GetSqlDispatchProxy<ISql>()

var sql = Db.GetSqlDispatchProxy<ISql>();

9.17.4 Sql 操作

9.17.4.1 返回 DataTable

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        // 执行sql并传入参数,基元类型        [SqlExecute("select * from person where id >@id and name like @name")]        DataTable GetPerson(int id, string name);        // 执行sql并传入参数,对象类型        [SqlExecute("select * from person where id >@id and name like @name")]        DataTable GetPerson(MyParam paras);        // 执行存储过程 sql,支持设置参数类型        [SqlExecute("exec PROP_NAME @id", CommandType = CommandType.StoredProcedure)]        DataTable GetPerson(int id);        // 支持多数据库操作        [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator))]        DataTable GetPerson();        // 异步方式        [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator))]        Task<DataTable> GetPersonAsync();    }}
关于参数

Sql 代理参数查找规则:

如果方法的参数是 基元类型(或 string值类型),则自动将这些类型组合成 Dictionary<string, object> 作为 Sql 参数。命令参数可使用方法同名参数加 @ 符号。

如果方法的参数是 类类型,那么自动遍历该类公开实例属性生成 DbParameter[] 数组,每一个属性名都将是命令参数,大部分数据库是不区分大小写,个别数据库除外,如 Sqlite,如:

public class MyModel{    public int Id {get;set;}    public string Name {get; set;}}

那么 sql 语句可以直接使用属性名作为参数:

select * from person where id > @id and name = @name;

9.17.4.2 返回 List<T>

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        // 执行sql并传入参数,基元类型        [SqlExecute("select * from person where id >@id and name like @name")]        List<Person> GetPerson(int id, string name);        // 执行sql并传入参数,对象类型        [SqlExecute("select * from person where id >@id and name like @name")]        List<Person> GetPerson(MyParam paras);        // 执行存储过程 sql,支持设置参数类型        [SqlExecute("exec PROP_NAME @id", CommandType = CommandType.StoredProcedure)]        List<Person> GetPerson(int id);        // 支持多数据库操作        [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]        List<Person> GetPerson();        // 异步方式        [SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]        Task<List<Person>> GetPersonAsync();    }}

9.17.4.3 返回 DataSet

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        // 执行sql并传入参数,基元类型        [SqlExecute(@"            select * from person where id >@id and name like @name;            select top 10 * from student where Id >@id;")]        DataSet GetData(int id, string name);        // 执行sql并传入参数,对象类型        [SqlExecute(@"            select * from person where id >@id and name like @name;            select top 10 * from student where Id >@id;")]        DataSet GetData(MyParam paras);        // 执行存储过程 sql,支持设置参数类型        [SqlExecute(@"            exec PROP_NAME @id;            select * from person;", CommandType = CommandType.StoredProcedure)]        DataSet GetData(int id);        // 支持多数据库操作        [SqlExecute(@"            select * from person;            select * from student;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]        DataSet GetData();        // 异步方式        [SqlExecute(@"            select * from person;            select * from student;            select 1;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]        Task<DataSet> GetDataAsync());    }}

9.17.4.4 返回 Tuple<T1,...T8>

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        // 执行sql并传入参数,基元类型        [SqlExecute(@"            select * from person where id >@id and name like @name;            select top 10 * from student where Id >@id;")]        (List<Person>,List<Student>) GetData(int id, string name);        // 执行sql并传入参数,对象类型        [SqlExecute(@"            select * from person where id >@id and name like @name;            select top 10 * from student where Id >@id;")]        (List<Person>,List<Student>) GetData(MyParam paras);        // 执行存储过程 sql,支持设置参数类型        [SqlExecute(@"            exec PROP_NAME @id;            select * from person;", CommandType = CommandType.StoredProcedure)]        (List<Person>,List<Student>) GetData(int id);        // 支持多数据库操作        [SqlExecute(@"            select * from person;            select * from student;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]        (List<Person>,List<Student>) GetData();        // 异步方式        [SqlExecute(@"            select * from person;            select * from student;            select 1;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]        Task<(List<Person>,List<Student>,List<int>)> GetDataAsync();        // 自 v3.7.3+ 版本支持返回单个类类型参数        [SqlExecute(@"            select * from person where id =@id;            select * from person")]        (Person, List<Person>) GetData(int id); // 注意返回值是 `(Person, List<Person>)` 组合}

9.17.4.5 返回 单行单列

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlExecute("select Name from person where id = @id")]        string GetValue(int id);        [SqlExecute("select age from person where id = @id")]        int GetValue(int id);        [SqlExecute("select Name from person where id = @id")]        Task<string> GetValueAsync(int id);    }}

9.17.4.6 无返回值

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlExecute("insert into person(Name,Age) values(@name,@age)")]        void Insert(MyParam dto);        [SqlExecute("delete from person where id = @id")]        void Delete(int id);        [SqlExecute("update person set name=@name where id=@id")]        void Update(int id, string name);    }}

9.17.4.7 返回单个类类型参数

版本说明

以下内容仅限 Furion 3.7.1 + 版本使用。

public interface ISql : ISqlDispatchProxy{    // 自 v3.7.3+ 版本支持返回单个类类型参数    [SqlExecute("select * from person where id=@id")]    Person GetPerson(int id);}

9.17.5 存储过程 操作

9.17.5.1 返回 DataTable

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlProcedure("PROC_Name")]        DataTable GetPersons(MyParam dto);        [SqlProcedure("PROC_Name")]        DataTable GetPersons(int id);        [SqlProcedure("PROC_Name")]        DataTable GetPersons(int id, string name);    }}

9.17.5.2 返回 List<T>

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlProcedure("PROC_Name")]        List<Person> GetPersons(MyParam dto);        [SqlProcedure("PROC_Name")]        List<Person> GetPersons(int id);        [SqlProcedure("PROC_Name")]        List<Person> GetPersons(int id, string name);    }}

9.17.5.3 返回 DataSet

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlProcedure("PROC_Name")]        DataSet GetData(MyParam dto);        [SqlProcedure("PROC_Name")]        DataSet GetData(int id);        [SqlProcedure("PROC_Name")]        DataSet GetData(int id, string name);    }}

9.17.5.4 返回 Tuple(T1,...T8)

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlProcedure("PROC_Name")]        (List<Person>, List<Student>) GetData(MyParam dto);        [SqlProcedure("PROC_Name")]        (List<Person>, List<Student>) GetData(int id);        [SqlProcedure("PROC_Name")]        (List<Person>, List<Student>, Person, int) GetData(int id, string name);        // 自 v3.7.3+ 版本支持返回单个类类型参数        [SqlProcedure(@"PROC_Name)]        (Person, List<Person>) GetData(int id); // 注意返回值是 `(Person, List<Person>)` 组合    }}

9.17.5.5 返回 单行单列

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlProcedure("PROC_Name")]        object GetValue(MyParam dto);        [SqlProcedure("PROC_Name")]        string GetValue(int id);        [SqlProcedure("PROC_Name")]        int GetValue(int id, string name);    }}

9.17.5.6 无返回值

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlProcedure("PROC_Name")]        void GetValue(MyParam dto);        [SqlProcedure("PROC_Name")]        void GetValue(int id);        [SqlProcedure("PROC_Name")]        void GetValue(int id, string name);    }}

9.17.5.7 带 OUTPUT/RETURN 返回

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlProcedure("PROC_Name")]        ProcedureOutputResult GetOutput(ProcOutputModel pams);        [SqlProcedure("PROC_Name")]        ProcedureOutputResult GetOutput(ProcOutputModel pams);        [SqlProcedure("PROC_Name")]        ProcedureOutputResult<(List<Person>, List<Student>)> GetOutput(ProcOutputModel pams);    }}

9.17.5.8 返回单个类类型参数

版本说明

以下内容仅限 Furion 3.7.1 + 版本使用。

public interface ISql : ISqlDispatchProxy{    // 自 v3.7.3+ 版本支持返回单个类类型参数    [SqlProcedure("PROC_Name")]    Person GetPerson(int id);}

9.17.6 函数 操作

using Furion.DatabaseAccessor;namespace Furion.Application{    public interface ISql : ISqlDispatchProxy    {        [SqlFunction("FN_Name")]    // 标量函数        string GetValue(MyParam dto);        [SqlProcedure("FN_Name")]   // 表值函数        List<Person> GetPersons(int id);    }}
补充说明

Sql 代理会自动判断返回值然后自动执行特定函数类型。

9.17.7 Sql 模板替换

在最新的 1.18.3 版本中提供了模板替换功能,如:

[SqlExecute("select * from person where id > {id} and name like {name} and age > {user.Age}")]List<Person> GetPerson(int id, string name, User user);
两者区别

模板字符串有别于命令参数替换,模板字符串采用 { } 方式,运行时直接替换为实际的内容, @ 而是转换成 DbParameter 参数。

9.17.8 切换数据库

Sql 代理方式的支持三种切换数据库的方式:

9.17.8.1 单个方法方式

主要通过在方法上贴 [SqlDbContextLocator] 特性

[SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]List<Person> GetPerson();

9.17.8.2 接口方式

在接口中贴 [SqlDbContextLocator] 特性,此方式下,接口所有方法将采用指定的数据库执行。

[SqlDbContextLocator(typeof(MySqlDbContextLocator)]public interface ISql : ISqlDispatchProxy{    [SqlFunction("FN_Name")]    // 标量函数    string GetValue(MyParam dto);    [SqlProcedure("FN_Name")]   // 表值函数    List<Person> GetPersons(int id);}

9.17.8.3 运行时 .Change 方法切换

除了以上两种 静态 配置方式,Furion 框架还提供 动态 方式,如:

// 将 sql 代理数据库切换成特定数据库_sql.Change<MySqlDbContextLocator>();_sql.GetPerson();// 多次切换_sql.Change<OracleDbContextLocator>();_sql.GetPerson();// 还支持重置数据库上下文定位器为初始状态_sql.ResetIt();_sql.GetPerson();
关于优先级问题

.Change<> 优先级大于 方法贴 [SqlDbContextLocator] 大于 接口贴 [SqlDbContextLocator]

默认情况下,不指定 DbContextLocator 属性,则为 MasterDbContextLocator

9.17.9 Sql 代理拦截

Furion v2.13 + 版本新增了 Sql 代理拦截功能,可以篡改特定方法或所有代理方法实际执行的参数,如 sql语句、参数、执行对象等等

若在 Sql 代理中实现拦截功能,必须满足两个条件

  • 方法必须是 static 静态方法且返回值为 void 且只有一个 SqlProxyMethod 参数
  • 方法必须贴 [Interceptor] 特性

如:

public interface ISql : ISqlDispatchProxy{    [SqlFunction("FN_Name")]    string GetValue(MyParam dto);    [SqlProcedure("FN_Name")]    List<Person> GetPersons(int id);    [SqlExecute("select name from person", InterceptorId = "GetPersonsByName")] // 通过 InterceptorId 解决方法名重载问题    Task<List<string>> GetPersons();    // 只拦截 GetValue 方法    [Interceptor(nameof(GetValue))]    static void 拦截1(SqlProxyMethod method)    {        method.FinalSql += " where id > 1"; // 篡改最终执行 sql    }    // 拦截 GetValue 和 GetPersons 方法    [Interceptor(nameof(GetValue), nameof(GetPersons))]    static void 拦截2(SqlProxyMethod method)    {        method.FinalSql += " where id > 1"; // 篡改最终执行 sql    }    [Interceptor("GetPersonsByName")]   // 对应上面的 InterceptorId 配置    static void 解决方法名重载拦截(SqlProxyMethod method)    {        // 。。。    }    [Interceptor]    static void 全局拦截(SqlProxyMethod method)    {        // 这里会拦截所有的方法    }}

9.17.10 设置超时时间

[Timeout(1000)]public interface ISql : ISqlDispatchProxy{    [SqlFunction("FN_Name"), Timeout(500)]   // 单位秒    string GetValue(MyParam dto);}

9.17.11 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-sql-template/index.html b/handbook/build/docs/dbcontext-sql-template/index.html index c69b36e69b..a888540d21 100644 --- a/handbook/build/docs/dbcontext-sql-template/index.html +++ b/handbook/build/docs/dbcontext-sql-template/index.html @@ -2,22 +2,21 @@ - - - + +9.16 Sql 模板 | Furion -9.16 Sql 模板 | Furion - - + + +
-

9.16 Sql 模板

9.16.1 Sql 模板

通常我们程序中执行数据库的 sql 语句都写在了程序集中,随程序一起编译,后续需要修改,则重新编译代码。

所以,Furion 创造出一种 Sql 模板的方式,程序执行 Sql 时,只需要使用特殊标记即可:#(模板Key),这些真实的 Sql 配置在 .json.xml 配置文件中。

如:

  • Json 方式
{  "Select.User": "select * from User where id > @id"}
  • Xml 方式
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<Select.User>select * from User where id > @id</Select.User>
</configuration>

9.16.2 Sql 模板优缺点

9.16.2.1 优点

  • 支持 Sql 动态配置,可在程序运行时动态调配 Sql 语句
  • 支持程序 Sql 语句加密

9.16.2.2 缺点

  • 需增加对应配置文件
  • 不容易调试 Sql 代码

9.16.3 如何使用

在执行 Sql 的时候,只需要填写指定模板即可。

9.16.3.1 常规使用

// 仓储方式var users = repository.SqlQuery<User>("#(Select.User)", new { id = 1});// 懒人方式var users = "#(Select.User)".SqlQuery<User>(new { id = 1});// Sql 代理方式[SqlExecute("#(Select.User)")]List<User> GetUser(int id);

9.16.3.2 高级嵌套

var users = repository.SqlQuery<User>(@"select * from user uleft join #(User.Detail) d on u.Id = d.UserIdwhere id > @id");

9.16.4 Sql 模板配置

9.16.4.1 普通模式

{  "Select.User": "select * from User"}

9.16.4.2 更多配置

功能移除声明

以下内容在 Furion 2.13 + 版本中已移除。

{  "Select.User": {    "Sql": "select * from User where id > @id and Name = @name",    "Params": [      {        "Name": " Id",        "Value": "1",        "DbType": "Int16",        "Size": 10      },      {        "Name": " Name",        "Value": "百小僧",        "DbType": "String",        "Size": 10      }    ]  }}

9.16.5 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.16 Sql 模板

9.16.1 Sql 模板

通常我们程序中执行数据库的 sql 语句都写在了程序集中,随程序一起编译,后续需要修改,则重新编译代码。

所以,Furion 创造出一种 Sql 模板的方式,程序执行 Sql 时,只需要使用特殊标记即可:#(模板Key),这些真实的 Sql 配置在 .json.xml 配置文件中。

如:

  • Json 方式
{  "Select.User": "select * from User where id > @id"}
  • Xml 方式
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<Select.User>select * from User where id > @id</Select.User>
</configuration>

9.16.2 Sql 模板优缺点

9.16.2.1 优点

  • 支持 Sql 动态配置,可在程序运行时动态调配 Sql 语句
  • 支持程序 Sql 语句加密

9.16.2.2 缺点

  • 需增加对应配置文件
  • 不容易调试 Sql 代码

9.16.3 如何使用

在执行 Sql 的时候,只需要填写指定模板即可。

9.16.3.1 常规使用

// 仓储方式var users = repository.SqlQuery<User>("#(Select.User)", new { id = 1});// 懒人方式var users = "#(Select.User)".SqlQuery<User>(new { id = 1});// Sql 代理方式[SqlExecute("#(Select.User)")]List<User> GetUser(int id);

9.16.3.2 高级嵌套

var users = repository.SqlQuery<User>(@"select * from user uleft join #(User.Detail) d on u.Id = d.UserIdwhere id > @id");

9.16.4 Sql 模板配置

9.16.4.1 普通模式

{  "Select.User": "select * from User"}

9.16.4.2 更多配置

功能移除声明

以下内容在 Furion 2.13 + 版本中已移除。

{  "Select.User": {    "Sql": "select * from User where id > @id and Name = @name",    "Params": [      {        "Name": " Id",        "Value": "1",        "DbType": "Int16",        "Size": 10      },      {        "Name": " Name",        "Value": "百小僧",        "DbType": "String",        "Size": 10      }    ]  }}

9.16.5 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-sql/index.html b/handbook/build/docs/dbcontext-sql/index.html index 84460aa5d7..7c852dc59f 100644 --- a/handbook/build/docs/dbcontext-sql/index.html +++ b/handbook/build/docs/dbcontext-sql/index.html @@ -2,22 +2,21 @@ - - - + +9.15 Sql 操作 | Furion -9.15 Sql 操作 | Furion - - + + +
-

9.15 Sql 操作

温馨提示

推荐使用 《9.17 Sql 高级代理》代替本章节功能。Sql 高级代理 能够提供更容易且更易维护的方式。

例子说明

本章节例子均以 sql server 数据库写的例子,命令参数统一用 @ 符号,但不同数据库的参数前缀有所不同,如:sql server 采用 @,oracle 采用 :,my sql 采用 ?

9.15.1 关于 Sql

Furion 框架提供非常多且灵活的 sql 操作方法,且性能不输于 dapper,同时逼近 ADO.NET 原生操作。

9.15.2 懒人无敌 Sql 🐮

9.15.2.1 返回 DataTable

// ==== 同步操作 ====// 示例一var dataTable = "select * from person".SqlQuery();// 示例二var dataTable = "select top 10 * from person where id > @id".SqlQuery(new {id = 10});// 示例三var dataTable = "select Id, Name, Age from person where name like @name".SqlQuery(new Dictionary<string,object>{ {"name", "%Furion%"} });// 示例四var dataTable = "select * from person where name=@name limit 1,10".SqlQuery(new []{ new MySqlParameter("name","Furion") });// 示例五var dataTable = "select * from person where id>@id and name like @name".SqlQuery(new YourModel { Id = 1, Name = "%Furion%" });// 示例六var dataTable = "exec PROC_GetPerson @id".SqlQuery(new {id = 10});// 示例七var dataTable = "select * from FN_GetPersons(@id)".SqlQuery(new {id = 10});// 示例八var dataTable = @"select * from person pleft join personDetail pd on p.Id == pd.pidwhere p.Id > @id;".SqlQuery(new {id = 10});// ==== 异步操作 ====// 示例一var dataTable = await "select * from person".SqlQueryAsync();// 示例二var dataTable = await "select top 10 * from person where id > @id".SqlQueryAsync(new {id = 10});// 示例三var dataTable = await "select Id, Name, Age from person where name like @name".SqlQueryAsync(new Dictionary<string,object>{ {"name", "%Furion%"} });// 示例四var dataTable = await "select * from person where name=@name limit 1,10".SqlQueryAsync(new []{ new MySqlParameter("name","Furion") });// 示例五var dataTable = await "select * from person where id>@id and name like @name".SqlQueryAsync(new YourModel { Id = 1, Name = "%Furion%" });// 示例六var dataTable = await "exec PROC_GetPerson @id".SqlQueryAsync(new {id = 10});// 示例七var dataTable = await "select * from FN_GetPersons(@id)".SqlQueryAsync(new {id = 10});// 示例八var dataTable = await @"select * from person pleft join personDetail pd on p.Id == pd.pidwhere p.Id > @id;".SqlQueryAsync(new {id = 10});

9.15.2.2 返回 List<T>

// ==== 同步操作 ====// 示例一var persons = "select * from person".SqlQuery<Person>();// 示例二var persons = "select top 10 * from person where id > @id".SqlQuery<Person>(new {id = 10});// 示例三var persons = "select Id, Name, Age from person where name like @name".SqlQuery<Person>(new Dictionary<string,object>{ {"name", "%Furion%"} });// 示例四var persons = "select * from person where name=@name limit 1,10".SqlQuery<Person>(new []{ new MySqlParameter("name","Furion") });// 示例五var persons = "select * from person where id>@id and name like @name".SqlQuery<Person>(new YourModel { Id = 1, Name = "%Furion%" });// 示例六var persons = "exec PROC_GetPerson @id".SqlQuery<Person>(new {id = 10});// 示例七var persons = "select * from FN_GetPersons(@id)".SqlQuery<Person>(new {id = 10});// 示例八var persons = @"select * from person pleft join personDetail pd on p.Id == pd.pidwhere p.Id > @id;".SqlQuery<Person>(new {id = 10});// ==== 异步操作 ====// 示例一var persons = await "select * from person".SqlQueryAsync<Person>();// 示例二var persons = await "select top 10 * from person where id > @id".SqlQueryAsync<Person>(new {id = 10});// 示例三var persons = await "select Id, Name, Age from person where name like @name".SqlQueryAsync<Person>(new Dictionary<string,object>{ {"name", "%Furion%"} });// 示例四var persons = await "select * from person where name=@name limit 1,10".SqlQueryAsync<Person>(new []{ new MySqlParameter("name","Furion") });// 示例五var persons = await "select * from person where id>@id and name like @name".SqlQueryAsync<Person>(new YourModel { Id = 1, Name = "%Furion%" });// 示例六var persons = await "exec PROC_GetPerson @id".SqlQueryAsync<Person>(new {id = 10});// 示例七var persons = await "select * from FN_GetPersons(@id)".SqlQueryAsync<Person>(new {id = 10});// 示例八var persons = await @"select * from person pleft join personDetail pd on p.Id == pd.pidwhere p.Id > @id;".SqlQueryAsync<Person>(new {id = 10});

9.15.2.3 返回 DataSet

// ==== 同步操作 ====// 示例一var dataSet = @"select * from person;select * from student;".SqlQueries();// 示例二var dataSet = @"select * from person where Id > @id;select * from student where Name like @name;".SqlQueries(new {id = 1, name = "%furion%"});// 示例三var dataSet = @"select * from person;exec PROC_GetStudents(@id);select 'Furion';select * from FN_GetPerson(@id);".SqlQueries(new {id = 1});// ==== 异步操作 ====// 示例一var dataSet = await @"select * from person;select * from student;".SqlQueriesAsync();// 示例二var dataSet = await @"select * from person where Id > @id;select * from student where Name like @name;".SqlQueriesAsync(new {id = 1, name = "%furion%"});// 示例三var dataSet = await @"select * from person;exec PROC_GetStudents(@id);select 'Furion';select * from FN_GetPerson(@id);".SqlQueriesAsync(new {id = 1});

9.15.2.4 返回 Tuple<T1,...T8>

// ==== 同步操作 ====// 示例一var (persons, students) = @"select * from person;select * from student;".SqlQueries<Person,Student>();// 示例二var (persons, students) = @"select * from person where Id > @id;select * from student where Name like @name;".SqlQueries<Person,Student>(new {id = 1, name = "%furion%"});// 示例三var (persons, students, string, PersonDto) = @"select * from person;exec PROC_GetStudents(@id);select 'Furion';select * from FN_GetPerson(@id);".SqlQueries<Person, Student, string, PersonDto>(new {id = 1});// ==== 异步操作 ====// 示例一var (persons, students) = await @"select * from person;select * from student;".SqlQueriesAsync<Person,Student>();// 示例二var (persons, students) = await @"select * from person where Id > @id;select * from student where Name like @name;".SqlQueriesAsync<Person,Student>(new {id = 1, name = "%furion%"});// 示例三var (persons, students, string, PersonDto) = await @"select * from person;exec PROC_GetStudents(@id);select 'Furion';select * from FN_GetPerson(@id);".SqlQueriesAsync<Person, Student, string, PersonDto>(new {id = 1});

9.15.2.5 返回 单行单列

// ==== 同步操作 ====// 示例一var value = "select Name from person where id = @id".SqlScalar(new {id = 1});// 示例二var value = "select Name from person where id = @id".SqlScalar<string>(new {id = 1});// 示例三var value = "select Age from person where id = @id".SqlScalar<int>(new {id = 1});// ==== 异步操作 ====// 示例一var value = await "select Name from person where id = @id".SqlScalarAsync(new {id = 1});// 示例二var value = await "select Name from person where id = @id".SqlScalarAsync<string>(new {id = 1});// 示例三var value = await "select Age from person where id = @id".SqlScalarAsync<int>(new {id = 1});

9.15.2.6 返回 受影响行数

// ==== 同步操作 ====// 示例一var rowEffects = "insert into person(Name,Age,Address) values(@name,@age,@address)".SqlNonQuery(person);// 示例二var rowEffects = @"insert into person(Name,Age,Address) values(@name,@age,@address);insert into person(Name,Age,Address) values(@name,@age,@address);".SqlNonQuery(persons);// 示例三var rowEffects = "update person set name=@name where id=@id".SqlNonQuery(new {id=1, name="百小僧"});// 示例四var rowEffects = "delete from person where @id > 10".SqlNonQuery(new {id=1});// ==== 异步操作 ====// 示例一var rowEffects = await "insert into person(Name,Age,Address) values(@name,@age,@address)".SqlNonQueryAsync(person);// 示例二var rowEffects = @"insert into person(Name,Age,Address) values(@name,@age,@address);insert into person(Name,Age,Address) values(@name,@age,@address);".SqlNonQueryAsync(persons);// 示例三var rowEffects = await "update person set name=@name where id=@id".SqlNonQueryAsync(new {id=1, name="百小僧"});// 示例四var rowEffects = await "delete from person where @id > 10".SqlNonQueryAsync(new {id=1});

9.15.3 懒人无敌 存储过程 🐮

9.15.3.1 返回 DataTable

// ==== 同步操作 ====// 示例一var dataTable = "PROC_Name".SqlProcedureQuery();// 示例二var dataTable = "PROC_Name".SqlProcedureQuery(new {id = 1});// 示例三var dataTable = "PROC_Name".SqlProcedureQuery(new {id = 1, age = 27});// ==== 异步操作 ====// 示例一var dataTable = await "PROC_Name".SqlProcedureQueryAsync();// 示例二var dataTable = await "PROC_Name".SqlProcedureQueryAsync(new {id = 1});// 示例三var dataTable = await "PROC_Name".SqlProcedureQueryAsync(new {id = 1, age = 27});

9.15.3.2 返回 List<T>

// ==== 同步操作 ====// 示例一var persons = "PROC_Name".SqlProcedureQuery<Person>();// 示例二var persons = "PROC_Name".SqlProcedureQuery<Person>(new {id = 1});// 示例三var persons = "PROC_Name".SqlProcedureQuery<Person>(new {id = 1, age = 27});// ==== 异步操作 ====// 示例一var persons = await "PROC_Name".SqlProcedureQueryAsync<Person>();// 示例二var persons = await "PROC_Name".SqlProcedureQueryAsync<Person>(new {id = 1});// 示例三var persons = await "PROC_Name".SqlProcedureQueryAsync<Person>(new {id = 1, age = 27});

9.15.3.3 返回 DataSet

// ==== 同步操作 ====// 示例一var dataSet = "PROC_Name".SqlProcedureQueries();// 示例二var dataSet = "PROC_Name".SqlProcedureQueries(new {id = 1});// 示例三var dataSet = "PROC_Name".SqlProcedureQueries(new {id = 1, age = 27});// ==== 异步操作 ====// 示例一var dataSet = await "PROC_Name".SqlProcedureQueriesAsync();// 示例二var dataSet = await "PROC_Name".SqlProcedureQueriesAsync(new {id = 1});// 示例三var dataSet = await "PROC_Name".SqlProcedureQueriesAsync(new {id = 1, age = 27});

9.15.3.4 返回 Tuple<T1,...T8>

// ==== 同步操作 ====// 示例一var persons = "PROC_Name".SqlProcedureQueries<Person>();// 示例二var (persons,students) = "PROC_Name".SqlProcedureQueries<Person,Student>(new {id = 1});// 示例三var (persons,students,string) = "PROC_Name".SqlProcedureQueries<Person,Student,string>(new {id = 1, age = 27});// 示例四var (persons,students,personDetail,string) = "PROC_Name".SqlProcedureQueries<Person,Student,PersonDetail,string>(new {id = 1, age = 27});// ==== 异步操作 ====// 示例一var persons = await "PROC_Name".SqlProcedureQueriesAsync<Person>();// 示例二var (persons,students) = await "PROC_Name".SqlProcedureQueriesAsync<Person,Student>(new {id = 1});// 示例三var (persons,students,string) = await "PROC_Name".SqlProcedureQueriesAsync<Person,Student,string>(new {id = 1, age = 27});// 示例四var (persons,students,personDetail,string) = await "PROC_Name".SqlProcedureQueriesAsync<Person,Student,PersonDetail,string>(new {id = 1, age = 27});

9.15.3.5 返回 单行单列

// ==== 同步操作 ====// 示例一var value = "PROC_Name".SqlProcedureScalar(new {id = 1});// 示例二var value = "PROC_Name".SqlProcedureScalar<string>(new {id = 1, name = "新生帝", address ="广东省中山市"});// 示例三var value = "PROC_Name".SqlProcedureScalar<int>(new {id = 1,  address ="广东省中山市"});// ==== 异步操作 ====// 示例一var value = await "PROC_Name".SqlProcedureScalarAsync(new {id = 1});// 示例二var value = await "PROC_Name".SqlProcedureScalarAsync<string>(new {id = 1, name = "新生帝", address ="广东省中山市"});// 示例三var value = await "PROC_Name".SqlProcedureScalarAsync<int>(new {id = 1,  address ="广东省中山市"});

9.15.3.6 返回 受影响行数

// ==== 同步操作 ====// 示例一var rowEffects = "PROC_Name".SqlProcedureNonQuery(person);// 示例二var rowEffects = "PROC_Name".SqlProcedureNonQuery(new {id = 1, name = "新生帝", address ="广东省中山市"});// 示例三var rowEffects = "PROC_Name".SqlProcedureNonQuery(new {id=1, name="百小僧"});// 示例四var rowEffects = "PROC_Name".SqlProcedureNonQuery(new {id=1});// ==== 异步操作 ====// 示例一var rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(person);// 示例二var rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new {id = 1, name = "新生帝", address ="广东省中山市"});// 示例三var rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new {id=1, name="百小僧"});// 示例四var rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new {id=1});

9.15.3.7 带 OUTPUT/RETURN 返回

CREATE PROC PROC_Output    @Id INT,    // 输入参数    @Name NVARCHAR(32) OUTPUT,  // 输出参数,还带长度    @Age INT OUTPUT // 输出参数ASBEGIN    SET @Name = 'Furion Output';    // 输出结果集    SELECT *    FROM dbo.Test    WHERE Id > @Id;    // 输出结果集    SELECT TOP 10           *    FROM dbo.Test;    SET @Age = 27;    // 带 RETURN 返回    RETURN 10;END;
using Furion.DatabaseAccessor;using System.Data;namespace Furion.Application{    public class ProcOutputModel    {        public int Id { get; set; } // 输入参数        [DbParameter(ParameterDirection.Output, Size = 32)]        public string Name { get; set; }    // 输出参数        [DbParameter(ParameterDirection.Output)]        public int Age { get; set; }    // 输出参数        [DbParameter(ParameterDirection.ReturnValue)]        public int ReturnValue { get; set; }    // 返回值    }}
// ==== 同步操作 ====// 示例一ProcedureOutputResult result = "PROC_Name".SqlProcedureOutput(new ProcOutputModel{ Id=1});// 示例二ProcedureOutputResult result = "PROC_Name".SqlProcedureOutput(new ProcOutputModel{ Id=1});// 示例三ProcedureOutputResult<(List<Person>, List<Student>)> result = "PROC_Name".SqlProcedureOutput<(List<Person>, List<Student>)>(new ProcOutputModel{ Id=1});// ==== 异步操作 ====// 示例一ProcedureOutputResult result = await "PROC_Name".SqlProcedureOutputAsync(new ProcOutputModel{ Id=1});// 示例二ProcedureOutputResult result = await "PROC_Name".SqlProcedureOutputAsync(new ProcOutputModel{ Id=1});// 示例三ProcedureOutputResult<(List<Person>, List<Student>)> result = await "PROC_Name".SqlProcedureOutputAsync<(List<Person>, List<Student>)>(new ProcOutputModel{ Id=1});

9.15.4 懒人无敌 函数 🐮

9.15.4.1 标量函数

// ==== 同步操作 ====// 示例一var value = "FN_Name".SqlFunctionScalar();// 示例二var value = "FN_Name".SqlFunctionScalar(new {id = 1});// 示例三var value = "FN_Name".SqlFunctionScalar<string>();// 示例四var value = "FN_Name".SqlFunctionScalar<int>(new {id = 1});// ==== 异步操作 ====// 示例一var value = await "FN_Name".SqlFunctionScalarAsync();// 示例二var value = await "FN_Name".SqlFunctionScalarAsync(new {id = 1});// 示例三var value = await "FN_Name".SqlFunctionScalarAsync<string>();// 示例四var value = await "FN_Name".SqlFunctionScalarAsync<int>(new {id = 1});

9.15.4.2 表值函数

// ==== 同步操作 ====// 示例一var dataTable = "FN_Name".SqlFunctionQuery();// 示例二var dataTable = "FN_Name".SqlFunctionQuery(new {id = 1});// 示例三var persons = "FN_Name".SqlFunctionQuery<Person>();// 示例四var persons = "FN_Name".SqlFunctionQuery<Person>(new {id = 1});// ==== 异步操作 ====// 示例一var dataTable = await "FN_Name".SqlFunctionQueryAsync();// 示例二var dataTable = await "FN_Name".SqlFunctionQueryAsync(new {id = 1});// 示例三var persons = await "FN_Name".SqlFunctionQueryAsync<Person>();// 示例四var persons = await "FN_Name".SqlFunctionQueryAsync<Person>(new {id = 1});

9.15.5 设置超时时间

var data = "select * from table".SetCommandTimeout(100).SqlQuery(); // 单位秒

9.15.6 ISqlRepository 操作

ISqlRepository 仓储是专门处理 Sql 操作的,无需实体方式,所有接口和 懒人无敌 方式一样:

// 示例一var dataTable = sqlRepository.SqlQuery("select * from person");// 示例二var dataTable = sqlRepository.SqlQuery("select * from person where id > @id", new { id = 10});// 示例四var persons = sqlRepository.SqlQuery<Person>("select * from person");// 示例五var persons = sqlRepository.SqlQuery<Person>("select * from person where id > @id", new { id = 10});// 不再举例子。。。
补充说明

不管是哪种方式操作 Sql ,方法名参数都是一致的,如:

  • SqlQuery
  • SqlQueryAsync
  • SqlQueries
  • SqlQueriesAsync
  • SqlNonQuery
  • SqlNonQueryAsync
  • SqlScalar
  • SqlScalarAsync
  • SqlProcedureQuery
  • SqlProcedureQueryAsync
  • SqlProcedureQueries
  • SqlProcedureQueriesAsync
  • SqlProcedureScalar
  • SqlProcedureScalarAsync
  • SqlProcedureNonQuery
  • SqlProcedureNonQueryAsync
  • SqlProcedureOutput
  • SqlProcedureOutputAsync
  • SqlFunctionScalar
  • SqlFunctionScalarAsync
  • SqlFunctionQuery
  • SqlFunctionQuery

9.15.7 IRepository 操作

IRepository 也能操作 sql,调用方法也是和上面一致的,如:

var dataTable = repository.Sql().SqlQuery("select * from person");
特别说明

由于篇幅有限,不再列举所有例子。

9.15.8 IRepository<TEntity> 操作

IRepository<TEntity> 也能操作 sql,调用方法也是和上面一致的,如:

var dataTable = personRepository.SqlQuery("select * from person");
特别说明

由于篇幅有限,不再列举所有例子。

9.15.9 关于 Sql 参数

所有 sql存储过程函数 参数都支持四种方式:

  • DbParameter[]:数组类型
  • new {}:匿名类型
  • new Class{}:强类型类型(支持复杂存储过程参数)
  • Dictionary<string,object> 类型
小知识

建议除了复杂的存储过程(带 OUTPUT/RETURN)的以外,所有参数建议使用 new {} 匿名类型,如果需要动态参数,则可以使用 Dictionary<string,object> 类型。

参数大小写问题

由于不同数据库对查询参数大小写问题处理不一致,所以建议所有查询参数和参数名或属性名完全一致

9.15.10 多数据库 Sql 操作 💯 💛

Furion 框架拥有非常灵活的多数据库操作方式,只需通过多数据库上下文定位器即可动态切换数据库。

9.15.10.1 懒人无敌 🐮 方式

var dataTable = "select * from person".Change<MySqlDbContextLocator>().SqlQuery();var persons = "select * from person whre id > @id".Change<SqliteDbContextLocator>().SqlQuery<Person>();
补充说明

懒人方式 只需要通过 Change<TDbContextLocator> 方式即可动态切换数据库。

9.15.10.2 ISqlRepository 方式

只需要通过 ISqlRepository<TDbContextLocator> 注入或通过 sqlRepository.Change<TDbContextLocator>() 切换。

9.15.10.3 IRepository 方式

只需要通过 repository.Change<TDbContextLocator>() 获取即可。

9.15.10.4 IRepository<TEntity> 方式

只需要通过 IRepository<TEntity, TDbContextLocator> 注入或通过 personRepository.Change<TEntity, TDbContextLocator>() 切换。

9.15.11 切换数据库

Furion 框架中,不管是懒人模式还是仓储模式都是通过 .Change<TDbContextLocator> 方式切换数据库,如:

// 懒人模式var data = "select * from table".Change<MySqlDbContextLocator>().SqlQuery<Data>();// 仓储方式var data = req.Change<MySqlDbContextLocator>().SqlQuery<Data>("select * from table");

9.15.12 多线程共享作用域

默认情况下,所有的 字符串实体 拓展都有自己独立维护的 ServiceProvider 作用域。

Web 请求中,默认是 HttpContext.RequestServices,但在 非 Web,如多线程操作,后台任务,事件总线等场景下会自动创建新的作用域,实际上这是非常不必要的内存开销。

这时,我们只需要通过 .SetXXXScoped(service) 共享当前服务提供器作用域即可,如:

Scoped.Create((fac, scope) => {    "select * from table".SetContextScoped(scope.ServiceProvider).SqlQuery();});

9.15.13 静态 Default 方式构建

SqlExecutePart.Default.SetSqlString("select * from person").SqlQuery();

9.15.14 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.15 Sql 操作

温馨提示

推荐使用 《9.17 Sql 高级代理》代替本章节功能。Sql 高级代理 能够提供更容易且更易维护的方式。

例子说明

本章节例子均以 sql server 数据库写的例子,命令参数统一用 @ 符号,但不同数据库的参数前缀有所不同,如:sql server 采用 @,oracle 采用 :,my sql 采用 ?

9.15.1 关于 Sql

Furion 框架提供非常多且灵活的 sql 操作方法,且性能不输于 dapper,同时逼近 ADO.NET 原生操作。

9.15.2 懒人无敌 Sql 🐮

9.15.2.1 返回 DataTable

// ==== 同步操作 ====// 示例一var dataTable = "select * from person".SqlQuery();// 示例二var dataTable = "select top 10 * from person where id > @id".SqlQuery(new {id = 10});// 示例三var dataTable = "select Id, Name, Age from person where name like @name".SqlQuery(new Dictionary<string,object>{ {"name", "%Furion%"} });// 示例四var dataTable = "select * from person where name=@name limit 1,10".SqlQuery(new []{ new MySqlParameter("name","Furion") });// 示例五var dataTable = "select * from person where id>@id and name like @name".SqlQuery(new YourModel { Id = 1, Name = "%Furion%" });// 示例六var dataTable = "exec PROC_GetPerson @id".SqlQuery(new {id = 10});// 示例七var dataTable = "select * from FN_GetPersons(@id)".SqlQuery(new {id = 10});// 示例八var dataTable = @"select * from person pleft join personDetail pd on p.Id == pd.pidwhere p.Id > @id;".SqlQuery(new {id = 10});// ==== 异步操作 ====// 示例一var dataTable = await "select * from person".SqlQueryAsync();// 示例二var dataTable = await "select top 10 * from person where id > @id".SqlQueryAsync(new {id = 10});// 示例三var dataTable = await "select Id, Name, Age from person where name like @name".SqlQueryAsync(new Dictionary<string,object>{ {"name", "%Furion%"} });// 示例四var dataTable = await "select * from person where name=@name limit 1,10".SqlQueryAsync(new []{ new MySqlParameter("name","Furion") });// 示例五var dataTable = await "select * from person where id>@id and name like @name".SqlQueryAsync(new YourModel { Id = 1, Name = "%Furion%" });// 示例六var dataTable = await "exec PROC_GetPerson @id".SqlQueryAsync(new {id = 10});// 示例七var dataTable = await "select * from FN_GetPersons(@id)".SqlQueryAsync(new {id = 10});// 示例八var dataTable = await @"select * from person pleft join personDetail pd on p.Id == pd.pidwhere p.Id > @id;".SqlQueryAsync(new {id = 10});

9.15.2.2 返回 List<T>

// ==== 同步操作 ====// 示例一var persons = "select * from person".SqlQuery<Person>();// 示例二var persons = "select top 10 * from person where id > @id".SqlQuery<Person>(new {id = 10});// 示例三var persons = "select Id, Name, Age from person where name like @name".SqlQuery<Person>(new Dictionary<string,object>{ {"name", "%Furion%"} });// 示例四var persons = "select * from person where name=@name limit 1,10".SqlQuery<Person>(new []{ new MySqlParameter("name","Furion") });// 示例五var persons = "select * from person where id>@id and name like @name".SqlQuery<Person>(new YourModel { Id = 1, Name = "%Furion%" });// 示例六var persons = "exec PROC_GetPerson @id".SqlQuery<Person>(new {id = 10});// 示例七var persons = "select * from FN_GetPersons(@id)".SqlQuery<Person>(new {id = 10});// 示例八var persons = @"select * from person pleft join personDetail pd on p.Id == pd.pidwhere p.Id > @id;".SqlQuery<Person>(new {id = 10});// ==== 异步操作 ====// 示例一var persons = await "select * from person".SqlQueryAsync<Person>();// 示例二var persons = await "select top 10 * from person where id > @id".SqlQueryAsync<Person>(new {id = 10});// 示例三var persons = await "select Id, Name, Age from person where name like @name".SqlQueryAsync<Person>(new Dictionary<string,object>{ {"name", "%Furion%"} });// 示例四var persons = await "select * from person where name=@name limit 1,10".SqlQueryAsync<Person>(new []{ new MySqlParameter("name","Furion") });// 示例五var persons = await "select * from person where id>@id and name like @name".SqlQueryAsync<Person>(new YourModel { Id = 1, Name = "%Furion%" });// 示例六var persons = await "exec PROC_GetPerson @id".SqlQueryAsync<Person>(new {id = 10});// 示例七var persons = await "select * from FN_GetPersons(@id)".SqlQueryAsync<Person>(new {id = 10});// 示例八var persons = await @"select * from person pleft join personDetail pd on p.Id == pd.pidwhere p.Id > @id;".SqlQueryAsync<Person>(new {id = 10});

9.15.2.3 返回 DataSet

// ==== 同步操作 ====// 示例一var dataSet = @"select * from person;select * from student;".SqlQueries();// 示例二var dataSet = @"select * from person where Id > @id;select * from student where Name like @name;".SqlQueries(new {id = 1, name = "%furion%"});// 示例三var dataSet = @"select * from person;exec PROC_GetStudents(@id);select 'Furion';select * from FN_GetPerson(@id);".SqlQueries(new {id = 1});// ==== 异步操作 ====// 示例一var dataSet = await @"select * from person;select * from student;".SqlQueriesAsync();// 示例二var dataSet = await @"select * from person where Id > @id;select * from student where Name like @name;".SqlQueriesAsync(new {id = 1, name = "%furion%"});// 示例三var dataSet = await @"select * from person;exec PROC_GetStudents(@id);select 'Furion';select * from FN_GetPerson(@id);".SqlQueriesAsync(new {id = 1});

9.15.2.4 返回 Tuple<T1,...T8>

// ==== 同步操作 ====// 示例一var (persons, students) = @"select * from person;select * from student;".SqlQueries<Person,Student>();// 示例二var (persons, students) = @"select * from person where Id > @id;select * from student where Name like @name;".SqlQueries<Person,Student>(new {id = 1, name = "%furion%"});// 示例三var (persons, students, string, PersonDto) = @"select * from person;exec PROC_GetStudents(@id);select 'Furion';select * from FN_GetPerson(@id);".SqlQueries<Person, Student, string, PersonDto>(new {id = 1});// ==== 异步操作 ====// 示例一var (persons, students) = await @"select * from person;select * from student;".SqlQueriesAsync<Person,Student>();// 示例二var (persons, students) = await @"select * from person where Id > @id;select * from student where Name like @name;".SqlQueriesAsync<Person,Student>(new {id = 1, name = "%furion%"});// 示例三var (persons, students, string, PersonDto) = await @"select * from person;exec PROC_GetStudents(@id);select 'Furion';select * from FN_GetPerson(@id);".SqlQueriesAsync<Person, Student, string, PersonDto>(new {id = 1});

9.15.2.5 返回 单行单列

// ==== 同步操作 ====// 示例一var value = "select Name from person where id = @id".SqlScalar(new {id = 1});// 示例二var value = "select Name from person where id = @id".SqlScalar<string>(new {id = 1});// 示例三var value = "select Age from person where id = @id".SqlScalar<int>(new {id = 1});// ==== 异步操作 ====// 示例一var value = await "select Name from person where id = @id".SqlScalarAsync(new {id = 1});// 示例二var value = await "select Name from person where id = @id".SqlScalarAsync<string>(new {id = 1});// 示例三var value = await "select Age from person where id = @id".SqlScalarAsync<int>(new {id = 1});

9.15.2.6 返回 受影响行数

// ==== 同步操作 ====// 示例一var rowEffects = "insert into person(Name,Age,Address) values(@name,@age,@address)".SqlNonQuery(person);// 示例二var rowEffects = @"insert into person(Name,Age,Address) values(@name,@age,@address);insert into person(Name,Age,Address) values(@name,@age,@address);".SqlNonQuery(persons);// 示例三var rowEffects = "update person set name=@name where id=@id".SqlNonQuery(new {id=1, name="百小僧"});// 示例四var rowEffects = "delete from person where @id > 10".SqlNonQuery(new {id=1});// ==== 异步操作 ====// 示例一var rowEffects = await "insert into person(Name,Age,Address) values(@name,@age,@address)".SqlNonQueryAsync(person);// 示例二var rowEffects = @"insert into person(Name,Age,Address) values(@name,@age,@address);insert into person(Name,Age,Address) values(@name,@age,@address);".SqlNonQueryAsync(persons);// 示例三var rowEffects = await "update person set name=@name where id=@id".SqlNonQueryAsync(new {id=1, name="百小僧"});// 示例四var rowEffects = await "delete from person where @id > 10".SqlNonQueryAsync(new {id=1});

9.15.3 懒人无敌 存储过程 🐮

9.15.3.1 返回 DataTable

// ==== 同步操作 ====// 示例一var dataTable = "PROC_Name".SqlProcedureQuery();// 示例二var dataTable = "PROC_Name".SqlProcedureQuery(new {id = 1});// 示例三var dataTable = "PROC_Name".SqlProcedureQuery(new {id = 1, age = 27});// ==== 异步操作 ====// 示例一var dataTable = await "PROC_Name".SqlProcedureQueryAsync();// 示例二var dataTable = await "PROC_Name".SqlProcedureQueryAsync(new {id = 1});// 示例三var dataTable = await "PROC_Name".SqlProcedureQueryAsync(new {id = 1, age = 27});

9.15.3.2 返回 List<T>

// ==== 同步操作 ====// 示例一var persons = "PROC_Name".SqlProcedureQuery<Person>();// 示例二var persons = "PROC_Name".SqlProcedureQuery<Person>(new {id = 1});// 示例三var persons = "PROC_Name".SqlProcedureQuery<Person>(new {id = 1, age = 27});// ==== 异步操作 ====// 示例一var persons = await "PROC_Name".SqlProcedureQueryAsync<Person>();// 示例二var persons = await "PROC_Name".SqlProcedureQueryAsync<Person>(new {id = 1});// 示例三var persons = await "PROC_Name".SqlProcedureQueryAsync<Person>(new {id = 1, age = 27});

9.15.3.3 返回 DataSet

// ==== 同步操作 ====// 示例一var dataSet = "PROC_Name".SqlProcedureQueries();// 示例二var dataSet = "PROC_Name".SqlProcedureQueries(new {id = 1});// 示例三var dataSet = "PROC_Name".SqlProcedureQueries(new {id = 1, age = 27});// ==== 异步操作 ====// 示例一var dataSet = await "PROC_Name".SqlProcedureQueriesAsync();// 示例二var dataSet = await "PROC_Name".SqlProcedureQueriesAsync(new {id = 1});// 示例三var dataSet = await "PROC_Name".SqlProcedureQueriesAsync(new {id = 1, age = 27});

9.15.3.4 返回 Tuple<T1,...T8>

// ==== 同步操作 ====// 示例一var persons = "PROC_Name".SqlProcedureQueries<Person>();// 示例二var (persons,students) = "PROC_Name".SqlProcedureQueries<Person,Student>(new {id = 1});// 示例三var (persons,students,string) = "PROC_Name".SqlProcedureQueries<Person,Student,string>(new {id = 1, age = 27});// 示例四var (persons,students,personDetail,string) = "PROC_Name".SqlProcedureQueries<Person,Student,PersonDetail,string>(new {id = 1, age = 27});// ==== 异步操作 ====// 示例一var persons = await "PROC_Name".SqlProcedureQueriesAsync<Person>();// 示例二var (persons,students) = await "PROC_Name".SqlProcedureQueriesAsync<Person,Student>(new {id = 1});// 示例三var (persons,students,string) = await "PROC_Name".SqlProcedureQueriesAsync<Person,Student,string>(new {id = 1, age = 27});// 示例四var (persons,students,personDetail,string) = await "PROC_Name".SqlProcedureQueriesAsync<Person,Student,PersonDetail,string>(new {id = 1, age = 27});

9.15.3.5 返回 单行单列

// ==== 同步操作 ====// 示例一var value = "PROC_Name".SqlProcedureScalar(new {id = 1});// 示例二var value = "PROC_Name".SqlProcedureScalar<string>(new {id = 1, name = "新生帝", address ="广东省中山市"});// 示例三var value = "PROC_Name".SqlProcedureScalar<int>(new {id = 1,  address ="广东省中山市"});// ==== 异步操作 ====// 示例一var value = await "PROC_Name".SqlProcedureScalarAsync(new {id = 1});// 示例二var value = await "PROC_Name".SqlProcedureScalarAsync<string>(new {id = 1, name = "新生帝", address ="广东省中山市"});// 示例三var value = await "PROC_Name".SqlProcedureScalarAsync<int>(new {id = 1,  address ="广东省中山市"});

9.15.3.6 返回 受影响行数

// ==== 同步操作 ====// 示例一var rowEffects = "PROC_Name".SqlProcedureNonQuery(person);// 示例二var rowEffects = "PROC_Name".SqlProcedureNonQuery(new {id = 1, name = "新生帝", address ="广东省中山市"});// 示例三var rowEffects = "PROC_Name".SqlProcedureNonQuery(new {id=1, name="百小僧"});// 示例四var rowEffects = "PROC_Name".SqlProcedureNonQuery(new {id=1});// ==== 异步操作 ====// 示例一var rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(person);// 示例二var rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new {id = 1, name = "新生帝", address ="广东省中山市"});// 示例三var rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new {id=1, name="百小僧"});// 示例四var rowEffects = await "PROC_Name".SqlProcedureNonQueryAsync(new {id=1});

9.15.3.7 带 OUTPUT/RETURN 返回

CREATE PROC PROC_Output    @Id INT,    // 输入参数    @Name NVARCHAR(32) OUTPUT,  // 输出参数,还带长度    @Age INT OUTPUT // 输出参数ASBEGIN    SET @Name = 'Furion Output';    // 输出结果集    SELECT *    FROM dbo.Test    WHERE Id > @Id;    // 输出结果集    SELECT TOP 10           *    FROM dbo.Test;    SET @Age = 27;    // 带 RETURN 返回    RETURN 10;END;
using Furion.DatabaseAccessor;using System.Data;namespace Furion.Application{    public class ProcOutputModel    {        public int Id { get; set; } // 输入参数        [DbParameter(ParameterDirection.Output, Size = 32)]        public string Name { get; set; }    // 输出参数        [DbParameter(ParameterDirection.Output)]        public int Age { get; set; }    // 输出参数        [DbParameter(ParameterDirection.ReturnValue)]        public int ReturnValue { get; set; }    // 返回值    }}
// ==== 同步操作 ====// 示例一ProcedureOutputResult result = "PROC_Name".SqlProcedureOutput(new ProcOutputModel{ Id=1});// 示例二ProcedureOutputResult result = "PROC_Name".SqlProcedureOutput(new ProcOutputModel{ Id=1});// 示例三ProcedureOutputResult<(List<Person>, List<Student>)> result = "PROC_Name".SqlProcedureOutput<(List<Person>, List<Student>)>(new ProcOutputModel{ Id=1});// ==== 异步操作 ====// 示例一ProcedureOutputResult result = await "PROC_Name".SqlProcedureOutputAsync(new ProcOutputModel{ Id=1});// 示例二ProcedureOutputResult result = await "PROC_Name".SqlProcedureOutputAsync(new ProcOutputModel{ Id=1});// 示例三ProcedureOutputResult<(List<Person>, List<Student>)> result = await "PROC_Name".SqlProcedureOutputAsync<(List<Person>, List<Student>)>(new ProcOutputModel{ Id=1});

9.15.4 懒人无敌 函数 🐮

9.15.4.1 标量函数

// ==== 同步操作 ====// 示例一var value = "FN_Name".SqlFunctionScalar();// 示例二var value = "FN_Name".SqlFunctionScalar(new {id = 1});// 示例三var value = "FN_Name".SqlFunctionScalar<string>();// 示例四var value = "FN_Name".SqlFunctionScalar<int>(new {id = 1});// ==== 异步操作 ====// 示例一var value = await "FN_Name".SqlFunctionScalarAsync();// 示例二var value = await "FN_Name".SqlFunctionScalarAsync(new {id = 1});// 示例三var value = await "FN_Name".SqlFunctionScalarAsync<string>();// 示例四var value = await "FN_Name".SqlFunctionScalarAsync<int>(new {id = 1});

9.15.4.2 表值函数

// ==== 同步操作 ====// 示例一var dataTable = "FN_Name".SqlFunctionQuery();// 示例二var dataTable = "FN_Name".SqlFunctionQuery(new {id = 1});// 示例三var persons = "FN_Name".SqlFunctionQuery<Person>();// 示例四var persons = "FN_Name".SqlFunctionQuery<Person>(new {id = 1});// ==== 异步操作 ====// 示例一var dataTable = await "FN_Name".SqlFunctionQueryAsync();// 示例二var dataTable = await "FN_Name".SqlFunctionQueryAsync(new {id = 1});// 示例三var persons = await "FN_Name".SqlFunctionQueryAsync<Person>();// 示例四var persons = await "FN_Name".SqlFunctionQueryAsync<Person>(new {id = 1});

9.15.5 设置超时时间

var data = "select * from table".SetCommandTimeout(100).SqlQuery(); // 单位秒

9.15.6 ISqlRepository 操作

ISqlRepository 仓储是专门处理 Sql 操作的,无需实体方式,所有接口和 懒人无敌 方式一样:

// 示例一var dataTable = sqlRepository.SqlQuery("select * from person");// 示例二var dataTable = sqlRepository.SqlQuery("select * from person where id > @id", new { id = 10});// 示例四var persons = sqlRepository.SqlQuery<Person>("select * from person");// 示例五var persons = sqlRepository.SqlQuery<Person>("select * from person where id > @id", new { id = 10});// 不再举例子。。。
补充说明

不管是哪种方式操作 Sql ,方法名参数都是一致的,如:

  • SqlQuery
  • SqlQueryAsync
  • SqlQueries
  • SqlQueriesAsync
  • SqlNonQuery
  • SqlNonQueryAsync
  • SqlScalar
  • SqlScalarAsync
  • SqlProcedureQuery
  • SqlProcedureQueryAsync
  • SqlProcedureQueries
  • SqlProcedureQueriesAsync
  • SqlProcedureScalar
  • SqlProcedureScalarAsync
  • SqlProcedureNonQuery
  • SqlProcedureNonQueryAsync
  • SqlProcedureOutput
  • SqlProcedureOutputAsync
  • SqlFunctionScalar
  • SqlFunctionScalarAsync
  • SqlFunctionQuery
  • SqlFunctionQuery

9.15.7 IRepository 操作

IRepository 也能操作 sql,调用方法也是和上面一致的,如:

var dataTable = repository.Sql().SqlQuery("select * from person");
特别说明

由于篇幅有限,不再列举所有例子。

9.15.8 IRepository<TEntity> 操作

IRepository<TEntity> 也能操作 sql,调用方法也是和上面一致的,如:

var dataTable = personRepository.SqlQuery("select * from person");
特别说明

由于篇幅有限,不再列举所有例子。

9.15.9 关于 Sql 参数

所有 sql存储过程函数 参数都支持四种方式:

  • DbParameter[]:数组类型
  • new {}:匿名类型
  • new Class{}:强类型类型(支持复杂存储过程参数)
  • Dictionary<string,object> 类型
小知识

建议除了复杂的存储过程(带 OUTPUT/RETURN)的以外,所有参数建议使用 new {} 匿名类型,如果需要动态参数,则可以使用 Dictionary<string,object> 类型。

参数大小写问题

由于不同数据库对查询参数大小写问题处理不一致,所以建议所有查询参数和参数名或属性名完全一致

9.15.10 多数据库 Sql 操作 💯 💛

Furion 框架拥有非常灵活的多数据库操作方式,只需通过多数据库上下文定位器即可动态切换数据库。

9.15.10.1 懒人无敌 🐮 方式

var dataTable = "select * from person".Change<MySqlDbContextLocator>().SqlQuery();var persons = "select * from person whre id > @id".Change<SqliteDbContextLocator>().SqlQuery<Person>();
补充说明

懒人方式 只需要通过 Change<TDbContextLocator> 方式即可动态切换数据库。

9.15.10.2 ISqlRepository 方式

只需要通过 ISqlRepository<TDbContextLocator> 注入或通过 sqlRepository.Change<TDbContextLocator>() 切换。

9.15.10.3 IRepository 方式

只需要通过 repository.Change<TDbContextLocator>() 获取即可。

9.15.10.4 IRepository<TEntity> 方式

只需要通过 IRepository<TEntity, TDbContextLocator> 注入或通过 personRepository.Change<TEntity, TDbContextLocator>() 切换。

9.15.11 切换数据库

Furion 框架中,不管是懒人模式还是仓储模式都是通过 .Change<TDbContextLocator> 方式切换数据库,如:

// 懒人模式var data = "select * from table".Change<MySqlDbContextLocator>().SqlQuery<Data>();// 仓储方式var data = req.Change<MySqlDbContextLocator>().SqlQuery<Data>("select * from table");

9.15.12 多线程共享作用域

默认情况下,所有的 字符串实体 拓展都有自己独立维护的 ServiceProvider 作用域。

Web 请求中,默认是 HttpContext.RequestServices,但在 非 Web,如多线程操作,后台任务,事件总线等场景下会自动创建新的作用域,实际上这是非常不必要的内存开销。

这时,我们只需要通过 .SetXXXScoped(service) 共享当前服务提供器作用域即可,如:

Scoped.Create((fac, scope) => {    "select * from table".SetContextScoped(scope.ServiceProvider).SqlQuery();});

9.15.13 静态 Default 方式构建

SqlExecutePart.Default.SetSqlString("select * from person").SqlQuery();

9.15.14 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-start/index.html b/handbook/build/docs/dbcontext-start/index.html index a7d3386b4f..d0cd898921 100644 --- a/handbook/build/docs/dbcontext-start/index.html +++ b/handbook/build/docs/dbcontext-start/index.html @@ -2,22 +2,21 @@ - - - + +9.0 入门简要 | Furion -9.0 入门简要 | Furion - - + + +
-

9.0 入门简要

9.0.1 入门准备

入门条件

EF/EFCore 有一定基础了解,还未接触的可先看 【EFCore 基础】

9.0.1.1 安装对应数据库包

tip

在本章节所在的类别中,所有数据库操作功能均需要依赖 EntityFramework Core 框架,但 Furion 框架底层并未集成 EntityFramework Core 包,而是采用动态加载程序集方式自动载入。

所以,如需使用本大类数据库功能,需安装对应的 EntityFramework Core 数据库包:

  • SqlServerMicrosoft.EntityFrameworkCore.SqlServer (支持 SqlServer 2005 +)
  • SqliteMicrosoft.EntityFrameworkCore.Sqlite
  • CosmosMicrosoft.EntityFrameworkCore.Cosmos
  • InMemoryDatabaseMicrosoft.EntityFrameworkCore.InMemory
  • MySql
    • Pomelo.EntityFrameworkCore.MySql:(支持 MySql 5.x +)
    • MySql.EntityFrameworkCore:支持 (MySql 8.x +)
  • PostgreSQLNpgsql.EntityFrameworkCore.PostgreSQL
  • OracleOracle.EntityFrameworkCore (支持 Oracle 10 +)
  • FirebirdFirebirdSql.EntityFrameworkCore.Firebird
  • DmMicrosoft.EntityFrameworkCore.Dm
小知识

这些数据库包应该安装在 Furion.EntityFramework.Core 层。特殊情况需安装在 Furion.Core 层中,如 Mysql HasCharset() 配置。

9.0.1.2 创建数据库上下文

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class DefaultDbContext : AppDbContext<DefaultDbContext>    {        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)        {        }    }}
特别注意

每一个数据库上下文都需继承 AppDbContext<TDbContext, TDbContextLocator> 基类,默认数据库的 TDbContextLocatorMasterDbContextLocator,无需显式编写。

非默认数据库则需显式继承并申明,如:AppDbContext<OtherDbContext, OtherDbContextLocator>

想了解更多可查阅 【数据库上下文定位器】 章节。

9.0.1.3 配置连接字符串

Furion 框架提供多种方式配置数据库连接字符串:

  • appsettings.json 中配置
{  "ConnectionStrings": {    "Sqlite3ConnectionString": "Data Source=./Furion.db"  }}
  • 自定义 .json 文件配置
{  "ConnectionStrings": {    "Sqlite3ConnectionString": "Data Source=./Furion.db"  }}

该方式和在 appsettings.json 的区别是自定义的 .json 文件不会自动添加到项目中,须在 Visual Studio 中配置 .json 右键属性,设置 复制 输出目录为 如果较新则复制,生成操作为:内容

  • [AppDbContext] 特性配置
[AppDbContext("Data Source=./Furion.db", DbProvider.Sqlite)]public class DefaultDbContext : AppDbContext<DefaultDbContext>{}
  • 在注册上下文时配置
services.AddDatabaseAccessor(options =>{    // options.AddDb<DefaultDbContext>(connectionMetadata: "配置Key或连接字符串");    options.AddDbPool<DefaultDbContext>(connectionMetadata: "配置Key或连接字符串");});
  • DbContext 中配置
using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    public class DefaultDbContext : AppDbContext<DefaultDbContext>    {        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)        {        }        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)        {            optionsBuilder.UseSqlite("连接字符串");            base.OnConfiguring(optionsBuilder);        }    }}

9.0.1.4 各类数据库连接字符串配置示例

  • SqliteData Source=./Furion.db
  • MySqlData Source=localhost;Database=Furion;User ID=root;Password=000000;pooling=true;port=3306;sslmode=none;CharSet=utf8;
  • SqlServerServer=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;
  • OracleUser Id=orcl;Password=orcl;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl)))
  • PostgreSQLPORT=5432;DATABASE=postgres;HOST=127.0.0.1;PASSWORD=postgres;USER ID=postgres;

9.0.1.5 注册数据库上下文

Furion.EntityFramework.Core\Startup.cs
using Furion.DependencyInjection;using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(600)]    public sealed class FurEntityFrameworkCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            // 配置数据库上下文,支持N个数据库            services.AddDatabaseAccessor(options =>            {                // 配置默认数据库                options.AddDbPool<DefaultDbContext>();                // 配置多个数据库,多个数据库必须指定数据库上下文定位器               //  options.AddDbPool<SqliteDbContext, SqliteDbContextLocaotr>();            });        }    }}
了解更多数据库数据库注册方式

如需了解各种数据库及版本注册方式可查阅 【多数据库注册章节

9.0.1.6 Code First 说明

特别注意

Furion 框架默认数据迁移的程序集为:Furion.Database.Migrations,所以如果您改了程序集名称或通过 Nuget 方式安装的 Furion 包,则需要配置迁移程序集名称:

services.AddDatabaseAccessor(options =>{    options.AddDbPool<DefaultDbContext>(DbProvider.Sqlite);}, "存放迁移文件的项目名称");

另外,如果应用中配置了多个数据库上下文,那么所有的 迁移命令 都需要指定 -Context 数据库上下文名称 参数。如:

Add-Migration v1.0.0 -Context DefaultDbContext

9.0.2 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.0 入门简要

9.0.1 入门准备

入门条件

EF/EFCore 有一定基础了解,还未接触的可先看 【EFCore 基础】

9.0.1.1 安装对应数据库包

tip

在本章节所在的类别中,所有数据库操作功能均需要依赖 EntityFramework Core 框架,但 Furion 框架底层并未集成 EntityFramework Core 包,而是采用动态加载程序集方式自动载入。

所以,如需使用本大类数据库功能,需安装对应的 EntityFramework Core 数据库包:

  • SqlServerMicrosoft.EntityFrameworkCore.SqlServer (支持 SqlServer 2005 +)
  • SqliteMicrosoft.EntityFrameworkCore.Sqlite
  • CosmosMicrosoft.EntityFrameworkCore.Cosmos
  • InMemoryDatabaseMicrosoft.EntityFrameworkCore.InMemory
  • MySql
    • Pomelo.EntityFrameworkCore.MySql:(支持 MySql 5.x +)
    • MySql.EntityFrameworkCore:支持 (MySql 8.x +)
  • PostgreSQLNpgsql.EntityFrameworkCore.PostgreSQL
  • OracleOracle.EntityFrameworkCore (支持 Oracle 10 +)
  • FirebirdFirebirdSql.EntityFrameworkCore.Firebird
  • DmMicrosoft.EntityFrameworkCore.Dm
小知识

这些数据库包应该安装在 Furion.EntityFramework.Core 层。特殊情况需安装在 Furion.Core 层中,如 Mysql HasCharset() 配置。

9.0.1.2 创建数据库上下文

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class DefaultDbContext : AppDbContext<DefaultDbContext>    {        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)        {        }    }}
特别注意

每一个数据库上下文都需继承 AppDbContext<TDbContext, TDbContextLocator> 基类,默认数据库的 TDbContextLocatorMasterDbContextLocator,无需显式编写。

非默认数据库则需显式继承并申明,如:AppDbContext<OtherDbContext, OtherDbContextLocator>

想了解更多可查阅 【数据库上下文定位器】 章节。

9.0.1.3 配置连接字符串

Furion 框架提供多种方式配置数据库连接字符串:

  • appsettings.json 中配置
{  "ConnectionStrings": {    "Sqlite3ConnectionString": "Data Source=./Furion.db"  }}
  • 自定义 .json 文件配置
{  "ConnectionStrings": {    "Sqlite3ConnectionString": "Data Source=./Furion.db"  }}

该方式和在 appsettings.json 的区别是自定义的 .json 文件不会自动添加到项目中,须在 Visual Studio 中配置 .json 右键属性,设置 复制 输出目录为 如果较新则复制,生成操作为:内容

  • [AppDbContext] 特性配置
[AppDbContext("Data Source=./Furion.db", DbProvider.Sqlite)]public class DefaultDbContext : AppDbContext<DefaultDbContext>{}
  • 在注册上下文时配置
services.AddDatabaseAccessor(options =>{    // options.AddDb<DefaultDbContext>(connectionMetadata: "配置Key或连接字符串");    options.AddDbPool<DefaultDbContext>(connectionMetadata: "配置Key或连接字符串");});
  • DbContext 中配置
using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    public class DefaultDbContext : AppDbContext<DefaultDbContext>    {        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)        {        }        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)        {            optionsBuilder.UseSqlite("连接字符串");            base.OnConfiguring(optionsBuilder);        }    }}

9.0.1.4 各类数据库连接字符串配置示例

  • SqliteData Source=./Furion.db
  • MySqlData Source=localhost;Database=Furion;User ID=root;Password=000000;pooling=true;port=3306;sslmode=none;CharSet=utf8;
  • SqlServerServer=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;
  • OracleUser Id=orcl;Password=orcl;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl)))
  • PostgreSQLPORT=5432;DATABASE=postgres;HOST=127.0.0.1;PASSWORD=postgres;USER ID=postgres;

9.0.1.5 注册数据库上下文

Furion.EntityFramework.Core\Startup.cs
using Furion.DependencyInjection;using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(600)]    public sealed class FurEntityFrameworkCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            // 配置数据库上下文,支持N个数据库            services.AddDatabaseAccessor(options =>            {                // 配置默认数据库                options.AddDbPool<DefaultDbContext>();                // 配置多个数据库,多个数据库必须指定数据库上下文定位器               //  options.AddDbPool<SqliteDbContext, SqliteDbContextLocaotr>();            });        }    }}
了解更多数据库数据库注册方式

如需了解各种数据库及版本注册方式可查阅 【多数据库注册章节

9.0.1.6 Code First 说明

特别注意

Furion 框架默认数据迁移的程序集为:Furion.Database.Migrations,所以如果您改了程序集名称或通过 Nuget 方式安装的 Furion 包,则需要配置迁移程序集名称:

services.AddDatabaseAccessor(options =>{    options.AddDbPool<DefaultDbContext>(DbProvider.Sqlite);}, "存放迁移文件的项目名称");

另外,如果应用中配置了多个数据库上下文,那么所有的 迁移命令 都需要指定 -Context 数据库上下文名称 参数。如:

Add-Migration v1.0.0 -Context DefaultDbContext

9.0.2 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-update/index.html b/handbook/build/docs/dbcontext-update/index.html index 736e645139..85c161908c 100644 --- a/handbook/build/docs/dbcontext-update/index.html +++ b/handbook/build/docs/dbcontext-update/index.html @@ -2,22 +2,21 @@ - - - + +9.6 更新操作 | Furion -9.6 更新操作 | Furion - - + + +
-

9.6 更新操作

功能移除声明

以下内容包含 Exists 单词的在 Furion 2.6.0 + 版本中已移除。

9.6.1 更新全部列(不立即提交)

// ==== 同步操作 ====// 示例一repository.Update(user);// 示例二user.Update();// 示例三repository.ChangeEntityState(user, EntityState.Modified);// 示例四repository.Entities.Update(user);// ==== 异步操作 ====// 示例一await repository.UpdateAsync(user);// 示例二await user.UpdateAsync();

9.6.2 更新全部列(立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateNow(user);// 示例二user.UpdateNow();// ==== 异步操作 ====// 示例一await repository.UpdateNowAsync(user);// 示例二await user.UpdateNowAsync();

9.6.3 更新部分列(不立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateInclude(user, new[] {"Age", "Name"});// 示例二repository.UpdateInclude(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateInclude(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四user.UpdateInclude(new[] {"Age", "Name"});// 示例五user.UpdateInclude(new[] {nameof(User.Name), nameof(User.Age)});// 示例六user.UpdateInclude(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateIncludeAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateIncludeAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateIncludeAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四await user.UpdateIncludeAsync(new[] {"Age", "Name"});// 示例五await user.UpdateIncludeAsync(new[] {nameof(User.Name), nameof(User.Age)});// 示例六await user.UpdateIncludeAsync(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.4 更新部分列(立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateIncludeNow(user, new[] {"Age", "Name"});// 示例二repository.UpdateIncludeNow(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateIncludeNow(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四user.UpdateIncludeNow(new[] {"Age", "Name"});// 示例五user.UpdateIncludeNow(new[] {nameof(User.Name), nameof(User.Age)});// 示例六user.UpdateInclude(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateIncludeNowAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateIncludeNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateIncludeNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四await user.UpdateIncludeNowAsync(new[] {"Age", "Name"});// 示例五await user.UpdateIncludeNowAsync(new[] {nameof(User.Name), nameof(User.Age)});// 示例六await user.UpdateIncludeNowAsync(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.5 排除特定列更新(不立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateExclude(user, new[] {"Age", "Name"});// 示例二repository.UpdateExclude(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateExclude(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四user.UpdateExclude(new[] {"Age", "Name"});// 示例五user.UpdateExclude(new[] {nameof(User.Name), nameof(User.Age)});// 示例六user.UpdateExclude(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateExcludeAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateExcludeAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateExcludeAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四await user.UpdateExcludeAsync(new[] {"Age", "Name"});// 示例五await user.UpdateExcludeAsync(new[] {nameof(User.Name), nameof(User.Age)});// 示例六await user.UpdateExcludeAsync(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.6 排除特定列更新(立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateExcludeNow(user, new[] {"Age", "Name"});// 示例二repository.UpdateExcludeNow(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateExcludeNow(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四user.UpdateExcludeNow(new[] {"Age", "Name"});// 示例五user.UpdateExcludeNow(new[] {nameof(User.Name), nameof(User.Age)});// 示例六user.UpdateExcludeNow(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateExcludeNowAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateExcludeNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateExcludeNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四await user.UpdateExcludeNowAsync(new[] {"Age", "Name"});// 示例五await user.UpdateExcludeNowAsync(new[] {nameof(User.Name), nameof(User.Age)});// 示例六await user.UpdateExcludeNowAsync(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.7 数据存在才更新所有列(不立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateExists(user);// ==== 异步操作 ====// 示例一await repository.UpdateExistsAsync(user);

9.6.8 数据存在才更新所有列(立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateExistsNow(user);// ==== 异步操作 ====// 示例一await repository.UpdateExistsNowAsync(user);

9.6.9 数据存在才更新部分列(不立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateIncludeExists(user, new[] {"Age", "Name"});// 示例二repository.UpdateIncludeExists(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateIncludeExists(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateIncludeExistsAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateIncludeExistsAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateIncludeExistsAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.10 数据存在才更新部分列(立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateIncludeExistsNow(user, new[] {"Age", "Name"});// 示例二repository.UpdateIncludeExistsNow(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateIncludeExistsNow(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateIncludeExistsNowAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateIncludeExistsNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateIncludeExistsNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.11 数据存在才排除特定部分列更新(不立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateExcludeExists(user, new[] {"Age", "Name"});// 示例二repository.UpdateExcludeExists(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateExcludeExists(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateExcludeExistsAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateExcludeExistsAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateExcludeExistsAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.12 数据存在才排除特定部分列更新(立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateExcludeExistsNow(user, new[] {"Age", "Name"});// 示例二repository.UpdateExcludeExistsNow(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateExcludeExistsNow(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateExcludeExistsNowAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateExcludeExistsNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateExcludeExistsNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.13 更新多条记录(不立即提交)

// ==== 同步操作 ====// 示例一repository.Update(user, user2);// 示例二repository.Update(new List<User> { user, user2 });// 示例三repository.Update(new[] {user, user2 });// ==== 异步操作 ====// 示例一await repository.UpdateAsync(user, user2);// 示例二await repository.UpdateAsync(new List<User> { user, user2 });// 示例三await repository.UpdateAsync(new[] {user, user2 });

9.6.14 更新多条记录(立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateNow(user, user2);// 示例二repository.UpdateNow(new List<User> { user, user2 });// 示例三repository.UpdateNow(new[] {user, user2 });// ==== 异步操作 ====// 示例一await repository.UpdateNowAsync(user, user2);// 示例二await repository.UpdateNowAsync(new List<User> { user, user2 });// 示例三await repository.UpdateNowAsync(new[] {user, user2 });
小知识

所有带 Now 结尾的表示立即提交到数据库,也就是立即调用 SaveChangesSaveChangesAsync

9.6.15 忽略空值更新

默认情况下,EFCore 更新会更新全部列(除实体跟踪方式以外),有些时候我们希望 Null 值无需更新,这是我们只需要在更新时候配置 ignoreNullValues 参数即可,如:

repository.Update(entity, ignoreNullValues: true);

也可以全局配置,在 AppDbContext 的派生类的构造函数中启用即可:

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class DefaultDbContext : AppDbContext<DefaultDbContext>    {        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)        {            InsertOrUpdateIgnoreNullValues = true;        }    }}

9.6.16 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.6 更新操作

功能移除声明

以下内容包含 Exists 单词的在 Furion 2.6.0 + 版本中已移除。

9.6.1 更新全部列(不立即提交)

// ==== 同步操作 ====// 示例一repository.Update(user);// 示例二user.Update();// 示例三repository.ChangeEntityState(user, EntityState.Modified);// 示例四repository.Entities.Update(user);// ==== 异步操作 ====// 示例一await repository.UpdateAsync(user);// 示例二await user.UpdateAsync();

9.6.2 更新全部列(立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateNow(user);// 示例二user.UpdateNow();// ==== 异步操作 ====// 示例一await repository.UpdateNowAsync(user);// 示例二await user.UpdateNowAsync();

9.6.3 更新部分列(不立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateInclude(user, new[] {"Age", "Name"});// 示例二repository.UpdateInclude(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateInclude(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四user.UpdateInclude(new[] {"Age", "Name"});// 示例五user.UpdateInclude(new[] {nameof(User.Name), nameof(User.Age)});// 示例六user.UpdateInclude(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateIncludeAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateIncludeAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateIncludeAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四await user.UpdateIncludeAsync(new[] {"Age", "Name"});// 示例五await user.UpdateIncludeAsync(new[] {nameof(User.Name), nameof(User.Age)});// 示例六await user.UpdateIncludeAsync(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.4 更新部分列(立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateIncludeNow(user, new[] {"Age", "Name"});// 示例二repository.UpdateIncludeNow(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateIncludeNow(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四user.UpdateIncludeNow(new[] {"Age", "Name"});// 示例五user.UpdateIncludeNow(new[] {nameof(User.Name), nameof(User.Age)});// 示例六user.UpdateInclude(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateIncludeNowAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateIncludeNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateIncludeNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四await user.UpdateIncludeNowAsync(new[] {"Age", "Name"});// 示例五await user.UpdateIncludeNowAsync(new[] {nameof(User.Name), nameof(User.Age)});// 示例六await user.UpdateIncludeNowAsync(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.5 排除特定列更新(不立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateExclude(user, new[] {"Age", "Name"});// 示例二repository.UpdateExclude(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateExclude(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四user.UpdateExclude(new[] {"Age", "Name"});// 示例五user.UpdateExclude(new[] {nameof(User.Name), nameof(User.Age)});// 示例六user.UpdateExclude(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateExcludeAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateExcludeAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateExcludeAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四await user.UpdateExcludeAsync(new[] {"Age", "Name"});// 示例五await user.UpdateExcludeAsync(new[] {nameof(User.Name), nameof(User.Age)});// 示例六await user.UpdateExcludeAsync(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.6 排除特定列更新(立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateExcludeNow(user, new[] {"Age", "Name"});// 示例二repository.UpdateExcludeNow(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateExcludeNow(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四user.UpdateExcludeNow(new[] {"Age", "Name"});// 示例五user.UpdateExcludeNow(new[] {nameof(User.Name), nameof(User.Age)});// 示例六user.UpdateExcludeNow(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateExcludeNowAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateExcludeNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateExcludeNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// 示例四await user.UpdateExcludeNowAsync(new[] {"Age", "Name"});// 示例五await user.UpdateExcludeNowAsync(new[] {nameof(User.Name), nameof(User.Age)});// 示例六await user.UpdateExcludeNowAsync(new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.7 数据存在才更新所有列(不立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateExists(user);// ==== 异步操作 ====// 示例一await repository.UpdateExistsAsync(user);

9.6.8 数据存在才更新所有列(立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateExistsNow(user);// ==== 异步操作 ====// 示例一await repository.UpdateExistsNowAsync(user);

9.6.9 数据存在才更新部分列(不立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateIncludeExists(user, new[] {"Age", "Name"});// 示例二repository.UpdateIncludeExists(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateIncludeExists(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateIncludeExistsAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateIncludeExistsAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateIncludeExistsAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.10 数据存在才更新部分列(立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateIncludeExistsNow(user, new[] {"Age", "Name"});// 示例二repository.UpdateIncludeExistsNow(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateIncludeExistsNow(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateIncludeExistsNowAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateIncludeExistsNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateIncludeExistsNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.11 数据存在才排除特定部分列更新(不立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateExcludeExists(user, new[] {"Age", "Name"});// 示例二repository.UpdateExcludeExists(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateExcludeExists(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateExcludeExistsAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateExcludeExistsAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateExcludeExistsAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.12 数据存在才排除特定部分列更新(立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateExcludeExistsNow(user, new[] {"Age", "Name"});// 示例二repository.UpdateExcludeExistsNow(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三repository.UpdateExcludeExistsNow(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值// ==== 异步操作 ====// 示例一await repository.UpdateExcludeExistsNowAsync(user, new[] {"Age", "Name"});// 示例二await repository.UpdateExcludeExistsNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)});// 示例三await repository.UpdateExcludeExistsNowAsync(user, new[] {nameof(User.Name), nameof(User.Age)}, true);  // 忽略空值

9.6.13 更新多条记录(不立即提交)

// ==== 同步操作 ====// 示例一repository.Update(user, user2);// 示例二repository.Update(new List<User> { user, user2 });// 示例三repository.Update(new[] {user, user2 });// ==== 异步操作 ====// 示例一await repository.UpdateAsync(user, user2);// 示例二await repository.UpdateAsync(new List<User> { user, user2 });// 示例三await repository.UpdateAsync(new[] {user, user2 });

9.6.14 更新多条记录(立即提交)

// ==== 同步操作 ====// 示例一repository.UpdateNow(user, user2);// 示例二repository.UpdateNow(new List<User> { user, user2 });// 示例三repository.UpdateNow(new[] {user, user2 });// ==== 异步操作 ====// 示例一await repository.UpdateNowAsync(user, user2);// 示例二await repository.UpdateNowAsync(new List<User> { user, user2 });// 示例三await repository.UpdateNowAsync(new[] {user, user2 });
小知识

所有带 Now 结尾的表示立即提交到数据库,也就是立即调用 SaveChangesSaveChangesAsync

9.6.15 忽略空值更新

默认情况下,EFCore 更新会更新全部列(除实体跟踪方式以外),有些时候我们希望 Null 值无需更新,这是我们只需要在更新时候配置 ignoreNullValues 参数即可,如:

repository.Update(entity, ignoreNullValues: true);

也可以全局配置,在 AppDbContext 的派生类的构造函数中启用即可:

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class DefaultDbContext : AppDbContext<DefaultDbContext>    {        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)        {            InsertOrUpdateIgnoreNullValues = true;        }    }}

9.6.16 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext-view/index.html b/handbook/build/docs/dbcontext-view/index.html index 988a401c59..7ebb2001fc 100644 --- a/handbook/build/docs/dbcontext-view/index.html +++ b/handbook/build/docs/dbcontext-view/index.html @@ -2,22 +2,21 @@ - - - + +9.12 视图操作 | Furion -9.12 视图操作 | Furion - - + + +
-

9.12 视图操作

9.12.1 关于视图

视图是数据库中非常重要的对象,是一张虚拟表,通过视图我们可以对结果进行筛选缓存,同时还能实现颗粒化权限控制,如控制指定行,指定列。

9.12.2 视图的使用

Furion 中实现视图的操作非常简单,只需要创建视图模型,并继承 EntityNotKey 基类即可。代码如下:

9.12.2.1 创建视图 SQL

CREATE VIEW V_Person ASSELECT Id,Name,Age,Address FROM person

9.12.2.2 视图模型

using Furion.DatabaseAccessor;namespace Furion.Core{    public class V_Person : EntityNotKey    {        /// <summary>        /// 配置视图名        /// </summary>        public V_Person() : base("V_Person")        {        }        /// <summary>        /// 主键Id        /// </summary>        public int Id { get; set; }        /// <summary>        /// 姓名        /// </summary>        public string Name { get; set; }        /// <summary>        /// 年龄        /// </summary>        public int Age { get; set; }        /// <summary>        /// 住址        /// </summary>        public string Address { get; set; }    }}
视图名称

视图实体只需要继承 EntityNotKey 基类并编写无参构造函数继承 base("视图名称") 即可。

9.12.3 视图使用

视图除了不能操作(写)以外,其他操作和表操作无异。

var vEntities = v_repository.Where(u => u.Id >10).ToList();

9.12.4 视图最佳读取方式 ✔

由于视图是虚拟表,不应该对其进行写操作,所以应该采用 只读仓储初始化视图

using Furion.Core;using Furion.DatabaseAccessor;using Furion.DynamicApiController;using System.Collections.Generic;using System.Threading.Tasks;namespace Furion.Application.Persons{    public class FurionService : IDynamicApiController    {        private readonly IReadableRepository<V_Person> _readableRepository;        public FurionService(IRepository<V_Person> repository)        {            // 初始化只读仓储            _readableRepository = repository.Constraint<IReadableRepository<V_Person>>();        }        /// <summary>        /// 读取视图        /// </summary>        /// <returns></returns>        public async Task<List<V_Person>> GetVPerson()        {            var list = await _readableRepository.AsQueryable().ToListAsync();            return list;        }    }}
小知识

通过 .Constraint<TEntity,TDbContextLocator> 方法可以将仓储约束为特定仓储,如只读仓储,可读可写仓储,只新增仓储等。

9.12.5 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.12 视图操作

9.12.1 关于视图

视图是数据库中非常重要的对象,是一张虚拟表,通过视图我们可以对结果进行筛选缓存,同时还能实现颗粒化权限控制,如控制指定行,指定列。

9.12.2 视图的使用

Furion 中实现视图的操作非常简单,只需要创建视图模型,并继承 EntityNotKey 基类即可。代码如下:

9.12.2.1 创建视图 SQL

CREATE VIEW V_Person ASSELECT Id,Name,Age,Address FROM person

9.12.2.2 视图模型

using Furion.DatabaseAccessor;namespace Furion.Core{    public class V_Person : EntityNotKey    {        /// <summary>        /// 配置视图名        /// </summary>        public V_Person() : base("V_Person")        {        }        /// <summary>        /// 主键Id        /// </summary>        public int Id { get; set; }        /// <summary>        /// 姓名        /// </summary>        public string Name { get; set; }        /// <summary>        /// 年龄        /// </summary>        public int Age { get; set; }        /// <summary>        /// 住址        /// </summary>        public string Address { get; set; }    }}
视图名称

视图实体只需要继承 EntityNotKey 基类并编写无参构造函数继承 base("视图名称") 即可。

9.12.3 视图使用

视图除了不能操作(写)以外,其他操作和表操作无异。

var vEntities = v_repository.Where(u => u.Id >10).ToList();

9.12.4 视图最佳读取方式 ✔

由于视图是虚拟表,不应该对其进行写操作,所以应该采用 只读仓储初始化视图

using Furion.Core;using Furion.DatabaseAccessor;using Furion.DynamicApiController;using System.Collections.Generic;using System.Threading.Tasks;namespace Furion.Application.Persons{    public class FurionService : IDynamicApiController    {        private readonly IReadableRepository<V_Person> _readableRepository;        public FurionService(IRepository<V_Person> repository)        {            // 初始化只读仓储            _readableRepository = repository.Constraint<IReadableRepository<V_Person>>();        }        /// <summary>        /// 读取视图        /// </summary>        /// <returns></returns>        public async Task<List<V_Person>> GetVPerson()        {            var list = await _readableRepository.AsQueryable().ToListAsync();            return list;        }    }}
小知识

通过 .Constraint<TEntity,TDbContextLocator> 方法可以将仓储约束为特定仓储,如只读仓储,可读可写仓储,只新增仓储等。

9.12.5 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dbcontext/index.html b/handbook/build/docs/dbcontext/index.html index 4627cd9056..11ea586de7 100644 --- a/handbook/build/docs/dbcontext/index.html +++ b/handbook/build/docs/dbcontext/index.html @@ -2,22 +2,21 @@ - - - + +9.1 数据库上下文 | Furion -9.1 数据库上下文 | Furion - - + + +
-

9.1 数据库上下文

连接字符串配置注意事项

如果连接字符串是配置在自定义的 .json 文件中,那么必须在 Visual Studio 中配置 .json 右键属性,设置 复制 输出目录为 如果较新则复制,生成操作为:内容

否则就会提示找不到配置或连接字符串的错误。

9.1.1 数据库上下文

简单来说,数据库上下文是负责和数据库交互的对象,提供程序对数据库存取提供了大量的方法。

Furion 框架中,默认集成了微软亲儿子:EntityFramework Core ,也就是通常数据库上下文指的是 DbContext 类或它的实现类。

9.1.2 AppDbContext

在我们实际项目开发过程中,使用 EFCore 提供的 DbContext 操作对象操作数据库有些繁琐和复杂,且默认不具备读写分离、多库等操作功能。

所以,Furion 框架提供了 AppDbContext<TDbContext, TDbContextLocator> 数据库上下文,该上下文继承自 DbContext

特别说明

后续章节,皆采用 EFCore 代替 EntityFramework Core

9.1.3 AppDbContextDbContext 区别

  • AppDbContext 继承自 DbContext,具备 DbContext 所有功能。
  • AppDbContext 支持多数据库操作泛型版本,如:AppDbContext<TDbContext, TDbContextLocator>
  • AppDbContext 自动配置实体信息,无需在 OnModelCreating 中配置
  • AppDbContext 支持内置多租户支持
  • AppDbContext 支持全局模型配置拦截器
  • AppDbContext 支持数据提交更改多个事件
  • AppDbContext 提供更加强大的模型操作能力,如 Sql 操作,读写分离等
  • AppDbContext 能够得到 Furion 框架更多的功能支持

9.1.4 如何定义数据库上下文

Furion 框架中了,提供了两种 AppDbContext 定义方式:

  • AppDbContext<TDbContext> 操作默认数据库
  • AppDbContext<TDbContext, TDbContextLocator> 操作 N 个数据库

其中 AppDbContext<TDbContext> 默认继承自 AppDbContext<TDbContext, TDbContextLocator>

下面是数据库上下文创建的多个例子:

9.1.4.1 创建默认数据库上下文

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("连接字符串或appsetting.json 键")]    public class FurionDbContext : AppDbContext<FurionDbContext>  // 继承 AppDbContext<> 类    {        /// <summary>        /// 继承父类构造函数        /// </summary>        /// <param name="options"></param>        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }    }}

9.1.4.2 创建其他数据库上下文

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("连接字符串或appsetting.json 键")]    public class FurOtherDbContext : AppDbContext<FurOtherDbContext, FurOtherDbContextLocator>  // 继承 AppDbContext<> 类    {        /// <summary>        /// 继承父类构造函数        /// </summary>        /// <param name="options"></param>        public FurOtherDbContext(DbContextOptions<FurOtherDbContext> options) : base(options)        {        }    }}
特别注意

所有数据库上下文都应该在 Furion.EntityFramework.Core 项目中创建。另外如果系统用到了多个数据库,那么从第二个开始必须指定数据库上下文定位器。关于 TDbContextLocator 将在下一章节 《9.2 数据库上下文定位器》阐述。

9.1.5 配置连接字符串

Furion 框架提供多种数据库连接字符串配置方式:

  • 在注册数据库服务时配置:AddDbPool<TDbContext>("连接字符串") 方式
  • 使用 [AppDbContext("连接字符串/Key")] 特性方式(只在 AppDbContext 实现类有效推荐
  • 通过重写 OnConfiguring(DbContextOptionsBuilder optionsBuilder) 配置

9.1.5.1 在注册数据库服务时配置

Furion.EntityFramework.Core\Startup.cs
using Furion.DependencyInjection;using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(600)]    public sealed class FurEntityFrameworkCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            // 配置数据库上下文,支持N个数据库            services.AddDatabaseAccessor(options =>            {                // 配置默认数据库                options.AddDbPool<FurionDbContext>(DbProvider.SqlServer, connectionMetadata:"连接字符串");                // 配置多个数据库,多个数据库必须指定数据库上下文定位器                options.AddDbPool<SqliteDbContext, SqliteDbContextLocaotr>(DbProvider.Sqlite, connectionMetadata:"连接字符串");            });        }    }}
新版 MySQL 注意

MySQL 在新版本包中注册有所修改,所以注册方式为:

services.AddDatabaseAccessor(options =>{    options.AddDbPool<FurionDbContext>($"{DbProvider.MySql}@8.0.22");});

9.1.5.2 [AppDbContext] 方式配置

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("DbConnectionString")]   // 支持 `appsetting.json` 名或 连接字符串    public class FurionDbContext : AppDbContext<FurionDbContext>    {        /// <summary>        /// 继承父类构造函数        /// </summary>        /// <param name="options"></param>        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }    }}
小提示

Furion 推荐使用此方式配置数据库连接字符串。

[AppDbContext] 内置属性:

  • ConnectionMetadata:支持数据库连接字符串,配置文件的 ConnectionStrings 中的 Key 或配置文件的完整的配置路径,如果是内存数据库,则为数据库名称。
  • TablePrefix:当前数据库上下文表统一前缀
  • TableSuffix:当前数据库上下文表统一后缀
  • ProviderName:配置数据库提供器类型,传入 DbProvider.Xxx
  • Mode:配置数据库上下文模式,DbContextMode 枚举类型,取值:
    • Cached:缓存模型数据库上下文,默认值
    • Dynamic:动态模型数据库上下文
  • SlaveDbContextLocators:主从库配置,设置多个从库定位器,Type[] 类型

9.1.5.3 OnConfiguring 方式配置

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    public class FurionDbContext : AppDbContext<FurionDbContext>    {        /// <summary>        /// 继承父类构造函数        /// </summary>        /// <param name="options"></param>        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)        {            base.OnConfiguring(optionsBuilder);            optionsBuilder.UseSqlServer("数据库连接字符串");        }    }}
特别注意

这三种方式可以同时使用,但是有优先级:[AppDbContext] -> 在注册数据库服务时配置 -> OnConfiguring(低到高)

也就是 OnConfiguring 配置会覆盖 在注册数据库服务时配置 配置,在注册数据库服务时配置 配置会覆盖 [AppDbContext] 配置所配置的连接字符串。

9.1.5.4 各类数据库连接字符串配置示例

  • SqliteData Source=./Furion.db
  • MySqlData Source=localhost;Database=Furion;User ID=root;Password=000000;pooling=true;port=3306;sslmode=none;CharSet=utf8;
  • SqlServerServer=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;
  • OracleUser Id=orcl;Password=orcl;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl)))
  • PostgreSQLPORT=5432;DATABASE=postgres;HOST=127.0.0.1;PASSWORD=postgres;USER ID=postgres;

9.1.6 数据库上下文定义位置

特别注意

Furion 框架中,数据库上下文需定义在 Furion.EntityFramework.Core 中,且每一个数据库上下文都必须拥有唯一的 DbContextLocator 定位器

9.1.7 数据库上下文注册

数据库上下文配置好数据库连接字符串后,需要注册该数据库上下文,并指定数据库类型,如:

Furion\framework\Furion.EntityFramework.Core\FurEntityFrameworkCoreStartup.cs
using Furion.DatabaseAccessor;using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(600)]    public sealed class FurEntityFrameworkCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddDatabaseAccessor(options =>            {                options.AddDbPool<FurionDbContext>(DbProvider.Sqlite);            });        }    }}

如果有多个数据库操作,那么从第二个起,就需要绑定数据库上下文定位器,如:

options.AddDbPool<FurionDbContext>(DbProvider.Sqlite); // 第一个数据库options.AddDbPool<SecondDbContext, SecondDbContextDbContextLocator>(DbProvider.SqlServer);  // 第二个数据库options.AddDbPool<ThirdDbContext, ThirdDbContextDbContextLocator>(DbProvider.SqlServer);  // 第三个数据库

9.1.8 自定义高级注册

Furion 框架中,为了能够实现数据库的简单使用进行了注册封装,但有些时候,我们可能需要添加更多配置,这时就需要使用原生自定义配置方式,如:

services.AddDatabaseAccessor(options =>{    // 自定义原生配置    options.AddDb<YourDbContext>((services, builder) =>    {        builder.UseSqlite(...);    }});
小知识

Furion 框架提供了快速解析连接字符串的静态方法,自动根据名称读取配置,自动解析 [AppContext("...")] 信息,如:

// 获取连接字符串var connStr = DbProvider.GetConnectionString<YourDbContext>(/*这里可写可不写*/);options.AddDb<YourDbContext>((services, builder) =>{    builder.UseSqlite(connStr, ...);}

9.1.9 动态数据库上下文对象

Furion 框架中,数据库上下文是定义在 Furion.EntityFramework.Core 项目层,并且该层不被 Furion.ApplicationFurion.Core 等层引用。

所以就不能直接在 Furion.Application 项目层直接使用 Furion.EntityFramework.Core 定义的数据库上下文。

Furion 为了解决这个问题,提供了两种方式处理:

  • repository.Context :当前数据库上下文对象,返回是 DbContext 抽象类型
  • repository.DynamicContext:当前数据库上下文对象,返回的是 dynamic 类型

如果你只是想使用 DbContext 的功能,直接使用 repository.Context 即可,如:

repository.Context.SaveChanges();

如果你想能够获取具体的数据库上下文类型,如 MyDbContext,那么使用 repository.DynamicContext 就可以获取到具体的 MyDbContext 类型。如:

var persons = repository.DynamicContext.Persons.Find(1);var users = repository.DynamicContext.Users;

这样就可以直接操作 MyDbContext 定义的属性和方法了。

9.1.10 在后台任务中使用

由于 DbContext 默认注册为 Scoped 生存周期,所以在后台任务中使用 IServiceScopeFactory 获取所有服务,如:

public class JobService : BackgroundService{    // 日志对象    private readonly ILogger<JobService> _logger;    // 服务工厂    private readonly IServiceScopeFactory _scopeFactory;    public JobService(ILogger<JobService> logger        , IServiceScopeFactory scopeFactory)    {        _logger = logger;        _scopeFactory = scopeFactory;    }    protected override Task ExecuteAsync(CancellationToken stoppingToken)    {        _logger.LogInformation("写日志~~");        using (var scope = _scopeFactory.CreateScope())        {            var services = scope.ServiceProvider;            // 获取数据库上下文            var dbContext = Db.GetDbContext(services);            // 获取仓储            var repository = Db.GetRepository<Person>(services);            // 解析其他服务            var otherService = services.GetService<XXX>();        }        return Task.CompletedTask;    }}
数据库操作注意

如果作用域中对数据库有任何变更操作,需手动调用 SaveChanges 或带 Now 结尾的方法。也可以使用 Scoped.CreateUow(handler) 代替。

9.1.11 AppDbContext 全局配置属性

  • InsertOrUpdateIgnoreNullValues:新增或更新忽略空值,默认 false在构造函数中配置
  • EnabledEntityStateTracked:启用实体跟踪,默认 true在构造函数中配置
  • EnabledEntityChangedListener:启用实体数据更改监听,默认 false在构造函数中配置
  • Tenant:默认内置多租户
  • FailedAutoRollback:是否启用保存失败后事务自动回滚,默认 true,可以在任何地方配置

9.1.12 配置实体 懒加载

  • 第一步:安装 EFCore 拓展包

在数据库上下文定义所在的层安装 Microsoft.EntityFrameworkCore.Proxies 拓展包

  • 第二步:采用 AddDb<TDbContext> 方式注册

确保数据库上下文采用 AddDb<TDbContext> 注册而非 AddDbPool<TDbContext>

  • 第三步:重写 OnConfiguring 方法
using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class DefaultDbContext : AppDbContext<DefaultDbContext>    {        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)        {        }        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)        {            optionsBuilder.UseLazyLoadingProxies()                          .UseSqlite(DbProvider.GetConnectionString<DefaultDbContext>());            base.OnConfiguring(optionsBuilder);        }    }}
小知识

更多 EFCore 懒加载可查看 【EFCore - 延迟加载】 文档。

9.1.13 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 数据库上下文 知识可查阅 EF Core - 配置 DbContext 章节。

演练场
- - +

9.1 数据库上下文

连接字符串配置注意事项

如果连接字符串是配置在自定义的 .json 文件中,那么必须在 Visual Studio 中配置 .json 右键属性,设置 复制 输出目录为 如果较新则复制,生成操作为:内容

否则就会提示找不到配置或连接字符串的错误。

9.1.1 数据库上下文

简单来说,数据库上下文是负责和数据库交互的对象,提供程序对数据库存取提供了大量的方法。

Furion 框架中,默认集成了微软亲儿子:EntityFramework Core ,也就是通常数据库上下文指的是 DbContext 类或它的实现类。

9.1.2 AppDbContext

在我们实际项目开发过程中,使用 EFCore 提供的 DbContext 操作对象操作数据库有些繁琐和复杂,且默认不具备读写分离、多库等操作功能。

所以,Furion 框架提供了 AppDbContext<TDbContext, TDbContextLocator> 数据库上下文,该上下文继承自 DbContext

特别说明

后续章节,皆采用 EFCore 代替 EntityFramework Core

9.1.3 AppDbContextDbContext 区别

  • AppDbContext 继承自 DbContext,具备 DbContext 所有功能。
  • AppDbContext 支持多数据库操作泛型版本,如:AppDbContext<TDbContext, TDbContextLocator>
  • AppDbContext 自动配置实体信息,无需在 OnModelCreating 中配置
  • AppDbContext 支持内置多租户支持
  • AppDbContext 支持全局模型配置拦截器
  • AppDbContext 支持数据提交更改多个事件
  • AppDbContext 提供更加强大的模型操作能力,如 Sql 操作,读写分离等
  • AppDbContext 能够得到 Furion 框架更多的功能支持

9.1.4 如何定义数据库上下文

Furion 框架中了,提供了两种 AppDbContext 定义方式:

  • AppDbContext<TDbContext> 操作默认数据库
  • AppDbContext<TDbContext, TDbContextLocator> 操作 N 个数据库

其中 AppDbContext<TDbContext> 默认继承自 AppDbContext<TDbContext, TDbContextLocator>

下面是数据库上下文创建的多个例子:

9.1.4.1 创建默认数据库上下文

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("连接字符串或appsetting.json 键")]    public class FurionDbContext : AppDbContext<FurionDbContext>  // 继承 AppDbContext<> 类    {        /// <summary>        /// 继承父类构造函数        /// </summary>        /// <param name="options"></param>        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }    }}

9.1.4.2 创建其他数据库上下文

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("连接字符串或appsetting.json 键")]    public class FurOtherDbContext : AppDbContext<FurOtherDbContext, FurOtherDbContextLocator>  // 继承 AppDbContext<> 类    {        /// <summary>        /// 继承父类构造函数        /// </summary>        /// <param name="options"></param>        public FurOtherDbContext(DbContextOptions<FurOtherDbContext> options) : base(options)        {        }    }}
特别注意

所有数据库上下文都应该在 Furion.EntityFramework.Core 项目中创建。另外如果系统用到了多个数据库,那么从第二个开始必须指定数据库上下文定位器。关于 TDbContextLocator 将在下一章节 《9.2 数据库上下文定位器》阐述。

9.1.5 配置连接字符串

Furion 框架提供多种数据库连接字符串配置方式:

  • 在注册数据库服务时配置:AddDbPool<TDbContext>("连接字符串") 方式
  • 使用 [AppDbContext("连接字符串/Key")] 特性方式(只在 AppDbContext 实现类有效推荐
  • 通过重写 OnConfiguring(DbContextOptionsBuilder optionsBuilder) 配置

9.1.5.1 在注册数据库服务时配置

Furion.EntityFramework.Core\Startup.cs
using Furion.DependencyInjection;using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(600)]    public sealed class FurEntityFrameworkCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            // 配置数据库上下文,支持N个数据库            services.AddDatabaseAccessor(options =>            {                // 配置默认数据库                options.AddDbPool<FurionDbContext>(DbProvider.SqlServer, connectionMetadata:"连接字符串");                // 配置多个数据库,多个数据库必须指定数据库上下文定位器                options.AddDbPool<SqliteDbContext, SqliteDbContextLocaotr>(DbProvider.Sqlite, connectionMetadata:"连接字符串");            });        }    }}
新版 MySQL 注意

MySQL 在新版本包中注册有所修改,所以注册方式为:

services.AddDatabaseAccessor(options =>{    options.AddDbPool<FurionDbContext>($"{DbProvider.MySql}@8.0.22");});

9.1.5.2 [AppDbContext] 方式配置

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("DbConnectionString")]   // 支持 `appsetting.json` 名或 连接字符串    public class FurionDbContext : AppDbContext<FurionDbContext>    {        /// <summary>        /// 继承父类构造函数        /// </summary>        /// <param name="options"></param>        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }    }}
小提示

Furion 推荐使用此方式配置数据库连接字符串。

[AppDbContext] 内置属性:

  • ConnectionMetadata:支持数据库连接字符串,配置文件的 ConnectionStrings 中的 Key 或配置文件的完整的配置路径,如果是内存数据库,则为数据库名称。
  • TablePrefix:当前数据库上下文表统一前缀
  • TableSuffix:当前数据库上下文表统一后缀
  • ProviderName:配置数据库提供器类型,传入 DbProvider.Xxx
  • Mode:配置数据库上下文模式,DbContextMode 枚举类型,取值:
    • Cached:缓存模型数据库上下文,默认值
    • Dynamic:动态模型数据库上下文
  • SlaveDbContextLocators:主从库配置,设置多个从库定位器,Type[] 类型

9.1.5.3 OnConfiguring 方式配置

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    public class FurionDbContext : AppDbContext<FurionDbContext>    {        /// <summary>        /// 继承父类构造函数        /// </summary>        /// <param name="options"></param>        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)        {            base.OnConfiguring(optionsBuilder);            optionsBuilder.UseSqlServer("数据库连接字符串");        }    }}
特别注意

这三种方式可以同时使用,但是有优先级:[AppDbContext] -> 在注册数据库服务时配置 -> OnConfiguring(低到高)

也就是 OnConfiguring 配置会覆盖 在注册数据库服务时配置 配置,在注册数据库服务时配置 配置会覆盖 [AppDbContext] 配置所配置的连接字符串。

9.1.5.4 各类数据库连接字符串配置示例

  • SqliteData Source=./Furion.db
  • MySqlData Source=localhost;Database=Furion;User ID=root;Password=000000;pooling=true;port=3306;sslmode=none;CharSet=utf8;
  • SqlServerServer=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;
  • OracleUser Id=orcl;Password=orcl;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl)))
  • PostgreSQLPORT=5432;DATABASE=postgres;HOST=127.0.0.1;PASSWORD=postgres;USER ID=postgres;

9.1.6 数据库上下文定义位置

特别注意

Furion 框架中,数据库上下文需定义在 Furion.EntityFramework.Core 中,且每一个数据库上下文都必须拥有唯一的 DbContextLocator 定位器

9.1.7 数据库上下文注册

数据库上下文配置好数据库连接字符串后,需要注册该数据库上下文,并指定数据库类型,如:

Furion\framework\Furion.EntityFramework.Core\FurEntityFrameworkCoreStartup.cs
using Furion.DatabaseAccessor;using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(600)]    public sealed class FurEntityFrameworkCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddDatabaseAccessor(options =>            {                options.AddDbPool<FurionDbContext>(DbProvider.Sqlite);            });        }    }}

如果有多个数据库操作,那么从第二个起,就需要绑定数据库上下文定位器,如:

options.AddDbPool<FurionDbContext>(DbProvider.Sqlite); // 第一个数据库options.AddDbPool<SecondDbContext, SecondDbContextDbContextLocator>(DbProvider.SqlServer);  // 第二个数据库options.AddDbPool<ThirdDbContext, ThirdDbContextDbContextLocator>(DbProvider.SqlServer);  // 第三个数据库

9.1.8 自定义高级注册

Furion 框架中,为了能够实现数据库的简单使用进行了注册封装,但有些时候,我们可能需要添加更多配置,这时就需要使用原生自定义配置方式,如:

services.AddDatabaseAccessor(options =>{    // 自定义原生配置    options.AddDb<YourDbContext>((services, builder) =>    {        builder.UseSqlite(...);    }});
小知识

Furion 框架提供了快速解析连接字符串的静态方法,自动根据名称读取配置,自动解析 [AppContext("...")] 信息,如:

// 获取连接字符串var connStr = DbProvider.GetConnectionString<YourDbContext>(/*这里可写可不写*/);options.AddDb<YourDbContext>((services, builder) =>{    builder.UseSqlite(connStr, ...);}

9.1.9 动态数据库上下文对象

Furion 框架中,数据库上下文是定义在 Furion.EntityFramework.Core 项目层,并且该层不被 Furion.ApplicationFurion.Core 等层引用。

所以就不能直接在 Furion.Application 项目层直接使用 Furion.EntityFramework.Core 定义的数据库上下文。

Furion 为了解决这个问题,提供了两种方式处理:

  • repository.Context :当前数据库上下文对象,返回是 DbContext 抽象类型
  • repository.DynamicContext:当前数据库上下文对象,返回的是 dynamic 类型

如果你只是想使用 DbContext 的功能,直接使用 repository.Context 即可,如:

repository.Context.SaveChanges();

如果你想能够获取具体的数据库上下文类型,如 MyDbContext,那么使用 repository.DynamicContext 就可以获取到具体的 MyDbContext 类型。如:

var persons = repository.DynamicContext.Persons.Find(1);var users = repository.DynamicContext.Users;

这样就可以直接操作 MyDbContext 定义的属性和方法了。

9.1.10 在后台任务中使用

由于 DbContext 默认注册为 Scoped 生存周期,所以在后台任务中使用 IServiceScopeFactory 获取所有服务,如:

public class JobService : BackgroundService{    // 日志对象    private readonly ILogger<JobService> _logger;    // 服务工厂    private readonly IServiceScopeFactory _scopeFactory;    public JobService(ILogger<JobService> logger        , IServiceScopeFactory scopeFactory)    {        _logger = logger;        _scopeFactory = scopeFactory;    }    protected override Task ExecuteAsync(CancellationToken stoppingToken)    {        _logger.LogInformation("写日志~~");        using (var scope = _scopeFactory.CreateScope())        {            var services = scope.ServiceProvider;            // 获取数据库上下文            var dbContext = Db.GetDbContext(services);            // 获取仓储            var repository = Db.GetRepository<Person>(services);            // 解析其他服务            var otherService = services.GetService<XXX>();        }        return Task.CompletedTask;    }}
数据库操作注意

如果作用域中对数据库有任何变更操作,需手动调用 SaveChanges 或带 Now 结尾的方法。也可以使用 Scoped.CreateUow(handler) 代替。

9.1.11 AppDbContext 全局配置属性

  • InsertOrUpdateIgnoreNullValues:新增或更新忽略空值,默认 false在构造函数中配置
  • EnabledEntityStateTracked:启用实体跟踪,默认 true在构造函数中配置
  • EnabledEntityChangedListener:启用实体数据更改监听,默认 false在构造函数中配置
  • Tenant:默认内置多租户
  • FailedAutoRollback:是否启用保存失败后事务自动回滚,默认 true,可以在任何地方配置

9.1.12 配置实体 懒加载

  • 第一步:安装 EFCore 拓展包

在数据库上下文定义所在的层安装 Microsoft.EntityFrameworkCore.Proxies 拓展包

  • 第二步:采用 AddDb<TDbContext> 方式注册

确保数据库上下文采用 AddDb<TDbContext> 注册而非 AddDbPool<TDbContext>

  • 第三步:重写 OnConfiguring 方法
using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class DefaultDbContext : AppDbContext<DefaultDbContext>    {        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)        {        }        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)        {            optionsBuilder.UseLazyLoadingProxies()                          .UseSqlite(DbProvider.GetConnectionString<DefaultDbContext>());            base.OnConfiguring(optionsBuilder);        }    }}
小知识

更多 EFCore 懒加载可查看 【EFCore - 延迟加载】 文档。

9.1.13 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 数据库上下文 知识可查阅 EF Core - 配置 DbContext 章节。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dependency-injection/index.html b/handbook/build/docs/dependency-injection/index.html index ff8213a799..c328204962 100644 --- a/handbook/build/docs/dependency-injection/index.html +++ b/handbook/build/docs/dependency-injection/index.html @@ -2,22 +2,21 @@ - - - + +12. 依赖注入/控制反转 | Furion -12. 依赖注入/控制反转 | Furion - - + + +
-

12. 依赖注入/控制反转

阅前必读

由于很多朋友第一次接触 依赖注入/控制反转 的架构理念,所以没搞明白 作用域多线程解析服务 的问题,从而不正确的使用导致内存不断飙高,正确的方式应该是:

  • 尽可能的采用构造函数注入(如果这个类支持)
  • 在非静态中(但在 Web 请求有效的声明周期内)可安全使用 App.GetService<> 解析服务,如果是 单例服务,优先推荐构造函数注入或 App.RootServices.GetService<> 方式
  • 🤐 在非 Web 环境、多线程环境、物联网等环境(含事件总线、定时任务等)🏒 除单例服务以外 🏒 必须采用 Scoped.Create() 方式创建作用域且服务在内部委托中解析! 🤐

12.1 依赖注入

所谓依赖注入,是指程序运行过程中,如果需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部的注入。

通俗来讲,就是把有依赖关系的类放到容器中,然后在我们需要这些类时,容器自动解析出这些类的实例。

依赖注入最大的好处时实现类的解耦,利于程序拓展、单元测试、自动化模拟测试等。

依赖注入的英文为:Dependency Injection,简称 DI

12.2 控制反转

控制反转只是一个概念,也就是将创建对象实例的控制权(原本是程序员)从代码控制权剥离到 IOC 容器 中控制。

控制反转的英文为:Inversion of Control,简称 IOC

12.3 IOC/DI 优缺点

传统的代码,每个对象负责管理与自己需要依赖的对象,导致如果需要切换依赖对象的实现类时,需要修改多处地方。同时,过度耦合也使得对象难以进行单元测试。

  • 优点

    • 依赖注入把对象的创造交给外部去管理,很好的解决了代码紧耦合(tight couple)的问题,是一种让代码实现松耦合(loose couple)的机制
    • 松耦合让代码更具灵活性,能更好地应对需求变动,以及方便单元测试
  • 缺点

    • 目前主流的 IOC/DI 基本采用反射的方式来实现依赖注入,在一定程度会影响性能
特别说明

在本章节不打算细讲 依赖注入/控制反转 具体实现和应用场景,想了解更多知识,可查阅 【ASP.NET Core 依赖注入】 官方文档。

12.4 依赖注入的三种方式

12.4.1 构造方法注入

目前构造方法注入是依赖注入推荐使用方式。

  • 优点

    • 在构造方法中体现出对其他类的依赖,一眼就能看出这个类需要依赖哪些类才能工作
    • 脱离了 IOC 框架,这个类仍然可以工作,POJO 的概念
    • 一旦对象初始化成功了,这个对象的状态肯定是正确的
  • 缺点

    • 构造函数会有很多参数(Bad smell)
    • 有些类是需要默认构造函数的,比如 MVC 框架的 Controller 类,一旦使用构造函数注入,就无法使用默认构造函数
    • 这个类里面的有些方法并不需要用到这些依赖(Bad smell)

代码示例:

public class FurionService{    private readonly IRepository _repository;    public FurionService(IRepository repository)    {        _repository = repository;    }}

12.4.2 属性方式注入

特别声明

Furion 新版本中,已经移除属性注入功能,建议使用构造函数或方法方式注入,也可以通过 App.GetService<TService> 方式注入。

通过属性方式注入容易和类的实例属性混淆,不建议使用。

  • 优点

    • 在对象的整个生命周期内,可以随时动态的改变依赖
    • 非常灵活
  • 缺点

    • 对象在创建后,被设置依赖对象之前这段时间状态是不对的
    • 不直观,无法清晰地表示哪些属性是必须的
public class FurionService{    public IRepository Repository { get; set; }}

12.4.3 方法参数注入

方法参数注入的意思是在创建对象后,通过自动调用某个方法来注入依赖。

  • 优点:

    • 比较灵活
  • 缺点:

    • 新加入依赖时会破坏原有的方法签名,如果这个方法已经被其他很多模块用到就很麻烦
    • 与构造方法注入一样,会有很多参数
public class FurionService{    public Person GetById([FromServices]IRepository repository, int id)    {        return repository.Find(id);    }}

12.5 注册对象生存期

12.5.1 暂时/瞬时 生存期

暂时生存期服务是每次从服务容器进行请求时创建的。 这种生存期适合轻量级、 无状态的服务。

在处理请求的应用中,在请求结束时会释放暂时服务。

通常我们使用 ITransient 接口依赖表示该生命周期。

12.5.2 作用域 生存期

作用域生存期服务针对每个客户端请求(连接)创建一次。在处理请求的应用中,在请求结束时会释放有作用域的服务。

通常我们使用 IScoped 接口依赖表示该生命周期。

12.5.3 单例 生存期

在首次请求它们时进行创建,之后每个后续请求都使用相同的实例。

通常我们使用 ISingleton 接口依赖表示该生命周期。

了解更多

想了解更多 服务生存期 知识可查阅 ASP.NET Core - 依赖注入 - 服务生存期 章节。

12.6 内置依赖接口

Furion 框架提供三个接口依赖分别对应不同的服务生存期:

  • ITransient:对应暂时/瞬时作用域服务生存期
  • IScoped:对应请求作用域服务生存期
  • ISingleton:对应单例作用域服务生存期
特别注意

以上三个接口只能实例类实现,其他静态类、抽象类、及接口不能实现。

12.7 常见使用

12.7.1 第一个例子

创建 IBusinessService 接口和 BusinessService 实现类,代码如下:

using Furion.Core;using Furion.DatabaseAccessor;using Furion.DependencyInjection;namespace Furion.Application{    public interface IBusinessService    {        Person Get(int id);    }    public class BusinessService : IBusinessService, ITransient    {        private readonly IRepository<Person> _personRepository;        public BusinessService(IRepository<Person> personRepository)        {            _personRepository = personRepository;        }        public Person Get(int id)        {            return _personRepository.Find(id);        }    }}

创建 PersonController 控制器,代码如下:

using Furion.Application;using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    [Route("api/[controller]")]    [ApiController]    public class PersonController : ControllerBase    {        private readonly IBusinessService _businessService;        public PersonController(IBusinessService businessService)        {            _businessService = businessService;        }        [HttpGet]        public IActionResult Get(int id)        {            var person = _businessService.Get(id);            return new JsonResult(person);        }    }}

例子解说

Furion 框架提供了非常灵活且方便的实现依赖注入的方式,只需要实例类继承对应生存期的接口即可,这里继承了 ITransient,也就表明了这是一个 暂时/瞬时 作用域实例类。该类就可以作为被注入对象,同时也能注入其他接口对象。

上面的例子中,BusinessService 注入了 IRepository<Person> 仓储接口,同时 PersonController 控制器注入了 IBusinessService 接口。

这样 PersonControllerBusinessService 之间就实现了解耦,不再依赖于具体的 BusinessService 实例。

这就是依赖注入/控制反转最经典的例子。

12.7.2 注册泛型实例

创建 IBusinessService<T> 接口和 BusinessService<T> 实现类,代码如下:

using Furion.Core;using Furion.DatabaseAccessor;using Furion.DependencyInjection;namespace Furion.Application{    public interface IBusinessService<T>    {        Person Get(int id);    }    public class BusinessService<T> : IBusinessService<T>, ITransient    {        private readonly IRepository<Person> _personRepository;        public BusinessService(IRepository<Person> personRepository)        {            _personRepository = personRepository;        }        public Person Get(int id)        {            return _personRepository.Find(id);        }    }}

创建 PersonController 控制器,代码如下:

using Furion.Application;using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    [Route("api/[controller]")]    [ApiController]    public class PersonController : ControllerBase    {        private readonly IBusinessService<int> _businessService;        public PersonController(IBusinessService<int> businessService)        {            _businessService = businessService;        }        [HttpGet]        public IActionResult Get(int id)        {            var person = _businessService.Get(id);            return new JsonResult(person);        }    }}

12.7.3 一个接口多个实现

默认情况下,一个接口只对应一个实现类,但有些特殊情况,需要多个实现类注册同一个接口,如 DbContext 多数据库情况。

这个时候我们可以通过依赖注入 Func<string, IPrivateDependency, object> 委托来解析多个实例,其中委托的参数分别为:

  • 参数 1:string 类型,不同实现类唯一标识,默认为 nameof(实现类) 名称
  • 参数 2:Type 类型,IPrivateDependency 派生接口,也就是 ITransientIScopedISingleton
  • 返回值:object 类型,返回具体的实现类实例

创建 IBusinessService 接口和 BusinessServiceOtherBusinessService 两个实现类,代码如下:

using Furion.DependencyInjection;namespace Furion.Application{    public interface IBusinessService    {        string GetName();    }    public class BusinessService : IBusinessService, ITransient    {        public string GetName()        {            return "我是:" + nameof(BusinessService);        }    }    public class OtherBusinessService : IBusinessService, ITransient    {        public string GetName()        {            return "我是:" + nameof(OtherBusinessService);        }    }}
新版本,推荐使用

Furion 3.8.6+ 版本之后新增了 INamedServiceProvider 服务接口,可替代 Func<string, ILifetime, object> 方式:

using Furion.Application.Services;namespace Furion.Application;public class TestNamedServices : IDynamicApiController{    private readonly INamedServiceProvider<IBusinessService> _namedServiceProvider;    public TestNamedServices(INamedServiceProvider<IBusinessService> namedServiceProvider)    {        _namedServiceProvider = namedServiceProvider;    }    public string GetName()    {        // 第一种用法,通过反射解析服务周期,性能有损耗        var service1 = _namedServiceProvider.GetService(nameof(BusinessService));        var service2 = _namedServiceProvider.GetService(nameof(OtherBusinessService));        // 第二种用法,无需反射,注意下面的泛型参数传入的是生命周期依赖接口,ITransient, IScoped, ISingleton        var service3 = _namedServiceProvider.GetService<ITransient>(nameof(BusinessService));        var service4 = _namedServiceProvider.GetService<ITransient>(nameof(OtherBusinessService));        return service1.GetName() + "-" + service2.GetName() + "-" + service3.GetName() + "-" + service4.GetName();    }}
不再推荐 Func<string, TLifetime, object> 方式
using Furion.Application;using Furion.DependencyInjection;using Microsoft.AspNetCore.Mvc;using System;namespace Furion.Web.Entry.Controllers{    [Route("api/[controller]")]    [ApiController]    public class ValueController : ControllerBase    {        private readonly IBusinessService _businessService;        private readonly IBusinessService _otherBusinessService;        public ValueController(Func<string, ITransient, object> resolveNamed)        {            _businessService = resolveNamed("BusinessService", default) as IBusinessService;            _otherBusinessService = resolveNamed("OtherBusinessService", default) as IBusinessService;        }        [HttpGet]        public string GetName()        {            return _businessService.GetName() + "----------" + _otherBusinessService.GetName();        }    }}
小知识

如果需要自定义解析名称,只需要贴 [Injection(Named = "名称")] 即可,如:

using Furion.DependencyInjection;namespace Furion.Application{    [Injection(Named = "BusName1")]    public class BusinessService : IBusinessService, ITransient    {        // ...    }    [Injection(Named = "BusName2")]    public class OtherBusinessService : IBusinessService, ITransient    {        // ...    }}

解析服务:

_businessService = resolveNamed("BusName1", default) as IBusinessService;_otherBusinessService = resolveNamed("BusName2", default) as IBusinessService;

12.7.4 无接口方式

有些时候,我们不想定义接口,而是想把实例类作为可依赖注入的对象,如 MVC 中的控制器。

创建 SelfService 实例类,代码如下:

using Furion.Core;using Furion.DatabaseAccessor;using Furion.DependencyInjection;namespace Furion.Application{    public class SelfService : ITransient    {        private readonly IRepository<Person> _personRepository;        public SelfService(IRepository<Person> personRepository)        {            _personRepository = personRepository;        }        public Person Get(int id)        {            return _personRepository.Find(id);        }    }}

创建 ValueController 控制器,代码如下:

using Furion.Application;using Furion.Core;using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    [Route("api/[controller]")]    [ApiController]    public class ValueController : ControllerBase    {        private readonly SelfService _selfService;        public ValueController(SelfService selfService)        {            _selfService = selfService;        }        [HttpGet]        public Person Get(int id)        {            return _selfService.Get(id);        }    }}

12.8 [Injection] 特性配置

Furion 框架提供 [Injection] 特性可以改变注册方式,同时还能配置 AOP 拦截。

[Injection] 提供以下配置支持:

  • Action:配置注册行为,InjectionActions 类型,可选值:
    • Add默认值,表示无限制添加注册服务,该方式支持一个接口多个实现
    • TryAdd:表示注册已存在则跳过注册
  • Pattern:配置注册选项,InjectionPatterns 类型,可选值:
    • Self:只注册自己
    • FirstInterface:只注册第一个接口
    • SelfWithFirstInterface:注册自己和第一个接口
    • ImplementedInterfaces:注册所有接口
    • All:注册自己包括所有接口 ,默认值
  • Named:配置实例别名,通过别名可以解析接口,如同一个接口有多个实现,那么可以通过别名解析不同的实现,默认只为实现类的类名
  • Order:注册排序,数字越大,则越在最后注册,默认 0
  • Proxy:配置代理拦截类型,也就是 AOP代理类型必须继承 AspectDispatchProxy 类和 IDispatchProxy 接口,无默认值
  • ExpectInterfaces:配置忽略注册的接口,Type[] 类型

12.9 自定义高级注册

默认情况下,Furion 提供的注册方式可以满足大多数依赖注入的需求,如有特别注册需求,只需要在 Startup 中配置即可,如:

services.AddScoped(typeof(ISpecService), provider = > {    // 自定义任何创建实例的方式    var instance = new SpecService();  // 或者可以通过 AOP插件返回代理实例    return instance;});
补充说明

Furion 框架中的 AppDbContext 数据库上下文还有 ISqlDispatchProxy 都是通过这种方式创建的。

知识导航

想了解更多自定义高级中注册,可查阅 【ASP.NET Core 依赖注入】 官方文档。

12.10 appsettings.json 配置注册

除了在代码中实现依赖注入,也可以实现动态依赖注入,无需修改代码或重新编译即可实现热插拔(插件)效果。配置如下:

{  "DependencyInjectionSettings": {    "Definitions": [      {        "Interface": "Furion.Application;Furion.Application.ITestService",        "Service": "Furion.Application;Furion.Application.TestService",        "RegisterType": "Transient",        "Action": "Add",        "Pattern": "SelfWithFirstInterface",        "Named": "TestService",        "Order": 1,        "Proxy": "Furion.Application;Furion.Application.LogDispathProxy"      }    ]  }}

配置说明:

  • DependencyInjectionSettings:依赖注入配置根节点
    • Definitions:动态依赖注入配置节点,ExternalService 数组类型
      • ExternalService:配置单个依赖注入信息
关于外部程序集

如果动态注入的对象是外部程序集,那么首先先注册外部程序集:

{  "AppSettings": {    "ExternalAssemblies": ["外部程序集名称", "Taobao.Pay"] // 支持多个  }}

12.11 注册顺序和优先级

Furion 框架中,默认注册顺序是按照程序集扫描顺序进行注册,如果需要改变注册顺序,可通过 [Injection(Order)] 特性指定,Order 值越大,则越在最后注册。

另外 appsettings.json 配置的优先级最大,appsettings.json 配置的注册会覆盖之前所有注册。

12.12 Aop 注册拦截

关于动态 API 和服务的区别

如果您的服务是动态 API,那么请使用 动态 API - AOP 拦截,原因是动态 API 本质是控制器,所以采用 Filter 方式。

AOP 是非常重要的思想和技术,也就是 面向切面 编程,可以让我们在不改动原来代码的情况下进行动态篡改业务代码。

Furion 框架中,实现 Aop 非常简单,如:

假设我们有 ITestServiceTestService 两个类型:

public interface ITestService{    string SayHello(string word);}
public class TestService: ITestService, ITransient{    public string SayHello(string word)    {        return $"Hello {word}";    }}

现在我们有一个需求,我们希望调用 SayHello 的时候可以记录日志和权限控制(之前没有考虑到的需求)。

这个时候我们只需要创建一个代理类即可,如 LogDispatchProxy

using Furion.DependencyInjection;using System;using System.Reflection;namespace Furion.Application{    public class LogDispatchProxy : AspectDispatchProxy, IDispatchProxy    {        /// <summary>        /// 当前服务实例        /// </summary>        public object Target { get; set; }        /// <summary>        /// 服务提供器,可以用来解析服务,如:Services.GetService()        /// </summary>        public IServiceProvider Services { get; set; }        /// <summary>        /// 拦截方法        /// </summary>        /// <param name="method"></param>        /// <param name="args"></param>        /// <returns></returns>        public override object Invoke(MethodInfo method, object[] args)        {            Console.WriteLine("SayHello 方法被调用了");            var result = method.Invoke(Target, args);            Console.WriteLine("SayHello 方法返回值:" + result);            return result;        }        // 异步无返回值        public override async Task InvokeAsync(MethodInfo method, object[] args)        {            Console.WriteLine("SayHello 方法被调用了");            var task = method.Invoke(Target, args) as Task;            await task;             Console.WriteLine("SayHello 方法调用完成");        }        // 异步带返回值        public override async Task<T> InvokeAsyncT<T>(MethodInfo method, object[] args)        {            Console.WriteLine("SayHello 方法被调用了");            var taskT = method.Invoke(Target, args) as Task<T>;            var result = await taskT;            Console.WriteLine("SayHello 方法返回值:" + result);            return result;        }    }}
获取特性

如果需要获取方法的特性,只需要通过 method.GetActualCustomAttribute<TArrbute>() 即可。所有获取真实的特性统一采用 method.GetActual....() 方法开头。

之后我们只需要为 TestService 增加 [Injection] 特性即可,如:

[Injection(Proxy = typeof(LogDispatchProxy))]public class TestService: ITestService, ITransient{    public string SayHello(string word)    {        return $"Hello {word}";    }}

之后 SayHello 方法被调用的时候就可以实现动态拦截了,比如这里写日志。

12.12.1 全局Aop拦截

Furion 框架也提供了全局拦截的方式,只需要将 IDispatchProxy 修改为 IGlobalDispatchProxy 即可。

using Furion;using System.Reflection;namespace Furion.Application{    public class LogDispatchProxy : AspectDispatchProxy, IGlobalDispatchProxy    {        // ....    }}

这样就会拦截所有的 Service,当然也可以通过给特定类贴 [SuppressProxy] 跳过全局拦截操作。

拦截优先级

[SuppressProxy] > [Injection(Proxy = typeof(LogDispatchProxy))] > 全局拦截

12.12.2 AOP 注入解析服务

Furion 框架未提供 Proxy 构造函数注入功能,但是提供了 Services 属性,如果需要解析服务,则可以通过以下方式:

var someServices = Services.GetService<ISomeService>(); // 推荐方式// 或var someServices = App.GetService<ISomeService>();

12.12.3 AOP 的作用

这种面向切面的能力(动态拦截/代理)可以实现很多很多功能,如:

  • 动态日志记录
  • 动态修改参数
  • 动态修改返回值
  • 动态方法重定向
  • 动态修改代码逻辑
  • 动态实现异常监听

还可以做更多更多的事情。

12.13 在非 Web 或多线程解析服务

默认情况下,在 Web 请求开始之前会自动创建范围作用域,这个作用域的生存周期是请求之前和响应之后,也就是在这个作用域内的所有服务都实现了自动管理,比如创建服务和释放服务的时机。

但在非 Web 或多线程中,框架并不会做这样的事情,也就是框架只负责了服务的创建,但是没有负责销毁,原因是框架无法得知具体的销毁时机,这样就导致了内存溢出。

解决方式是:在非 Web 或多线程中使用服务,应该主动创建作用域,类似过去的 using,目前框架提供了几种方式。

12.13.1 IServiceProvider 方式

using var scope = serviceProvider.CreateScope();var services = scope.ServiceProvider;// 获取数据库上下文var dbContext = Db.GetDbContext(services);// 获取仓储var respository = Db.GetRepository<Person>(services);// 解析其他服务var otherService = services.GetService<XXX>();var otherService2 = App.GetService<XXX>(services);

12.13.2 IServiceScopeFactory 方式

using var scope = serviceScopeFactory.CreateScope();var services = scope.ServiceProvider;

12.13.3 Scoped 静态类

为了方法快速创建服务作用域,Furion 框架提供了 Scoped 静态类,如:

Scoped.Create((factory, scope) => {     var services = scope.ServiceProvider;});

12.14 自定义扫描/筛选注册服务

Furion 框架中并未提供完全自定义依赖注入扫描的机制,但推荐一个非常优秀的 .NET Core 依赖注入拓展库:Scrutor,使用非常简单,主要通过 FromAssemblyOf<> 扫描程序集和 AddClasses(o) 进行筛选注册。

使用如下:

services.Scan(scan => scan    // 扫描特定类型所在的程序集,这里是 ITransientService 所在的程序集    .FromAssemblyOf<ITransientService>()        // .AddClasses 在上面获取到的程序集中扫描所有公开、非抽象类型        // 之后可以通过委托进行类型筛选,例如下面只扫描实现 ITransientService 的类型        .AddClasses(classes => classes.AssignableTo<ITransientService>())            // 将上面的类型作为它实现的所有接口进行注册            // 如果类型实现了 N 个接口,那么就会有三个独立的注册            .AsImplementedInterfaces()            // 最后指定注册的生存期,如瞬时,作用域,还是单例            .WithTransientLifetime()        // 重复上面操作,比如这里扫描 IScopedService 所在的程序集        .AddClasses(classes => classes.AssignableTo<IScopedService>())            // 这里和上面不一样的是,这里指定只实现特定的几口,也就是只注册一次            .As<IScopedService>()            // 指定注册的生存期            .WithScopedLifetime()        // 也支持泛型注册,单个泛型参数        .AddClasses(classes => classes.AssignableTo(typeof(IOpenGeneric<>)))            .AsImplementedInterfaces()        // 多个泛型参数        .AddClasses(classes => classes.AssignableTo(typeof(IQueryHandler<,>)))            .AsImplementedInterfaces());

详细文档请查阅 https://github.com/khellang/Scrutor

12.15 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

12. 依赖注入/控制反转

阅前必读

由于很多朋友第一次接触 依赖注入/控制反转 的架构理念,所以没搞明白 作用域多线程解析服务 的问题,从而不正确的使用导致内存不断飙高,正确的方式应该是:

  • 尽可能的采用构造函数注入(如果这个类支持)
  • 在非静态中(但在 Web 请求有效的声明周期内)可安全使用 App.GetService<> 解析服务,如果是 单例服务,优先推荐构造函数注入或 App.RootServices.GetService<> 方式
  • 🤐 在非 Web 环境、多线程环境、物联网等环境(含事件总线、定时任务等)🏒 除单例服务以外 🏒 必须采用 Scoped.Create() 方式创建作用域且服务在内部委托中解析! 🤐

12.1 依赖注入

所谓依赖注入,是指程序运行过程中,如果需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部的注入。

通俗来讲,就是把有依赖关系的类放到容器中,然后在我们需要这些类时,容器自动解析出这些类的实例。

依赖注入最大的好处时实现类的解耦,利于程序拓展、单元测试、自动化模拟测试等。

依赖注入的英文为:Dependency Injection,简称 DI

12.2 控制反转

控制反转只是一个概念,也就是将创建对象实例的控制权(原本是程序员)从代码控制权剥离到 IOC 容器 中控制。

控制反转的英文为:Inversion of Control,简称 IOC

12.3 IOC/DI 优缺点

传统的代码,每个对象负责管理与自己需要依赖的对象,导致如果需要切换依赖对象的实现类时,需要修改多处地方。同时,过度耦合也使得对象难以进行单元测试。

  • 优点

    • 依赖注入把对象的创造交给外部去管理,很好的解决了代码紧耦合(tight couple)的问题,是一种让代码实现松耦合(loose couple)的机制
    • 松耦合让代码更具灵活性,能更好地应对需求变动,以及方便单元测试
  • 缺点

    • 目前主流的 IOC/DI 基本采用反射的方式来实现依赖注入,在一定程度会影响性能
特别说明

在本章节不打算细讲 依赖注入/控制反转 具体实现和应用场景,想了解更多知识,可查阅 【ASP.NET Core 依赖注入】 官方文档。

12.4 依赖注入的三种方式

12.4.1 构造方法注入

目前构造方法注入是依赖注入推荐使用方式。

  • 优点

    • 在构造方法中体现出对其他类的依赖,一眼就能看出这个类需要依赖哪些类才能工作
    • 脱离了 IOC 框架,这个类仍然可以工作,POJO 的概念
    • 一旦对象初始化成功了,这个对象的状态肯定是正确的
  • 缺点

    • 构造函数会有很多参数(Bad smell)
    • 有些类是需要默认构造函数的,比如 MVC 框架的 Controller 类,一旦使用构造函数注入,就无法使用默认构造函数
    • 这个类里面的有些方法并不需要用到这些依赖(Bad smell)

代码示例:

public class FurionService{    private readonly IRepository _repository;    public FurionService(IRepository repository)    {        _repository = repository;    }}

12.4.2 属性方式注入

特别声明

Furion 新版本中,已经移除属性注入功能,建议使用构造函数或方法方式注入,也可以通过 App.GetService<TService> 方式注入。

通过属性方式注入容易和类的实例属性混淆,不建议使用。

  • 优点

    • 在对象的整个生命周期内,可以随时动态的改变依赖
    • 非常灵活
  • 缺点

    • 对象在创建后,被设置依赖对象之前这段时间状态是不对的
    • 不直观,无法清晰地表示哪些属性是必须的
public class FurionService{    public IRepository Repository { get; set; }}

12.4.3 方法参数注入

方法参数注入的意思是在创建对象后,通过自动调用某个方法来注入依赖。

  • 优点:

    • 比较灵活
  • 缺点:

    • 新加入依赖时会破坏原有的方法签名,如果这个方法已经被其他很多模块用到就很麻烦
    • 与构造方法注入一样,会有很多参数
public class FurionService{    public Person GetById([FromServices]IRepository repository, int id)    {        return repository.Find(id);    }}

12.5 注册对象生存期

12.5.1 暂时/瞬时 生存期

暂时生存期服务是每次从服务容器进行请求时创建的。 这种生存期适合轻量级、 无状态的服务。

在处理请求的应用中,在请求结束时会释放暂时服务。

通常我们使用 ITransient 接口依赖表示该生命周期。

12.5.2 作用域 生存期

作用域生存期服务针对每个客户端请求(连接)创建一次。在处理请求的应用中,在请求结束时会释放有作用域的服务。

通常我们使用 IScoped 接口依赖表示该生命周期。

12.5.3 单例 生存期

在首次请求它们时进行创建,之后每个后续请求都使用相同的实例。

通常我们使用 ISingleton 接口依赖表示该生命周期。

了解更多

想了解更多 服务生存期 知识可查阅 ASP.NET Core - 依赖注入 - 服务生存期 章节。

12.6 内置依赖接口

Furion 框架提供三个接口依赖分别对应不同的服务生存期:

  • ITransient:对应暂时/瞬时作用域服务生存期
  • IScoped:对应请求作用域服务生存期
  • ISingleton:对应单例作用域服务生存期
特别注意

以上三个接口只能实例类实现,其他静态类、抽象类、及接口不能实现。

12.7 常见使用

12.7.1 第一个例子

创建 IBusinessService 接口和 BusinessService 实现类,代码如下:

using Furion.Core;using Furion.DatabaseAccessor;using Furion.DependencyInjection;namespace Furion.Application{    public interface IBusinessService    {        Person Get(int id);    }    public class BusinessService : IBusinessService, ITransient    {        private readonly IRepository<Person> _personRepository;        public BusinessService(IRepository<Person> personRepository)        {            _personRepository = personRepository;        }        public Person Get(int id)        {            return _personRepository.Find(id);        }    }}

创建 PersonController 控制器,代码如下:

using Furion.Application;using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    [Route("api/[controller]")]    [ApiController]    public class PersonController : ControllerBase    {        private readonly IBusinessService _businessService;        public PersonController(IBusinessService businessService)        {            _businessService = businessService;        }        [HttpGet]        public IActionResult Get(int id)        {            var person = _businessService.Get(id);            return new JsonResult(person);        }    }}

例子解说

Furion 框架提供了非常灵活且方便的实现依赖注入的方式,只需要实例类继承对应生存期的接口即可,这里继承了 ITransient,也就表明了这是一个 暂时/瞬时 作用域实例类。该类就可以作为被注入对象,同时也能注入其他接口对象。

上面的例子中,BusinessService 注入了 IRepository<Person> 仓储接口,同时 PersonController 控制器注入了 IBusinessService 接口。

这样 PersonControllerBusinessService 之间就实现了解耦,不再依赖于具体的 BusinessService 实例。

这就是依赖注入/控制反转最经典的例子。

12.7.2 注册泛型实例

创建 IBusinessService<T> 接口和 BusinessService<T> 实现类,代码如下:

using Furion.Core;using Furion.DatabaseAccessor;using Furion.DependencyInjection;namespace Furion.Application{    public interface IBusinessService<T>    {        Person Get(int id);    }    public class BusinessService<T> : IBusinessService<T>, ITransient    {        private readonly IRepository<Person> _personRepository;        public BusinessService(IRepository<Person> personRepository)        {            _personRepository = personRepository;        }        public Person Get(int id)        {            return _personRepository.Find(id);        }    }}

创建 PersonController 控制器,代码如下:

using Furion.Application;using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    [Route("api/[controller]")]    [ApiController]    public class PersonController : ControllerBase    {        private readonly IBusinessService<int> _businessService;        public PersonController(IBusinessService<int> businessService)        {            _businessService = businessService;        }        [HttpGet]        public IActionResult Get(int id)        {            var person = _businessService.Get(id);            return new JsonResult(person);        }    }}

12.7.3 一个接口多个实现

默认情况下,一个接口只对应一个实现类,但有些特殊情况,需要多个实现类注册同一个接口,如 DbContext 多数据库情况。

这个时候我们可以通过依赖注入 Func<string, IPrivateDependency, object> 委托来解析多个实例,其中委托的参数分别为:

  • 参数 1:string 类型,不同实现类唯一标识,默认为 nameof(实现类) 名称
  • 参数 2:Type 类型,IPrivateDependency 派生接口,也就是 ITransientIScopedISingleton
  • 返回值:object 类型,返回具体的实现类实例

创建 IBusinessService 接口和 BusinessServiceOtherBusinessService 两个实现类,代码如下:

using Furion.DependencyInjection;namespace Furion.Application{    public interface IBusinessService    {        string GetName();    }    public class BusinessService : IBusinessService, ITransient    {        public string GetName()        {            return "我是:" + nameof(BusinessService);        }    }    public class OtherBusinessService : IBusinessService, ITransient    {        public string GetName()        {            return "我是:" + nameof(OtherBusinessService);        }    }}
新版本,推荐使用

Furion 3.8.6+ 版本之后新增了 INamedServiceProvider 服务接口,可替代 Func<string, ILifetime, object> 方式:

using Furion.Application.Services;namespace Furion.Application;public class TestNamedServices : IDynamicApiController{    private readonly INamedServiceProvider<IBusinessService> _namedServiceProvider;    public TestNamedServices(INamedServiceProvider<IBusinessService> namedServiceProvider)    {        _namedServiceProvider = namedServiceProvider;    }    public string GetName()    {        // 第一种用法,通过反射解析服务周期,性能有损耗        var service1 = _namedServiceProvider.GetService(nameof(BusinessService));        var service2 = _namedServiceProvider.GetService(nameof(OtherBusinessService));        // 第二种用法,无需反射,注意下面的泛型参数传入的是生命周期依赖接口,ITransient, IScoped, ISingleton        var service3 = _namedServiceProvider.GetService<ITransient>(nameof(BusinessService));        var service4 = _namedServiceProvider.GetService<ITransient>(nameof(OtherBusinessService));        return service1.GetName() + "-" + service2.GetName() + "-" + service3.GetName() + "-" + service4.GetName();    }}
不再推荐 Func<string, TLifetime, object> 方式
using Furion.Application;using Furion.DependencyInjection;using Microsoft.AspNetCore.Mvc;using System;namespace Furion.Web.Entry.Controllers{    [Route("api/[controller]")]    [ApiController]    public class ValueController : ControllerBase    {        private readonly IBusinessService _businessService;        private readonly IBusinessService _otherBusinessService;        public ValueController(Func<string, ITransient, object> resolveNamed)        {            _businessService = resolveNamed("BusinessService", default) as IBusinessService;            _otherBusinessService = resolveNamed("OtherBusinessService", default) as IBusinessService;        }        [HttpGet]        public string GetName()        {            return _businessService.GetName() + "----------" + _otherBusinessService.GetName();        }    }}
小知识

如果需要自定义解析名称,只需要贴 [Injection(Named = "名称")] 即可,如:

using Furion.DependencyInjection;namespace Furion.Application{    [Injection(Named = "BusName1")]    public class BusinessService : IBusinessService, ITransient    {        // ...    }    [Injection(Named = "BusName2")]    public class OtherBusinessService : IBusinessService, ITransient    {        // ...    }}

解析服务:

_businessService = resolveNamed("BusName1", default) as IBusinessService;_otherBusinessService = resolveNamed("BusName2", default) as IBusinessService;

12.7.4 无接口方式

有些时候,我们不想定义接口,而是想把实例类作为可依赖注入的对象,如 MVC 中的控制器。

创建 SelfService 实例类,代码如下:

using Furion.Core;using Furion.DatabaseAccessor;using Furion.DependencyInjection;namespace Furion.Application{    public class SelfService : ITransient    {        private readonly IRepository<Person> _personRepository;        public SelfService(IRepository<Person> personRepository)        {            _personRepository = personRepository;        }        public Person Get(int id)        {            return _personRepository.Find(id);        }    }}

创建 ValueController 控制器,代码如下:

using Furion.Application;using Furion.Core;using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    [Route("api/[controller]")]    [ApiController]    public class ValueController : ControllerBase    {        private readonly SelfService _selfService;        public ValueController(SelfService selfService)        {            _selfService = selfService;        }        [HttpGet]        public Person Get(int id)        {            return _selfService.Get(id);        }    }}

12.8 [Injection] 特性配置

Furion 框架提供 [Injection] 特性可以改变注册方式,同时还能配置 AOP 拦截。

[Injection] 提供以下配置支持:

  • Action:配置注册行为,InjectionActions 类型,可选值:
    • Add默认值,表示无限制添加注册服务,该方式支持一个接口多个实现
    • TryAdd:表示注册已存在则跳过注册
  • Pattern:配置注册选项,InjectionPatterns 类型,可选值:
    • Self:只注册自己
    • FirstInterface:只注册第一个接口
    • SelfWithFirstInterface:注册自己和第一个接口
    • ImplementedInterfaces:注册所有接口
    • All:注册自己包括所有接口 ,默认值
  • Named:配置实例别名,通过别名可以解析接口,如同一个接口有多个实现,那么可以通过别名解析不同的实现,默认只为实现类的类名
  • Order:注册排序,数字越大,则越在最后注册,默认 0
  • Proxy:配置代理拦截类型,也就是 AOP代理类型必须继承 AspectDispatchProxy 类和 IDispatchProxy 接口,无默认值
  • ExpectInterfaces:配置忽略注册的接口,Type[] 类型

12.9 自定义高级注册

默认情况下,Furion 提供的注册方式可以满足大多数依赖注入的需求,如有特别注册需求,只需要在 Startup 中配置即可,如:

services.AddScoped(typeof(ISpecService), provider = > {    // 自定义任何创建实例的方式    var instance = new SpecService();  // 或者可以通过 AOP插件返回代理实例    return instance;});
补充说明

Furion 框架中的 AppDbContext 数据库上下文还有 ISqlDispatchProxy 都是通过这种方式创建的。

知识导航

想了解更多自定义高级中注册,可查阅 【ASP.NET Core 依赖注入】 官方文档。

12.10 appsettings.json 配置注册

除了在代码中实现依赖注入,也可以实现动态依赖注入,无需修改代码或重新编译即可实现热插拔(插件)效果。配置如下:

{  "DependencyInjectionSettings": {    "Definitions": [      {        "Interface": "Furion.Application;Furion.Application.ITestService",        "Service": "Furion.Application;Furion.Application.TestService",        "RegisterType": "Transient",        "Action": "Add",        "Pattern": "SelfWithFirstInterface",        "Named": "TestService",        "Order": 1,        "Proxy": "Furion.Application;Furion.Application.LogDispathProxy"      }    ]  }}

配置说明:

  • DependencyInjectionSettings:依赖注入配置根节点
    • Definitions:动态依赖注入配置节点,ExternalService 数组类型
      • ExternalService:配置单个依赖注入信息
关于外部程序集

如果动态注入的对象是外部程序集,那么首先先注册外部程序集:

{  "AppSettings": {    "ExternalAssemblies": ["外部程序集名称", "Taobao.Pay"] // 支持多个  }}

12.11 注册顺序和优先级

Furion 框架中,默认注册顺序是按照程序集扫描顺序进行注册,如果需要改变注册顺序,可通过 [Injection(Order)] 特性指定,Order 值越大,则越在最后注册。

另外 appsettings.json 配置的优先级最大,appsettings.json 配置的注册会覆盖之前所有注册。

12.12 Aop 注册拦截

关于动态 API 和服务的区别

如果您的服务是动态 API,那么请使用 动态 API - AOP 拦截,原因是动态 API 本质是控制器,所以采用 Filter 方式。

AOP 是非常重要的思想和技术,也就是 面向切面 编程,可以让我们在不改动原来代码的情况下进行动态篡改业务代码。

Furion 框架中,实现 Aop 非常简单,如:

假设我们有 ITestServiceTestService 两个类型:

public interface ITestService{    string SayHello(string word);}
public class TestService: ITestService, ITransient{    public string SayHello(string word)    {        return $"Hello {word}";    }}

现在我们有一个需求,我们希望调用 SayHello 的时候可以记录日志和权限控制(之前没有考虑到的需求)。

这个时候我们只需要创建一个代理类即可,如 LogDispatchProxy

using Furion.DependencyInjection;using System;using System.Reflection;namespace Furion.Application{    public class LogDispatchProxy : AspectDispatchProxy, IDispatchProxy    {        /// <summary>        /// 当前服务实例        /// </summary>        public object Target { get; set; }        /// <summary>        /// 服务提供器,可以用来解析服务,如:Services.GetService()        /// </summary>        public IServiceProvider Services { get; set; }        /// <summary>        /// 拦截方法        /// </summary>        /// <param name="method"></param>        /// <param name="args"></param>        /// <returns></returns>        public override object Invoke(MethodInfo method, object[] args)        {            Console.WriteLine("SayHello 方法被调用了");            var result = method.Invoke(Target, args);            Console.WriteLine("SayHello 方法返回值:" + result);            return result;        }        // 异步无返回值        public override async Task InvokeAsync(MethodInfo method, object[] args)        {            Console.WriteLine("SayHello 方法被调用了");            var task = method.Invoke(Target, args) as Task;            await task;             Console.WriteLine("SayHello 方法调用完成");        }        // 异步带返回值        public override async Task<T> InvokeAsyncT<T>(MethodInfo method, object[] args)        {            Console.WriteLine("SayHello 方法被调用了");            var taskT = method.Invoke(Target, args) as Task<T>;            var result = await taskT;            Console.WriteLine("SayHello 方法返回值:" + result);            return result;        }    }}
获取特性

如果需要获取方法的特性,只需要通过 method.GetActualCustomAttribute<TArrbute>() 即可。所有获取真实的特性统一采用 method.GetActual....() 方法开头。

之后我们只需要为 TestService 增加 [Injection] 特性即可,如:

[Injection(Proxy = typeof(LogDispatchProxy))]public class TestService: ITestService, ITransient{    public string SayHello(string word)    {        return $"Hello {word}";    }}

之后 SayHello 方法被调用的时候就可以实现动态拦截了,比如这里写日志。

12.12.1 全局Aop拦截

Furion 框架也提供了全局拦截的方式,只需要将 IDispatchProxy 修改为 IGlobalDispatchProxy 即可。

using Furion;using System.Reflection;namespace Furion.Application{    public class LogDispatchProxy : AspectDispatchProxy, IGlobalDispatchProxy    {        // ....    }}

这样就会拦截所有的 Service,当然也可以通过给特定类贴 [SuppressProxy] 跳过全局拦截操作。

拦截优先级

[SuppressProxy] > [Injection(Proxy = typeof(LogDispatchProxy))] > 全局拦截

12.12.2 AOP 注入解析服务

Furion 框架未提供 Proxy 构造函数注入功能,但是提供了 Services 属性,如果需要解析服务,则可以通过以下方式:

var someServices = Services.GetService<ISomeService>(); // 推荐方式// 或var someServices = App.GetService<ISomeService>();

12.12.3 AOP 的作用

这种面向切面的能力(动态拦截/代理)可以实现很多很多功能,如:

  • 动态日志记录
  • 动态修改参数
  • 动态修改返回值
  • 动态方法重定向
  • 动态修改代码逻辑
  • 动态实现异常监听

还可以做更多更多的事情。

12.13 在非 Web 或多线程解析服务

默认情况下,在 Web 请求开始之前会自动创建范围作用域,这个作用域的生存周期是请求之前和响应之后,也就是在这个作用域内的所有服务都实现了自动管理,比如创建服务和释放服务的时机。

但在非 Web 或多线程中,框架并不会做这样的事情,也就是框架只负责了服务的创建,但是没有负责销毁,原因是框架无法得知具体的销毁时机,这样就导致了内存溢出。

解决方式是:在非 Web 或多线程中使用服务,应该主动创建作用域,类似过去的 using,目前框架提供了几种方式。

12.13.1 IServiceProvider 方式

using var scope = serviceProvider.CreateScope();var services = scope.ServiceProvider;// 获取数据库上下文var dbContext = Db.GetDbContext(services);// 获取仓储var respository = Db.GetRepository<Person>(services);// 解析其他服务var otherService = services.GetService<XXX>();var otherService2 = App.GetService<XXX>(services);

12.13.2 IServiceScopeFactory 方式

using var scope = serviceScopeFactory.CreateScope();var services = scope.ServiceProvider;

12.13.3 Scoped 静态类

为了方法快速创建服务作用域,Furion 框架提供了 Scoped 静态类,如:

Scoped.Create((factory, scope) => {     var services = scope.ServiceProvider;});

12.14 自定义扫描/筛选注册服务

Furion 框架中并未提供完全自定义依赖注入扫描的机制,但推荐一个非常优秀的 .NET Core 依赖注入拓展库:Scrutor,使用非常简单,主要通过 FromAssemblyOf<> 扫描程序集和 AddClasses(o) 进行筛选注册。

使用如下:

services.Scan(scan => scan    // 扫描特定类型所在的程序集,这里是 ITransientService 所在的程序集    .FromAssemblyOf<ITransientService>()        // .AddClasses 在上面获取到的程序集中扫描所有公开、非抽象类型        // 之后可以通过委托进行类型筛选,例如下面只扫描实现 ITransientService 的类型        .AddClasses(classes => classes.AssignableTo<ITransientService>())            // 将上面的类型作为它实现的所有接口进行注册            // 如果类型实现了 N 个接口,那么就会有三个独立的注册            .AsImplementedInterfaces()            // 最后指定注册的生存期,如瞬时,作用域,还是单例            .WithTransientLifetime()        // 重复上面操作,比如这里扫描 IScopedService 所在的程序集        .AddClasses(classes => classes.AssignableTo<IScopedService>())            // 这里和上面不一样的是,这里指定只实现特定的几口,也就是只注册一次            .As<IScopedService>()            // 指定注册的生存期            .WithScopedLifetime()        // 也支持泛型注册,单个泛型参数        .AddClasses(classes => classes.AssignableTo(typeof(IOpenGeneric<>)))            .AsImplementedInterfaces()        // 多个泛型参数        .AddClasses(classes => classes.AssignableTo(typeof(IQueryHandler<,>)))            .AsImplementedInterfaces());

详细文档请查阅 https://github.com/khellang/Scrutor

12.15 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/deploy-docker-auto/index.html b/handbook/build/docs/deploy-docker-auto/index.html index 4a262b29d4..6c2ac26172 100644 --- a/handbook/build/docs/deploy-docker-auto/index.html +++ b/handbook/build/docs/deploy-docker-auto/index.html @@ -2,23 +2,22 @@ - - - + +35.1 Docker 环境持续部署 | Furion -35.1 Docker 环境持续部署 | Furion - - + + +
-

35.1 Docker 环境持续部署

35.1.1 关于全 Docker 环境部署

利用拥有 .NET 环境的 Jenkins,进行持续化部署

35.1.2 安装 DockerJenkins

正常在 Docker 中拉取的 Jenkins:lts 是无法执行 dotnet 命令的(就算你宿主机有 dotnet 环境、docker 中也有 dotnet 环境也不可以), +

35.1 Docker 环境持续部署

35.1.1 关于全 Docker 环境部署

利用拥有 .NET 环境的 Jenkins,进行持续化部署

35.1.2 安装 DockerJenkins

正常在 Docker 中拉取的 Jenkins:lts 是无法执行 dotnet 命令的(就算你宿主机有 dotnet 环境、docker 中也有 dotnet 环境也不可以), 所以我们只能构建一个包含 dotnet 的镜像

35.1.2.1 使用 Dockerfile 制作镜像

使用 Dockerfile 创建包含 dotnetJenkins 镜像

  • 👉 编写 Dockerfile
# 封装Jenkins镜像(带有dotnet环境的) sdk=5.1FROM jenkins/jenkins:ltsUSER rootWORKDIR /dotnetRUN apt-get update && apt-get install -y wget && rm -rf /var/lib/apt/lists/*RUN wget -O dotnet.tar.gz https://download.visualstudio.microsoft.com/download/pr/820db713-c9a5-466e-b72a-16f2f5ed00e2/628aa2a75f6aa270e77f4a83b3742fb8/dotnet-sdk-5.0.100-linux-x64.tar.gzRUN tar zxf dotnet.tar.gz -C ./RUN rm -rf dotnet.tar.gzENV PATH="${PATH}:/dotnet:/var/jenkins_home/.dotnet/tools"ENV DOTNET_ROOT="/dotnet"RUN apt update -yRUN apt install icu-devtools vim zip unzip -yRUN usermod -a -G root jenkinsUSER jenkins
  • 👉 命令解释
- 1. 这个Docker镜像基于jenkins- 2. 设置当前用户为root,因为后面安装需要使用root- 3. 设置当前工作目录为dotnet- 4. 下载dotnet SDK包,保存为dotnet.tar.gz。这里要注意下载正确版本的SDK,可前往微软官方网站获取下载链接:https://dotnet.microsoft.com/download- 5. 解压dotnet SDK到当前目录,即/dotnet目录- 6. 删除dotnet SDK包- 7. 把dotnet目录和dotnet tools目录添加到环境变量PATH,这样就可以使用dotnet命令了- 8. 设置DOTNET_ROOT变量- 9. 更新源- 10. 安装一些必需的,常用的工具包,其中icu-devtools是运行dotnet需要的- 11. 修改jenkins用户到root附加组- 12. 设置当前用户为jenkins
  • 👉 构建 Docker 镜像 name=jenkins:dotnet

cd 到根目录下(必须含 Dockerfile) 只需构建命令:

 docker build -t jenkins:dotnet .
特别注意

结尾 . 不能省略

35.1.2.2 运行 Jenkins:dotnet 镜像

docker run -d -p 8080:8080 -p 50000:50000 --name mjenkins  \           --privileged=true \           --restart always \           -u root \           -e TZ="Asia/Shanghai" \           -v /mudata/jenkins:/var/jenkins_home \           -v /usr/bin/docker:/usr/bin/docker \           -v /var/run/docker.sock:/var/run/docker.sock \           -v /mudata/webroot/:/mudata/webroot \           jenkins:dotnet

接下来就是比较俗套的安装 Jenkins 步骤,网上资料很多,不展开了。

35.1.3 Jenkins 的自动化部署

35.1.3.1 编写 Shell 脚本

# Jenkins 构建 测试服echo '============查看打包环境================'pwdlsecho $PATHimage_version=`date +%Y%m%d%H%M`;echo $image_version;dotnet --infodotnet --version# 获取短版本号GITHASH=`git rev-parse --short HEAD`echo '============================begin restore======================================='dotnet restoreecho '============================end restore======================================='#要构建的解决方案名称solutionName=MUSaas.SCM.BasicData#docker run的容器名称containerName=jenkinsscmbasic#指定run的端口port=9994#.sln文件全路径#solutionDir=20-Solution/${solutionName}.sln#.csproj文件全路径csprojDir=${solutionName}/${solutionName}.csproj#项目发布的目录webDir=/mudata/webroot/jenkins/publish/webapp#归档目录archivesDir=/mudata/webroot/jenkins/publish/archives#清空文件夹rm -rf ${webDir}/${JOB_NAME}/*#发布网站到webDirdotnet publish ${JENKINS_HOME}/workspace/${JOB_NAME}/${csprojDir} -c Release -o ${webDir}/${JOB_NAME} /p:Version=1.0.${BUILD_NUMBER}#复制配置文件#cp -rf /vdb1/jenkins/DotNetCoreWebPublishToDockerCommonConfigs/* ${webDir}/${JOB_NAME}/#判斷是否存在CID=$(docker ps | grep "${containerName}" | awk '{print $1}')echo $CIDif [ "$CID" != "" ];then    docker stop ${containerName}    docker rm ${containerName}    docker rmi ${containerName}#docker stop $CID#docker rm $CIDfi#通过Dockerfile重新构建镜像docker build -t ${containerName} ${webDir}/${JOB_NAME}/.#docker run容器并绑定到端口#docker run -d -p ${port}:80 --name ${containerName} ${containerName}docker run --name ${containerName} --restart=always -d -p ${port}:${port} -v /etc/localtime:/etc/localtime:ro ${containerName}echo "success!"

就这样自动化部署就好了。 测试服的 Jenkins 将源码拉下来,Publish,Docker Build,Docker Run

这里想要发布的时候,每次都需要手动去点击“构建”才会执行。也可以做成当分支合并成功后自动运行。反正 Jenkins 装好之后,你想要什么都能玩起来。比如指定分支提交后自动“构建”、比如构建成功后合并到 Master 等等

35.1.4 Jenkins 的自动化远程部署

35.1.4.1 安装插件

Publish Over SSH

35.1.4.2 配置

系统管理 => Publish over SSH

35.1.4.3 写脚本

# Jenkins 构建  正式服echo '============查看打包环境================'pwdlsecho $PATHimage_version=`date +%Y%m%d%H%M`;echo $image_version;dotnet --infodotnet --version# 获取短版本号GITHASH=`git rev-parse --short HEAD`echo '============================begin restore======================================='dotnet restoreecho '============================end restore======================================='#要构建的解决方案名称solutionName=MUSaas.SCM.BulkOrder#docker run的容器名称containerName=jenkinsscmbulk#指定run的端口port=9986#.csproj文件全路径csprojDir=/${solutionName}/${solutionName}.csproj#项目发布的目录webDir=/mudata/webroot/jenkins/publish/webapp#归档目录archivesDir=/mudata/webroot/jenkins/publish/archives#清空文件夹rm -rf ${webDir}/${JOB_NAME}/*#发布网站到webDirdotnet publish ${JENKINS_HOME}/workspace/${JOB_NAME}/${csprojDir} -c Release -o ${webDir}/${JOB_NAME} /p:Version=1.0.${BUILD_NUMBER}#复制配置文件#cp -rf /vdb1/jenkins/DotNetCoreWebPublishToDockerCommonConfigs/* ${webDir}/${JOB_NAME}/#构建远程包rm -rf ${JENKINS_HOME}/workspace/${JOB_NAME}/publishmkdir ${JENKINS_HOME}/workspace/${JOB_NAME}/publishtar -czvf ${JENKINS_HOME}/workspace/${JOB_NAME}/publish/${JOB_NAME}.${BUILD_NUMBER}.tar.gz -C ${webDir}/${JOB_NAME} .echo "success!"

大概逻辑就是发布后,打个包。然后丢给远程,远程再执行 shell

注意这里一定要发布到自己的 workspace 下,防止下一步死活找不到位置。如果找不到位置,只能慢慢用 ls 命令,一级一级去测,很麻烦

35.1.4.4 构建后操作(关键)

选择 Send Build artifacts over SSH

Source files: publish/Remove prefix(不填)Remote directory:/mudata/webroot/publish/Exec command:bash /mudata/shell/publish.sh  ${JOB_NAME} jenkinsscmbase ${JOB_NAME}.${BUILD_NUMBER}  9994
  • 选择自己的 SSH 服务器
  • Source files:一定是 workspace 下的地址
  • Remote directory:远程地址,从根目录开始
  • Exec command:要执行的 shell。这里所有的 Jenkins 环境变量都可以用

35.1.4.5 远程执行

publish.sh
# Jenkins Prod服 调用脚本solutionName=$1containerName=$2filename=$3port=$4#.publisecho ${solutionName}echo ${containerName}echo ${filename}baseDir=/mudata/webroot/publishwebDir=${baseDir}/publish/${filename}rm -rf ${webDir}mkdir ${webDir}tar -zxvf ${baseDir}/publish/${filename}.tar.gz -C ${webDir}/rm -f  ${webDir}/appsettings.json && mv  ${webDir}/appsettings.Prod.json  ${webDir}/appsettings.json#判斷是否存在CID=$(docker ps | grep "${containerName}" | awk '{print $1}')echo $CIDif [ "$CID" != "" ];then    docker stop ${containerName}    docker rm ${containerName}    docker rmi ${containerName}#docker stop $CID#docker rm $CIDficd  ${webDir}/ && docker build -t ${containerName} .docker run --name ${containerName} --restart=always -d -p ${port}:${port} --link myredis:myredis  -v /etc/localtime:/etc/localtime:ro ${containerName}

这里的逻辑就是解压,然后 Docker 相关。每次构建都是带着版本号来的。

35.1.5 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - + + \ No newline at end of file diff --git a/handbook/build/docs/deploy-docker/index.html b/handbook/build/docs/deploy-docker/index.html index 145efa4415..5098943df2 100644 --- a/handbook/build/docs/deploy-docker/index.html +++ b/handbook/build/docs/deploy-docker/index.html @@ -2,22 +2,21 @@ - - - + +34.2 在 Docker 部署 | Furion -34.2 在 Docker 部署 | Furion - - + + +
-

34.2 在 Docker 部署

精简发布文件

如果需要精简发布后的文件,也就是删除不必要的文件夹,可以编辑 Web 项目的 .csproj 并添加 <SatelliteResourceLanguages>en-US</SatelliteResourceLanguages>,如:

<PropertyGroup>  <TargetFramework>net6.0</TargetFramework>  <SatelliteResourceLanguages>en-US</SatelliteResourceLanguages></PropertyGroup>

34.2.1 关于 Docker 部署

Docker 中部署网站有两种方式:

  • 发布后构建:此方式是先发布网站后在再构建镜像,这样可以减少不必要的构建层,而且还能缩减镜像大小。(推荐)
  • 编译+构建+发布:也就是说在 Dockerfile 中配置网站从构建到发布的完整过程,此方式会速度慢,而且会产生冗余层,增加镜像大小。

34.2.2 两种方式构建

34.2.2.1 发布后构建

  • 👉 发布网站

首先在 Visual Studiodotnet cli 中发布网站,可以参考 在 IIS 部署-发布网站

  • 👉 编写 Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:5.0.9WORKDIR /appEXPOSE 80EXPOSE 443COPY . .ENTRYPOINT ["dotnet", "Furion.Web.Entry.dll"]
  • 👉 将 Dockerfile 文件拷贝到发布根目录

将编写好的 Dockerfile 文件(注意 D 大写)拷贝到发布网站的根目录下。

  • 👉 构建 Docker 镜像

在网站发布后的路径根目录下(必须含 Dockerfile)打开 CMD/PowerShell 只需构建命令:

docker build -t 网站名称:网站版本号 .
特别注意

后端的 . 不能省略

  • 👉 启动镜像
docker run --name 容器名称 -p 5000:80 --restart=always -d 网站名称:网站版本号
发布到 hub.docker.com

如果需要将该网站的镜像公开出去,那么可以发布到 hub.docker.com 中。发布步骤如下:

  • 👉 为镜像打 tag 标签
docker tag 网站名称:网站版本号 docker账号名/网站名称:网站版本号

如:

docker tag furion:v2.20 monksoul/furion:v2.20
  • 👉 登录 docker
docker login
  • 👉 推送到 hub.docker.com
docker push docker账号名/网站名称:网站版本号

如:

docker push monksoul/furion:v2.20

34.2.2.2 编译+构建+发布

此方式可以偷懒,但是不太推荐,不过在某些场景下非常有用,就是集成 Devops 工具链可以做到一步到位。

  • 👉 编写 Dockerfile

这种方式只需要把 Dockerfile 内容替换成以下即可:

FROM mcr.microsoft.com/dotnet/sdk:5.0.9 AS buildWORKDIR /source# Download SourceRUN git initRUN git remote add -t master -m master origin 你的源码Git地址RUN git config core.sparseCheckout trueRUN echo samples >> .git/info/sparse-checkoutRUN git pull --depth 1 origin main# Restore And PublishWORKDIR /source/samplesRUN dotnet restoreRUN dotnet publish -c release -o /app --no-restore# RunFROM mcr.microsoft.com/dotnet/aspnet:5.0.9WORKDIR /appCOPY --from=build /app ./EXPOSE 80EXPOSE 443ENTRYPOINT ["dotnet", "Furion.Web.Entry.dll"]
  • 👉 在 Dockerfile 所在路径构建

接下来的步骤和上述步骤一致,不再重复编写。

34.2.3 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

34.2 在 Docker 部署

精简发布文件

如果需要精简发布后的文件,也就是删除不必要的文件夹,可以编辑 Web 项目的 .csproj 并添加 <SatelliteResourceLanguages>en-US</SatelliteResourceLanguages>,如:

<PropertyGroup>  <TargetFramework>net6.0</TargetFramework>  <SatelliteResourceLanguages>en-US</SatelliteResourceLanguages></PropertyGroup>

34.2.1 关于 Docker 部署

Docker 中部署网站有两种方式:

  • 发布后构建:此方式是先发布网站后在再构建镜像,这样可以减少不必要的构建层,而且还能缩减镜像大小。(推荐)
  • 编译+构建+发布:也就是说在 Dockerfile 中配置网站从构建到发布的完整过程,此方式会速度慢,而且会产生冗余层,增加镜像大小。

34.2.2 两种方式构建

34.2.2.1 发布后构建

  • 👉 发布网站

首先在 Visual Studiodotnet cli 中发布网站,可以参考 在 IIS 部署-发布网站

  • 👉 编写 Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:5.0.9WORKDIR /appEXPOSE 80EXPOSE 443COPY . .ENTRYPOINT ["dotnet", "Furion.Web.Entry.dll"]
  • 👉 将 Dockerfile 文件拷贝到发布根目录

将编写好的 Dockerfile 文件(注意 D 大写)拷贝到发布网站的根目录下。

  • 👉 构建 Docker 镜像

在网站发布后的路径根目录下(必须含 Dockerfile)打开 CMD/PowerShell 只需构建命令:

docker build -t 网站名称:网站版本号 .
特别注意

后端的 . 不能省略

  • 👉 启动镜像
docker run --name 容器名称 -p 5000:80 --restart=always -d 网站名称:网站版本号
发布到 hub.docker.com

如果需要将该网站的镜像公开出去,那么可以发布到 hub.docker.com 中。发布步骤如下:

  • 👉 为镜像打 tag 标签
docker tag 网站名称:网站版本号 docker账号名/网站名称:网站版本号

如:

docker tag furion:v2.20 monksoul/furion:v2.20
  • 👉 登录 docker
docker login
  • 👉 推送到 hub.docker.com
docker push docker账号名/网站名称:网站版本号

如:

docker push monksoul/furion:v2.20

34.2.2.2 编译+构建+发布

此方式可以偷懒,但是不太推荐,不过在某些场景下非常有用,就是集成 Devops 工具链可以做到一步到位。

  • 👉 编写 Dockerfile

这种方式只需要把 Dockerfile 内容替换成以下即可:

FROM mcr.microsoft.com/dotnet/sdk:5.0.9 AS buildWORKDIR /source# Download SourceRUN git initRUN git remote add -t master -m master origin 你的源码Git地址RUN git config core.sparseCheckout trueRUN echo samples >> .git/info/sparse-checkoutRUN git pull --depth 1 origin main# Restore And PublishWORKDIR /source/samplesRUN dotnet restoreRUN dotnet publish -c release -o /app --no-restore# RunFROM mcr.microsoft.com/dotnet/aspnet:5.0.9WORKDIR /appCOPY --from=build /app ./EXPOSE 80EXPOSE 443ENTRYPOINT ["dotnet", "Furion.Web.Entry.dll"]
  • 👉 在 Dockerfile 所在路径构建

接下来的步骤和上述步骤一致,不再重复编写。

34.2.3 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/deploy-iis/index.html b/handbook/build/docs/deploy-iis/index.html index 4333e6a80d..9f0f92a0a4 100644 --- a/handbook/build/docs/deploy-iis/index.html +++ b/handbook/build/docs/deploy-iis/index.html @@ -2,22 +2,21 @@ - - - + +34.1 在 IIS 部署 | Furion -34.1 在 IIS 部署 | Furion - - + + +
-

34.1 在 IIS 部署

精简发布文件

如果需要精简发布后的文件,也就是删除不必要的文件夹,可以编辑 Web 项目的 .csproj 并添加 <SatelliteResourceLanguages>en-US</SatelliteResourceLanguages>,如:

<PropertyGroup>  <TargetFramework>net6.0</TargetFramework>  <SatelliteResourceLanguages>en-US</SatelliteResourceLanguages></PropertyGroup>

34.1.1 发布网站

34.1.1.1 选择启动项发布

34.1.1.2 选择发布到文件夹

34.1.1.3 配置发布后路径

34.1.1.4 点击发布

34.1.2 服务器环境配置

34.1.2.1 第一步

安装.NET Core 运行时捆绑包:点击下载

34.1.2.2 第二步(命令)

net stop was /y

34.1.2.3 第三步(命令)

net start w3svc

34.1.2.4 第四步(命令)

set ASPNETCORE_ENVIRONMENT=Production

34.1.3 部署到 IIS

34.1.3.1 添加新网站

34.1.3.2 配置网站信息

34.1.3.3 配置应用程序池

34.1.3.4 设置为 非托管

34.1.3.5 重启网站

只需重启网站或应用程序池即可。

34.1.4 常见问题

34.1.4.1 405 状态码,不支持 PUT,DELETE 请求

默认情况下,IIS拒绝 PUTDELETE 请求,原因为 IIS 默认注册了一个名为 WebDAVModule 的自定义 HttpModule 导致的。

解决该问题,只需要在 web.config 移除即可:

<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="webDAVModule"/>
</modules>
</system.webServer>
</configuration>

34.1.4.2 WebSocket/ SignalR 连接报错

如果项目部署在 IIS 中出现 WebSoket/SignalR 不能连接或连接失败等问题,请确保 IIS 服务中的 WebSocket 协议 是勾选状态

34.1.4.3 部署之后缺失 api-ms-win.xxxx.dll 问题

有时候将发布文件发布到服务器后,出现丢失 api.ms-win.xxxx.dll 文件,这时只需要重新发布并选择服务器特定的架构即可。

34.1.5 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

34.1 在 IIS 部署

精简发布文件

如果需要精简发布后的文件,也就是删除不必要的文件夹,可以编辑 Web 项目的 .csproj 并添加 <SatelliteResourceLanguages>en-US</SatelliteResourceLanguages>,如:

<PropertyGroup>  <TargetFramework>net6.0</TargetFramework>  <SatelliteResourceLanguages>en-US</SatelliteResourceLanguages></PropertyGroup>

34.1.1 发布网站

34.1.1.1 选择启动项发布

34.1.1.2 选择发布到文件夹

34.1.1.3 配置发布后路径

34.1.1.4 点击发布

34.1.2 服务器环境配置

34.1.2.1 第一步

安装.NET Core 运行时捆绑包:点击下载

34.1.2.2 第二步(命令)

net stop was /y

34.1.2.3 第三步(命令)

net start w3svc

34.1.2.4 第四步(命令)

set ASPNETCORE_ENVIRONMENT=Production

34.1.3 部署到 IIS

34.1.3.1 添加新网站

34.1.3.2 配置网站信息

34.1.3.3 配置应用程序池

34.1.3.4 设置为 非托管

34.1.3.5 重启网站

只需重启网站或应用程序池即可。

34.1.4 常见问题

34.1.4.1 405 状态码,不支持 PUT,DELETE 请求

默认情况下,IIS拒绝 PUTDELETE 请求,原因为 IIS 默认注册了一个名为 WebDAVModule 的自定义 HttpModule 导致的。

解决该问题,只需要在 web.config 移除即可:

<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="webDAVModule"/>
</modules>
</system.webServer>
</configuration>

34.1.4.2 WebSocket/ SignalR 连接报错

如果项目部署在 IIS 中出现 WebSoket/SignalR 不能连接或连接失败等问题,请确保 IIS 服务中的 WebSocket 协议 是勾选状态

34.1.4.3 部署之后缺失 api-ms-win.xxxx.dll 问题

有时候将发布文件发布到服务器后,出现丢失 api.ms-win.xxxx.dll 文件,这时只需要重新发布并选择服务器特定的架构即可。

34.1.5 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/deploy-nginx/index.html b/handbook/build/docs/deploy-nginx/index.html index 837ff57b39..cbfdc0e156 100644 --- a/handbook/build/docs/deploy-nginx/index.html +++ b/handbook/build/docs/deploy-nginx/index.html @@ -2,22 +2,21 @@ - - - + +34.3 在 Nginx 部署 | Furion -34.3 在 Nginx 部署 | Furion - - + + +
-
演练场
- - +
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/devops/index.html b/handbook/build/docs/devops/index.html index 44b1b06745..1479dc11cb 100644 --- a/handbook/build/docs/devops/index.html +++ b/handbook/build/docs/devops/index.html @@ -2,22 +2,21 @@ - - - + +35.2 持续部署集成 | Furion -35.2 持续部署集成 | Furion - - + + +
-
演练场
- - +
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/donate/index.html b/handbook/build/docs/donate/index.html index 6c208bf547..42b0138e1d 100644 --- a/handbook/build/docs/donate/index.html +++ b/handbook/build/docs/donate/index.html @@ -2,22 +2,21 @@ - - - + +1.5 支持 Furion | Furion -1.5 支持 Furion | Furion - - + + +
-

1.5 支持 Furion

开源免费

Furion 发展到如今,全靠社区小伙伴和各位开发者的支持,并且我们保证 Furion 持续开源免费。

但为了项目能够健康持续的发展下去,我们期望获得相应的支持。 如果你觉得 Furion 确实有用,并且实实在在的帮助到了你,那么可以考虑支持一下,你可以通过下列的方法来支持我们的开发:

1.5.1 帮助推广

你可将 Furion 开源地址,转发到你的朋友圈、个人博客或者其他平台,让更多的人知道 Furion 这款好用框架。

如果你喜欢 Furion ,可以在 Gitee 中给 Furion 点个 Star

1.5.2 成为赞助商

1.5.2.1 赞助商列表

注:排序按赞助顺序书写

赞助人昵称赞助金额(元)附语
🤴 爱吃油麦菜100感谢您的开源项目!
👳‍♂️ 麦壳饼200感谢您的开源项目!
👨 Sun100感谢您的开源项目!
👶 d61761720感谢您的开源项目!
👦 Diqiguoji00816.66见贤思齐
👲 nodyang100感谢您的开源项目!
👳‍♀️ mictxd100吹过的牛都实现。
🧓 欧流全10希望将来超越 Spring
👨‍⚕️ lionkon10...看了框架感觉拿来学习是很不错的...
😤 好人!10Nice 的小僧,我们的 dotnetchina 马上火起来了
😮 木木 Woody10感谢您的开源项目!
😚 Joker HouQQ 超级会员一个月
🤠 ccdfzQQ 专属红包 199
🌝 天夫李总支付宝 6666Furion 非常有意思,持续关注
😝 六尘子微信红包 199公司已经使用,小小敬意
🤠 ccdfzQQ 专属红包 200赞助一根内存条
🤑 邓亮灯28.88感谢您的开源项目!
😬 天道酬勤微信二维码 188小小心意
🥰 却月居士QQ 专属红包 100恭喜发财
🤩 鲁旭100感谢您的开源项目!
😬 散客行微信二维码 666终于找到一个不错的框架
😌 本心100项目功能很强大
🙆‍♂️ 毕业生100请你喝杯咖啡
🦹‍♀️ 猪鼻子微信二维码 668
🧟‍♂️ 明年·今日200使用的框架里最爽的,最理想的!加油
👨‍🎓 过去的过去50感谢您的开源项目!
👨‍🔧 万里兮100新公司的第一个项目从 Furion 开始
👴 Muphalem20很热心很亲切的开发者,加油!
💂‍♂️ 吃锅巴的码农微信二维码 500就冲你的文档写得好!
🤴 三重罗生门微信红包 200下次烤鱼你请!
🤵 李涛10加油,我们看到了 dotnet 美好的明天 :)
😂 !@#$%^&QQ 专属红包 100刚接触 furion,文档真棒
😵 李斌20看到一个不错的框架,学习学习,感谢作者的无私奉献
😞 逞强QQ 专属红包 20恭喜发财
🤒 顾锦松QQ 专属红包 200期待文档完成时候
🧟‍♀️ 哈哈微信赞赏码 1000点赞作者!
🍍 Z微信赞赏码 100恭喜孩子诞生,谢谢大佬
🍲 海涛50恭喜
😣 h微信赞赏码 100qq82683656
👱‍♀️ 冷大大微信赞赏码 100加快文档和教学补充哦,另外需要钉钉群,平常不用 QQ
👜 腾坤微信赞赏码 10感谢您的开源项目,QQ:565728589
🚆 文耶耶微信赞赏码 10很棒
🎟 Cynthiax微信转账 5000一路看着过来,小小心意
🥴 一花一世界微信赞赏码 10感谢开源,感谢持续更新
🥪 。微信赞赏码 2感谢
🎄微信赞赏码 20感谢你的开源项目
🍖 班卓微信赞赏码 9.9新年快乐
🥖 雨天裸奔的猫微信赞赏码 10加油!好东西,期待更多新特性
🍖 班卓微信赞赏码 9.9加个鸡腿
🍘 Egota Tiya微信赞赏码 6.66真的不错,准备使用这个框架
🤩 李氏天下微信赞赏码 200坚持下去
🎗 Trube微信赞赏码 200感恩
🧦 不长胡子的毛微信赞赏码 100Fur
👓 醉酒码农微信赞赏码 1000单次只能赞助 200,捐赠 5 次,支持 Furion
😢 XIUXIN微信赞赏码 20谢大佬,春天里的第一杯奶茶
👩‍🦳 吴鹏微信赞赏码 100感谢这么好的框架和文档
🧔 SymmmeeQQ 专属红包 20太牛了
🤴 隐居~~~QQ 专属红包 100支持一下吧
👵 饭粥微信赞赏码 666666666666
🎭 Free微信赞赏码 20感谢开源。比较敬业的架构师,支持一下
👑 时不待我微信赞赏码 50请你喝咖啡
😋 Eway5微信赞赏码 99找 abp 搜到 Furion 的,没想到国内有这么优秀的贡献者
🍛 吃瓜青蛙微信赞赏码 100加油,点赞
👩‍🎤 陈启表微信赞赏码 100敬佩开源,希望能成为未来.NET 项目框架之星!!
👨‍🔧 sunshuaize100感谢您的开源项目!
🚍 淘小涛10略尽绵薄之力,加油~大家
🍖 常松微信赞赏码 100开源不易,感谢您的开源
🍙 种一抹馨香微信赞赏码 50每次犯低级错误问你,都很耐心解答
😐 Ray微信赞赏码 8.88ray@wwads.cn 求合作
😁 王歆微信赞赏码 10略表心意,希望你的教程早些出来
🧶 Mark微信赞赏码 166
🎡 顾龙飞10感谢你的开源项目
🎏 石头微信赞赏码 20加油,给力
😣 慢慢微信赞赏码 100学习学习,挺好的架构
🎊 Minhoz微信赞赏码 8Furion 必火,大势所趋
🏹 瓯印软件88.88感谢你的开源项目
🤩 独、特10希望越来越好
🧵微信赞赏码 20
👸 李孟良微信赞赏码 100支持开源,感谢付出
🥰 易旭锋微信赞赏码 50
😆 liupan微信赞赏码 200
😏 君临天下微信赞赏码 20
🎉 海绵微信赞赏码 100大佬加油
🎊 好名字微信赞赏码 10希望尽快使用上 Furion 全家桶
🤗 A.LO微信赞赏码 100wash 3rd foot only
🤣 朱鹏程微信赞赏码 50午夜小精灵
😉 空问微信赞赏码 50加油,感谢!
😃 某人微信赞赏码 50大佬,喝阔落
😃 june微信赞赏码 10june-WHQ
😃 A.Mr 厘米微信赞赏码 101加油!
😃 大漠胡杨微信赞赏码 50再接再厉
😃 Anybody微信赞赏码 1000坚持下去
😃 听风微信赞赏码 200
🌝 dZhang Davil支付宝 10000great project.
🌝 aifie50YYDS,佩服,感谢您的开源项目!
🌝 🎄++微信赞赏码 10正在学习中,大佬加油!
🌝 无服务微信赞赏码 20感谢你的开源项目
🌝 铭微信赞赏码 10
🌝 生旦净末丑微信赞赏码 200加油,666
🌝 Mog微信赞赏码 50挺好用的
🌝 其实 °微信赞赏码 20事件总线太好用了
🌝 SU微信赞赏码 10功能强度大,持续关注
🌝微信赞赏码 100项目挺好!
🌝 M微信赞赏码 10希望国货崛起
🌝 EE微信赞赏码 20感谢那么棒的项目
🌝 陈春胜微信赞赏码 20浪里星辰
🌝 whd微信赞赏码 200支持
🌝 Dong微信赞赏码 20感谢开源,聊表心意!
🌝 琳琅水月微信赞赏码 100非常棒。省时省力。持续关注!
🌝 种花家村长微信赞赏码 20希望事件总线优化一下性能
🌝 刘强微信赞赏码 200感谢开源!期待更好的未来!
🌝 刘强微信转账 1000请兄弟们吃顿饭
🌝 芝麻芯微信赞赏码 100初学者,感谢让我们能专注于业务
🌝 june微信赞赏码 10june-WHQ
🌝 jamie微信赞赏码 10感谢无私奉献,收获满满
🌝 君子兰微信赞赏码 20NET 开发者加油~
🌝 王雾微信赞赏码 20希望 Furion 越来越好
🌝 李孟良微信赞赏码 100Furion 越来越好 赞
🌝 黄微信赞赏码 100感谢你的开源项目
🌝 HOMING_HNLY微信赞赏码 10感谢开源,敬佩持之以恒的更新!
🌝 Xukaige微信赞赏码 5钱虽少,一片心意,加油
🌝 快乐的小帅哥微信赞赏码 20支持一下,基础功能不错,节省开发时间
🌝 TR微信赞赏码 10很赞,小小的支持一下开源上项目!
🚍 wangshiqiao12510感谢您的开源项目!
🚍 Xukaige微信赞赏码 5钱虽少,一片心意,加油。
🚍 Coder_Army50感谢您的开源项目!和尚辛苦啦
🚍 fujin微信赞赏码 166.66感谢开源。
🚍 木三科技-软件开发微信赞赏码 66.66Furion 很强大,公司已开始使用,感谢开源。
🚍 dd微信赞赏码 50感谢您的开源项目!
🚍 chenYuAn微信赞赏码 10感谢您的开源项目!
🚍 keni微信赞赏码 20很棒,要是有纯英文版的更容易推广
🚍 Talk is cheap微信赞赏码 30感谢大佬无私奉献,文档细致全面,乃我辈典范
🚍 李涛微信赞赏码 20感谢您的开源项目,一直在使用
🚍 七色^_^微信赞赏码 100坚持下去,我是你的铁杆粉丝
🚍 鱼微信赞赏码 50桂电鱼
🚍 文林50感谢您的开源项目
🚍 AndyLi微信赞赏码 100让.NET 开发更简单,更通用,更流行。
🚍 未来微信赞赏码 20从 20 年开始用到现在,感谢付出

非常感谢您们的支持,正是因为您们,中国开源才可以越走越远,.NET 才能越走越远,Furion 也能越走越远。

1.5.3 赞助商广告

Furion 是基于 MIT 开源免费的项目,但我们的团队每年都在支付第三方域名、云服务器、全文搜索服务、QQ 群年费等费用,为了团队持续健康发展,Furion 官网提供多个赞助商广告位,皆在显眼位置展示,赞助费用仅需 5000/年。

赞助商广告位尺寸要求:261px x 60px

1.5.4 企业技术支持

如有长期技术支持、技术顾问的合作需求可添加微信号:ibaiqian,非诚勿扰。

每月合作费用不少于 6000元,合作期限不少于 3个月,需一次性支付合作期限费用。

技术支持/技术顾问提供以下服务:

  • Furion 技术培训
  • Furion 技术指导
  • Furion 技术问题排查/修复
  • .NET/C# 技术问题排查/修复(需另协商)
  • 其他协商要求
演练场
- - +

1.5 支持 Furion

开源免费

Furion 发展到如今,全靠社区小伙伴和各位开发者的支持,并且我们保证 Furion 持续开源免费。

但为了项目能够健康持续的发展下去,我们期望获得相应的支持。 如果你觉得 Furion 确实有用,并且实实在在的帮助到了你,那么可以考虑支持一下,你可以通过下列的方法来支持我们的开发:

1.5.1 帮助推广

你可将 Furion 开源地址,转发到你的朋友圈、个人博客或者其他平台,让更多的人知道 Furion 这款好用框架。

如果你喜欢 Furion ,可以在 Gitee 中给 Furion 点个 Star

1.5.2 成为赞助商

1.5.2.1 赞助商列表

注:排序按赞助顺序书写

赞助人昵称赞助金额(元)附语
🤴 爱吃油麦菜100感谢您的开源项目!
👳‍♂️ 麦壳饼200感谢您的开源项目!
👨 Sun100感谢您的开源项目!
👶 d61761720感谢您的开源项目!
👦 Diqiguoji00816.66见贤思齐
👲 nodyang100感谢您的开源项目!
👳‍♀️ mictxd100吹过的牛都实现。
🧓 欧流全10希望将来超越 Spring
👨‍⚕️ lionkon10...看了框架感觉拿来学习是很不错的...
😤 好人!10Nice 的小僧,我们的 dotnetchina 马上火起来了
😮 木木 Woody10感谢您的开源项目!
😚 Joker HouQQ 超级会员一个月
🤠 ccdfzQQ 专属红包 199
🌝 天夫李总支付宝 6666Furion 非常有意思,持续关注
😝 六尘子微信红包 199公司已经使用,小小敬意
🤠 ccdfzQQ 专属红包 200赞助一根内存条
🤑 邓亮灯28.88感谢您的开源项目!
😬 天道酬勤微信二维码 188小小心意
🥰 却月居士QQ 专属红包 100恭喜发财
🤩 鲁旭100感谢您的开源项目!
😬 散客行微信二维码 666终于找到一个不错的框架
😌 本心100项目功能很强大
🙆‍♂️ 毕业生100请你喝杯咖啡
🦹‍♀️ 猪鼻子微信二维码 668
🧟‍♂️ 明年·今日200使用的框架里最爽的,最理想的!加油
👨‍🎓 过去的过去50感谢您的开源项目!
👨‍🔧 万里兮100新公司的第一个项目从 Furion 开始
👴 Muphalem20很热心很亲切的开发者,加油!
💂‍♂️ 吃锅巴的码农微信二维码 500就冲你的文档写得好!
🤴 三重罗生门微信红包 200下次烤鱼你请!
🤵 李涛10加油,我们看到了 dotnet 美好的明天 :)
😂 !@#$%^&QQ 专属红包 100刚接触 furion,文档真棒
😵 李斌20看到一个不错的框架,学习学习,感谢作者的无私奉献
😞 逞强QQ 专属红包 20恭喜发财
🤒 顾锦松QQ 专属红包 200期待文档完成时候
🧟‍♀️ 哈哈微信赞赏码 1000点赞作者!
🍍 Z微信赞赏码 100恭喜孩子诞生,谢谢大佬
🍲 海涛50恭喜
😣 h微信赞赏码 100qq82683656
👱‍♀️ 冷大大微信赞赏码 100加快文档和教学补充哦,另外需要钉钉群,平常不用 QQ
👜 腾坤微信赞赏码 10感谢您的开源项目,QQ:565728589
🚆 文耶耶微信赞赏码 10很棒
🎟 Cynthiax微信转账 5000一路看着过来,小小心意
🥴 一花一世界微信赞赏码 10感谢开源,感谢持续更新
🥪 。微信赞赏码 2感谢
🎄微信赞赏码 20感谢你的开源项目
🍖 班卓微信赞赏码 9.9新年快乐
🥖 雨天裸奔的猫微信赞赏码 10加油!好东西,期待更多新特性
🍖 班卓微信赞赏码 9.9加个鸡腿
🍘 Egota Tiya微信赞赏码 6.66真的不错,准备使用这个框架
🤩 李氏天下微信赞赏码 200坚持下去
🎗 Trube微信赞赏码 200感恩
🧦 不长胡子的毛微信赞赏码 100Fur
👓 醉酒码农微信赞赏码 1000单次只能赞助 200,捐赠 5 次,支持 Furion
😢 XIUXIN微信赞赏码 20谢大佬,春天里的第一杯奶茶
👩‍🦳 吴鹏微信赞赏码 100感谢这么好的框架和文档
🧔 SymmmeeQQ 专属红包 20太牛了
🤴 隐居~~~QQ 专属红包 100支持一下吧
👵 饭粥微信赞赏码 666666666666
🎭 Free微信赞赏码 20感谢开源。比较敬业的架构师,支持一下
👑 时不待我微信赞赏码 50请你喝咖啡
😋 Eway5微信赞赏码 99找 abp 搜到 Furion 的,没想到国内有这么优秀的贡献者
🍛 吃瓜青蛙微信赞赏码 100加油,点赞
👩‍🎤 陈启表微信赞赏码 100敬佩开源,希望能成为未来.NET 项目框架之星!!
👨‍🔧 sunshuaize100感谢您的开源项目!
🚍 淘小涛10略尽绵薄之力,加油~大家
🍖 常松微信赞赏码 100开源不易,感谢您的开源
🍙 种一抹馨香微信赞赏码 50每次犯低级错误问你,都很耐心解答
😐 Ray微信赞赏码 8.88ray@wwads.cn 求合作
😁 王歆微信赞赏码 10略表心意,希望你的教程早些出来
🧶 Mark微信赞赏码 166
🎡 顾龙飞10感谢你的开源项目
🎏 石头微信赞赏码 20加油,给力
😣 慢慢微信赞赏码 100学习学习,挺好的架构
🎊 Minhoz微信赞赏码 8Furion 必火,大势所趋
🏹 瓯印软件88.88感谢你的开源项目
🤩 独、特10希望越来越好
🧵微信赞赏码 20
👸 李孟良微信赞赏码 100支持开源,感谢付出
🥰 易旭锋微信赞赏码 50
😆 liupan微信赞赏码 200
😏 君临天下微信赞赏码 20
🎉 海绵微信赞赏码 100大佬加油
🎊 好名字微信赞赏码 10希望尽快使用上 Furion 全家桶
🤗 A.LO微信赞赏码 100wash 3rd foot only
🤣 朱鹏程微信赞赏码 50午夜小精灵
😉 空问微信赞赏码 50加油,感谢!
😃 某人微信赞赏码 50大佬,喝阔落
😃 june微信赞赏码 10june-WHQ
😃 A.Mr 厘米微信赞赏码 101加油!
😃 大漠胡杨微信赞赏码 50再接再厉
😃 Anybody微信赞赏码 1000坚持下去
😃 听风微信赞赏码 200
🌝 dZhang Davil支付宝 10000great project.
🌝 aifie50YYDS,佩服,感谢您的开源项目!
🌝 🎄++微信赞赏码 10正在学习中,大佬加油!
🌝 无服务微信赞赏码 20感谢你的开源项目
🌝 铭微信赞赏码 10
🌝 生旦净末丑微信赞赏码 200加油,666
🌝 Mog微信赞赏码 50挺好用的
🌝 其实 °微信赞赏码 20事件总线太好用了
🌝 SU微信赞赏码 10功能强度大,持续关注
🌝微信赞赏码 100项目挺好!
🌝 M微信赞赏码 10希望国货崛起
🌝 EE微信赞赏码 20感谢那么棒的项目
🌝 陈春胜微信赞赏码 20浪里星辰
🌝 whd微信赞赏码 200支持
🌝 Dong微信赞赏码 20感谢开源,聊表心意!
🌝 琳琅水月微信赞赏码 100非常棒。省时省力。持续关注!
🌝 种花家村长微信赞赏码 20希望事件总线优化一下性能
🌝 刘强微信赞赏码 200感谢开源!期待更好的未来!
🌝 刘强微信转账 1000请兄弟们吃顿饭
🌝 芝麻芯微信赞赏码 100初学者,感谢让我们能专注于业务
🌝 june微信赞赏码 10june-WHQ
🌝 jamie微信赞赏码 10感谢无私奉献,收获满满
🌝 君子兰微信赞赏码 20NET 开发者加油~
🌝 王雾微信赞赏码 20希望 Furion 越来越好
🌝 李孟良微信赞赏码 100Furion 越来越好 赞
🌝 黄微信赞赏码 100感谢你的开源项目
🌝 HOMING_HNLY微信赞赏码 10感谢开源,敬佩持之以恒的更新!
🌝 Xukaige微信赞赏码 5钱虽少,一片心意,加油
🌝 快乐的小帅哥微信赞赏码 20支持一下,基础功能不错,节省开发时间
🌝 TR微信赞赏码 10很赞,小小的支持一下开源上项目!
🚍 wangshiqiao12510感谢您的开源项目!
🚍 Xukaige微信赞赏码 5钱虽少,一片心意,加油。
🚍 Coder_Army50感谢您的开源项目!和尚辛苦啦
🚍 fujin微信赞赏码 166.66感谢开源。
🚍 木三科技-软件开发微信赞赏码 66.66Furion 很强大,公司已开始使用,感谢开源。
🚍 dd微信赞赏码 50感谢您的开源项目!
🚍 chenYuAn微信赞赏码 10感谢您的开源项目!
🚍 keni微信赞赏码 20很棒,要是有纯英文版的更容易推广
🚍 Talk is cheap微信赞赏码 30感谢大佬无私奉献,文档细致全面,乃我辈典范
🚍 李涛微信赞赏码 20感谢您的开源项目,一直在使用
🚍 七色^_^微信赞赏码 100坚持下去,我是你的铁杆粉丝
🚍 鱼微信赞赏码 50桂电鱼
🚍 文林50感谢您的开源项目
🚍 AndyLi微信赞赏码 100让.NET 开发更简单,更通用,更流行。
🚍 未来微信赞赏码 20从 20 年开始用到现在,感谢付出

非常感谢您们的支持,正是因为您们,中国开源才可以越走越远,.NET 才能越走越远,Furion 也能越走越远。

1.5.3 赞助商广告

Furion 是基于 MIT 开源免费的项目,但我们的团队每年都在支付第三方域名、云服务器、全文搜索服务、QQ 群年费等费用,为了团队持续健康发展,Furion 官网提供多个赞助商广告位,皆在显眼位置展示,赞助费用仅需 5000/年。

赞助商广告位尺寸要求:261px x 60px

1.5.4 企业技术支持

如有长期技术支持、技术顾问的合作需求可添加微信号:ibaiqian,非诚勿扰。

每月合作费用不少于 6000元,合作期限不少于 3个月,需一次性支付合作期限费用。

技术支持/技术顾问提供以下服务:

  • Furion 技术培训
  • Furion 技术指导
  • Furion 技术问题排查/修复
  • .NET/C# 技术问题排查/修复(需另协商)
  • 其他协商要求
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dotnet-tools/index.html b/handbook/build/docs/dotnet-tools/index.html index 2cfa9c0457..7dd04fb349 100644 --- a/handbook/build/docs/dotnet-tools/index.html +++ b/handbook/build/docs/dotnet-tools/index.html @@ -2,22 +2,21 @@ - - - + +37. 编写包管理工具 | Furion -37. 编写包管理工具 | Furion - - + + +
-

37. 编写包管理工具

37.1 关于包管理工具

使用过 NodeJs 的朋友一定对 npm 命令不会陌生,可以通过 npm 安装项目需要的包或环境需要的工具,在 .NET Core 2.1+ 之后,微软也推出了新的特性,Global/Local Tools,该特性功能也正是受到 npm 启发下诞生的。

不同的是,npm 中的包采用的是 Javascript 编写并发布到 https://www.npmjs.com/ 平台,而 dotnet tools 采用 C# 编写并发布到 https://www.nuget.org/ 平台供安装使用。

37.1.2 dotnet tools 包管理好处

  • 跨平台,支持 Linux/Mac/Windows 平台供安装使用
  • 完整的 C# 生态支持
  • 为所欲为~~~(拥有操作系统的权限)

37.2 了解包命令语法

通常包命令语法都遵循以下规则:

<-|--|/>argument-name<=|:| >["|']value['|"] [--] [operand] ... [operand]

在这里,Furion 将简单介绍命令常用的知识:

  • 工具符:通常指的是你工具的唯一名称,也就是关键字,而且总是在最开头编写,如:dotnetnpmnode
  • 短参数:短参数指的是 单个字符 的字符串,我们通常使用 - 一个横杆指定参数及值,如:-v-v 0.0.1
  • 长参数:长参数指的是一个或多个单词连接的字符串,该参数通常和 短参数 同时存在,通常使用 -- 指定参数及值,如:--version--version 0.0.1
  • 操作符:字符串中与参数值格式不匹配的任何文本都被视为操作数,任何出现在双连字符 -- 之后且未包含在单引号或双引号中且两侧有空格的文本都被视为操作数,无论它是否与参数值格式匹配,通常用于归类/分类作用。

37.2.1 短参数例子

  • -a foo
短参数参数值
afoo
  • -ab
短参数参数值
a
b
  • -abc bar
短参数参数值
a
b
cbar

37.2.2 长参数例子

  • --foo bar
长参数参数值
foobar
  • --foo --bar
长参数参数值
foo
bar
  • --foo bar --hello world
长参数参数值
foobar
helloworld

37.2.3 混合参数例子

  • -abc foo --hello world /new="slashes are ok too"
短/长参数参数值
a
b
cfoo
helloworld
newslashes are ok too

37.2.4 多个值参数

  • --list 1 --list 2 --list 3
长参数参数值
list1,2,3

37.2.5 操作符

  • -a foo bar "hello world" -b -- -explicit operand
短参数参数值
afoo
b
操作符
bar
"hello world"
-explicit
operand

了解更多关于包命令语法的官方知识:https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html

37.3 编写第一个包

dotnet tools 工具实际上是一个 控制台 应用程序,不同的是 .csproj 项目文件需要添加特定配置。下面将给大家编写一个 HelloTools 包管理工具。

37.3.1 创建 HelloTools 控制台应用

37.3.2 编辑 HelloTools.csproj

将控制台项目标记成 dotnet tools 需要配置以下节点,如下图所示:

<Project Sdk="Microsoft.NET.Sdk">    <PropertyGroup>        <OutputType>Exe</OutputType>        <TargetFramework>net5.0</TargetFramework>        <Version>0.0.1</Version>        <Description>第一个 dotnet tools 工具</Description>        <ToolCommandName>hello-tools</ToolCommandName>        <PackAsTool>true</PackAsTool>        <GeneratePackageOnBuild>true</GeneratePackageOnBuild>        <PackageOutputPath>./nupkg</PackageOutputPath>    </PropertyGroup></Project>

配置关键节点说明

  • Version:包工具版本号
  • Description:包工具介绍
  • ToolCommandName:包工具关键字,如 dotnetnpm,后续使用都是通过该关键字使用
  • PackAsTool:是否声明为包管理工具,设置 true
  • GeneratePackageOnBuild:是否编译时自动生成 .nupkg 包,方便后续上传到 Nuget 平台
  • PackageOutputPath:配置 .nupkg 包存储目录,推荐使用 ./nupkg

37.3.3 安装 Furion.Tools.CommandLine

为了方便管理工具包开发,Furion 官方特意开发了 Furion.Tools.CommandLine 包,帮助大家快速开发管理工具包。

37.3.4 编写逻辑代码

我们先定义几个需求,然后编写逻辑代码:

需求一:输入 hello-tools 打印介绍信息

需求二:输入 -n--name 输出 Hello 名字

需求三:输入 -v--version 输出当前版本

需求四:输入 -h--help 输出帮助文档

using Furion.Tools.CommandLine;using System;using System.Collections.Generic;namespace HelloTools{    class Program    {        // 通过 Cli.Inject() 完成准备工作        static void Main(string[] args) => Cli.Inject();        /// <summary>        /// 输出 Hello 名字        /// </summary>        [Argument('n', "name", "您的名字")]        static string Name { get; set; }        // 定义参数处理程序,必须 [属性名]+Handler        static void NameHandler(ArgumentMetadata argument)        {            Console.WriteLine($"Hello {Name}");        }        /// <summary>        /// 查看版本        /// </summary>        [Argument('v', "version", "工具版本号")]        static bool Version { get; set; }        // 定义参数处理程序,必须 [属性名]+Handler        static void VersionHandler(ArgumentMetadata argument)        {            Console.WriteLine(Cli.GetVersion());        }        /// <summary>        /// 查看帮助文档        /// </summary>        [Argument('h', "help", "查看帮助文档")]        static bool Help { get; set; }        // 定义参数处理程序,必须 [属性名]+Handler        static void HelpHandler(ArgumentMetadata argument)        {            Cli.GetHelpText("hello-tools");        }        // 所有未匹配的参数/操作符处理程序,固定 NoMatchesHandler 方法名        static void NoMatchesHandler(bool isEmpty, string[] operands, Dictionary<string, object> noMatches)        {            if (isEmpty)            {                Console.WriteLine(@"  _    _      _ _         _______          _ | |  | |    | | |       |__   __|        | | | |__| | ___| | | ___      | | ___   ___ | |___ |  __  |/ _ \ | |/ _ \     | |/ _ \ / _ \| / __| | |  | |  __/ | | (_) |    | | (_) | (_) | \__ \ |_|  |_|\___|_|_|\___/     |_|\___/ \___/|_|___/");                Console.WriteLine($"欢迎使用{Cli.GetDescription()}");            }        }    }}
代码说明
  • Furion 工具包提供了非常方便的 Cli.Inject() 方法,可以实现一次性完成所有初始化工作,只需要在 Main 方法调用即可
  • 通过 [Argument(短参数,长参数,提示文档)] 定义每一个参数属性,参数必须是 static 静态
  • 通过 [属性名]Handler 定义每个参数匹配后的处理程序,如:VersionHandler,格式为:static void 属性名Handler(ArgumentMetadata argument)
  • 通过固定方法名 NoMatchesHandler 定义未匹配的参数及操作符,该方法有三个参数:
    • isEmpty:判断是否没有传递任何参数,通常用于输出介绍
    • operands:获取所有操作符列表
    • noMatches:获取所有未匹配的参数字典

37.3.5 如何调试包工具 👏

包管理工具调试有别于普通的控制台,主要区别是测试各个参数的使用,也就是如何传递 Main 方法的 args 参数。只需要以下两个步骤即可:

  • 在项目根目录添加 Properties 目录
  • Properties 目录中添加 launchSettings.json 文件,并遵循以下规则:
{  "profiles": {    "项目名称": {      "commandName": "Project",      "commandLineArgs": "你的命令"    }  }}
  • 项目名称:写你的项目实际名称,如:HelloTools
  • commandName:固定为 Project
  • commandLineArgs:编写测试命令,只需要写参数/操作符部分即可,如:-v-v -h --Name Furion

如,我们需要测试 HelloTools-n 参数

{  "profiles": {    "HelloTools": {      "commandName": "Project",      "commandLineArgs": "-n Furion"    }  }}

点击 运行/调试/F5 启动调试

37.3.6 测试各个参数情况

需求一:输入 hello-tools 打印介绍信息

{  "profiles": {    "HelloTools": {      "commandName": "Project",      "commandLineArgs": ""    }  }}

需求二:输入 -n--name 输出 Hello 名字

{  "profiles": {    "HelloTools": {      "commandName": "Project",      "commandLineArgs": "-n Furion"    }  }}

需求三:输入 -v--version 输出当前版本

{  "profiles": {    "HelloTools": {      "commandName": "Project",      "commandLineArgs": "--version"    }  }}

需求四:输入 -h--help 输出帮助文档

{  "profiles": {    "HelloTools": {      "commandName": "Project",      "commandLineArgs": "-h"    }  }}

37.4 打包(本机)测试

刚刚我们已经学会调试包工具了,但是还未做到类似 npm 包一样,在 cmd/powershell 中安装之后可在命令行全局测试,下面将教大家如何实现 全局安装本地安装

37.4.1 全局打包安装

全局打包安装就是配置在系统环境变量中,在任何地方都可以使用。

HelloTools 项目根目录下打开 cmd/powershell尽量使用管理员工具)执行以下命令:

✔ 安装全局包

dotnet tool install --global --add-source ./nupkg HelloTools

其中 HelloTools 就是 项目名称

之后我们就可以通过之前 HelloTools.csproj 中配置的 <ToolCommandName>hello-tools</ToolCommandName> 使用了。

✔ 测试全局包

✔ 更新全局包

如果源码发生改变,只需要编译项目后重新更新包工具即可:

dotnet tool update --global --add-source ./nupkg HelloTools

✔ 卸载全局包

dotnet tool uninstall --global HelloTools

想了解更多全局打包安装知识查阅官方文档即可:https://docs.microsoft.com/zh-cn/dotnet/core/tools/global-tools-how-to-use

37.4.2 本地打包安装

本地打包安装就是只有在项目所在目录及子孙目录方可使用。

HelloTools 项目根目录下打开 cmd/powershell 执行以下命令:

✔ 创建本地清单文件

dotnet new tool-manifest

执行该命令后会自动创建 .config 文件夹并添加 dotnet-tools.json 文件:

{  "version": 1,  "isRoot": true,  "tools": {}}
注意事项

通常该文件内容不需要手动更改。

✔ 安装本地包

dotnet tool install --add-source ./nupkg HelloTools

✔ 测试本地包

本地包测试和全局包不一样的是本地包是通过 dotnet 关键字 参数 测试:

dotnet hello-tools -n Furion

✔ 更新本地包

如果源码发生改变,只需要编译项目后重新更新包工具即可:

dotnet tool update --add-source ./nupkg HelloTools

✔ 卸载本地包

dotnet tool uninstall HelloTools

想了解更多本地打包安装知识查阅官方文档即可:https://docs.microsoft.com/zh-cn/dotnet/core/tools/local-tools-how-to-use

37.5 发布到 Nuget 平台 👏

发布到 Nuget 平台非常简单,只需要两个步骤即可:

上传 Nuget 平台补齐信息

建议上传到 Nuget 平台编辑 .csproj 文件补齐以下信息:

<Project Sdk="Microsoft.NET.Sdk">    <PropertyGroup>        <OutputType>Exe</OutputType>        <TargetFramework>net5.0</TargetFramework>        <Version>0.0.1</Version>        <Description>第一个 dotnet tools 工具</Description>        <ToolCommandName>hello-tools</ToolCommandName>        <PackAsTool>true</PackAsTool>        <GeneratePackageOnBuild>true</GeneratePackageOnBuild>        <PackageOutputPath>./nupkg</PackageOutputPath>        <Authors>百小僧</Authors>        <Company>Baiqian Co.,Ltd.</Company>        <Product>Furion</Product>        <Copyright>© 2020-2021 百小僧, Baiqian Co.,Ltd.</Copyright>        <RepositoryUrl>https://gitee.com/dotnetchina/Furion</RepositoryUrl>        <RepositoryType>Gitee</RepositoryType>        <GeneratePackageOnBuild>true</GeneratePackageOnBuild>        <PackageLicenseExpression>MIT</PackageLicenseExpression>        <PackageProjectUrl>https://furion.icu</PackageProjectUrl>    </PropertyGroup>    <ItemGroup>        <PackageReference Include="Furion.Tools.CommandLine" Version="2.6.0" />    </ItemGroup></Project>

发布到 Nuget 平台后,别人就可以通过:

✔ 安装 Nuget 包到本地

dotnet tool install --global 项目名 --version 版本号

37.6 Cli 静态类说明

为了简化包工具的开发,Furion.Tools.CommandLineCli 静态类提供了很多方便的静态方法:

37.6.1 消息类

// 输出空行Cli.EmptyLine();// 输出一行Cli.WriteLine("消息");Cli.WriteLine("消息", ConsoleColor.Blue);   // 字体颜色Cli.WriteLine("消息", ConsoleColor.Blue, ConsoleColor.White);   // 背景颜色Cli.WriteLine("消息", ConsoleColor.Blue, ConsoleColor.White, fillLine: true);   // 填充整行// 输出(不换行)Cli.Write("消息");Cli.Write("消息", ConsoleColor.Blue);   // 字体颜色Cli.Write("消息", ConsoleColor.Blue, ConsoleColor.White);   // 背景颜色Cli.Write("消息", ConsoleColor.Blue, ConsoleColor.White, fillLine: true);   // 填充整行// 输出提示消息Cli.Success("成功");Cli.Warn("警告");Cli.Error("错误");Cli.Tip("提示");// 收集用户输入(支持多行)var inputs = Cli.ReadInput(); // 输入 exit 退出输入// 选择消息var selectId = Cli.ReadOptions("请选择喜欢的水果:", new []{ "西瓜", "苹果", "凤梨"});  // selectId 从 1 开始

37.6.2 工具类

// 完成参数填充属性初始化操作Cli.Inject();// 获取参数所有信息var arguments = Cli.ArgumentMetadatas;// 手动检查参数是否匹配Cli.Check(nameof(属性名), argument => {    // 如果用户输入该参数    if(argument?.IsTransmission == true){        Cli.WriteLine(argument.Value);    }    else {        Cli.Error("用户没有输入");    }});// 只有参数匹配才进入Cli.CheckMatch(nameof(属性名), argument => {    Cli.WriteLine(argument.Value);})// 无属性检查Cli.Check(new[] {"v", "version"}, (isMatch, value) => {    // 如果用户输入该参数    if(isMatch){        Cli.WriteLine(value);    }    else {        Cli.Error("用户没有输入");    }});// 无属性匹配Cli.CheckMatch(new[] {"v", "version"}, value => {    Cli.WriteLine(value);});// 所有未匹配的参数、操作符Cli.CheckNoMatches((isEmpty, operands, noMatches) => {     if (isEmpty) Cli.WriteLine($"欢迎使用 {Cli.GetDescription()}");     if (operands.Length > 0) Cli.Error($"未找到该操作符:{string.Join(",", operands)}");     if (noMatches.Count > 0) Cli.Error($"未找到该参数:{string.Join(",", noMatches.Keys)}");});// 解析 Main 方法参数信息var argumentModel = Cli.Parse();// 手动解析命令字符串var argumentModel = Cli.Parse("-abc foo --hello world");// 终止输出/结束输出Cli.Exit();

37.6.2 信息类

// 获取当前工具包版本号var version = Cli.GetVersion();// 获取当前工具包描述var description = Cli.GetDescription();

37.6.3 其他类

我们可以通过 Environment 获取当前环境更多信息,如下图所示:

// 当前执行命令目录var currentDirectory = Environment.CurrentDirectory;// 获取机器名称var machineName = Environment.MachineName;// 等等。。。。。

37.7 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

37. 编写包管理工具

37.1 关于包管理工具

使用过 NodeJs 的朋友一定对 npm 命令不会陌生,可以通过 npm 安装项目需要的包或环境需要的工具,在 .NET Core 2.1+ 之后,微软也推出了新的特性,Global/Local Tools,该特性功能也正是受到 npm 启发下诞生的。

不同的是,npm 中的包采用的是 Javascript 编写并发布到 https://www.npmjs.com/ 平台,而 dotnet tools 采用 C# 编写并发布到 https://www.nuget.org/ 平台供安装使用。

37.1.2 dotnet tools 包管理好处

  • 跨平台,支持 Linux/Mac/Windows 平台供安装使用
  • 完整的 C# 生态支持
  • 为所欲为~~~(拥有操作系统的权限)

37.2 了解包命令语法

通常包命令语法都遵循以下规则:

<-|--|/>argument-name<=|:| >["|']value['|"] [--] [operand] ... [operand]

在这里,Furion 将简单介绍命令常用的知识:

  • 工具符:通常指的是你工具的唯一名称,也就是关键字,而且总是在最开头编写,如:dotnetnpmnode
  • 短参数:短参数指的是 单个字符 的字符串,我们通常使用 - 一个横杆指定参数及值,如:-v-v 0.0.1
  • 长参数:长参数指的是一个或多个单词连接的字符串,该参数通常和 短参数 同时存在,通常使用 -- 指定参数及值,如:--version--version 0.0.1
  • 操作符:字符串中与参数值格式不匹配的任何文本都被视为操作数,任何出现在双连字符 -- 之后且未包含在单引号或双引号中且两侧有空格的文本都被视为操作数,无论它是否与参数值格式匹配,通常用于归类/分类作用。

37.2.1 短参数例子

  • -a foo
短参数参数值
afoo
  • -ab
短参数参数值
a
b
  • -abc bar
短参数参数值
a
b
cbar

37.2.2 长参数例子

  • --foo bar
长参数参数值
foobar
  • --foo --bar
长参数参数值
foo
bar
  • --foo bar --hello world
长参数参数值
foobar
helloworld

37.2.3 混合参数例子

  • -abc foo --hello world /new="slashes are ok too"
短/长参数参数值
a
b
cfoo
helloworld
newslashes are ok too

37.2.4 多个值参数

  • --list 1 --list 2 --list 3
长参数参数值
list1,2,3

37.2.5 操作符

  • -a foo bar "hello world" -b -- -explicit operand
短参数参数值
afoo
b
操作符
bar
"hello world"
-explicit
operand

了解更多关于包命令语法的官方知识:https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html

37.3 编写第一个包

dotnet tools 工具实际上是一个 控制台 应用程序,不同的是 .csproj 项目文件需要添加特定配置。下面将给大家编写一个 HelloTools 包管理工具。

37.3.1 创建 HelloTools 控制台应用

37.3.2 编辑 HelloTools.csproj

将控制台项目标记成 dotnet tools 需要配置以下节点,如下图所示:

<Project Sdk="Microsoft.NET.Sdk">    <PropertyGroup>        <OutputType>Exe</OutputType>        <TargetFramework>net5.0</TargetFramework>        <Version>0.0.1</Version>        <Description>第一个 dotnet tools 工具</Description>        <ToolCommandName>hello-tools</ToolCommandName>        <PackAsTool>true</PackAsTool>        <GeneratePackageOnBuild>true</GeneratePackageOnBuild>        <PackageOutputPath>./nupkg</PackageOutputPath>    </PropertyGroup></Project>

配置关键节点说明

  • Version:包工具版本号
  • Description:包工具介绍
  • ToolCommandName:包工具关键字,如 dotnetnpm,后续使用都是通过该关键字使用
  • PackAsTool:是否声明为包管理工具,设置 true
  • GeneratePackageOnBuild:是否编译时自动生成 .nupkg 包,方便后续上传到 Nuget 平台
  • PackageOutputPath:配置 .nupkg 包存储目录,推荐使用 ./nupkg

37.3.3 安装 Furion.Tools.CommandLine

为了方便管理工具包开发,Furion 官方特意开发了 Furion.Tools.CommandLine 包,帮助大家快速开发管理工具包。

37.3.4 编写逻辑代码

我们先定义几个需求,然后编写逻辑代码:

需求一:输入 hello-tools 打印介绍信息

需求二:输入 -n--name 输出 Hello 名字

需求三:输入 -v--version 输出当前版本

需求四:输入 -h--help 输出帮助文档

using Furion.Tools.CommandLine;using System;using System.Collections.Generic;namespace HelloTools{    class Program    {        // 通过 Cli.Inject() 完成准备工作        static void Main(string[] args) => Cli.Inject();        /// <summary>        /// 输出 Hello 名字        /// </summary>        [Argument('n', "name", "您的名字")]        static string Name { get; set; }        // 定义参数处理程序,必须 [属性名]+Handler        static void NameHandler(ArgumentMetadata argument)        {            Console.WriteLine($"Hello {Name}");        }        /// <summary>        /// 查看版本        /// </summary>        [Argument('v', "version", "工具版本号")]        static bool Version { get; set; }        // 定义参数处理程序,必须 [属性名]+Handler        static void VersionHandler(ArgumentMetadata argument)        {            Console.WriteLine(Cli.GetVersion());        }        /// <summary>        /// 查看帮助文档        /// </summary>        [Argument('h', "help", "查看帮助文档")]        static bool Help { get; set; }        // 定义参数处理程序,必须 [属性名]+Handler        static void HelpHandler(ArgumentMetadata argument)        {            Cli.GetHelpText("hello-tools");        }        // 所有未匹配的参数/操作符处理程序,固定 NoMatchesHandler 方法名        static void NoMatchesHandler(bool isEmpty, string[] operands, Dictionary<string, object> noMatches)        {            if (isEmpty)            {                Console.WriteLine(@"  _    _      _ _         _______          _ | |  | |    | | |       |__   __|        | | | |__| | ___| | | ___      | | ___   ___ | |___ |  __  |/ _ \ | |/ _ \     | |/ _ \ / _ \| / __| | |  | |  __/ | | (_) |    | | (_) | (_) | \__ \ |_|  |_|\___|_|_|\___/     |_|\___/ \___/|_|___/");                Console.WriteLine($"欢迎使用{Cli.GetDescription()}");            }        }    }}
代码说明
  • Furion 工具包提供了非常方便的 Cli.Inject() 方法,可以实现一次性完成所有初始化工作,只需要在 Main 方法调用即可
  • 通过 [Argument(短参数,长参数,提示文档)] 定义每一个参数属性,参数必须是 static 静态
  • 通过 [属性名]Handler 定义每个参数匹配后的处理程序,如:VersionHandler,格式为:static void 属性名Handler(ArgumentMetadata argument)
  • 通过固定方法名 NoMatchesHandler 定义未匹配的参数及操作符,该方法有三个参数:
    • isEmpty:判断是否没有传递任何参数,通常用于输出介绍
    • operands:获取所有操作符列表
    • noMatches:获取所有未匹配的参数字典

37.3.5 如何调试包工具 👏

包管理工具调试有别于普通的控制台,主要区别是测试各个参数的使用,也就是如何传递 Main 方法的 args 参数。只需要以下两个步骤即可:

  • 在项目根目录添加 Properties 目录
  • Properties 目录中添加 launchSettings.json 文件,并遵循以下规则:
{  "profiles": {    "项目名称": {      "commandName": "Project",      "commandLineArgs": "你的命令"    }  }}
  • 项目名称:写你的项目实际名称,如:HelloTools
  • commandName:固定为 Project
  • commandLineArgs:编写测试命令,只需要写参数/操作符部分即可,如:-v-v -h --Name Furion

如,我们需要测试 HelloTools-n 参数

{  "profiles": {    "HelloTools": {      "commandName": "Project",      "commandLineArgs": "-n Furion"    }  }}

点击 运行/调试/F5 启动调试

37.3.6 测试各个参数情况

需求一:输入 hello-tools 打印介绍信息

{  "profiles": {    "HelloTools": {      "commandName": "Project",      "commandLineArgs": ""    }  }}

需求二:输入 -n--name 输出 Hello 名字

{  "profiles": {    "HelloTools": {      "commandName": "Project",      "commandLineArgs": "-n Furion"    }  }}

需求三:输入 -v--version 输出当前版本

{  "profiles": {    "HelloTools": {      "commandName": "Project",      "commandLineArgs": "--version"    }  }}

需求四:输入 -h--help 输出帮助文档

{  "profiles": {    "HelloTools": {      "commandName": "Project",      "commandLineArgs": "-h"    }  }}

37.4 打包(本机)测试

刚刚我们已经学会调试包工具了,但是还未做到类似 npm 包一样,在 cmd/powershell 中安装之后可在命令行全局测试,下面将教大家如何实现 全局安装本地安装

37.4.1 全局打包安装

全局打包安装就是配置在系统环境变量中,在任何地方都可以使用。

HelloTools 项目根目录下打开 cmd/powershell尽量使用管理员工具)执行以下命令:

✔ 安装全局包

dotnet tool install --global --add-source ./nupkg HelloTools

其中 HelloTools 就是 项目名称

之后我们就可以通过之前 HelloTools.csproj 中配置的 <ToolCommandName>hello-tools</ToolCommandName> 使用了。

✔ 测试全局包

✔ 更新全局包

如果源码发生改变,只需要编译项目后重新更新包工具即可:

dotnet tool update --global --add-source ./nupkg HelloTools

✔ 卸载全局包

dotnet tool uninstall --global HelloTools

想了解更多全局打包安装知识查阅官方文档即可:https://docs.microsoft.com/zh-cn/dotnet/core/tools/global-tools-how-to-use

37.4.2 本地打包安装

本地打包安装就是只有在项目所在目录及子孙目录方可使用。

HelloTools 项目根目录下打开 cmd/powershell 执行以下命令:

✔ 创建本地清单文件

dotnet new tool-manifest

执行该命令后会自动创建 .config 文件夹并添加 dotnet-tools.json 文件:

{  "version": 1,  "isRoot": true,  "tools": {}}
注意事项

通常该文件内容不需要手动更改。

✔ 安装本地包

dotnet tool install --add-source ./nupkg HelloTools

✔ 测试本地包

本地包测试和全局包不一样的是本地包是通过 dotnet 关键字 参数 测试:

dotnet hello-tools -n Furion

✔ 更新本地包

如果源码发生改变,只需要编译项目后重新更新包工具即可:

dotnet tool update --add-source ./nupkg HelloTools

✔ 卸载本地包

dotnet tool uninstall HelloTools

想了解更多本地打包安装知识查阅官方文档即可:https://docs.microsoft.com/zh-cn/dotnet/core/tools/local-tools-how-to-use

37.5 发布到 Nuget 平台 👏

发布到 Nuget 平台非常简单,只需要两个步骤即可:

上传 Nuget 平台补齐信息

建议上传到 Nuget 平台编辑 .csproj 文件补齐以下信息:

<Project Sdk="Microsoft.NET.Sdk">    <PropertyGroup>        <OutputType>Exe</OutputType>        <TargetFramework>net5.0</TargetFramework>        <Version>0.0.1</Version>        <Description>第一个 dotnet tools 工具</Description>        <ToolCommandName>hello-tools</ToolCommandName>        <PackAsTool>true</PackAsTool>        <GeneratePackageOnBuild>true</GeneratePackageOnBuild>        <PackageOutputPath>./nupkg</PackageOutputPath>        <Authors>百小僧</Authors>        <Company>Baiqian Co.,Ltd.</Company>        <Product>Furion</Product>        <Copyright>© 2020-2021 百小僧, Baiqian Co.,Ltd.</Copyright>        <RepositoryUrl>https://gitee.com/dotnetchina/Furion</RepositoryUrl>        <RepositoryType>Gitee</RepositoryType>        <GeneratePackageOnBuild>true</GeneratePackageOnBuild>        <PackageLicenseExpression>MIT</PackageLicenseExpression>        <PackageProjectUrl>https://furion.icu</PackageProjectUrl>    </PropertyGroup>    <ItemGroup>        <PackageReference Include="Furion.Tools.CommandLine" Version="2.6.0" />    </ItemGroup></Project>

发布到 Nuget 平台后,别人就可以通过:

✔ 安装 Nuget 包到本地

dotnet tool install --global 项目名 --version 版本号

37.6 Cli 静态类说明

为了简化包工具的开发,Furion.Tools.CommandLineCli 静态类提供了很多方便的静态方法:

37.6.1 消息类

// 输出空行Cli.EmptyLine();// 输出一行Cli.WriteLine("消息");Cli.WriteLine("消息", ConsoleColor.Blue);   // 字体颜色Cli.WriteLine("消息", ConsoleColor.Blue, ConsoleColor.White);   // 背景颜色Cli.WriteLine("消息", ConsoleColor.Blue, ConsoleColor.White, fillLine: true);   // 填充整行// 输出(不换行)Cli.Write("消息");Cli.Write("消息", ConsoleColor.Blue);   // 字体颜色Cli.Write("消息", ConsoleColor.Blue, ConsoleColor.White);   // 背景颜色Cli.Write("消息", ConsoleColor.Blue, ConsoleColor.White, fillLine: true);   // 填充整行// 输出提示消息Cli.Success("成功");Cli.Warn("警告");Cli.Error("错误");Cli.Tip("提示");// 收集用户输入(支持多行)var inputs = Cli.ReadInput(); // 输入 exit 退出输入// 选择消息var selectId = Cli.ReadOptions("请选择喜欢的水果:", new []{ "西瓜", "苹果", "凤梨"});  // selectId 从 1 开始

37.6.2 工具类

// 完成参数填充属性初始化操作Cli.Inject();// 获取参数所有信息var arguments = Cli.ArgumentMetadatas;// 手动检查参数是否匹配Cli.Check(nameof(属性名), argument => {    // 如果用户输入该参数    if(argument?.IsTransmission == true){        Cli.WriteLine(argument.Value);    }    else {        Cli.Error("用户没有输入");    }});// 只有参数匹配才进入Cli.CheckMatch(nameof(属性名), argument => {    Cli.WriteLine(argument.Value);})// 无属性检查Cli.Check(new[] {"v", "version"}, (isMatch, value) => {    // 如果用户输入该参数    if(isMatch){        Cli.WriteLine(value);    }    else {        Cli.Error("用户没有输入");    }});// 无属性匹配Cli.CheckMatch(new[] {"v", "version"}, value => {    Cli.WriteLine(value);});// 所有未匹配的参数、操作符Cli.CheckNoMatches((isEmpty, operands, noMatches) => {     if (isEmpty) Cli.WriteLine($"欢迎使用 {Cli.GetDescription()}");     if (operands.Length > 0) Cli.Error($"未找到该操作符:{string.Join(",", operands)}");     if (noMatches.Count > 0) Cli.Error($"未找到该参数:{string.Join(",", noMatches.Keys)}");});// 解析 Main 方法参数信息var argumentModel = Cli.Parse();// 手动解析命令字符串var argumentModel = Cli.Parse("-abc foo --hello world");// 终止输出/结束输出Cli.Exit();

37.6.2 信息类

// 获取当前工具包版本号var version = Cli.GetVersion();// 获取当前工具包描述var description = Cli.GetDescription();

37.6.3 其他类

我们可以通过 Environment 获取当前环境更多信息,如下图所示:

// 当前执行命令目录var currentDirectory = Environment.CurrentDirectory;// 获取机器名称var machineName = Environment.MachineName;// 等等。。。。。

37.7 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/dynamic-api-controller/index.html b/handbook/build/docs/dynamic-api-controller/index.html index 329078c7f5..981c9c9789 100644 --- a/handbook/build/docs/dynamic-api-controller/index.html +++ b/handbook/build/docs/dynamic-api-controller/index.html @@ -2,22 +2,21 @@ - - - + +5.1 动态 WebAPI | Furion -5.1 动态 WebAPI | Furion - - + + +
-

5.1 动态 WebAPI

小知识

动态WebAPI 实际上就是将普通的类变为 Controller,也就是 动态WebAPI 就是控制器,支持控制器一切功能。

5.1.1 什么是控制器

简单来说,控制器是一个承上启下的作用,根据用户输入,执行响应行为(动作方法),同时在行为中调用模型的业务逻辑,返回给用户结果(视图)。

ASP.NET Core 中,控制器有两种表现形式:

  • Mvc(带视图)
  • WebAPI(RESTful API)
using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    public class MvcController : Controller    {        public IActionResult Index()        {            return View();        }    }}

Mvc 控制器和 WebAPI 控制器最大的区别是 WebAPI 控制器不带 视图 和通过 请求谓词和路由地址响应行为

5.1.2 Mvc 控制器 约定和缺点

在学习动态 WebAPI 控制器之前,首先了解 ASP.NET CoreWebAPI 的一些约定和注意事项。

5.1.2.1 WebAPI 约定

ASP.NET Core 应用中,一个 WebAPI 控制器需遵循以下约定:

  • 控制器类必须继承 ControllerBase 或间接继承
  • 动作方法必须贴有 [HttpMethod] 特性,如:[HttpGet]
  • 控制器或动作方法至少有一个配置 [Route] 特性
  • 生成 WebAPI 路由地址时会自动去掉控制器名称 Controller 后缀,同时也会去掉动作方法匹配的 HttpVerb 谓词,如 GET,POST,DELETE,PUT
  • 不支持返回非 IEnumerable<T> 泛型对象
  • 不支持类类型参数在 GET,HEAD 请求下生成 Query 参数

除了上述约定外,WebAPI 路由地址基本靠手工完成,不利于书写,不利于维护,再者,在移动应用对接中难以进行多版本控制。

5.1.2.2 .NET Core WebAPI 缺点

通过上一章节可以看出,ASP.NET Core 应用实现 WebAPI 需要遵循种种约定,而且容易出错。

除了这些约定,.NET Core WebAPI 有以下缺点:

  • 路由地址基本靠手工完成
  • 在现在移动为王的时代,不利于进行多版本控制
  • 对接 Swagger 文档分组比较复杂
  • 实现 Policy 策略授权也比较复杂
  • 不支持控制器热插拔插件化
  • 难以实现复杂自定义的 RESTful API 风格

5.1.3 动态 WebAPI 控制器

针对以上 ASP.NET Core 提供的 WebAPI 必须遵循的约定和不可避免的缺点,Furion 框架创造出一种更加灵活创建 WebAPI 控制器的方式。

这个方式在继承了 ASP.NET Core WebAPI 所有优点,同时进行了大量拓展和优化。优化后的 WebAPI 具有以下优点:

  • 具备原有的 ControllerBase 所有功能
  • 支持任意公开 非静态 非抽象 非泛型类转控制器
  • 提供更加灵活方便的 IDynamicApiController 空接口或 [DynamicApiController] 特性替代 ControllerBase 抽象类
  • 无需手动配置 [HttpMethod] 特性,同时支持一个动作方法多个 HttpVerb
  • 无需手动配置 [Route] 特性,支持更加灵活的配置及自动路由生成
  • 支持返回泛型接口,泛型类
  • Swagger 深度结合,提供极其方便的创建 Swagger 分组配置
  • 支持 Basic Auth,Jwt,ApiKey 等多种权限灵活配置
  • 支持控制器、动作方法版本控制功能
  • 支持 GET、HEAD 请求自动转换 类类型参数
  • 支持生成 OAS3 接口规范

5.1.4 注册动态 WebAPI 服务

备注

.AddDynamicApiControllers() 默认已经集成在 AddInject() 中了,无需再次注册。也就是下列代码可不配置。

Furion.Web.Core\FurWebCoreStartup.cs
using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Core{    [AppStartup(800)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddControllers()                    .AddDynamicApiControllers();        }    }}
特别注意

.AddDynamicApiControllers() 必须在 services.AddControllers() 之后注册。

5.1.5 第一个例子

创建一个 FurionAppService 类继承 IDynamicApiController 接口 或 贴 [DynamicApiController] 特性,并在这个类中编写一个 Get 方法。

  • IDynamicApiController 方式
using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public string Get()        {            return $"Hello {nameof(Furion)}";        }    }}
  • [DynamicApiController] 方式
using Furion.DynamicApiController;namespace Furion.Application{    [DynamicApiController]    public class FurionAppService    {        public string Get()        {            return $"Hello {nameof(Furion)}";        }    }}

如下图所示,一个 WebAPI 接口就这么生成了。

5.1.6 动态 WebAPI 原理解析

5.1.6.1 控制器特性提供器

Furion 框架会在应用启动时注册 DynamicApiControllerFeatureProvider 控制器特性提供器,该提供器继承自 ControllerFeatureProvider 类。

接着重写 bool IsController(TypeInfo typeInfo) 方法,用来标识控制器类型。在 Furion 框架中,继承自 ControllerBase 类或 IDynamicApiController 接口或 [DynamicApiController] 特性都会被标记为控制器类型。

5.1.6.2 应用模型转换器

Furion 框架同时在应用启动时注册 DynamicApiControllerApplicationModelConvention 应用模型转换器,该转换器继承自 IApplicationModelConvention 接口。

接着实现 void Apply(ApplicationModel application) 接口方法。在该方法中配置控制器名称、路由、导出可见性及动作方法名称、路由、导出可见性等。

实际上该方法做的就是按照 WebAPI 约定 提前帮我们配置好路由、请求谓词等信息。避免了手动配置的同时还增加了许多新特性,如版本控制。

5.1.7 动态 WebAPI 配置约定

5.1.7.1 控制器默认约定

  • 生成控制器名称默认去除以 AppServices,AppService,ApiController,Controller,Services,Service 作为前后缀的字符串。见第一个例子中的 FurionAppService -> Furion 支持自定义配置
  • 控制器名称带 V[0-9_] 结尾的,会自动生成控制器版本号,如 FurionAppServiceV2 -> Furion@2FurionAppServiceV1_1_0 -> Furion@1.1.0支持版本分隔符配置
  • 控制名称以 骆驼命名(CamelCase) 会自动切割成多个单词 - 连接。支持自定义配置

5.1.7.2 动作方法默认约定

  • 生成的动作方法名称默认去除以 Post/Add/Create/Insert/Submit,GetAll/GetList/Get/Find/Fetch/Query/Search,Put/Update,Delete/Remove/Clear,Patch 开头的字符串。支持自定义配置
  • 生成的动作方法名称默认去除以 Async 作为前后缀的字符串。支持自定义配置
  • 动作方法名称带 V[0-9_] 结尾的,会自动生成动作方法版本号,如 ChangePasswordV2 -> ChangePassword@2ChangePasswordV1_1_0 -> ChangePassword@1.1.0支持版本分隔符配置
  • 动作方法名称以 骆驼(驼峰)/帕斯卡命名(CamelCase/Pascal) 会自动切割成多个单词 - 连接。支持自定义配置
  • 动作方法参数将自动转为小写。支持自定义配置

5.1.7.3 请求谓词默认约定

  • 动作方法名
    • Post/Add/Create/Insert/Submit/Change 开头,则添加 [HttpPost] 特性。
    • GetAll/GetList/Get/Find/Fetch/Query 开头,则添加 [HttpGet] 特性。
    • Put/Update 开头,则添加 [HttpPut] 特性。
    • Delete/Remove/Clear 开头,则添加 [HttpDelete] 特性。
    • Patch 开头,则添加 [HttpPatch] 特性
    • 支持自定义配置
  • 如果不在上面约定中,则默认添加 [HttpPost] 特性。支持自定义配置

5.1.7.4 路由地址默认约定

  • 默认以 api 开头。支持自定义配置
  • 默认转换为小写路由地址。支持自定义配置
  • 生成控制器路由模板格式为:api/前置参数列表/模块名或默认区域名/[controller@版本号]/后置参数列表
  • 生成动作方法路由模板格式为:前置参数列表/模块名/[action@版本号]/后置参数列表

5.1.7.5 其他约定

  • 默认不处理 ControllerBase 控制器类型。支持自定义配置
  • 默认不处理 GET,HEAD 请求的引用类型参数。支持自定义配置

5.1.8 更多例子

5.1.8.1 多种请求谓词方法

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public string Get()        {            return $"GET 请求";        }        public string Post()        {            return $"POST 请求";        }        public string Delete()        {            return $"DELETE 请求";        }        public string Put()        {            return $"PUT 请求";        }        public string Patch()        {            return $"PATCH 请求";        }    }}

如下图所示:

5.1.8.2 多个自定义动作方法

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public string GetVersion()        {            return $"v1.0.0";        }        public string ChangeProfile()        {            return "修改成功";        }        public string DeleteUser()        {            return "删除成功";        }    }}

如下图所示:

5.1.8.3 带参数动作方法

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public string GetUser(int id)        {            return $"{id}";        }        public string GetUser(int id, string name)        {            return $"{id} {name}";        }        public TestDto Add(TestDto testDto)        {            return testDto;        }    }}

如下图所示:

5.1.8.4 GET/HEAD 类类型参数

默认情况下,ASP.NET Core 会将 GET/HEAD 请求中的 类类型参数 设置为 [FromBody] 绑定,如:

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public TestDto GetTest(TestDto testDto)        {            return testDto;        }    }}

如下图所示:

但是,GET、HEAD 请求不支持 From Body 绑定。所以我们需要转换为 Query 查询参数。

Furion 框架支持以下两种方式配置:

using Furion.DynamicApiController;using Microsoft.AspNetCore.Mvc;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public TestDto GetTest([FromQuery] TestDto testDto)        {            return testDto;        }    }}

如下图所示:

5.1.8.5 自定义参数位置

Furion 框架提供了非常方便的自定义参数位置的特性 [ApiSeat],通过 [ApiSeat] 可配置参数位置,支持以下四种位置:

  • ApiSeats.ControllerStart:控制器之前
  • ApiSeats.ControllerEnd:控制器之后
  • ApiSeats.ActionStart:动作方法之前
  • ApiSeats.ActionEnd:动作方法之后。默认值
using Furion.DynamicApiController;using System;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        // 参数默认为 ApiSeats.ActionEnd        public string RouteSeat(int id, string name)        {            return "配置路由参数位置";        }        public string RouteSeat(            [ApiSeat(ApiSeats.ControllerStart)] int id, // 控制器名称之前            [ApiSeat(ApiSeats.ControllerEnd)] string name, // 控制器名称之后            [ApiSeat(ApiSeats.ControllerEnd)] int age, // 控制器名称之后            [ApiSeat(ApiSeats.ActionStart)] decimal weight, // 动作方法名称之前            [ApiSeat(ApiSeats.ActionStart)] float height, // 动作方法名称之前            [ApiSeat(ApiSeats.ActionEnd)] DateTime birthday) // 动作方法名称之后(默认值)        {            return "配置路由参数位置";        }    }}

如下图所示:

温馨提示

多个 同位置 配置的参数将按照 定义参数顺序 进行排序。

特别注意

[ApiSeat] 只能应用于贴了 [FromRoute] 特性的参数或 基元类型、值类型、可空基元类型和可空值类型

5.1.8.6 自定义请求谓词

using Furion.DynamicApiController;using Microsoft.AspNetCore.Mvc;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [HttpPost]        public string GetVersion()        {            return "1.0.0";        }    }}

如下图所示:

5.1.8.7 支持多个谓词

using Furion.DynamicApiController;using Microsoft.AspNetCore.Mvc;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [HttpPost, HttpGet, AcceptVerbs("PUT", "DELETE")]        public string GetVersion()        {            return "1.0.0";        }    }}

如下图所示:

特别注意

如果动作方法中含有 类类型参数,且含有 POST/PUT/DELETE 任意请求谓词,那么该参数会自动添加 [FromBody] 参数,即使在 GET/HEAD 请求中不支持。

5.1.8.8 支持自定义路由

支持控制器和动作方法自定义路由:

using Furion.DynamicApiController;using Microsoft.AspNetCore.Mvc;namespace Furion.Application{    [Route("customapi/mobile/[controller]")]    public class FurionAppService : IDynamicApiController    {        public string GetVersion()        {            return "1.0.0";        }    }}

如下图所示:

小提示

动作方法自定义路由如果以 / 开头,则不会合并控制器路由。

推荐配置

自定义路由如果需要用到 控制器/动作方法名称,推荐使用 [controller][action] 占位符,因为该占位符已经自动处理了 前后缀、版本号、模块名称等。

5.1.8.9 多路由随意组合

Furion 框架提供了非常灵活的各种路由组合方式,支持一对多,多对多路由组合:

using Furion.DynamicApiController;using Microsoft.AspNetCore.Mvc;namespace Furion.Application{    [Route("api/[controller]")]    [Route("api/[controller]/second")]    [Route("api/[controller]/three")]    public class FurionAppService : IDynamicApiController    {        [HttpGet]        [HttpGet("get/[action]")]        [HttpPost]        [HttpPost("post/cus-version")]        public string GetVersion()        {            return "1.0.0";        }    }}

如下图所示:

特别注意

动作方法不能同时贴 [Route][HttpMethod] 特性,只能二取一。

5.1.8.10 支持版本控制

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppServiceV1 : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }    }    public class FurionAppServiceV1_2 : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }    }    public class FurionAppServiceV1_2_1 : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }    }}

如下图所示:

版本生成原理

V[0-9_] 结尾的命名自动解析成版本号,如 FurionAppServiceV2 -> Furion@2

版本复写

除了通过特定后缀方式以外,版本还直接通过 [ApiDescriptionSettings] 进行复写。如:

[ApiDescriptionSettings(Version = "4.0")]public string GetV1(){    return nameof(Furion);}

这时,生成版本将采用 4.0 替代 1

5.1.8.11 不公开控制器或动作方法

有些时候,我们无需导出某个动作方法或控制器(不显示到 Swagger),只需要添加 [ApiDescriptionSettings(false)][ApiExplorerSettings(IgnoreApi = true)]即可。

另外动作方法还支持 [NonAction] 标记不是一个有效的控制器或 Action。

推荐使用

推荐控制器或动作方法设置不导出使用 [ApiDescriptionSettings(false)] 特性。该特性默认继承自 ApiExplorerSettingsAttribute 类。

5.1.8.12 保持控制器和方法命名

默认情况下,动态 API 会将控制器和方法名输出为 RESTFul 风格的路由,如需保留原有设计,只需配置:

{  "DynamicApiControllerSettings": {    "KeepName": true,    "KeepVerb": true,    "LowercaseRoute": false  }}

5.1.8.13 方法参数 [FromQuery] 化/参数非必填/参数可选

默认情况下,所有的基元类型参数都会贴上 [FromRoute] 特性,如果需要将参数调整为 [FromQuery] 修饰,只需要在方法上面贴 [QueryParameters] 特性即可,如:

[QueryParameters]public string Get(int id, string name){    return nameof($"{id} {name}");}

生成的路由为:https://xxx.com?id=1&name=Furion

如果不喜欢每个都配置,也可以全局配置(只会影响基元类型的参数):

{  "DynamicApiControllerSettings": {    "UrlParameterization": true  }}
特别注意

贴了 [QueryParameters] 之后,会对所有参数影响,包括类类型参数,如果不需要处理某个参数,只需要贴 [FromXXX] 特性即可。

5.1.8.14 参数绑定配置

Furion 框架提供了多种参数特性配置参数绑定规则:

  • [FromRoute]:通过路由参数绑定值
  • [FromQuery]:通过 Url 地址参数绑定值
  • [FromBody]:通过 Request Body 参数绑定值
  • [FromForm]:通过表单提交绑定值
  • [FromHeader]:通过 Request Header 参数绑定值

5.1.8.15 自定义根据方法名生成 [HttpMethod] 规则

Furion 框架中,在没有配置 [HttpMethod] 特性的情况下,会自动根据方法名第一个参数进行分析,并生成对应的 [HttpMethod] 特性,规则如下:

  • 动作方法名
    • Post/Add/Create/Insert/Submit 开头,则添加 [HttpPost] 特性。
    • GetAll/GetList/Get/Find/Fetch/Query 开头,则添加 [HttpGet] 特性。
    • Put/Update 开头,则添加 [HttpPut] 特性。
    • Delete/Remove/Clear 开头,则添加 [HttpDelete] 特性。
    • Patch 开头,则添加 [HttpPatch] 特性
    • Head 开头,则添加 [HttpHead] 特性
    • 支持自定义配置
  • 如果不在上面约定中,则默认添加 [HttpPost] 特性。支持自定义配置

但是,有些时候这不是我们想要的规则,这时我们只需要在 appsettings.json 中配置即可:

{  "DynamicApiControllerSettings": {    "VerbToHttpMethods": [      ["getall", "HEAD"], // => getall 会被复写为 `[HttpHead]`      ["other", "PUT"] // => 新增一条新规则,比如,一 `[other]` 开头会转换为 `[HttpPut]` 请求    ]  }}
特别注意

二维数组中的每一个元素的第一个元素必须是全小写,第二个元素必须是全大写大写,第二个元素取值有:HEAD, GET, PUT, POST, PATCH, DELETE

5.1.8.16 路由参数非必填/选填

Furion v2.8.6 版本中实现了 [FromRoute] 参数非必填功能,支持以下几种方式:

// 方式一,通过可空 ?public object Method1(int id, Datetime? dateTime){}// 方式二,通过默认值public object Method1(int id, int age = 10){}// 方式三,默认值 + 可空 ?public object Method1(int id, int? age = 10){}// 方式四,[FromQuery] 修饰public object Method1(int id, [FromQuery]string keyword){}

5.1.8.17 [FormRoute] 路由约束

Furion v2.8.6 版本中,添加了 [RouteConstraint] 特性,可配置路由约束,如:[RouteConstraint(":min(10)")]

// 最小值 10public object Method1([RouteConstraint(":min(10)")] int id){}

[RouteConstraint] 支持路由约束符号如下:

符号描述例子
alpha匹配大写或小写拉丁字母字符(a-z、A-Z):alpha
boolbool 类型:bool
datetimeDateTime 类型:datetime
decimaldecimal 类型:decimal
doubledouble 类型:double
floatfloat 类型:float
guidguid 类型:guid
intint 类型:int
longlong 类型:long
length匹配长度(字符串):length(6):length(1,20)
max最大值:max(10)
maxlength最大长度(字符串):maxlength(10)
min最小值:min(10)
minlength最小长度(字符串):minlength(10)
range取值范围:range(10,50)
regex正则表达式:regex(^\d{3}-\d{3}-\d{4}$)

5.1.8.18 小驼峰 路由路径

{  "DynamicApiControllerSettings": {    "LowercaseRoute": false,    "KeepName": true,    "AsLowerCamelCase": true  }}

5.1.9 [ApiDescriptionSettings]

除了上述 ASP.NET Core 提供的配置外,Furion 框架还提供了非常强大且灵活的 [ApiDescriptionSettings] 特性。

5.1.9.1 内置配置

  • Name:自定义控制器/动作方法名称,string,默认 null
  • KeepName:是否保持原有名称不处理,bool,默认 false
  • SplitCamelCase:切割骆驼(驼峰)/帕斯卡命名,bool,默认 true
  • KeepVerb:是否保留动作方法请求谓词,bool,默认 false
  • Enabled:是否导出接口,bool,默认 true
  • Module:模块名,string,默认 null
  • Version:版本号,string,默认 null
  • Groups:接口分组,可结合 Swagger 一起使用,string[],默认 null
  • Tags:接口标签,可结合 Swagger 一起使用,string[],默认 null
  • Order:配置控制器/动作方法排序
  • LowercaseRoute:是否采用小写路由,bool 类型,默认 true
  • AsLowerCamelCase:启用小驼峰命名(首字母小写),默认 false
  • Area:配置区域名称,默认空,只作用于类中贴
  • Description:配置单一接口更多描述功能,只在 方法 中有效,仅限 v3.3.5+版本有效
  • ForceWithRoutePrefix:配置是否强制添加 DefaultRoutePrefix,当控制器自定义了 [Route] 有效,仅限 v3.4.1+版本有效

5.1.9.2 Name 配置

Name 参数可以覆盖动态 WebAPI 自动生成的控制器或动作方法名称。如:

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings(Name = "MyFur")]    public class FurionAppService : IDynamicApiController    {        [ApiDescriptionSettings(Name = "MyGet")]        public string Get()        {            return nameof(Furion);        }    }}

如下图所示:

5.1.9.3 KeepName 配置

KeepName 参数可以保留原有的控制器或动作方法名称。如:

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings(KeepName = true)]    public class FurionAppService : IDynamicApiController    {        [ApiDescriptionSettings(KeepName = true)]        public string Get()        {            return nameof(Furion);        }    }}

如下图所示:

5.1.9.4 SplitCamelCase 配置

SplitCamelCase 参数默认将骆驼(驼峰)命名切割成多个单词并通过指定 占位符 连接起来。默认 占位符-。默认为 true。如:

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings(SplitCamelCase = false)]    public class MyFurionAppService : IDynamicApiController    {        [ApiDescriptionSettings(SplitCamelCase = true)]        public string ChangeUserName()        {            return nameof(Furion);        }    }}

如下图所示:

特别注意

KeepName 优先级高于 SplitCamelCase,也就是 KeepName 设置为 true,则不会处理 SplitCamelCase 参数。

5.1.9.5 KeepVerb 配置

KeepVerb 参数作用于动作方法,标识是否保留动作谓词。如:

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [ApiDescriptionSettings(KeepVerb = true)]        public string GetVersion()        {            return nameof(Furion);        }    }}

如下图所示:

5.1.9.6 Enabled 配置

Enabled 参数配置接口是否导出。通常用于动作方法,如果用于控制器实际作用不大。

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public string GetVersion()        {            return nameof(Furion);        }        [ApiDescriptionSettings(false)]        public string NoExport()        {            return nameof(Furion);        }    }}

如下图所示:

5.1.9.7 Module 配置

Module 参数可以配置路由分离,类似于 Mvc 区域 的作用。

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings(Module = "mobile")]    public class FurionAppService : IDynamicApiController    {        [ApiDescriptionSettings(Module = "user")]        public string GetVersion()        {            return nameof(Furion);        }    }}

如下图所示:

5.1.9.8 Version 配置

Version 参数可以配置接口版本,同时又可以复写特殊版本命名配置。默认版本分隔符为 @。如:

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings(Version = "1.0")]    public class FurionAppService : IDynamicApiController    {        // V2.0.0 被复写成 V2.1.1        [ApiDescriptionSettings(Version = "2.1.1")]        public string GetVersionV2_0_0()        {            return nameof(Furion);        }    }}

如下图所示:

5.1.9.9 Groups 配置

Groups 配置主要用于配置 Swagger 分组信息。

通过配置 Groups 参数可以将控制器和动作方法 进行归类和多个分组直接共享。可通过 [ApiDescriptionSettings(params Groups)] 构造函数传入或指定 Groups 参数配置接口是否导出。通常用于动作方法,如果用于控制器实际作用不大。

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings("Default", "Common")]    public class FurionAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        [ApiDescriptionSettings("Custom")]        public int Get(int id)        {            return id;        }    }}

如下图所示:

5.1.9.10 Tag 配置

Tag 配置主要用于配置 Swagger 标签分组信息及合并标签。也就是 组中组:

未贴标签之前

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }    public class TestAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }}

贴标签之后

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings(Tag = "分组一")]    public class FurionAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }    [ApiDescriptionSettings(Tag = "分组二")]    public class TestAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }}

如下图所示:

小知识

如果 Tag 名字一样,则会自动合并,否则只是命名。

5.1.10 DynamicApiControllerSettings 配置

Furion 还提供动态 WebAPI 接口一些全局配置选项,如:

  • DefaultRoutePrefix:默认路由前缀,string,默认 api
  • DefaultHttpMethod:默认请求谓词,string,默认:POST
  • DefaultModule:默认模块名称(区域),可用作接口版本,string,默认:v1
  • LowercaseRoute:小写路由格式,bool,默认:true
  • AsLowerCamelCase:启用小驼峰命名(首字母小写),默认 false
  • KeepVerb:是否保留动作谓词,bool,默认:false
  • KeepName:是否保留默认名称,bool,默认:fasle
  • CamelCaseSeparator:骆驼(驼峰)/帕斯卡命名分隔符,string,默认:-
  • VersionSeparator:版本分隔符,string,默认:@
  • ModelToQueryGET/HEAD 请求将 类类型参数转查询参数bool,默认 false
  • SupportedMvcController:是否支持 Mvc Controller 动态配置,bool,默认 false
  • UrlParameterization:路由参数采用 [FromQuery] 化,默认 false[FromRoute] 方式)
  • DefaultArea:配置默认区域,默认 null
  • ForceWithRoutePrefix:配置是否强制添加 DefaultRoutePrefix,当控制器自定义了 [Route] 有效,仅限 v3.4.1+版本有效
  • AbandonControllerAffixes:默认去除控制器名称前后缀列表名,string[],默认:
    • AppServices
    • AppService
    • ApiController
    • Controller
    • Services
    • Service
  • AbandonActionAffixes:默认去除动作方法名称前后缀列表名,string[],默认:
    • Async
    • VerbToHttpMethods:复写默认方法名转 [HttpMethod] 规则,string[][] 二维数组类型,内置匹配规则为:
      ["post"] = "POST",["add"] = "POST",["create"] = "POST",["insert"] = "POST",["submit"] = "POST",["get"] = "GET",["find"] = "GET",["fetch"] = "GET",["query"] = "GET",["getlist"] = "GET",["getall"] = "GET",["put"] = "PUT",["update"] = "PUT",["delete"] = "DELETE",["remove"] = "DELETE",["clear"] = "DELETE",["patch"] = "PATCH"
      • 复写示例
      "DynamicApiControllerSettings": {    "VerbToHttpMethods": [      [ "getall", "HEAD" ],  // => getall 会被复写为 `[HttpHead]`      [ "other", "PUT" ]  // => 新增一条新规则,比如,一 `[other]` 开头会转换为 `[HttpPut]` 请求    ]  }

5.1.10.1 支持 Mvc 控制器 动态配置

默认情况下,Furion 动态 WebAPI 接口不对 ControllerBase 类型进行任何处理。当然,我们也可以手动启用 ControllerBase 支持。

Furion.Web.Entry/appsettings.json
{  "DynamicApiControllerSettings": {    "SupportedMvcController": true  }}

设置 SupportedMvcController: true 后,Mvc ControllerBase 类型也能和动态 WebAPI 一样的灵活了。代码如下:

using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    public class MvcController : ControllerBase    {        public string Get()        {            return nameof(Furion);        }    }}
注意事项

启用该配置后,如果 Mvc 控制器 没有任何 [Route] 特性,但是贴了 [ApiController] 特性将会报错。原因是 [ApiController] 特性内部做了路由特性检测。所以建议使用 [ApiDataValidation] 代替。

查看 ASP.NET Core - ApiBehaviorApplicationModelProvider 源码

5.1.11 关于 AOP 拦截

动态WebAPI 支持 Controller 的所有过滤器/筛选器拦截,也就是可以通过 ActionFilterResultFilter 进行拦截操作。如:

public class SampleAsyncActionFilter : IAsyncActionFilter{    public async Task OnActionExecutionAsync(ActionExecutingContext context,ActionExecutionDelegate next)    {        // 拦截之前        var resultContext = await next();        // 拦截之后        // 异常拦截        if(resultContext.Exception != null)        {        }    }}

详细用法可参见 ASP.NET Core 5.0 - 筛选器

5.1.12 设置 api 超时请求时间

Program.cs 中添加 .UseKestrel 配置即可,如:

  • .NET5 版本
public static IHostBuilder CreateHostBuilder(string[] args){    return Host.CreateDefaultBuilder(args)        .ConfigureWebHostDefaults(webBuilder =>        {            webBuilder.Inject()                      .UseStartup<Startup>()                      .UseKestrel(option =>                      {                          option.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(20);                          option.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(20);                      });        });}
  • .NET6 版本
var app = builder.Build();app.Configuration.Get<WebHostBuilder>().ConfigureKestrel(x =>{    x.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(20);    x.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(20);});

5.1.13 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

5.1 动态 WebAPI

小知识

动态WebAPI 实际上就是将普通的类变为 Controller,也就是 动态WebAPI 就是控制器,支持控制器一切功能。

5.1.1 什么是控制器

简单来说,控制器是一个承上启下的作用,根据用户输入,执行响应行为(动作方法),同时在行为中调用模型的业务逻辑,返回给用户结果(视图)。

ASP.NET Core 中,控制器有两种表现形式:

  • Mvc(带视图)
  • WebAPI(RESTful API)
using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    public class MvcController : Controller    {        public IActionResult Index()        {            return View();        }    }}

Mvc 控制器和 WebAPI 控制器最大的区别是 WebAPI 控制器不带 视图 和通过 请求谓词和路由地址响应行为

5.1.2 Mvc 控制器 约定和缺点

在学习动态 WebAPI 控制器之前,首先了解 ASP.NET CoreWebAPI 的一些约定和注意事项。

5.1.2.1 WebAPI 约定

ASP.NET Core 应用中,一个 WebAPI 控制器需遵循以下约定:

  • 控制器类必须继承 ControllerBase 或间接继承
  • 动作方法必须贴有 [HttpMethod] 特性,如:[HttpGet]
  • 控制器或动作方法至少有一个配置 [Route] 特性
  • 生成 WebAPI 路由地址时会自动去掉控制器名称 Controller 后缀,同时也会去掉动作方法匹配的 HttpVerb 谓词,如 GET,POST,DELETE,PUT
  • 不支持返回非 IEnumerable<T> 泛型对象
  • 不支持类类型参数在 GET,HEAD 请求下生成 Query 参数

除了上述约定外,WebAPI 路由地址基本靠手工完成,不利于书写,不利于维护,再者,在移动应用对接中难以进行多版本控制。

5.1.2.2 .NET Core WebAPI 缺点

通过上一章节可以看出,ASP.NET Core 应用实现 WebAPI 需要遵循种种约定,而且容易出错。

除了这些约定,.NET Core WebAPI 有以下缺点:

  • 路由地址基本靠手工完成
  • 在现在移动为王的时代,不利于进行多版本控制
  • 对接 Swagger 文档分组比较复杂
  • 实现 Policy 策略授权也比较复杂
  • 不支持控制器热插拔插件化
  • 难以实现复杂自定义的 RESTful API 风格

5.1.3 动态 WebAPI 控制器

针对以上 ASP.NET Core 提供的 WebAPI 必须遵循的约定和不可避免的缺点,Furion 框架创造出一种更加灵活创建 WebAPI 控制器的方式。

这个方式在继承了 ASP.NET Core WebAPI 所有优点,同时进行了大量拓展和优化。优化后的 WebAPI 具有以下优点:

  • 具备原有的 ControllerBase 所有功能
  • 支持任意公开 非静态 非抽象 非泛型类转控制器
  • 提供更加灵活方便的 IDynamicApiController 空接口或 [DynamicApiController] 特性替代 ControllerBase 抽象类
  • 无需手动配置 [HttpMethod] 特性,同时支持一个动作方法多个 HttpVerb
  • 无需手动配置 [Route] 特性,支持更加灵活的配置及自动路由生成
  • 支持返回泛型接口,泛型类
  • Swagger 深度结合,提供极其方便的创建 Swagger 分组配置
  • 支持 Basic Auth,Jwt,ApiKey 等多种权限灵活配置
  • 支持控制器、动作方法版本控制功能
  • 支持 GET、HEAD 请求自动转换 类类型参数
  • 支持生成 OAS3 接口规范

5.1.4 注册动态 WebAPI 服务

备注

.AddDynamicApiControllers() 默认已经集成在 AddInject() 中了,无需再次注册。也就是下列代码可不配置。

Furion.Web.Core\FurWebCoreStartup.cs
using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Core{    [AppStartup(800)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddControllers()                    .AddDynamicApiControllers();        }    }}
特别注意

.AddDynamicApiControllers() 必须在 services.AddControllers() 之后注册。

5.1.5 第一个例子

创建一个 FurionAppService 类继承 IDynamicApiController 接口 或 贴 [DynamicApiController] 特性,并在这个类中编写一个 Get 方法。

  • IDynamicApiController 方式
using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public string Get()        {            return $"Hello {nameof(Furion)}";        }    }}
  • [DynamicApiController] 方式
using Furion.DynamicApiController;namespace Furion.Application{    [DynamicApiController]    public class FurionAppService    {        public string Get()        {            return $"Hello {nameof(Furion)}";        }    }}

如下图所示,一个 WebAPI 接口就这么生成了。

5.1.6 动态 WebAPI 原理解析

5.1.6.1 控制器特性提供器

Furion 框架会在应用启动时注册 DynamicApiControllerFeatureProvider 控制器特性提供器,该提供器继承自 ControllerFeatureProvider 类。

接着重写 bool IsController(TypeInfo typeInfo) 方法,用来标识控制器类型。在 Furion 框架中,继承自 ControllerBase 类或 IDynamicApiController 接口或 [DynamicApiController] 特性都会被标记为控制器类型。

5.1.6.2 应用模型转换器

Furion 框架同时在应用启动时注册 DynamicApiControllerApplicationModelConvention 应用模型转换器,该转换器继承自 IApplicationModelConvention 接口。

接着实现 void Apply(ApplicationModel application) 接口方法。在该方法中配置控制器名称、路由、导出可见性及动作方法名称、路由、导出可见性等。

实际上该方法做的就是按照 WebAPI 约定 提前帮我们配置好路由、请求谓词等信息。避免了手动配置的同时还增加了许多新特性,如版本控制。

5.1.7 动态 WebAPI 配置约定

5.1.7.1 控制器默认约定

  • 生成控制器名称默认去除以 AppServices,AppService,ApiController,Controller,Services,Service 作为前后缀的字符串。见第一个例子中的 FurionAppService -> Furion 支持自定义配置
  • 控制器名称带 V[0-9_] 结尾的,会自动生成控制器版本号,如 FurionAppServiceV2 -> Furion@2FurionAppServiceV1_1_0 -> Furion@1.1.0支持版本分隔符配置
  • 控制名称以 骆驼命名(CamelCase) 会自动切割成多个单词 - 连接。支持自定义配置

5.1.7.2 动作方法默认约定

  • 生成的动作方法名称默认去除以 Post/Add/Create/Insert/Submit,GetAll/GetList/Get/Find/Fetch/Query/Search,Put/Update,Delete/Remove/Clear,Patch 开头的字符串。支持自定义配置
  • 生成的动作方法名称默认去除以 Async 作为前后缀的字符串。支持自定义配置
  • 动作方法名称带 V[0-9_] 结尾的,会自动生成动作方法版本号,如 ChangePasswordV2 -> ChangePassword@2ChangePasswordV1_1_0 -> ChangePassword@1.1.0支持版本分隔符配置
  • 动作方法名称以 骆驼(驼峰)/帕斯卡命名(CamelCase/Pascal) 会自动切割成多个单词 - 连接。支持自定义配置
  • 动作方法参数将自动转为小写。支持自定义配置

5.1.7.3 请求谓词默认约定

  • 动作方法名
    • Post/Add/Create/Insert/Submit/Change 开头,则添加 [HttpPost] 特性。
    • GetAll/GetList/Get/Find/Fetch/Query 开头,则添加 [HttpGet] 特性。
    • Put/Update 开头,则添加 [HttpPut] 特性。
    • Delete/Remove/Clear 开头,则添加 [HttpDelete] 特性。
    • Patch 开头,则添加 [HttpPatch] 特性
    • 支持自定义配置
  • 如果不在上面约定中,则默认添加 [HttpPost] 特性。支持自定义配置

5.1.7.4 路由地址默认约定

  • 默认以 api 开头。支持自定义配置
  • 默认转换为小写路由地址。支持自定义配置
  • 生成控制器路由模板格式为:api/前置参数列表/模块名或默认区域名/[controller@版本号]/后置参数列表
  • 生成动作方法路由模板格式为:前置参数列表/模块名/[action@版本号]/后置参数列表

5.1.7.5 其他约定

  • 默认不处理 ControllerBase 控制器类型。支持自定义配置
  • 默认不处理 GET,HEAD 请求的引用类型参数。支持自定义配置

5.1.8 更多例子

5.1.8.1 多种请求谓词方法

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public string Get()        {            return $"GET 请求";        }        public string Post()        {            return $"POST 请求";        }        public string Delete()        {            return $"DELETE 请求";        }        public string Put()        {            return $"PUT 请求";        }        public string Patch()        {            return $"PATCH 请求";        }    }}

如下图所示:

5.1.8.2 多个自定义动作方法

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public string GetVersion()        {            return $"v1.0.0";        }        public string ChangeProfile()        {            return "修改成功";        }        public string DeleteUser()        {            return "删除成功";        }    }}

如下图所示:

5.1.8.3 带参数动作方法

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public string GetUser(int id)        {            return $"{id}";        }        public string GetUser(int id, string name)        {            return $"{id} {name}";        }        public TestDto Add(TestDto testDto)        {            return testDto;        }    }}

如下图所示:

5.1.8.4 GET/HEAD 类类型参数

默认情况下,ASP.NET Core 会将 GET/HEAD 请求中的 类类型参数 设置为 [FromBody] 绑定,如:

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public TestDto GetTest(TestDto testDto)        {            return testDto;        }    }}

如下图所示:

但是,GET、HEAD 请求不支持 From Body 绑定。所以我们需要转换为 Query 查询参数。

Furion 框架支持以下两种方式配置:

using Furion.DynamicApiController;using Microsoft.AspNetCore.Mvc;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public TestDto GetTest([FromQuery] TestDto testDto)        {            return testDto;        }    }}

如下图所示:

5.1.8.5 自定义参数位置

Furion 框架提供了非常方便的自定义参数位置的特性 [ApiSeat],通过 [ApiSeat] 可配置参数位置,支持以下四种位置:

  • ApiSeats.ControllerStart:控制器之前
  • ApiSeats.ControllerEnd:控制器之后
  • ApiSeats.ActionStart:动作方法之前
  • ApiSeats.ActionEnd:动作方法之后。默认值
using Furion.DynamicApiController;using System;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        // 参数默认为 ApiSeats.ActionEnd        public string RouteSeat(int id, string name)        {            return "配置路由参数位置";        }        public string RouteSeat(            [ApiSeat(ApiSeats.ControllerStart)] int id, // 控制器名称之前            [ApiSeat(ApiSeats.ControllerEnd)] string name, // 控制器名称之后            [ApiSeat(ApiSeats.ControllerEnd)] int age, // 控制器名称之后            [ApiSeat(ApiSeats.ActionStart)] decimal weight, // 动作方法名称之前            [ApiSeat(ApiSeats.ActionStart)] float height, // 动作方法名称之前            [ApiSeat(ApiSeats.ActionEnd)] DateTime birthday) // 动作方法名称之后(默认值)        {            return "配置路由参数位置";        }    }}

如下图所示:

温馨提示

多个 同位置 配置的参数将按照 定义参数顺序 进行排序。

特别注意

[ApiSeat] 只能应用于贴了 [FromRoute] 特性的参数或 基元类型、值类型、可空基元类型和可空值类型

5.1.8.6 自定义请求谓词

using Furion.DynamicApiController;using Microsoft.AspNetCore.Mvc;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [HttpPost]        public string GetVersion()        {            return "1.0.0";        }    }}

如下图所示:

5.1.8.7 支持多个谓词

using Furion.DynamicApiController;using Microsoft.AspNetCore.Mvc;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [HttpPost, HttpGet, AcceptVerbs("PUT", "DELETE")]        public string GetVersion()        {            return "1.0.0";        }    }}

如下图所示:

特别注意

如果动作方法中含有 类类型参数,且含有 POST/PUT/DELETE 任意请求谓词,那么该参数会自动添加 [FromBody] 参数,即使在 GET/HEAD 请求中不支持。

5.1.8.8 支持自定义路由

支持控制器和动作方法自定义路由:

using Furion.DynamicApiController;using Microsoft.AspNetCore.Mvc;namespace Furion.Application{    [Route("customapi/mobile/[controller]")]    public class FurionAppService : IDynamicApiController    {        public string GetVersion()        {            return "1.0.0";        }    }}

如下图所示:

小提示

动作方法自定义路由如果以 / 开头,则不会合并控制器路由。

推荐配置

自定义路由如果需要用到 控制器/动作方法名称,推荐使用 [controller][action] 占位符,因为该占位符已经自动处理了 前后缀、版本号、模块名称等。

5.1.8.9 多路由随意组合

Furion 框架提供了非常灵活的各种路由组合方式,支持一对多,多对多路由组合:

using Furion.DynamicApiController;using Microsoft.AspNetCore.Mvc;namespace Furion.Application{    [Route("api/[controller]")]    [Route("api/[controller]/second")]    [Route("api/[controller]/three")]    public class FurionAppService : IDynamicApiController    {        [HttpGet]        [HttpGet("get/[action]")]        [HttpPost]        [HttpPost("post/cus-version")]        public string GetVersion()        {            return "1.0.0";        }    }}

如下图所示:

特别注意

动作方法不能同时贴 [Route][HttpMethod] 特性,只能二取一。

5.1.8.10 支持版本控制

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppServiceV1 : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }    }    public class FurionAppServiceV1_2 : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }    }    public class FurionAppServiceV1_2_1 : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }    }}

如下图所示:

版本生成原理

V[0-9_] 结尾的命名自动解析成版本号,如 FurionAppServiceV2 -> Furion@2

版本复写

除了通过特定后缀方式以外,版本还直接通过 [ApiDescriptionSettings] 进行复写。如:

[ApiDescriptionSettings(Version = "4.0")]public string GetV1(){    return nameof(Furion);}

这时,生成版本将采用 4.0 替代 1

5.1.8.11 不公开控制器或动作方法

有些时候,我们无需导出某个动作方法或控制器(不显示到 Swagger),只需要添加 [ApiDescriptionSettings(false)][ApiExplorerSettings(IgnoreApi = true)]即可。

另外动作方法还支持 [NonAction] 标记不是一个有效的控制器或 Action。

推荐使用

推荐控制器或动作方法设置不导出使用 [ApiDescriptionSettings(false)] 特性。该特性默认继承自 ApiExplorerSettingsAttribute 类。

5.1.8.12 保持控制器和方法命名

默认情况下,动态 API 会将控制器和方法名输出为 RESTFul 风格的路由,如需保留原有设计,只需配置:

{  "DynamicApiControllerSettings": {    "KeepName": true,    "KeepVerb": true,    "LowercaseRoute": false  }}

5.1.8.13 方法参数 [FromQuery] 化/参数非必填/参数可选

默认情况下,所有的基元类型参数都会贴上 [FromRoute] 特性,如果需要将参数调整为 [FromQuery] 修饰,只需要在方法上面贴 [QueryParameters] 特性即可,如:

[QueryParameters]public string Get(int id, string name){    return nameof($"{id} {name}");}

生成的路由为:https://xxx.com?id=1&name=Furion

如果不喜欢每个都配置,也可以全局配置(只会影响基元类型的参数):

{  "DynamicApiControllerSettings": {    "UrlParameterization": true  }}
特别注意

贴了 [QueryParameters] 之后,会对所有参数影响,包括类类型参数,如果不需要处理某个参数,只需要贴 [FromXXX] 特性即可。

5.1.8.14 参数绑定配置

Furion 框架提供了多种参数特性配置参数绑定规则:

  • [FromRoute]:通过路由参数绑定值
  • [FromQuery]:通过 Url 地址参数绑定值
  • [FromBody]:通过 Request Body 参数绑定值
  • [FromForm]:通过表单提交绑定值
  • [FromHeader]:通过 Request Header 参数绑定值

5.1.8.15 自定义根据方法名生成 [HttpMethod] 规则

Furion 框架中,在没有配置 [HttpMethod] 特性的情况下,会自动根据方法名第一个参数进行分析,并生成对应的 [HttpMethod] 特性,规则如下:

  • 动作方法名
    • Post/Add/Create/Insert/Submit 开头,则添加 [HttpPost] 特性。
    • GetAll/GetList/Get/Find/Fetch/Query 开头,则添加 [HttpGet] 特性。
    • Put/Update 开头,则添加 [HttpPut] 特性。
    • Delete/Remove/Clear 开头,则添加 [HttpDelete] 特性。
    • Patch 开头,则添加 [HttpPatch] 特性
    • Head 开头,则添加 [HttpHead] 特性
    • 支持自定义配置
  • 如果不在上面约定中,则默认添加 [HttpPost] 特性。支持自定义配置

但是,有些时候这不是我们想要的规则,这时我们只需要在 appsettings.json 中配置即可:

{  "DynamicApiControllerSettings": {    "VerbToHttpMethods": [      ["getall", "HEAD"], // => getall 会被复写为 `[HttpHead]`      ["other", "PUT"] // => 新增一条新规则,比如,一 `[other]` 开头会转换为 `[HttpPut]` 请求    ]  }}
特别注意

二维数组中的每一个元素的第一个元素必须是全小写,第二个元素必须是全大写大写,第二个元素取值有:HEAD, GET, PUT, POST, PATCH, DELETE

5.1.8.16 路由参数非必填/选填

Furion v2.8.6 版本中实现了 [FromRoute] 参数非必填功能,支持以下几种方式:

// 方式一,通过可空 ?public object Method1(int id, Datetime? dateTime){}// 方式二,通过默认值public object Method1(int id, int age = 10){}// 方式三,默认值 + 可空 ?public object Method1(int id, int? age = 10){}// 方式四,[FromQuery] 修饰public object Method1(int id, [FromQuery]string keyword){}

5.1.8.17 [FormRoute] 路由约束

Furion v2.8.6 版本中,添加了 [RouteConstraint] 特性,可配置路由约束,如:[RouteConstraint(":min(10)")]

// 最小值 10public object Method1([RouteConstraint(":min(10)")] int id){}

[RouteConstraint] 支持路由约束符号如下:

符号描述例子
alpha匹配大写或小写拉丁字母字符(a-z、A-Z):alpha
boolbool 类型:bool
datetimeDateTime 类型:datetime
decimaldecimal 类型:decimal
doubledouble 类型:double
floatfloat 类型:float
guidguid 类型:guid
intint 类型:int
longlong 类型:long
length匹配长度(字符串):length(6):length(1,20)
max最大值:max(10)
maxlength最大长度(字符串):maxlength(10)
min最小值:min(10)
minlength最小长度(字符串):minlength(10)
range取值范围:range(10,50)
regex正则表达式:regex(^\d{3}-\d{3}-\d{4}$)

5.1.8.18 小驼峰 路由路径

{  "DynamicApiControllerSettings": {    "LowercaseRoute": false,    "KeepName": true,    "AsLowerCamelCase": true  }}

5.1.9 [ApiDescriptionSettings]

除了上述 ASP.NET Core 提供的配置外,Furion 框架还提供了非常强大且灵活的 [ApiDescriptionSettings] 特性。

5.1.9.1 内置配置

  • Name:自定义控制器/动作方法名称,string,默认 null
  • KeepName:是否保持原有名称不处理,bool,默认 false
  • SplitCamelCase:切割骆驼(驼峰)/帕斯卡命名,bool,默认 true
  • KeepVerb:是否保留动作方法请求谓词,bool,默认 false
  • Enabled:是否导出接口,bool,默认 true
  • Module:模块名,string,默认 null
  • Version:版本号,string,默认 null
  • Groups:接口分组,可结合 Swagger 一起使用,string[],默认 null
  • Tags:接口标签,可结合 Swagger 一起使用,string[],默认 null
  • Order:配置控制器/动作方法排序
  • LowercaseRoute:是否采用小写路由,bool 类型,默认 true
  • AsLowerCamelCase:启用小驼峰命名(首字母小写),默认 false
  • Area:配置区域名称,默认空,只作用于类中贴
  • Description:配置单一接口更多描述功能,只在 方法 中有效,仅限 v3.3.5+版本有效
  • ForceWithRoutePrefix:配置是否强制添加 DefaultRoutePrefix,当控制器自定义了 [Route] 有效,仅限 v3.4.1+版本有效

5.1.9.2 Name 配置

Name 参数可以覆盖动态 WebAPI 自动生成的控制器或动作方法名称。如:

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings(Name = "MyFur")]    public class FurionAppService : IDynamicApiController    {        [ApiDescriptionSettings(Name = "MyGet")]        public string Get()        {            return nameof(Furion);        }    }}

如下图所示:

5.1.9.3 KeepName 配置

KeepName 参数可以保留原有的控制器或动作方法名称。如:

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings(KeepName = true)]    public class FurionAppService : IDynamicApiController    {        [ApiDescriptionSettings(KeepName = true)]        public string Get()        {            return nameof(Furion);        }    }}

如下图所示:

5.1.9.4 SplitCamelCase 配置

SplitCamelCase 参数默认将骆驼(驼峰)命名切割成多个单词并通过指定 占位符 连接起来。默认 占位符-。默认为 true。如:

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings(SplitCamelCase = false)]    public class MyFurionAppService : IDynamicApiController    {        [ApiDescriptionSettings(SplitCamelCase = true)]        public string ChangeUserName()        {            return nameof(Furion);        }    }}

如下图所示:

特别注意

KeepName 优先级高于 SplitCamelCase,也就是 KeepName 设置为 true,则不会处理 SplitCamelCase 参数。

5.1.9.5 KeepVerb 配置

KeepVerb 参数作用于动作方法,标识是否保留动作谓词。如:

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [ApiDescriptionSettings(KeepVerb = true)]        public string GetVersion()        {            return nameof(Furion);        }    }}

如下图所示:

5.1.9.6 Enabled 配置

Enabled 参数配置接口是否导出。通常用于动作方法,如果用于控制器实际作用不大。

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public string GetVersion()        {            return nameof(Furion);        }        [ApiDescriptionSettings(false)]        public string NoExport()        {            return nameof(Furion);        }    }}

如下图所示:

5.1.9.7 Module 配置

Module 参数可以配置路由分离,类似于 Mvc 区域 的作用。

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings(Module = "mobile")]    public class FurionAppService : IDynamicApiController    {        [ApiDescriptionSettings(Module = "user")]        public string GetVersion()        {            return nameof(Furion);        }    }}

如下图所示:

5.1.9.8 Version 配置

Version 参数可以配置接口版本,同时又可以复写特殊版本命名配置。默认版本分隔符为 @。如:

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings(Version = "1.0")]    public class FurionAppService : IDynamicApiController    {        // V2.0.0 被复写成 V2.1.1        [ApiDescriptionSettings(Version = "2.1.1")]        public string GetVersionV2_0_0()        {            return nameof(Furion);        }    }}

如下图所示:

5.1.9.9 Groups 配置

Groups 配置主要用于配置 Swagger 分组信息。

通过配置 Groups 参数可以将控制器和动作方法 进行归类和多个分组直接共享。可通过 [ApiDescriptionSettings(params Groups)] 构造函数传入或指定 Groups 参数配置接口是否导出。通常用于动作方法,如果用于控制器实际作用不大。

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings("Default", "Common")]    public class FurionAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        [ApiDescriptionSettings("Custom")]        public int Get(int id)        {            return id;        }    }}

如下图所示:

5.1.9.10 Tag 配置

Tag 配置主要用于配置 Swagger 标签分组信息及合并标签。也就是 组中组:

未贴标签之前

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }    public class TestAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }}

贴标签之后

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings(Tag = "分组一")]    public class FurionAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }    [ApiDescriptionSettings(Tag = "分组二")]    public class TestAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }}

如下图所示:

小知识

如果 Tag 名字一样,则会自动合并,否则只是命名。

5.1.10 DynamicApiControllerSettings 配置

Furion 还提供动态 WebAPI 接口一些全局配置选项,如:

  • DefaultRoutePrefix:默认路由前缀,string,默认 api
  • DefaultHttpMethod:默认请求谓词,string,默认:POST
  • DefaultModule:默认模块名称(区域),可用作接口版本,string,默认:v1
  • LowercaseRoute:小写路由格式,bool,默认:true
  • AsLowerCamelCase:启用小驼峰命名(首字母小写),默认 false
  • KeepVerb:是否保留动作谓词,bool,默认:false
  • KeepName:是否保留默认名称,bool,默认:fasle
  • CamelCaseSeparator:骆驼(驼峰)/帕斯卡命名分隔符,string,默认:-
  • VersionSeparator:版本分隔符,string,默认:@
  • ModelToQueryGET/HEAD 请求将 类类型参数转查询参数bool,默认 false
  • SupportedMvcController:是否支持 Mvc Controller 动态配置,bool,默认 false
  • UrlParameterization:路由参数采用 [FromQuery] 化,默认 false[FromRoute] 方式)
  • DefaultArea:配置默认区域,默认 null
  • ForceWithRoutePrefix:配置是否强制添加 DefaultRoutePrefix,当控制器自定义了 [Route] 有效,仅限 v3.4.1+版本有效
  • AbandonControllerAffixes:默认去除控制器名称前后缀列表名,string[],默认:
    • AppServices
    • AppService
    • ApiController
    • Controller
    • Services
    • Service
  • AbandonActionAffixes:默认去除动作方法名称前后缀列表名,string[],默认:
    • Async
    • VerbToHttpMethods:复写默认方法名转 [HttpMethod] 规则,string[][] 二维数组类型,内置匹配规则为:
      ["post"] = "POST",["add"] = "POST",["create"] = "POST",["insert"] = "POST",["submit"] = "POST",["get"] = "GET",["find"] = "GET",["fetch"] = "GET",["query"] = "GET",["getlist"] = "GET",["getall"] = "GET",["put"] = "PUT",["update"] = "PUT",["delete"] = "DELETE",["remove"] = "DELETE",["clear"] = "DELETE",["patch"] = "PATCH"
      • 复写示例
      "DynamicApiControllerSettings": {    "VerbToHttpMethods": [      [ "getall", "HEAD" ],  // => getall 会被复写为 `[HttpHead]`      [ "other", "PUT" ]  // => 新增一条新规则,比如,一 `[other]` 开头会转换为 `[HttpPut]` 请求    ]  }

5.1.10.1 支持 Mvc 控制器 动态配置

默认情况下,Furion 动态 WebAPI 接口不对 ControllerBase 类型进行任何处理。当然,我们也可以手动启用 ControllerBase 支持。

Furion.Web.Entry/appsettings.json
{  "DynamicApiControllerSettings": {    "SupportedMvcController": true  }}

设置 SupportedMvcController: true 后,Mvc ControllerBase 类型也能和动态 WebAPI 一样的灵活了。代码如下:

using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    public class MvcController : ControllerBase    {        public string Get()        {            return nameof(Furion);        }    }}
注意事项

启用该配置后,如果 Mvc 控制器 没有任何 [Route] 特性,但是贴了 [ApiController] 特性将会报错。原因是 [ApiController] 特性内部做了路由特性检测。所以建议使用 [ApiDataValidation] 代替。

查看 ASP.NET Core - ApiBehaviorApplicationModelProvider 源码

5.1.11 关于 AOP 拦截

动态WebAPI 支持 Controller 的所有过滤器/筛选器拦截,也就是可以通过 ActionFilterResultFilter 进行拦截操作。如:

public class SampleAsyncActionFilter : IAsyncActionFilter{    public async Task OnActionExecutionAsync(ActionExecutingContext context,ActionExecutionDelegate next)    {        // 拦截之前        var resultContext = await next();        // 拦截之后        // 异常拦截        if(resultContext.Exception != null)        {        }    }}

详细用法可参见 ASP.NET Core 5.0 - 筛选器

5.1.12 设置 api 超时请求时间

Program.cs 中添加 .UseKestrel 配置即可,如:

  • .NET5 版本
public static IHostBuilder CreateHostBuilder(string[] args){    return Host.CreateDefaultBuilder(args)        .ConfigureWebHostDefaults(webBuilder =>        {            webBuilder.Inject()                      .UseStartup<Startup>()                      .UseKestrel(option =>                      {                          option.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(20);                          option.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(20);                      });        });}
  • .NET6 版本
var app = builder.Build();app.Configuration.Get<WebHostBuilder>().ConfigureKestrel(x =>{    x.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(20);    x.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(20);});

5.1.13 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/efcore-recommend/index.html b/handbook/build/docs/efcore-recommend/index.html index c5061ca42f..a3cbb2e6e8 100644 --- a/handbook/build/docs/efcore-recommend/index.html +++ b/handbook/build/docs/efcore-recommend/index.html @@ -2,22 +2,21 @@ - - - + +9.29 EFCore 最佳实践 | Furion -9.29 EFCore 最佳实践 | Furion - - + + +
-

9.29 EFCore 最佳实践

9.29.1 EFCore 高性能

Furion 框架,默认推荐使用 EFCore 操作数据库,但很多朋友对 EFCore 使用不当,特意编写此文档说明。

  • 尽可能的采用 IRepository/IRepository<TEntity> 仓储方式在构造函数中初始化,避免使用 Db.GetRepository<TEntity> 方式
  • 请以异步方式调用所有数据访问 api。
  • 检索的数据不是必需的。 编写查询以仅返回当前 HTTP 请求所必需的数据
  • 如果数据可以接受,请考虑缓存经常访问的从数据库或远程服务检索的数据。 使用 MemoryCache 或 microsoft.web.distributedcache ,具体取决于方案。
  • 尽量减少网络往返次数。 目标是使用单个调用而不是多个调用来检索所需数据。
  • 如果当前请求只有数据查询,请使用无跟踪查询方式
  • 如果请求中含有操作数据时,请不要在 Entity Framework Core 中使用无跟踪查询。 EF Core 可以更有效地返回无跟踪查询的结果。 筛选和聚合 LINQ 查询(例如, .Where 使用.Select、或.Sum 语句),以便数据库执行筛选。
  • 对于需要进行复杂逻辑计算查询数据情况,请尽可能在返回查询后再在客户端计算。
  • 不要对集合使用投影查询,这可能会导致执行 "N + 1" 个 SQL 查询。
  • 使用 ·DbContextPool· 池来管理 DbContext,类似 ADO.NET 的连接池。
  • 手动或显式编译的查询 API,允许应用程序缓存查询转换,使其可仅被计算一次并执行多次。
// Create an explicitly compiled queryprivate static Func<CustomerContext, int, Customer> _customerById =    EF.CompileQuery((CustomerContext db, int id) =>        db.Customers            .Include(c => c.Address)            .Single(c => c.Id == id));// Use the compiled query by invoking itusing (var db = new CustomerContext()){   var customer = _customerById(db, 147);}

9.29.2 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.29 EFCore 最佳实践

9.29.1 EFCore 高性能

Furion 框架,默认推荐使用 EFCore 操作数据库,但很多朋友对 EFCore 使用不当,特意编写此文档说明。

  • 尽可能的采用 IRepository/IRepository<TEntity> 仓储方式在构造函数中初始化,避免使用 Db.GetRepository<TEntity> 方式
  • 请以异步方式调用所有数据访问 api。
  • 检索的数据不是必需的。 编写查询以仅返回当前 HTTP 请求所必需的数据
  • 如果数据可以接受,请考虑缓存经常访问的从数据库或远程服务检索的数据。 使用 MemoryCache 或 microsoft.web.distributedcache ,具体取决于方案。
  • 尽量减少网络往返次数。 目标是使用单个调用而不是多个调用来检索所需数据。
  • 如果当前请求只有数据查询,请使用无跟踪查询方式
  • 如果请求中含有操作数据时,请不要在 Entity Framework Core 中使用无跟踪查询。 EF Core 可以更有效地返回无跟踪查询的结果。 筛选和聚合 LINQ 查询(例如, .Where 使用.Select、或.Sum 语句),以便数据库执行筛选。
  • 对于需要进行复杂逻辑计算查询数据情况,请尽可能在返回查询后再在客户端计算。
  • 不要对集合使用投影查询,这可能会导致执行 "N + 1" 个 SQL 查询。
  • 使用 ·DbContextPool· 池来管理 DbContext,类似 ADO.NET 的连接池。
  • 手动或显式编译的查询 API,允许应用程序缓存查询转换,使其可仅被计算一次并执行多次。
// Create an explicitly compiled queryprivate static Func<CustomerContext, int, Customer> _customerById =    EF.CompileQuery((CustomerContext db, int id) =>        db.Customers            .Include(c => c.Address)            .Single(c => c.Id == id));// Use the compiled query by invoking itusing (var db = new CustomerContext()){   var customer = _customerById(db, 147);}

9.29.2 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/encryption/index.html b/handbook/build/docs/encryption/index.html index 15225c6660..d5c98264f2 100644 --- a/handbook/build/docs/encryption/index.html +++ b/handbook/build/docs/encryption/index.html @@ -2,22 +2,21 @@ - - - + +20. 数据加解密 | Furion -20. 数据加解密 | Furion - - + + +
-

20. 数据加解密

20.1 数据加解密

由于现在的互联网越具发达,数据成为了我们生活的一部分,当然也带来了很多数据安全性的问题,比如用户密码明文存储,用户信息明文存在在浏览器 cookies 中等等不安全操作。

所以,对数据的加解密是系统开发必要的环节。

20.2 内置加密算法

  • MD5 加密
  • DESC 加解密
  • AES 加解密
  • JWT 加解密
  • PBKDF2 加密(Furion v2.12 + 版本已移除)
  • RSA 加解密

20.3 加解密使用

20.3.1 MD5 加密

// 测试 MD5 加密,比较var md5Hash = MD5Encryption.Encrypt("百小僧");  // 加密var isEqual = MD5Encryption.Compare("百小僧", md5Hash); // 比较return (md5Hash, isEqual);// 输出大写 MD5 加密var md5Hash = MD5Encryption.Encrypt("百小僧", true);// 输出 16位 MD5 加密,Furion 4.2.6+ 版本var md5Hash16 = MD5Encryption.Encrypt("百小僧", is16: true);

20.3.2 DESC 加解密

// 测试 DESC 加解密var descHash = DESCEncryption.Encrypt("百小僧", "Furion"); // 加密var str = DESCEncryption.Decrypt(descHash, "Furion");  // 解密return (descHash, str);

20.3.3 AES 加解密

// 测试 AES 加解密var key = Guid.NewGuid().ToString("N"); // 密钥,长度必须为24位或32位var aesHash = AESEncryption.Encrypt("百小僧", key); // 加密var str2 = AESEncryption.Decrypt(aesHash, key); // 解密return (aesHash, str2);

20.3.4 JWT 加解密

var token = JWTEncryption.Encrypt(new Dictionary<string, object>()  // 加密            {                { "UserId", user.Id },                { "Account",user.Account }            });var tokenData = JWTEncryption.ReadJwtToken("你的token");  // 解密var (isValid, tokenData) = JWTEncryption.Validate("你的token"); // 验证token有效期
特别注意

JWTEncryption 加解密并未包含在 Furion 框架中,需要安装 Furion 框架提供的 Furion.Extras.Authentication.JwtBearer 拓展包。

20.3.5 PBKDF2 加密

Furion v2.12 + 版本已移除。

// 测试 PBKDF2 加密,比较var basestring = PBKDF2Encryption.Encrypt("百小僧");  // 加密var isEqual = PBKDF2Encryption.Compare("百小僧", basestring); // 比较
支持选择更多参数

PBKDF2 还可以配置更多参数:

  • Startup.cs 中注册服务
services.AddPBKDF2EncryptionOptions();
  • appsettings.json 配置:
{  "PBKDF2EncryptionSettings": {    "InitialIterationCount": 110, // 初始迭代次数累加值    "KeyDerivation": "HMACSHA256", // 加密算法规则  KeyDerivationPrf.HMACSHA256    "NumBytesRequested": 64 // 派生密钥的长度 (以字节为单位) 512 / 8  }}
  • KeyDerivation 可选值有:HMACSHA1HMACSHA256HMACSHA512

20.3.6 RSA 加密

// 测试 RSA 加密var (publicKey, privateKey) = RSAEncryption.GenerateSecretKey(2048);  //生成 RSA 秘钥 秘钥大小必须为 2048 到 16384,并且是 8 的倍数var basestring = RSAEncryption.Encrypt("百小僧", publicKey);  // 加密var str2 = RSAEncryption.Decrypt(basestring, privateKey); // 解密return (basestring, str2);
关于 RSA 签名和校验

Furion 框架底层不内置 RSA 签名和校验功能,如需添加该功能可查阅开发者提交的代码:查看 RSA 签名和校验

20.4 字符串拓展方式

Furion 框架也提供了字符串拓展方式进行 MD5加密、AES/DESC加解密、RSA加解密

using Furion.DataEncryption.Extensions;// MD5 加密var s = "Furion".ToMD5Encrypt();var b = "Furion".ToMD5Compare(s);   // 比较// AES加解密var s = "Furion".ToAESEncrypt("sfdsfdsfdsfdsfdsfdsfdsfdsfdfdsfdsfdfdfdfd");var str = s.ToAESDecrypt("sfdsfdsfdsfdsfdsfdsfdsfdsfdfdsfdsfdfdfdfd");// DESC 加解密var s = "Furion".ToDESCEncrypt("sfdsfdsfdsfdsfdsfdsfdsfdsfdfdsfdsfdfdfdfd");var str = s.ToDESCDecrypt("sfdsfdsfdsfdsfdsfdsfdsfdsfdfdsfdsfdfdfdfd");// PBKDF2 加密(`Furion v2.12 +` 版本已移除!!!!!!!!)var s = "Furion".ToPBKDF2Encrypt();var b = "Furion".ToPBKDF2Compare(s);   // 比较// RSA 加解密var (publicKey, privateKey) = RSAEncryption.GenerateSecretKey(2048);  //生成 RSA 秘钥 秘钥大小必须为 2048 到 16384,并且是 8 的倍数var s= "Furion".ToRSAEncrpyt(publicKey);  // 加密var str=s.ToRSADecrypt(privateKey);  // 解密

20.5 SM2SM3SM4 国密

Furion 框架未内置国密算法 SM2-4,但是已有开发者贡献实现并开源,可查阅 Gitee 仓库,感谢 QQ(373696184)形影相印²º²² 贡献

var data = "{\"lx\":\"1\",\"wxid\":\"\",\"ehealth_code_id\":\"68A018036186B717CC1B051C10996F4EEE805F5F81EB1594C9EB43592545F7F6\",\"ehealth_code\":\"68A018036186B717CC1B051C10996F4EEE805F5F81EB1594C9EB43592545F7F6\",\"xm\":\"测试\"}";// SM2var b = SM2Utils.加密("123");var b1 = SM2Utils.解密(b);// SM3 一般用于数字签名var sM3Utils = new SM3Utils();sM3Utils.secretKey = "ASAFSDFDSGSDFSDFSDFSFSF";var token= sM3Utils.加密("123");// SM4var sM4Utils = new SM4Utils();sM4Utils.secretKey = "BDBDBDBDBDBDBDBDBDBDBDBDBDBDBD";var a = sM4Utils.加密(data);var a1 = sM4Utils.解密(a);

20.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

20. 数据加解密

20.1 数据加解密

由于现在的互联网越具发达,数据成为了我们生活的一部分,当然也带来了很多数据安全性的问题,比如用户密码明文存储,用户信息明文存在在浏览器 cookies 中等等不安全操作。

所以,对数据的加解密是系统开发必要的环节。

20.2 内置加密算法

  • MD5 加密
  • DESC 加解密
  • AES 加解密
  • JWT 加解密
  • PBKDF2 加密(Furion v2.12 + 版本已移除)
  • RSA 加解密

20.3 加解密使用

20.3.1 MD5 加密

// 测试 MD5 加密,比较var md5Hash = MD5Encryption.Encrypt("百小僧");  // 加密var isEqual = MD5Encryption.Compare("百小僧", md5Hash); // 比较return (md5Hash, isEqual);// 输出大写 MD5 加密var md5Hash = MD5Encryption.Encrypt("百小僧", true);// 输出 16位 MD5 加密,Furion 4.2.6+ 版本var md5Hash16 = MD5Encryption.Encrypt("百小僧", is16: true);

20.3.2 DESC 加解密

// 测试 DESC 加解密var descHash = DESCEncryption.Encrypt("百小僧", "Furion"); // 加密var str = DESCEncryption.Decrypt(descHash, "Furion");  // 解密return (descHash, str);

20.3.3 AES 加解密

// 测试 AES 加解密var key = Guid.NewGuid().ToString("N"); // 密钥,长度必须为24位或32位var aesHash = AESEncryption.Encrypt("百小僧", key); // 加密var str2 = AESEncryption.Decrypt(aesHash, key); // 解密return (aesHash, str2);

20.3.4 JWT 加解密

var token = JWTEncryption.Encrypt(new Dictionary<string, object>()  // 加密            {                { "UserId", user.Id },                { "Account",user.Account }            });var tokenData = JWTEncryption.ReadJwtToken("你的token");  // 解密var (isValid, tokenData) = JWTEncryption.Validate("你的token"); // 验证token有效期
特别注意

JWTEncryption 加解密并未包含在 Furion 框架中,需要安装 Furion 框架提供的 Furion.Extras.Authentication.JwtBearer 拓展包。

20.3.5 PBKDF2 加密

Furion v2.12 + 版本已移除。

// 测试 PBKDF2 加密,比较var basestring = PBKDF2Encryption.Encrypt("百小僧");  // 加密var isEqual = PBKDF2Encryption.Compare("百小僧", basestring); // 比较
支持选择更多参数

PBKDF2 还可以配置更多参数:

  • Startup.cs 中注册服务
services.AddPBKDF2EncryptionOptions();
  • appsettings.json 配置:
{  "PBKDF2EncryptionSettings": {    "InitialIterationCount": 110, // 初始迭代次数累加值    "KeyDerivation": "HMACSHA256", // 加密算法规则  KeyDerivationPrf.HMACSHA256    "NumBytesRequested": 64 // 派生密钥的长度 (以字节为单位) 512 / 8  }}
  • KeyDerivation 可选值有:HMACSHA1HMACSHA256HMACSHA512

20.3.6 RSA 加密

// 测试 RSA 加密var (publicKey, privateKey) = RSAEncryption.GenerateSecretKey(2048);  //生成 RSA 秘钥 秘钥大小必须为 2048 到 16384,并且是 8 的倍数var basestring = RSAEncryption.Encrypt("百小僧", publicKey);  // 加密var str2 = RSAEncryption.Decrypt(basestring, privateKey); // 解密return (basestring, str2);
关于 RSA 签名和校验

Furion 框架底层不内置 RSA 签名和校验功能,如需添加该功能可查阅开发者提交的代码:查看 RSA 签名和校验

20.4 字符串拓展方式

Furion 框架也提供了字符串拓展方式进行 MD5加密、AES/DESC加解密、RSA加解密

using Furion.DataEncryption.Extensions;// MD5 加密var s = "Furion".ToMD5Encrypt();var b = "Furion".ToMD5Compare(s);   // 比较// AES加解密var s = "Furion".ToAESEncrypt("sfdsfdsfdsfdsfdsfdsfdsfdsfdfdsfdsfdfdfdfd");var str = s.ToAESDecrypt("sfdsfdsfdsfdsfdsfdsfdsfdsfdfdsfdsfdfdfdfd");// DESC 加解密var s = "Furion".ToDESCEncrypt("sfdsfdsfdsfdsfdsfdsfdsfdsfdfdsfdsfdfdfdfd");var str = s.ToDESCDecrypt("sfdsfdsfdsfdsfdsfdsfdsfdsfdfdsfdsfdfdfdfd");// PBKDF2 加密(`Furion v2.12 +` 版本已移除!!!!!!!!)var s = "Furion".ToPBKDF2Encrypt();var b = "Furion".ToPBKDF2Compare(s);   // 比较// RSA 加解密var (publicKey, privateKey) = RSAEncryption.GenerateSecretKey(2048);  //生成 RSA 秘钥 秘钥大小必须为 2048 到 16384,并且是 8 的倍数var s= "Furion".ToRSAEncrpyt(publicKey);  // 加密var str=s.ToRSADecrypt(privateKey);  // 解密

20.5 SM2SM3SM4 国密

Furion 框架未内置国密算法 SM2-4,但是已有开发者贡献实现并开源,可查阅 Gitee 仓库,感谢 QQ(373696184)形影相印²º²² 贡献

var data = "{\"lx\":\"1\",\"wxid\":\"\",\"ehealth_code_id\":\"68A018036186B717CC1B051C10996F4EEE805F5F81EB1594C9EB43592545F7F6\",\"ehealth_code\":\"68A018036186B717CC1B051C10996F4EEE805F5F81EB1594C9EB43592545F7F6\",\"xm\":\"测试\"}";// SM2var b = SM2Utils.加密("123");var b1 = SM2Utils.解密(b);// SM3 一般用于数字签名var sM3Utils = new SM3Utils();sM3Utils.secretKey = "ASAFSDFDSGSDFSDFSDFSFSF";var token= sM3Utils.加密("123");// SM4var sM4Utils = new SM4Utils();sM4Utils.secretKey = "BDBDBDBDBDBDBDBDBDBDBDBDBDBDBD";var a = sM4Utils.加密(data);var a1 = sM4Utils.解密(a);

20.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/entity/index.html b/handbook/build/docs/entity/index.html index 58c6f363c0..3f55137bee 100644 --- a/handbook/build/docs/entity/index.html +++ b/handbook/build/docs/entity/index.html @@ -2,22 +2,21 @@ - - - + +9.3 数据库实体 | Furion -9.3 数据库实体 | Furion - - + + +
-

9.3 数据库实体

特别提醒

一旦定义了实体或改变了实体结构或实体配置,需要重新执行 Add-MigrationUpdate-Database 命令。

9.3.1 数据库实体

在面向对象开发思想中,最重要尤为对象二字,在 .NET 开发过去,操作数据库往往采用 DataTableDataSet 来接收数据库返回结果集,而操作数据库也离不开手写 sql 语句。

在过去面向过程和应用不发达的时代,这些操作确实好使。然后随着中国互联网网民的激增,电子化时代的到来,各行各业对应用需求也达到了前所未有的量级。

所以,在过去手写 sql 的时代各种问题显露无疑:

  • 程序员能力参差不齐,写出的 sql 性能自然也天差地别
  • sql 属于字符串硬编程,后期维护难上加难
  • 许多单表甚至多表结构一致,出现大量重复 sql 代码
  • sql 本身在不同的数据库提供器中写法有差,后续迁移头痛不已

当然,sql 是时代的产物,我们也离不开 sql,但对于大多数程序员和项目来说,sql 未必能够带给他们多大的效益。

所以,ORM 就诞生了,所谓的 ORM 就是对象关系映射,英文:Object Relational Mapping,简单点说,ORM 根据特有的 POCO 贫血模型 规则生成 sql 语句。大大避免了重复 sqlsql 能力参差不齐等问题。(当然 ORM 作者 sql 能力也会影响最终性能)

上面所说的 POCO 贫血模型正是我们本章节的 数据库实体

简单来说,数据库实体就是数据库表的类表现,通过一定的规则使这个类能够一一对应表结构。通常这样的类也称为:POCO 贫血模型,也就是只有定义,没有行为。

9.3.2 如何定义实体

Furion 框架提供多种定义实体的接口依赖:

  • IEntity:实体基接口,是所有实体的基接口
  • IEntityNotKey:无键实体接口,也就是视图、存储过程、函数依赖接口
  • EntityBase:实体基抽象类,内置了 IdTenantId 字段
  • Entity:实体通用抽象类,继承自 EntityBase,同时内置 CreatedTimeUpdatedTime 字段
  • EntityNotKey:无键实体抽象类,视图、存储过程、函数依赖抽象类
实体定义位置

Furion 框架中有约定,实体统一定义在 Furion.Core 层。

9.3.2.1 实体继承选用原则

  • 如果你不需要 Furion 为实体添加任何内置特性,选用 IEntity,无键实体选用 IEntityNotKey
  • 如果你只需要 Id 属性,选用 EntityBase
  • 如果你需要 Furion 为你自动添加常用字段,则选用 Entity
  • 如果你需要视图、存储过程、函数可以通过 DbSet 操作,则继承 EntityNotKey

9.3.2.2 IEntity 示范:

using Furion.DatabaseAccessor;namespace Furion.Core{    public class User : IEntity    {        /// <summary>        /// 手工定义 Id        /// </summary>        public int Id { get; set; }        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }    }}

9.3.2.3 EntityBase 示范:

using Furion.DatabaseAccessor;namespace Furion.Core{    public class User : EntityBase    {        // 无需定义 Id 属性        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }    }}

9.3.2.4 Entity 示范:

using Furion.DatabaseAccessor;namespace Furion.Core{    public class User : Entity    {        // 无需定义 Id 属性        // 并自动添加 CreatedTime,UpdatedTime 属性        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }    }}

9.3.2.5 EntityNotKey 示范:

using Furion.DatabaseAccessor;namespace Furion.Core{    public class UserView : EntityNotKey    {        public UserView() : base("视图名称")        {        }        /// <summary>        /// Id        /// </summary>        public int Id { get; set; }        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }    }}
特别注意

Furion 框架中,数据库实体必须直接或间接继承 IEntity 才能进行仓储等操作。

9.3.3 自定义公共实体

在实际项目开发中,我们通常每个应用的数据库表都有一些公共的类,比如创建人,创建时间等,这个时候我们就需要自定义公共实体类了。

Furion 框架中,创建公共实体类需要满足以下条件:

  • 公共实体类必须是公开且是抽象类
  • 公共实体类必须含有无参构造函数
  • 公共实体类必须提供数据库定位器的支持

如:

using System;using System.ComponentModel.DataAnnotations;using System.ComponentModel.DataAnnotations.Schema;namespace Your.Namespace{    public abstract class CommonEntity : CommonEntity<int, MasterDbContextLocator>    {    }    public abstract class CommonEntity<TKey> : CommonEntity<TKey, MasterDbContextLocator>    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1, TDbContextLocator2> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator        where TDbContextLocator2 : class, IDbContextLocator    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1, TDbContextLocator2, TDbContextLocator3> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator        where TDbContextLocator2 : class, IDbContextLocator        where TDbContextLocator3 : class, IDbContextLocator    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1, TDbContextLocator2, TDbContextLocator3, TDbContextLocator4> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator        where TDbContextLocator2 : class, IDbContextLocator        where TDbContextLocator3 : class, IDbContextLocator        where TDbContextLocator4 : class, IDbContextLocator    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1, TDbContextLocator2, TDbContextLocator3, TDbContextLocator4, TDbContextLocator5> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator        where TDbContextLocator2 : class, IDbContextLocator        where TDbContextLocator3 : class, IDbContextLocator        where TDbContextLocator4 : class, IDbContextLocator        where TDbContextLocator5 : class, IDbContextLocator    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1, TDbContextLocator2, TDbContextLocator3, TDbContextLocator4, TDbContextLocator5, TDbContextLocator6> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator        where TDbContextLocator2 : class, IDbContextLocator        where TDbContextLocator3 : class, IDbContextLocator        where TDbContextLocator4 : class, IDbContextLocator        where TDbContextLocator5 : class, IDbContextLocator        where TDbContextLocator6 : class, IDbContextLocator    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1, TDbContextLocator2, TDbContextLocator3, TDbContextLocator4, TDbContextLocator5, TDbContextLocator6, TDbContextLocator7> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator        where TDbContextLocator2 : class, IDbContextLocator        where TDbContextLocator3 : class, IDbContextLocator        where TDbContextLocator4 : class, IDbContextLocator        where TDbContextLocator5 : class, IDbContextLocator        where TDbContextLocator6 : class, IDbContextLocator        where TDbContextLocator7 : class, IDbContextLocator    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1, TDbContextLocator2, TDbContextLocator3, TDbContextLocator4, TDbContextLocator5, TDbContextLocator6, TDbContextLocator7, TDbContextLocator8> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator        where TDbContextLocator2 : class, IDbContextLocator        where TDbContextLocator3 : class, IDbContextLocator        where TDbContextLocator4 : class, IDbContextLocator        where TDbContextLocator5 : class, IDbContextLocator        where TDbContextLocator6 : class, IDbContextLocator        where TDbContextLocator7 : class, IDbContextLocator        where TDbContextLocator8 : class, IDbContextLocator    {    }    public abstract class PrivateCommonEntity<TKey> : IPrivateEntity    {        // 注意是在这里定义你的公共实体        public virtual TKey Id { get; set; }        public virtual DateTime CreatedTime { get; set; }        // 更多属性定义    }}
特别说明

通过上面的格式定义可以完美的支持多数据库操作,建议采用这种格式,而且所有的公共属性都应该定义在 PrivateXXXX 有类中。

9.3.4 数据库实体配置

在过去的 EF Core 项目开发中,数据库实体配置需要在 DbContextOnModelCreating 中配置。Furion 为了简化配置和提高开发效率,抽象出了 IEntityTypeBuilder<TEntity> 接口。

通过 IEntityTypeBuilder<TEntity> 接口,我们无需在 DbContextOnModelCreating 中配置,可在任意地方配置。

9.3.4.1 在数据库实体中配置

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;namespace Furion.Core{    public class User : Entity, IEntityTypeBuilder<User>    {        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }        /// <summary>        /// 年龄        /// </summary>        public int Age { get; set; }        // 配置数据库实体        public void Configure(EntityTypeBuilder<User> entityBuilder, DbContext dbContext, Type dbContextLocator)        {            entityBuilder.HasKey(u => u.Id);            entityBuilder.HasIndex(u => u.Name);        }    }}

9.3.4.2 在任何实例类中配置

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;namespace Furion.Core{    public class SomeClass : IEntityTypeBuilder<User>    {        public void Configure(EntityTypeBuilder<User> entityBuilder, DbContext dbContext, Type dbContextLocator)        {            entityBuilder.HasKey(u => u.Id);            entityBuilder.HasIndex(u => u.Name);        }    }}

如上面例子,通过 SomeClass 配置 User 数据库实体。

特别注意

SomeClass必须声明为public,否则无法自动注册。

更多知识

如需了解实体配置支持哪些配置可查阅 【EFCore - 创建模型】 章节。

9.3.5 数据库实体配置说明

Furion 框架会自动扫描所有继承 IEntity 接口的类进行 DbSet<TEntity> 注册,也就是实现自动配置 DbContextOnModelCreating

如果需要跳过自动注册,只需要贴 [Manual][SuppressSniffer] 特性即可。一旦贴了此特性,那么就需要手动配置 DbContextOnModelCreating

9.3.6 配置列名及列类型

有时候我们需要手动设置列名或列类型,比如 decimal(18,2),这时候只需要在属性上面贴 [Column("列名", TypeName="decimal(18,2)")] 即可。

9.3.7 配置数据库表名和 Schema

可以通过在实体类型贴 [Table("表名", "dbo")] 配置。

9.3.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

9.3 数据库实体

特别提醒

一旦定义了实体或改变了实体结构或实体配置,需要重新执行 Add-MigrationUpdate-Database 命令。

9.3.1 数据库实体

在面向对象开发思想中,最重要尤为对象二字,在 .NET 开发过去,操作数据库往往采用 DataTableDataSet 来接收数据库返回结果集,而操作数据库也离不开手写 sql 语句。

在过去面向过程和应用不发达的时代,这些操作确实好使。然后随着中国互联网网民的激增,电子化时代的到来,各行各业对应用需求也达到了前所未有的量级。

所以,在过去手写 sql 的时代各种问题显露无疑:

  • 程序员能力参差不齐,写出的 sql 性能自然也天差地别
  • sql 属于字符串硬编程,后期维护难上加难
  • 许多单表甚至多表结构一致,出现大量重复 sql 代码
  • sql 本身在不同的数据库提供器中写法有差,后续迁移头痛不已

当然,sql 是时代的产物,我们也离不开 sql,但对于大多数程序员和项目来说,sql 未必能够带给他们多大的效益。

所以,ORM 就诞生了,所谓的 ORM 就是对象关系映射,英文:Object Relational Mapping,简单点说,ORM 根据特有的 POCO 贫血模型 规则生成 sql 语句。大大避免了重复 sqlsql 能力参差不齐等问题。(当然 ORM 作者 sql 能力也会影响最终性能)

上面所说的 POCO 贫血模型正是我们本章节的 数据库实体

简单来说,数据库实体就是数据库表的类表现,通过一定的规则使这个类能够一一对应表结构。通常这样的类也称为:POCO 贫血模型,也就是只有定义,没有行为。

9.3.2 如何定义实体

Furion 框架提供多种定义实体的接口依赖:

  • IEntity:实体基接口,是所有实体的基接口
  • IEntityNotKey:无键实体接口,也就是视图、存储过程、函数依赖接口
  • EntityBase:实体基抽象类,内置了 IdTenantId 字段
  • Entity:实体通用抽象类,继承自 EntityBase,同时内置 CreatedTimeUpdatedTime 字段
  • EntityNotKey:无键实体抽象类,视图、存储过程、函数依赖抽象类
实体定义位置

Furion 框架中有约定,实体统一定义在 Furion.Core 层。

9.3.2.1 实体继承选用原则

  • 如果你不需要 Furion 为实体添加任何内置特性,选用 IEntity,无键实体选用 IEntityNotKey
  • 如果你只需要 Id 属性,选用 EntityBase
  • 如果你需要 Furion 为你自动添加常用字段,则选用 Entity
  • 如果你需要视图、存储过程、函数可以通过 DbSet 操作,则继承 EntityNotKey

9.3.2.2 IEntity 示范:

using Furion.DatabaseAccessor;namespace Furion.Core{    public class User : IEntity    {        /// <summary>        /// 手工定义 Id        /// </summary>        public int Id { get; set; }        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }    }}

9.3.2.3 EntityBase 示范:

using Furion.DatabaseAccessor;namespace Furion.Core{    public class User : EntityBase    {        // 无需定义 Id 属性        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }    }}

9.3.2.4 Entity 示范:

using Furion.DatabaseAccessor;namespace Furion.Core{    public class User : Entity    {        // 无需定义 Id 属性        // 并自动添加 CreatedTime,UpdatedTime 属性        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }    }}

9.3.2.5 EntityNotKey 示范:

using Furion.DatabaseAccessor;namespace Furion.Core{    public class UserView : EntityNotKey    {        public UserView() : base("视图名称")        {        }        /// <summary>        /// Id        /// </summary>        public int Id { get; set; }        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }    }}
特别注意

Furion 框架中,数据库实体必须直接或间接继承 IEntity 才能进行仓储等操作。

9.3.3 自定义公共实体

在实际项目开发中,我们通常每个应用的数据库表都有一些公共的类,比如创建人,创建时间等,这个时候我们就需要自定义公共实体类了。

Furion 框架中,创建公共实体类需要满足以下条件:

  • 公共实体类必须是公开且是抽象类
  • 公共实体类必须含有无参构造函数
  • 公共实体类必须提供数据库定位器的支持

如:

using System;using System.ComponentModel.DataAnnotations;using System.ComponentModel.DataAnnotations.Schema;namespace Your.Namespace{    public abstract class CommonEntity : CommonEntity<int, MasterDbContextLocator>    {    }    public abstract class CommonEntity<TKey> : CommonEntity<TKey, MasterDbContextLocator>    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1, TDbContextLocator2> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator        where TDbContextLocator2 : class, IDbContextLocator    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1, TDbContextLocator2, TDbContextLocator3> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator        where TDbContextLocator2 : class, IDbContextLocator        where TDbContextLocator3 : class, IDbContextLocator    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1, TDbContextLocator2, TDbContextLocator3, TDbContextLocator4> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator        where TDbContextLocator2 : class, IDbContextLocator        where TDbContextLocator3 : class, IDbContextLocator        where TDbContextLocator4 : class, IDbContextLocator    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1, TDbContextLocator2, TDbContextLocator3, TDbContextLocator4, TDbContextLocator5> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator        where TDbContextLocator2 : class, IDbContextLocator        where TDbContextLocator3 : class, IDbContextLocator        where TDbContextLocator4 : class, IDbContextLocator        where TDbContextLocator5 : class, IDbContextLocator    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1, TDbContextLocator2, TDbContextLocator3, TDbContextLocator4, TDbContextLocator5, TDbContextLocator6> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator        where TDbContextLocator2 : class, IDbContextLocator        where TDbContextLocator3 : class, IDbContextLocator        where TDbContextLocator4 : class, IDbContextLocator        where TDbContextLocator5 : class, IDbContextLocator        where TDbContextLocator6 : class, IDbContextLocator    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1, TDbContextLocator2, TDbContextLocator3, TDbContextLocator4, TDbContextLocator5, TDbContextLocator6, TDbContextLocator7> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator        where TDbContextLocator2 : class, IDbContextLocator        where TDbContextLocator3 : class, IDbContextLocator        where TDbContextLocator4 : class, IDbContextLocator        where TDbContextLocator5 : class, IDbContextLocator        where TDbContextLocator6 : class, IDbContextLocator        where TDbContextLocator7 : class, IDbContextLocator    {    }    public abstract class CommonEntity<TKey, TDbContextLocator1, TDbContextLocator2, TDbContextLocator3, TDbContextLocator4, TDbContextLocator5, TDbContextLocator6, TDbContextLocator7, TDbContextLocator8> : PrivateCommonEntity<TKey>        where TDbContextLocator1 : class, IDbContextLocator        where TDbContextLocator2 : class, IDbContextLocator        where TDbContextLocator3 : class, IDbContextLocator        where TDbContextLocator4 : class, IDbContextLocator        where TDbContextLocator5 : class, IDbContextLocator        where TDbContextLocator6 : class, IDbContextLocator        where TDbContextLocator7 : class, IDbContextLocator        where TDbContextLocator8 : class, IDbContextLocator    {    }    public abstract class PrivateCommonEntity<TKey> : IPrivateEntity    {        // 注意是在这里定义你的公共实体        public virtual TKey Id { get; set; }        public virtual DateTime CreatedTime { get; set; }        // 更多属性定义    }}
特别说明

通过上面的格式定义可以完美的支持多数据库操作,建议采用这种格式,而且所有的公共属性都应该定义在 PrivateXXXX 有类中。

9.3.4 数据库实体配置

在过去的 EF Core 项目开发中,数据库实体配置需要在 DbContextOnModelCreating 中配置。Furion 为了简化配置和提高开发效率,抽象出了 IEntityTypeBuilder<TEntity> 接口。

通过 IEntityTypeBuilder<TEntity> 接口,我们无需在 DbContextOnModelCreating 中配置,可在任意地方配置。

9.3.4.1 在数据库实体中配置

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;namespace Furion.Core{    public class User : Entity, IEntityTypeBuilder<User>    {        /// <summary>        /// 名称        /// </summary>        public string Name { get; set; }        /// <summary>        /// 年龄        /// </summary>        public int Age { get; set; }        // 配置数据库实体        public void Configure(EntityTypeBuilder<User> entityBuilder, DbContext dbContext, Type dbContextLocator)        {            entityBuilder.HasKey(u => u.Id);            entityBuilder.HasIndex(u => u.Name);        }    }}

9.3.4.2 在任何实例类中配置

using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;namespace Furion.Core{    public class SomeClass : IEntityTypeBuilder<User>    {        public void Configure(EntityTypeBuilder<User> entityBuilder, DbContext dbContext, Type dbContextLocator)        {            entityBuilder.HasKey(u => u.Id);            entityBuilder.HasIndex(u => u.Name);        }    }}

如上面例子,通过 SomeClass 配置 User 数据库实体。

特别注意

SomeClass必须声明为public,否则无法自动注册。

更多知识

如需了解实体配置支持哪些配置可查阅 【EFCore - 创建模型】 章节。

9.3.5 数据库实体配置说明

Furion 框架会自动扫描所有继承 IEntity 接口的类进行 DbSet<TEntity> 注册,也就是实现自动配置 DbContextOnModelCreating

如果需要跳过自动注册,只需要贴 [Manual][SuppressSniffer] 特性即可。一旦贴了此特性,那么就需要手动配置 DbContextOnModelCreating

9.3.6 配置列名及列类型

有时候我们需要手动设置列名或列类型,比如 decimal(18,2),这时候只需要在属性上面贴 [Column("列名", TypeName="decimal(18,2)")] 即可。

9.3.7 配置数据库表名和 Schema

可以通过在实体类型贴 [Table("表名", "dbo")] 配置。

9.3.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/event-bus-old/index.html b/handbook/build/docs/event-bus-old/index.html index 78153618b0..9df19d4ec0 100644 --- a/handbook/build/docs/event-bus-old/index.html +++ b/handbook/build/docs/event-bus-old/index.html @@ -2,22 +2,21 @@ - - - + +22. 事件总线 | Furion -22. 事件总线 | Furion - - + + +
-

22. 事件总线

v2.20+ 版本说明

Furion v2.20+ 版本后采用 Jaina 事件总线替换原有的 EventBus😶查看新文档

22.1 什么是事件总线

事件总线是对发布-订阅模式的一种实现。它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需要相互依赖,达到一种解耦的目的。

我们来看看事件总线的处理流程:

22.2 MessageCenter 消息中心

Furion 框架中,实现了一种轻量级的事件总线实现机制:MessageCenter(消息中心),MessageCenter 采用字符串消息机制进行广播, 可以在绝大多数中小型项目中发挥作用,缺点是消息处理是在主线程中完成并且消息不支持分布式存储。

另外,MessageCenter 支持单播、多播发布及多订阅。如图所示:

22.2.1 注册 轻量级事件总线服务

如果想使用 MessageCenter 轻量级事件总线,只需要在 Startup.cs 中注册服务即可,如:

public void ConfigureServices(IServiceCollection services){    services.AddSimpleEventBus();}

22.2.2 定义订阅处理程序

MessageCenter 是根据 MesseageId 消息 Id 来触发对应的处理程序的,所以我们需要定义 订阅处理程序类,该类需实现 ISubscribeHandler 接口,如:

public class UserChangeSubscribeHandler : ISubscribeHandler{    // 定义一条消息    [SubscribeMessage("create:user")]    public void CreateUser(string eventId, object payload)    {        Console.WriteLine("我是"+eventId);    }    // 多条消息共用同一个处理程序    [SubscribeMessage("delete:user")]    [SubscribeMessage("remove:user")]    public void RemoveUser(string eventId, object payload)    {        Console.WriteLine("我是"+eventId);    }    // 支持异步    [SubscribeMessage("delete:user")]    public async Task SupportAsync(string eventId, object payload)    {        await MethodAsync();    }}

22.2.3 发布消息

定义好订阅处理程序后,我们就可以在程序任何地方进行广播消息,事件总线会自动根据 消息 Id 触发对应的处理程序方法:

MessageCenter.Send("create:user", new User {}); // => 打印:我是create:userMessageCenter.Send("delete:user", new User {}); // => 打印:我是delete:userMessageCenter.Send("remove:user", new User {}); // => 打印:我是remove:user

22.2.4 直接订阅消息

在上面的例子中,我们需要创建 ISubscribeHandler 的派生类进行相关配置才能实现订阅处理。

在某些特殊情况下,可能只需要订阅一次即可。所以,在 Furion 框架中,为了更简便的订阅消息,也提供了 MessageCenter.Subscribe<T> 静态方法,如:

MessageCenter.Subscribe<User>("create:user", (i,p) => {    // do something。。。});

22.3 同步方式执行

默认情况下,事件总线总是采用新线程方式执行,但是我们可以配置为同步方式,如:

MessageCenter.Send("create:user", isSync: true);

22.4 关于依赖注入

Furion 框架中,事件总线是不支持构造函数注入的,而且构造函数也只会执行一次。所以需要用到服务,应该通过静态类解析,App.GetService<xx>()Db.GetRepository<XX>()

public class UserChangeSubscribeHandler : ISubscribeHandler{    public UserChangeSubscribeHandler()    {        // 不支持这里解析服务!!!!!!!!!!!    }    // 定义一条消息    [SubscribeMessage("create:user")]    public void CreateUser(string eventId, object payload)    {        // 创建一个作用域,对象使用完成自动释放        Scoped.Create((_, scope) =>        {            var services = scope.ServiceProvider;            var repository = Db.GetRepository<Person>(services);    // services 传递进去            var someService = App.GetService<ISomeService>(services);   // services 传递进去            var otherService = services.GetService<IOtherService>();    // 直接用 services 解析        });    }}
关于 App.GetService<TService>() 解析服务

在高频定时任务中调用App.GetService(TService),可能会出现内存无法回收的情况,建议始终使用scope.ServiceProvider.GetService(TService)来获取TService

数据库操作注意

如果作用域中对数据库有任何变更操作,需手动调用 SaveChanges 或带 Now 结尾的方法。也可以使用 Scoped.CreateUow(handler) 代替。

关于依赖注入

ISubscribeHandler 接口主要是用来查找定义事件对象的,也就是它的实现类并未提供依赖注入功能,所以在实现类并不支持构造函数注入依赖项。

22.5 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

22. 事件总线

v2.20+ 版本说明

Furion v2.20+ 版本后采用 Jaina 事件总线替换原有的 EventBus😶查看新文档

22.1 什么是事件总线

事件总线是对发布-订阅模式的一种实现。它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需要相互依赖,达到一种解耦的目的。

我们来看看事件总线的处理流程:

22.2 MessageCenter 消息中心

Furion 框架中,实现了一种轻量级的事件总线实现机制:MessageCenter(消息中心),MessageCenter 采用字符串消息机制进行广播, 可以在绝大多数中小型项目中发挥作用,缺点是消息处理是在主线程中完成并且消息不支持分布式存储。

另外,MessageCenter 支持单播、多播发布及多订阅。如图所示:

22.2.1 注册 轻量级事件总线服务

如果想使用 MessageCenter 轻量级事件总线,只需要在 Startup.cs 中注册服务即可,如:

public void ConfigureServices(IServiceCollection services){    services.AddSimpleEventBus();}

22.2.2 定义订阅处理程序

MessageCenter 是根据 MesseageId 消息 Id 来触发对应的处理程序的,所以我们需要定义 订阅处理程序类,该类需实现 ISubscribeHandler 接口,如:

public class UserChangeSubscribeHandler : ISubscribeHandler{    // 定义一条消息    [SubscribeMessage("create:user")]    public void CreateUser(string eventId, object payload)    {        Console.WriteLine("我是"+eventId);    }    // 多条消息共用同一个处理程序    [SubscribeMessage("delete:user")]    [SubscribeMessage("remove:user")]    public void RemoveUser(string eventId, object payload)    {        Console.WriteLine("我是"+eventId);    }    // 支持异步    [SubscribeMessage("delete:user")]    public async Task SupportAsync(string eventId, object payload)    {        await MethodAsync();    }}

22.2.3 发布消息

定义好订阅处理程序后,我们就可以在程序任何地方进行广播消息,事件总线会自动根据 消息 Id 触发对应的处理程序方法:

MessageCenter.Send("create:user", new User {}); // => 打印:我是create:userMessageCenter.Send("delete:user", new User {}); // => 打印:我是delete:userMessageCenter.Send("remove:user", new User {}); // => 打印:我是remove:user

22.2.4 直接订阅消息

在上面的例子中,我们需要创建 ISubscribeHandler 的派生类进行相关配置才能实现订阅处理。

在某些特殊情况下,可能只需要订阅一次即可。所以,在 Furion 框架中,为了更简便的订阅消息,也提供了 MessageCenter.Subscribe<T> 静态方法,如:

MessageCenter.Subscribe<User>("create:user", (i,p) => {    // do something。。。});

22.3 同步方式执行

默认情况下,事件总线总是采用新线程方式执行,但是我们可以配置为同步方式,如:

MessageCenter.Send("create:user", isSync: true);

22.4 关于依赖注入

Furion 框架中,事件总线是不支持构造函数注入的,而且构造函数也只会执行一次。所以需要用到服务,应该通过静态类解析,App.GetService<xx>()Db.GetRepository<XX>()

public class UserChangeSubscribeHandler : ISubscribeHandler{    public UserChangeSubscribeHandler()    {        // 不支持这里解析服务!!!!!!!!!!!    }    // 定义一条消息    [SubscribeMessage("create:user")]    public void CreateUser(string eventId, object payload)    {        // 创建一个作用域,对象使用完成自动释放        Scoped.Create((_, scope) =>        {            var services = scope.ServiceProvider;            var repository = Db.GetRepository<Person>(services);    // services 传递进去            var someService = App.GetService<ISomeService>(services);   // services 传递进去            var otherService = services.GetService<IOtherService>();    // 直接用 services 解析        });    }}
关于 App.GetService<TService>() 解析服务

在高频定时任务中调用App.GetService(TService),可能会出现内存无法回收的情况,建议始终使用scope.ServiceProvider.GetService(TService)来获取TService

数据库操作注意

如果作用域中对数据库有任何变更操作,需手动调用 SaveChanges 或带 Now 结尾的方法。也可以使用 Scoped.CreateUow(handler) 代替。

关于依赖注入

ISubscribeHandler 接口主要是用来查找定义事件对象的,也就是它的实现类并未提供依赖注入功能,所以在实现类并不支持构造函数注入依赖项。

22.5 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/event-bus/index.html b/handbook/build/docs/event-bus/index.html index 0e3b7f8d8e..fee7ccc68b 100644 --- a/handbook/build/docs/event-bus/index.html +++ b/handbook/build/docs/event-bus/index.html @@ -2,22 +2,21 @@ - - - + +22. 事件总线 | Furion -22. 事件总线 | Furion - - + + +
-

22. 事件总线

v2.20 以下版本说明

Furion v2.20+ 版本后采用 Jaina 事件总线替换原有的 EventBus查看旧文档

22.1 关于事件总线

事件总线是对发布-订阅模式的一种实现。它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需要相互依赖,达到一种解耦的目的。

22.2 快速入门

  1. 定义事件订阅者 ToDoEventSubscriber
// 实现 IEventSubscriber 接口public class ToDoEventSubscriber : IEventSubscriber{    private readonly ILogger<ToDoEventSubscriber> _logger;    public ToDoEventSubscriber(ILogger<ToDoEventSubscriber> logger)    {        _logger = logger;    }    [EventSubscribe("ToDo:Create")]    public async Task CreateToDo(EventHandlerExecutingContext context)    {        var todo = context.Source;        _logger.LogInformation("创建一个 ToDo:{Name}", todo.Payload);        await Task.CompletedTask;    }    // 支持多个    [EventSubscribe("ToDo:Create")]    [EventSubscribe("ToDo:Update")]    public async Task CreateOrUpdateToDo(EventHandlerExecutingContext context)    {        var todo = context.Source;        _logger.LogInformation("创建或更新一个 ToDo:{Name}", todo.Payload);        await Task.CompletedTask;    }    // 支持枚举类型,v3.4.3+ 版本支持    [EventSubscribe(YourEnum.Some)]    public async Task EnumHandler(EventHandlerExecutingContext context)    {        var eventEnum = context.Source.EventId.ParseToEnum(); // 将事件 Id 转换成枚举对象        await Task.CompletedTask;    }    // 支持正则表达式匹配,4.2.10+ 版本支持    [EventSubscribe("(^1[3456789][0-9]{9}$)|((^[0-9]{3,4}\\-[0-9]{3,8}$)|(^[0-9]{3,8}$)|(^\\([0-9]{3,4}\\)[0-9]{3,8}$)|(^0{0,1}13[0-9]{9}$))", FuzzyMatch = true)]    public async Task RegexHandler(EventHandlerExecutingContext context)    {        var eventId = context.Source.EventId;        await Task.CompletedTask;    }    // 支持多种异常重试配置,4.2.10+ 版本支持    [EventSubscribe("test:error", NumRetries = 3)]    [EventSubscribe("test:error", NumRetries = 3, RetryTimeout = 1000)] // 重试间隔时间    [EventSubscribe("test:error", NumRetries = 3, ExceptionTypes = new[] { typeof(ArgumentException) })]    // 特定类型异常才重试    public async Task ExceptionHandler(EventHandlerExecutingContext context)    {        var eventId = context.Source.EventId;        await Task.CompletedTask;    }}
  1. 创建控制器 ToDoController,依赖注入 IEventPublisher 服务:
public class ToDoController : ControllerBase{    // 依赖注入事件发布者 IEventPublisher    private readonly IEventPublisher _eventPublisher;    public ToDoController(IEventPublisher eventPublisher)    {        _eventPublisher = eventPublisher;    }    // 发布 ToDo:Create 消息    public async Task CreateDoTo(string name)    {        await _eventPublisher.PublishAsync(new ChannelEventSource("ToDo:Create", name));    }    // v3.4.3+ 版本支持发送消息简化    public async Task CreateDoTo(string name)    {        await _eventPublisher.PublishAsync("ToDo:Create", name);        // 也支持枚举        await _eventPublisher.PublishAsync(YourEnum.Some);    }}
  1. Startup.cs 注册 EventBus 服务:
// 注册 EventBus 服务services.AddEventBus(builder =>{    // 注册 ToDo 事件订阅者    builder.AddSubscriber<ToDoEventSubscriber>();    // 通过类型注册,Furion 4.2.1+ 版本    builder.AddSubscriber(typeof(ToDoEventSubscriber));    // 批量注册事件订阅者    builder.AddSubscribers(ass1, ass2, ....);});
懒人提醒

Furion 中可以不用通过 builder.AddSubscriber<T>() 方式一一注册,只需要实现 ISingleton 接口即可,如:

public class ToDoEventSubscriber : IEventSubscriber, ISingleton{}

这样就无需写 builder.AddSubscriber<ToDoEventSubscriber>(); 代码了,只需保留 services.AddEventBus() 服务即可。

  1. 运行项目:
info: Jaina.Samples.ToDoEventSubscriber[0]      创建一个 ToDo:Jaina

22.3 自定义事件源

Furion 使用 IEventSource 作为消息载体,任何实现该接口的类都可以充当消息载体。

如需自定义,只需实现 IEventSource 接口即可:

public class ToDoEventSource : IEventSource{    public ToDoEventSource()    {    }    public ToDoEventSource(string eventId, string todoName)    {        EventId = eventId;        ToDoName = todoName;    }    // 自定义属性    public string ToDoName { get; set; }    /// <summary>    /// 事件 Id    /// </summary>    public string EventId { get; set; }    /// <summary>    /// 事件承载(携带)数据    /// </summary>    public object Payload { get; set; }    /// <summary>    /// 事件创建时间    /// </summary>    public DateTime CreatedTime { get; set; } = DateTime.UtcNow;    /// <summary>    /// 取消任务 Token    /// </summary>    /// <remarks>用于取消本次消息处理</remarks>    [Newtonsoft.Json.JsonIgnore]    [System.Text.Json.Serialization.JsonIgnore]    public CancellationToken CancellationToken { get; set; }}

使用:

await _eventPublisher.PublishAsync(new ToDoEventSource ("ToDo:Create", "我的 ToDo Name"));

22.4 自定义事件源存储器

Fruion 默认采用 Channel 作为事件源 IEventSource 存储器,开发者可以使用任何消息队列组件进行替换,如 Kafka、RabbitMQ、ActiveMQ 等,也可以使用部分数据库 Redis、SQL Server、MySql 实现。

如需自定义,只需实现 IEventSourceStorer 接口即可:

public class RedisEventSourceStorer : IEventSourceStorer{    private readonly IRedisClient _redisClient;    public RedisEventSourceStorer(IRedisClient redisClient)    {        _redisClient = redisClient;    }    // 往 Redis 中写入一条    public async ValueTask WriteAsync(IEventSource eventSource, CancellationToken cancellationToken)    {        await _redisClient.WriteAsync(...., cancellationToken);    }    // 从 Redis 中读取一条    public async ValueTask<IEventSource> ReadAsync(CancellationToken cancellationToken)    {       return await _redisClient.ReadAsync(...., cancellationToken);    }}

最后,在注册 EventBus 服务中替换默认 IEventSourceStorer

services.AddEventBus(builder =>{    // 替换事件源存储器    builder.ReplaceStorer(serviceProvider =>    {        var redisClient = serviceProvider.GetService<IRedisClient>();        return new RedisEventSourceStorer(redisClient);    });});

22.4.1 RabbitMQ 自定义指南

版本说明

以下内容仅限 Furion 4.3.4 + 版本使用。

由于使用 RabbitMQ 作为事件总线存储器的比较多,所以这里提供了完整的使用例子。

1. 安装 RabbitMQ.Client 拓展包

Install-Package RabbitMQ.Client -Version 6.4.0

2. 创建 RabbitMQEventSourceStorer 自定义存储器

using Furion.EventBus;using RabbitMQ.Client;using RabbitMQ.Client.Events;using System;using System.Text;using System.Text.Json;using System.Threading;using System.Threading.Channels;using System.Threading.Tasks;namespace Furion.Core;public sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable{    /// <summary>    /// 内存通道事件源存储器    /// </summary>    private readonly Channel<IEventSource> _channel;    /// <summary>    /// 通道对象    /// </summary>    private readonly IModel _model;    /// <summary>    /// 连接对象    /// </summary>    private readonly IConnection _connection;    /// <summary>    /// 路由键    /// </summary>    private readonly string _routeKey;    /// <summary>    /// 构造函数    /// </summary>    /// <param name="factory">连接工厂</param>    /// <param name="routeKey">路由键</param>    /// <param name="capacity">存储器最多能够处理多少消息,超过该容量进入等待写入</param>    public RabbitMQEventSourceStorer(ConnectionFactory factory, string routeKey, int capacity)    {        // 配置通道,设置超出默认容量后进入等待        var boundedChannelOptions = new BoundedChannelOptions(capacity)        {            FullMode = BoundedChannelFullMode.Wait        };        // 创建有限容量通道        _channel = Channel.CreateBounded<IEventSource>(boundedChannelOptions);        // 创建连接        _connection = factory.CreateConnection();        _routeKey = routeKey;        // 创建通道        _model = _connection.CreateModel();        // 声明路由队列        _model.QueueDeclare(routeKey, false, false, false, null);        // 创建消息订阅者        var consumer = new EventingBasicConsumer(_model);        // 订阅消息并写入内存 Channel        consumer.Received += (ch, ea) =>        {            // 读取原始消息            var stringEventSource = Encoding.UTF8.GetString(ea.Body.ToArray());            // 转换为 IEventSource,这里可以选择自己喜欢的序列化工具,如果自定义了 EventSource,注意属性是可读可写            var eventSource = JsonSerializer.Deserialize<ChannelEventSource>(stringEventSource);            // 写入内存管道存储器            _channel.Writer.TryWrite(eventSource);            // 确认该消息已被消费            _model.BasicAck(ea.DeliveryTag, false);        };        // 启动消费者 设置为手动应答消息        _model.BasicConsume(routeKey, false, consumer);    }    /// <summary>    /// 将事件源写入存储器    /// </summary>    /// <param name="eventSource">事件源对象</param>    /// <param name="cancellationToken">取消任务 Token</param>    /// <returns><see cref="ValueTask"/></returns>    public ValueTask WriteAsync(IEventSource eventSource, CancellationToken cancellationToken)    {        // 空检查        if (eventSource == default)        {            throw new ArgumentNullException(nameof(eventSource));        }        // 序列化,这里可以选择自己喜欢的序列化工具        var data = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(eventSource));        // 发布        _model.BasicPublish("", _routeKey, null, data);        return ValueTask.CompletedTask;    }    /// <summary>    /// 从存储器中读取一条事件源    /// </summary>    /// <param name="cancellationToken">取消任务 Token</param>    /// <returns>事件源对象</returns>    public async ValueTask<IEventSource> ReadAsync(CancellationToken cancellationToken)    {        // 读取一条事件源        var eventSource = await _channel.Reader.ReadAsync(cancellationToken);        return eventSource;    }    /// <summary>    /// 释放非托管资源    /// </summary>    public void Dispose()    {        _model.Dispose();        _connection.Dispose();    }}

3. 替换默认事件存储器

services.AddEventBus(options =>{    // 创建连接工厂    var factory = new ConnectionFactory    {        UserName = "admin",        Password = "q1w2e3",    };    // 创建默认内存通道事件源对象,可自定义队列路由key,比如这里是 eventbus    var rbmqEventSourceStorer = new RabbitMQEventSourceStorer(factory, "eventbus", 3000);    // 替换默认事件总线存储器    options.ReplaceStorer(serviceProvider =>    {        return rbmqEventSourceStorer;    });});

22.5 自定义事件发布者

Furion 默认内置基于 Channel 的事件发布者 ChannelEventPublisher

如需自定义,只需实现 IEventPublisher 接口即可:

public class ToDoEventPublisher : IEventPublisher{    private readonly IEventSourceStorer _eventSourceStorer;    public ChannelEventPublisher(IEventSourceStorer eventSourceStorer)    {        _eventSourceStorer = eventSourceStorer;    }    public async Task PublishAsync(IEventSource eventSource)    {        await _eventSourceStorer.WriteAsync(eventSource, eventSource.CancellationToken);    }}

最后,在注册 EventBus 服务中替换默认 IEventPublisher

services.AddEventBus(builder =>{    // 替换事件源存储器    builder.ReplacePublisher<ToDoEventPublisher>();});

22.6 添加事件执行监视器

Furion 提供了 IEventHandlerMonitor 监视器接口,实现该接口可以监视所有订阅事件,包括 执行之前、执行之后,执行异常,共享上下文数据

如添加 ToDoEventHandlerMonitor

public class ToDoEventHandlerMonitor : IEventHandlerMonitor{    private readonly ILogger<ToDoEventHandlerMonitor> _logger;    public ToDoEventHandlerMonitor(ILogger<ToDoEventHandlerMonitor> logger)    {        _logger = logger;    }    public Task OnExecutingAsync(EventHandlerExecutingContext context)    {        _logger.LogInformation("执行之前:{EventId}", context.Source.EventId);        return Task.CompletedTask;    }    public Task OnExecutedAsync(EventHandlerExecutedContext context)    {        _logger.LogInformation("执行之后:{EventId}", context.Source.EventId);        if (context.Exception != null)        {            _logger.LogError(context.Exception, "执行出错啦:{EventId}", context.Source.EventId);        }        return Task.CompletedTask;    }}

最后,在注册 EventBus 服务中注册 ToDoEventHandlerMonitor

services.AddEventBus(builder =>{    // 添加事件执行监视器    builder.AddMonitor<ToDoEventHandlerMonitor>();});

22.7 添加事件执行器

Furion 提供了 IEventHandlerExecutor 执行器接口,可以让开发者自定义事件处理函数执行策略,如 超时控制,失败重试、熔断等等

如添加 RetryEventHandlerExecutor

public class RetryEventHandlerExecutor : IEventHandlerExecutor{    public async Task ExecuteAsync(EventHandlerExecutingContext context, Func<EventHandlerExecutingContext, Task> handler)    {        // 如果执行失败,每隔 1s 重试,最多三次        await Retry.InvokeAsync(async () => {            await handler(context);        }, 3, 1000);    }}

最后,在注册 EventBus 服务中注册 RetryEventHandlerExecutor

services.AddEventBus(builder =>{    // 添加事件执行器    builder.AddExecutor<RetryEventHandlerExecutor>();});

22.8 使用有作用域的服务

Furion 中, Event Bus 所有服务均注册为单例,如需使用作用域服务(单例服务可直接注入),可通过依赖注入 IServiceProvider 实例并通过 CreateScope() 创建一个作用域,如:

public class ToDoEventSubscriber : IEventSubscriber{    private readonly ILogger<ToDoEventSubscriber> _logger;    public ToDoEventSubscriber(IServiceProvider services        , ILogger<ToDoEventSubscriber> logger)    {        Services = services;        _logger = logger;    }    public IServiceProvider Services { get; }    [EventSubscribe("ToDo:Create")]    public async Task CreateToDo(EventHandlerExecutingContext context)    {        // 创建新的作用域        using var scope = Services.CreateScope();        // 解析服务        var scopedProcessingService = scope.ServiceProvider.GetRequiredService<IScopedProcessingService>();        // ....    }}

22.9 订阅执行任务意外异常

services.AddEventBus(builder =>{    // 订阅 EventBus 未捕获异常    builder.UnobservedTaskExceptionHandler = (obj, args) =>    {        // ....    };});

22.10 事件总线工厂

版本说明

以下内容仅限 Furion 4.2.10 + 版本使用。

在该版本中,Furion 提供了 IEventBusFactory 工厂服务,可在运行时动态新增或删除订阅,如:

public class TestEventBus : IDynamicApiController{    private readonly IEventPublisher _eventPublisher;    private readonly IEventBusFactory _eventBusFactory;    public TestEventBus(IEventPublisher eventPublisher, IEventBusFactory eventBusFactory)    {        _eventPublisher = eventPublisher;        _eventBusFactory = eventBusFactory;    }    // 运行时动态添加一个订阅器    public async Task AddSubscriber()    {        await _eventBusFactory.Subscribe("xxx", async (ctx) =>        {            Console.WriteLine("我是动态的");            await Task.CompletedTask;        });    }    // 运行时动态删除一个订阅器    public async Task RemoveDynamic(string eventId)    {        await _eventBusFactory.Unsubscribe(eventId);    }}

22.11 MessageCenter 静态类

版本说明

以下内容仅限 Furion 4.3.3 + 版本使用。

Furion 4.3.3 版本新增了 MessageCenter 静态类,可在任何地方发送事件消息或订阅消息。

// 发送消息(含诸多重载)await MessageCenter.PublishAsync("messageId", new {});// 动态订阅消息MessageCenter.Subscribe("messageId", async (ctx) => {    Console.WriteLine("我是动态的");    await Task.CompletedTask;});// 取消订阅MessageCenter.Unsubscribe("messageId");

22.12 EventBusOptionsBuilder 配置

EventBusOptionsBuilderAddEventBus 构建服务选项,该选项包含以下属性和方法:

  • 属性
    • ChannelCapacity:默认内存通道容量
    • UnobservedTaskExceptionHandler:订阅执行任务未察觉异常
    • UseUtcTimestamp:是否使用 UTC 事件,默认 false
    • FuzzyMatch:是否开启全局模糊匹配(正则表达式)事件 Id,默认 false
  • 方法
    • AddSubscriber<TEventSubscriber>:添加订阅者
    • ReplacePublisher<TEventPublisher>:替换发布者
    • ReplaceStorer(Func<IServiceProvider, IEventSourceStorer>):替换存储器
    • AddMonitor<TEventHandlerMonitor>:添加监视器
    • AddExecutor<TEventHandlerExecutor>:添加执行器

22.13 如何实现数据库事务控制

相信很多朋友都使用了事件总线进行数据库操作,但是不知道如何实现事务控制,实际上并不难,如:

await _eventPublisher.PublishAsync(eventId, new YourModel {    OtherArgs = ...,    Exception = ex    // 有异常传入,否则 null});[EventSubscribe("ToDo:Create")]public async Task CreateToDo(EventHandlerExecutingContext context){    // 开启事务....    var model = context.Source.Payload as YourModel;    if(model.Exception != null)    {        // 回滚事务    }    else    {        // 提交事务    }    // 结束事务...    await Task.CompletedTask;}

22.14 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

22. 事件总线

v2.20 以下版本说明

Furion v2.20+ 版本后采用 Jaina 事件总线替换原有的 EventBus查看旧文档

22.1 关于事件总线

事件总线是对发布-订阅模式的一种实现。它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需要相互依赖,达到一种解耦的目的。

22.2 快速入门

  1. 定义事件订阅者 ToDoEventSubscriber
// 实现 IEventSubscriber 接口public class ToDoEventSubscriber : IEventSubscriber{    private readonly ILogger<ToDoEventSubscriber> _logger;    public ToDoEventSubscriber(ILogger<ToDoEventSubscriber> logger)    {        _logger = logger;    }    [EventSubscribe("ToDo:Create")]    public async Task CreateToDo(EventHandlerExecutingContext context)    {        var todo = context.Source;        _logger.LogInformation("创建一个 ToDo:{Name}", todo.Payload);        await Task.CompletedTask;    }    // 支持多个    [EventSubscribe("ToDo:Create")]    [EventSubscribe("ToDo:Update")]    public async Task CreateOrUpdateToDo(EventHandlerExecutingContext context)    {        var todo = context.Source;        _logger.LogInformation("创建或更新一个 ToDo:{Name}", todo.Payload);        await Task.CompletedTask;    }    // 支持枚举类型,v3.4.3+ 版本支持    [EventSubscribe(YourEnum.Some)]    public async Task EnumHandler(EventHandlerExecutingContext context)    {        var eventEnum = context.Source.EventId.ParseToEnum(); // 将事件 Id 转换成枚举对象        await Task.CompletedTask;    }    // 支持正则表达式匹配,4.2.10+ 版本支持    [EventSubscribe("(^1[3456789][0-9]{9}$)|((^[0-9]{3,4}\\-[0-9]{3,8}$)|(^[0-9]{3,8}$)|(^\\([0-9]{3,4}\\)[0-9]{3,8}$)|(^0{0,1}13[0-9]{9}$))", FuzzyMatch = true)]    public async Task RegexHandler(EventHandlerExecutingContext context)    {        var eventId = context.Source.EventId;        await Task.CompletedTask;    }    // 支持多种异常重试配置,4.2.10+ 版本支持    [EventSubscribe("test:error", NumRetries = 3)]    [EventSubscribe("test:error", NumRetries = 3, RetryTimeout = 1000)] // 重试间隔时间    [EventSubscribe("test:error", NumRetries = 3, ExceptionTypes = new[] { typeof(ArgumentException) })]    // 特定类型异常才重试    public async Task ExceptionHandler(EventHandlerExecutingContext context)    {        var eventId = context.Source.EventId;        await Task.CompletedTask;    }}
  1. 创建控制器 ToDoController,依赖注入 IEventPublisher 服务:
public class ToDoController : ControllerBase{    // 依赖注入事件发布者 IEventPublisher    private readonly IEventPublisher _eventPublisher;    public ToDoController(IEventPublisher eventPublisher)    {        _eventPublisher = eventPublisher;    }    // 发布 ToDo:Create 消息    public async Task CreateDoTo(string name)    {        await _eventPublisher.PublishAsync(new ChannelEventSource("ToDo:Create", name));    }    // v3.4.3+ 版本支持发送消息简化    public async Task CreateDoTo(string name)    {        await _eventPublisher.PublishAsync("ToDo:Create", name);        // 也支持枚举        await _eventPublisher.PublishAsync(YourEnum.Some);    }}
  1. Startup.cs 注册 EventBus 服务:
// 注册 EventBus 服务services.AddEventBus(builder =>{    // 注册 ToDo 事件订阅者    builder.AddSubscriber<ToDoEventSubscriber>();    // 通过类型注册,Furion 4.2.1+ 版本    builder.AddSubscriber(typeof(ToDoEventSubscriber));    // 批量注册事件订阅者    builder.AddSubscribers(ass1, ass2, ....);});
懒人提醒

Furion 中可以不用通过 builder.AddSubscriber<T>() 方式一一注册,只需要实现 ISingleton 接口即可,如:

public class ToDoEventSubscriber : IEventSubscriber, ISingleton{}

这样就无需写 builder.AddSubscriber<ToDoEventSubscriber>(); 代码了,只需保留 services.AddEventBus() 服务即可。

  1. 运行项目:
info: Jaina.Samples.ToDoEventSubscriber[0]      创建一个 ToDo:Jaina

22.3 自定义事件源

Furion 使用 IEventSource 作为消息载体,任何实现该接口的类都可以充当消息载体。

如需自定义,只需实现 IEventSource 接口即可:

public class ToDoEventSource : IEventSource{    public ToDoEventSource()    {    }    public ToDoEventSource(string eventId, string todoName)    {        EventId = eventId;        ToDoName = todoName;    }    // 自定义属性    public string ToDoName { get; set; }    /// <summary>    /// 事件 Id    /// </summary>    public string EventId { get; set; }    /// <summary>    /// 事件承载(携带)数据    /// </summary>    public object Payload { get; set; }    /// <summary>    /// 事件创建时间    /// </summary>    public DateTime CreatedTime { get; set; } = DateTime.UtcNow;    /// <summary>    /// 取消任务 Token    /// </summary>    /// <remarks>用于取消本次消息处理</remarks>    [Newtonsoft.Json.JsonIgnore]    [System.Text.Json.Serialization.JsonIgnore]    public CancellationToken CancellationToken { get; set; }}

使用:

await _eventPublisher.PublishAsync(new ToDoEventSource ("ToDo:Create", "我的 ToDo Name"));

22.4 自定义事件源存储器

Fruion 默认采用 Channel 作为事件源 IEventSource 存储器,开发者可以使用任何消息队列组件进行替换,如 Kafka、RabbitMQ、ActiveMQ 等,也可以使用部分数据库 Redis、SQL Server、MySql 实现。

如需自定义,只需实现 IEventSourceStorer 接口即可:

public class RedisEventSourceStorer : IEventSourceStorer{    private readonly IRedisClient _redisClient;    public RedisEventSourceStorer(IRedisClient redisClient)    {        _redisClient = redisClient;    }    // 往 Redis 中写入一条    public async ValueTask WriteAsync(IEventSource eventSource, CancellationToken cancellationToken)    {        await _redisClient.WriteAsync(...., cancellationToken);    }    // 从 Redis 中读取一条    public async ValueTask<IEventSource> ReadAsync(CancellationToken cancellationToken)    {       return await _redisClient.ReadAsync(...., cancellationToken);    }}

最后,在注册 EventBus 服务中替换默认 IEventSourceStorer

services.AddEventBus(builder =>{    // 替换事件源存储器    builder.ReplaceStorer(serviceProvider =>    {        var redisClient = serviceProvider.GetService<IRedisClient>();        return new RedisEventSourceStorer(redisClient);    });});

22.4.1 RabbitMQ 自定义指南

版本说明

以下内容仅限 Furion 4.3.4 + 版本使用。

由于使用 RabbitMQ 作为事件总线存储器的比较多,所以这里提供了完整的使用例子。

1. 安装 RabbitMQ.Client 拓展包

Install-Package RabbitMQ.Client -Version 6.4.0

2. 创建 RabbitMQEventSourceStorer 自定义存储器

using Furion.EventBus;using RabbitMQ.Client;using RabbitMQ.Client.Events;using System;using System.Text;using System.Text.Json;using System.Threading;using System.Threading.Channels;using System.Threading.Tasks;namespace Furion.Core;public sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable{    /// <summary>    /// 内存通道事件源存储器    /// </summary>    private readonly Channel<IEventSource> _channel;    /// <summary>    /// 通道对象    /// </summary>    private readonly IModel _model;    /// <summary>    /// 连接对象    /// </summary>    private readonly IConnection _connection;    /// <summary>    /// 路由键    /// </summary>    private readonly string _routeKey;    /// <summary>    /// 构造函数    /// </summary>    /// <param name="factory">连接工厂</param>    /// <param name="routeKey">路由键</param>    /// <param name="capacity">存储器最多能够处理多少消息,超过该容量进入等待写入</param>    public RabbitMQEventSourceStorer(ConnectionFactory factory, string routeKey, int capacity)    {        // 配置通道,设置超出默认容量后进入等待        var boundedChannelOptions = new BoundedChannelOptions(capacity)        {            FullMode = BoundedChannelFullMode.Wait        };        // 创建有限容量通道        _channel = Channel.CreateBounded<IEventSource>(boundedChannelOptions);        // 创建连接        _connection = factory.CreateConnection();        _routeKey = routeKey;        // 创建通道        _model = _connection.CreateModel();        // 声明路由队列        _model.QueueDeclare(routeKey, false, false, false, null);        // 创建消息订阅者        var consumer = new EventingBasicConsumer(_model);        // 订阅消息并写入内存 Channel        consumer.Received += (ch, ea) =>        {            // 读取原始消息            var stringEventSource = Encoding.UTF8.GetString(ea.Body.ToArray());            // 转换为 IEventSource,这里可以选择自己喜欢的序列化工具,如果自定义了 EventSource,注意属性是可读可写            var eventSource = JsonSerializer.Deserialize<ChannelEventSource>(stringEventSource);            // 写入内存管道存储器            _channel.Writer.TryWrite(eventSource);            // 确认该消息已被消费            _model.BasicAck(ea.DeliveryTag, false);        };        // 启动消费者 设置为手动应答消息        _model.BasicConsume(routeKey, false, consumer);    }    /// <summary>    /// 将事件源写入存储器    /// </summary>    /// <param name="eventSource">事件源对象</param>    /// <param name="cancellationToken">取消任务 Token</param>    /// <returns><see cref="ValueTask"/></returns>    public ValueTask WriteAsync(IEventSource eventSource, CancellationToken cancellationToken)    {        // 空检查        if (eventSource == default)        {            throw new ArgumentNullException(nameof(eventSource));        }        // 序列化,这里可以选择自己喜欢的序列化工具        var data = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(eventSource));        // 发布        _model.BasicPublish("", _routeKey, null, data);        return ValueTask.CompletedTask;    }    /// <summary>    /// 从存储器中读取一条事件源    /// </summary>    /// <param name="cancellationToken">取消任务 Token</param>    /// <returns>事件源对象</returns>    public async ValueTask<IEventSource> ReadAsync(CancellationToken cancellationToken)    {        // 读取一条事件源        var eventSource = await _channel.Reader.ReadAsync(cancellationToken);        return eventSource;    }    /// <summary>    /// 释放非托管资源    /// </summary>    public void Dispose()    {        _model.Dispose();        _connection.Dispose();    }}

3. 替换默认事件存储器

services.AddEventBus(options =>{    // 创建连接工厂    var factory = new ConnectionFactory    {        UserName = "admin",        Password = "q1w2e3",    };    // 创建默认内存通道事件源对象,可自定义队列路由key,比如这里是 eventbus    var rbmqEventSourceStorer = new RabbitMQEventSourceStorer(factory, "eventbus", 3000);    // 替换默认事件总线存储器    options.ReplaceStorer(serviceProvider =>    {        return rbmqEventSourceStorer;    });});

22.5 自定义事件发布者

Furion 默认内置基于 Channel 的事件发布者 ChannelEventPublisher

如需自定义,只需实现 IEventPublisher 接口即可:

public class ToDoEventPublisher : IEventPublisher{    private readonly IEventSourceStorer _eventSourceStorer;    public ChannelEventPublisher(IEventSourceStorer eventSourceStorer)    {        _eventSourceStorer = eventSourceStorer;    }    public async Task PublishAsync(IEventSource eventSource)    {        await _eventSourceStorer.WriteAsync(eventSource, eventSource.CancellationToken);    }}

最后,在注册 EventBus 服务中替换默认 IEventPublisher

services.AddEventBus(builder =>{    // 替换事件源存储器    builder.ReplacePublisher<ToDoEventPublisher>();});

22.6 添加事件执行监视器

Furion 提供了 IEventHandlerMonitor 监视器接口,实现该接口可以监视所有订阅事件,包括 执行之前、执行之后,执行异常,共享上下文数据

如添加 ToDoEventHandlerMonitor

public class ToDoEventHandlerMonitor : IEventHandlerMonitor{    private readonly ILogger<ToDoEventHandlerMonitor> _logger;    public ToDoEventHandlerMonitor(ILogger<ToDoEventHandlerMonitor> logger)    {        _logger = logger;    }    public Task OnExecutingAsync(EventHandlerExecutingContext context)    {        _logger.LogInformation("执行之前:{EventId}", context.Source.EventId);        return Task.CompletedTask;    }    public Task OnExecutedAsync(EventHandlerExecutedContext context)    {        _logger.LogInformation("执行之后:{EventId}", context.Source.EventId);        if (context.Exception != null)        {            _logger.LogError(context.Exception, "执行出错啦:{EventId}", context.Source.EventId);        }        return Task.CompletedTask;    }}

最后,在注册 EventBus 服务中注册 ToDoEventHandlerMonitor

services.AddEventBus(builder =>{    // 添加事件执行监视器    builder.AddMonitor<ToDoEventHandlerMonitor>();});

22.7 添加事件执行器

Furion 提供了 IEventHandlerExecutor 执行器接口,可以让开发者自定义事件处理函数执行策略,如 超时控制,失败重试、熔断等等

如添加 RetryEventHandlerExecutor

public class RetryEventHandlerExecutor : IEventHandlerExecutor{    public async Task ExecuteAsync(EventHandlerExecutingContext context, Func<EventHandlerExecutingContext, Task> handler)    {        // 如果执行失败,每隔 1s 重试,最多三次        await Retry.InvokeAsync(async () => {            await handler(context);        }, 3, 1000);    }}

最后,在注册 EventBus 服务中注册 RetryEventHandlerExecutor

services.AddEventBus(builder =>{    // 添加事件执行器    builder.AddExecutor<RetryEventHandlerExecutor>();});

22.8 使用有作用域的服务

Furion 中, Event Bus 所有服务均注册为单例,如需使用作用域服务(单例服务可直接注入),可通过依赖注入 IServiceProvider 实例并通过 CreateScope() 创建一个作用域,如:

public class ToDoEventSubscriber : IEventSubscriber{    private readonly ILogger<ToDoEventSubscriber> _logger;    public ToDoEventSubscriber(IServiceProvider services        , ILogger<ToDoEventSubscriber> logger)    {        Services = services;        _logger = logger;    }    public IServiceProvider Services { get; }    [EventSubscribe("ToDo:Create")]    public async Task CreateToDo(EventHandlerExecutingContext context)    {        // 创建新的作用域        using var scope = Services.CreateScope();        // 解析服务        var scopedProcessingService = scope.ServiceProvider.GetRequiredService<IScopedProcessingService>();        // ....    }}

22.9 订阅执行任务意外异常

services.AddEventBus(builder =>{    // 订阅 EventBus 未捕获异常    builder.UnobservedTaskExceptionHandler = (obj, args) =>    {        // ....    };});

22.10 事件总线工厂

版本说明

以下内容仅限 Furion 4.2.10 + 版本使用。

在该版本中,Furion 提供了 IEventBusFactory 工厂服务,可在运行时动态新增或删除订阅,如:

public class TestEventBus : IDynamicApiController{    private readonly IEventPublisher _eventPublisher;    private readonly IEventBusFactory _eventBusFactory;    public TestEventBus(IEventPublisher eventPublisher, IEventBusFactory eventBusFactory)    {        _eventPublisher = eventPublisher;        _eventBusFactory = eventBusFactory;    }    // 运行时动态添加一个订阅器    public async Task AddSubscriber()    {        await _eventBusFactory.Subscribe("xxx", async (ctx) =>        {            Console.WriteLine("我是动态的");            await Task.CompletedTask;        });    }    // 运行时动态删除一个订阅器    public async Task RemoveDynamic(string eventId)    {        await _eventBusFactory.Unsubscribe(eventId);    }}

22.11 MessageCenter 静态类

版本说明

以下内容仅限 Furion 4.3.3 + 版本使用。

Furion 4.3.3 版本新增了 MessageCenter 静态类,可在任何地方发送事件消息或订阅消息。

// 发送消息(含诸多重载)await MessageCenter.PublishAsync("messageId", new {});// 动态订阅消息MessageCenter.Subscribe("messageId", async (ctx) => {    Console.WriteLine("我是动态的");    await Task.CompletedTask;});// 取消订阅MessageCenter.Unsubscribe("messageId");

22.12 EventBusOptionsBuilder 配置

EventBusOptionsBuilderAddEventBus 构建服务选项,该选项包含以下属性和方法:

  • 属性
    • ChannelCapacity:默认内存通道容量
    • UnobservedTaskExceptionHandler:订阅执行任务未察觉异常
    • UseUtcTimestamp:是否使用 UTC 事件,默认 false
    • FuzzyMatch:是否开启全局模糊匹配(正则表达式)事件 Id,默认 false
  • 方法
    • AddSubscriber<TEventSubscriber>:添加订阅者
    • ReplacePublisher<TEventPublisher>:替换发布者
    • ReplaceStorer(Func<IServiceProvider, IEventSourceStorer>):替换存储器
    • AddMonitor<TEventHandlerMonitor>:添加监视器
    • AddExecutor<TEventHandlerExecutor>:添加执行器

22.13 如何实现数据库事务控制

相信很多朋友都使用了事件总线进行数据库操作,但是不知道如何实现事务控制,实际上并不难,如:

await _eventPublisher.PublishAsync(eventId, new YourModel {    OtherArgs = ...,    Exception = ex    // 有异常传入,否则 null});[EventSubscribe("ToDo:Create")]public async Task CreateToDo(EventHandlerExecutingContext context){    // 开启事务....    var model = context.Source.Payload as YourModel;    if(model.Exception != null)    {        // 回滚事务    }    else    {        // 提交事务    }    // 结束事务...    await Task.CompletedTask;}

22.14 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/file-provider/index.html b/handbook/build/docs/file-provider/index.html index 7a53557459..987dc9ac23 100644 --- a/handbook/build/docs/file-provider/index.html +++ b/handbook/build/docs/file-provider/index.html @@ -2,22 +2,21 @@ - - - + +31. 虚拟文件系统 | Furion -31. 虚拟文件系统 | Furion - - + + +
-

31. 虚拟文件系统

版本说明

以下内容仅限 Furion 2.5.0 + 版本使用。

31.1 关于文件系统

本章所谓的 文件系统 有点名不副实,其实根本算不上一个系统,它仅仅是利用一个抽象化的 IFileProvider 以统一的方式提供所需的文件而已。通过该 文件系统 可以读取物理文件和嵌入资源文件,包括目录结果读取,文件内容读取,文件内容监听等等。

31.1.1 文件系统类型

Furion 提供了两种文件系统类型:

  • Physical:物理文件系统类型,也就是物理机中实际存在的文件
  • Embedded:嵌入资源文件系统类型,也就是资源文件嵌入到了程序集中,常用于模块化开发

31.2 注册虚拟文件系统服务

services.AddVirtualFileServer();

31.3 获取文件系统 IFileProvider 实例

31.3.1 Func<FileProviderTypes, object, IFileProvider> 方式

Furion 框架提供了 Func<FileProviderTypes, object, IFileProvider> 委托供构造函数注入或解析服务,如:

public class PersonServices{    private readonly IFileProvider _physicalFileProvider;    private readonly IFileProvider _embeddedFileProvider;    public PersonServices(Func<FileProviderTypes, object, IFileProvider> fileProviderResolve)    {        // 解析物理文件系统        _physicalFileProvider = fileProviderResolve(FileProviderTypes.Physical, @"c:/test");        // 解析嵌入资源文件系统        _embeddedFileProvider = fileProviderResolve(FileProviderTypes.Embedded, Assembly.GetEntryAssembly());    }}

31.3.2 FS 静态类方式

Furion 框架也提供了 FS 静态类方式创建,如:

// 解析物理文件系统var physicalFileProvider = FS.GetPhysicalFileProvider(@"c:/test");// 解析嵌入资源文件系统var embeddedFileProvider = FS.GetEmbeddedFileProvider(Assembly.GetEntryAssembly());

31.4 IFileProvider 常见操作

31.4.1 读取文件内容

byte[] buffer;using (Stream readStream = _fileProvider.GetFileInfo("你的文件路径").CreateReadStream()){    buffer = new byte[readStream.Length];    await readStream.ReadAsync(buffer.AsMemory(0, buffer.Length));}// 读取文件内容var content = Encoding.UTF8.GetString(buffer);

31.4.2 获取文件目录内容(需递归查找)

var rootPath = "当前目录路径";var fileinfos = _fileProvider.GetDirectoryContents(rootPath);foreach (var fileinfo in fileinfos){    if(fileinfo.IsDirectory)    {        // 这里递归。。。    }}

31.4.4 监听文件变化

ChangeToken.OnChange(() => _fileProvider.Watch("监听的文件"), () =>{    // 这里写你的逻辑});

31.5 模块化静态资源配置

通常我们采用模块化开发,静态资源都是嵌入进程序集中,这时候我们需要通过配置 UseFileServer 指定模块静态资源路径,如:

// 默认静态资源调用,wwwrootapp.UseStaticFiles();// 配置模块化静态资源app.UseFileServer(new FileServerOptions{    FileProvider = new EmbeddedFileProvider(模块程序集),    RequestPath = "/模块名称",  // 后续所有资源都是通过 /模块名称/xxx.css 调用    EnableDirectoryBrowsing = true});

31.6 文件上传下载

在应用开发中,文件上传下载属于非常常用的功能,这里贴出常见的文件上传下载示例。

31.6.1 文件下载

  • 文件路径的方式
[HttpGet, NonUnify]public IActionResult FileDownload(){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") {        FileDownloadName = fileName // 配置文件下载显示名    };}
  • byte[] 方式
[HttpGet, NonUnify]public IActionResult FileDownload(){    return new FileStreamResult(byte数组, "application/octet-stream") {        FileDownloadName = fileName // 配置文件下载显示名    };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

31.6.2 文件上传

小提醒

IFormFile 类型对应前端的 Content-Type 为: multipart/form-data

  • 单文件 IFormFile 类型参数(存储到硬盘)
[HttpPost]public async Task<IActionResult> UploadFileAsync(IFormFile file){    // 如:保存到网站根目录下的 uploads 目录    var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");    if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);    //// 这里还可以获取文件的信息    // var size = file.Length / 1024.0;  // 文件大小 KB    // var clientFileName = file.FileName; // 客户端上传的文件名    // var contentType = file.ContentType; // 获取文件 ContentType 或解析 MIME 类型    // 避免文件名重复,采用 GUID 生成    var fileName = Guid.NewGuid().ToString("N") + Path.GetExtension(file.FileName);    var filePath = Path.Combine(savePath, fileName);    // 保存到指定路径    using (var stream = System.IO.File.Create(filePath))    {        await file.CopyToAsync(stream);    }    // 在动态 API 直接返回对象即可,无需 OK 和 IActionResult    return Ok(new { filename });}
  • 单文件 Base64 类型参数(存储到硬盘)
[HttpPost]public async Task UploadFileAsync([FromBody] string fileBase64, string clientFileName){    // 如:保存到网站根目录下的 uploads 目录    var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");    if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);    // 将 base64 字符串转 byte[]    var bytes = Convert.FromBase64String(fileBase64);    // 这里还可以获取文件的信息    // var size = bytes.Length / 1024.0;  // 文件大小 KB    // 避免文件名重复,采用 GUID 生成    var fileName = Guid.NewGuid().ToString("N") + Path.GetExtension(clientFileName);    var filePath = Path.Combine(savePath, fileName);    // 保存到指定路径    using (var fs = new FileStream(filePath, FileMode.Create))    {        await fs.WriteAsync(bytes);    }    // 在动态 API 直接返回对象即可,无需 OK 和 IActionResult    return Ok(new { fileName });}
特别注意

文件 Base64 字符串如果带 data:text/plain;base64, 开头则,需要手动去掉 , 之前(含逗号)的字符串。

  • 多文件 List<IFormFile> 类型参数(存储到硬盘)

代码和 单文件处理一致,只需 foreach 即可。

[HttpPost]public async Task<IActionResult> UploadFileAsync(List<IFormFile> files){    // 保存到网站根目录下的 uploads 目录    var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");    if(!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);    // 总上传大小    long size = files.Sum(f => f.Length);    // 遍历所有文件逐一上传    foreach (var formFile in files)    {        if (formFile.Length > 0)        {            // 避免文件名重复,采用 GUID 生成            var fileName = Guid.NewGuid().ToString("N") + Path.GetExtension(clientFileName);            var filePath = Path.Combine(savePath, fileName);            // 保存到指定路径            using (var stream = System.IO.File.Create(filePath))            {                await formFile.CopyToAsync(stream);            }        }    }    // 在动态 API 直接返回对象即可,无需 OK 和 IActionResult    return Ok(new { count = files.Count, size });}
  • 多文件 List<string> Base64 类型参数(存储到硬盘)

代码和 单文件处理一致,只需 foreach 即可(参上)。

31.6.3 将 IFormFilebyte[]

有时候我们需要将文件转换成 byte[] 存储到数据库,而不是存储到硬盘中。

[HttpPost]public async Task<IActionResult> UploadFileAsync(IFormFile file){    var fileLength = file.Length;    using var stream = file.OpenReadStream();    var bytes = new byte[fileLength];    stream.Read(bytes, 0, (int)fileLength);    // 这里将 bytes 存储到你想要的介质中即可}
便捷拓展方法

在 Furion v3.2.0 新增了 IFormFileToByteArray 拓展,如:

[HttpPost]public async Task<IActionResult> UploadFileAsync(IFormFile file){    var bytes = file.ToByteArray();    // 这里将 bytes 存储到你想要的介质中即可}

31.6.4 将 byte[] 输出为 Url 地址

由于一些项目直接将文件二进制存储在数据库中,读取到内存的时候都是 byte[] 数组,比如我们将图片文件存储在数据库中,然后前端通过 Url 链接进行访问,这个时候就需要将 byte[] 转换为有效的资源路径格式,如:

[NonUnify, HttpGet, AllowAnonymous]public async Task<IActionResult> attachment(string resourceId){    // 根据 resourceId 查询 byte[] 字节数组和 content-type    // 返回 FileContentResult 类型    return new FileContentResult(字节数组,content-type);}

之后我们就可以通过 https://localhost/attachment/资源id 访问文件或图片了。

31.7 请求大小控制(上传文件大小控制)

Web 项目中,KestrelHttpSys 都强制实施 30M (~28.6MiB) 的最大请求正文大小限制,如果请求正文大小超过配置的最大请求正文大小限制,则引发 Request body too large. The max request body size is xxxxx 异常,状态码为 413500

31.7.1 对特定的接口进行控制

可通过 [RequestSizeLimit] 特性进行特定限制

[HttpPost][RequestSizeLimit(100_000_000)]public IActionResult MyAction([FromBody] MyViewModel data){}

31.7.2 对特定接口取消限制

如果不需要对请求大小进行限制,也就是支持提交无限大小,则贴 [DisableRequestSizeLimit] 特性即可。

31.7.3 通用中间件进行控制

我们也可以通过中间件的方式在 Startup.cs 中进行配置:

app.Run(async context =>{    context.Features.Get<IHttpMaxRequestBodySizeFeature>().MaxRequestBodySize = 100_000_000; // 设置 null 就是不限制,具体值就是限制最大多少 M}

如果设置 MaxRequestBodySizenull ,则等同于取消限制,也就是 [DisableRequestSizeLimit] 的效果。

小注意

有时候配置了中间件效果发现没起作用,很有可能和中间件顺序有关,可以通过 .IsReadOnly 属性判断,如果为 true ,说明你的配置无效,只有 false 才有效。

31.7.4 全局配置

  • IIS 方式:
  1. 开发环境(IISExpress)

Web 启动层(通常是 XXX.Web.Entry)根目录下创建 web.config 文件,内容如下:

<?xml version="1.0" encoding="utf-8"?><configuration>    <system.webServer>        <security>            <requestFiltering>                <requestLimits maxAllowedContentLength="1073741824" />            </requestFiltering>        </security>    </system.webServer></configuration>
  1. 生产环境

通常生产环境 IIS 自动项目添加了 web.config 文件,这时候只需要在 <configuration> 节点下添加下面内容即可:

<system.webServer>    <security>        <requestFiltering>            <requestLimits maxAllowedContentLength="1073741824" />        </requestFiltering>    </security></system.webServer>
  • Kestrel 方式:
小知识

未使用 IIS 托管时,ASP.NET Core 默认使用 Kestrel 方式。

// .NET5 方式,在 .ConfigureWebHostDefaults 里面配置.UseStartup<Startup>().UseKestrel(options =>{    options.Limits.MaxRequestBodySize = null;   // 设置 null 就是不限制,具体值就是限制最大多少 M}// .NET6 方式,在 progame.cs 文件 var app = builder.Build(); 之后配置app.Configuration.Get<WebHostBuilder>().ConfigureKestrel(options =>{    options.Limits.MaxRequestBodySize = null;   // 设置 null 就是不限制,具体值就是限制最大多少 M});
  • HttpSys 方式:
小知识

HTTP.sys 是仅在 Windows 上运行的适用于 ASP.NET CoreWeb 服务器。 HTTP.sysKestrel 服务器的替代选择,提供了一些 Kestrel 不提供的功能。

// .NET5 方式同上.UseHttpSys(options =>{    options.MaxRequestBodySize = 100_000_000;   // 设置 null 就是不限制,具体值就是限制最大多少 M}// .NET6 方式同上

31.8 反馈与建议

与我们交流

给 Furion 提 Issue


演练场
- - +

31. 虚拟文件系统

版本说明

以下内容仅限 Furion 2.5.0 + 版本使用。

31.1 关于文件系统

本章所谓的 文件系统 有点名不副实,其实根本算不上一个系统,它仅仅是利用一个抽象化的 IFileProvider 以统一的方式提供所需的文件而已。通过该 文件系统 可以读取物理文件和嵌入资源文件,包括目录结果读取,文件内容读取,文件内容监听等等。

31.1.1 文件系统类型

Furion 提供了两种文件系统类型:

  • Physical:物理文件系统类型,也就是物理机中实际存在的文件
  • Embedded:嵌入资源文件系统类型,也就是资源文件嵌入到了程序集中,常用于模块化开发

31.2 注册虚拟文件系统服务

services.AddVirtualFileServer();

31.3 获取文件系统 IFileProvider 实例

31.3.1 Func<FileProviderTypes, object, IFileProvider> 方式

Furion 框架提供了 Func<FileProviderTypes, object, IFileProvider> 委托供构造函数注入或解析服务,如:

public class PersonServices{    private readonly IFileProvider _physicalFileProvider;    private readonly IFileProvider _embeddedFileProvider;    public PersonServices(Func<FileProviderTypes, object, IFileProvider> fileProviderResolve)    {        // 解析物理文件系统        _physicalFileProvider = fileProviderResolve(FileProviderTypes.Physical, @"c:/test");        // 解析嵌入资源文件系统        _embeddedFileProvider = fileProviderResolve(FileProviderTypes.Embedded, Assembly.GetEntryAssembly());    }}

31.3.2 FS 静态类方式

Furion 框架也提供了 FS 静态类方式创建,如:

// 解析物理文件系统var physicalFileProvider = FS.GetPhysicalFileProvider(@"c:/test");// 解析嵌入资源文件系统var embeddedFileProvider = FS.GetEmbeddedFileProvider(Assembly.GetEntryAssembly());

31.4 IFileProvider 常见操作

31.4.1 读取文件内容

byte[] buffer;using (Stream readStream = _fileProvider.GetFileInfo("你的文件路径").CreateReadStream()){    buffer = new byte[readStream.Length];    await readStream.ReadAsync(buffer.AsMemory(0, buffer.Length));}// 读取文件内容var content = Encoding.UTF8.GetString(buffer);

31.4.2 获取文件目录内容(需递归查找)

var rootPath = "当前目录路径";var fileinfos = _fileProvider.GetDirectoryContents(rootPath);foreach (var fileinfo in fileinfos){    if(fileinfo.IsDirectory)    {        // 这里递归。。。    }}

31.4.4 监听文件变化

ChangeToken.OnChange(() => _fileProvider.Watch("监听的文件"), () =>{    // 这里写你的逻辑});

31.5 模块化静态资源配置

通常我们采用模块化开发,静态资源都是嵌入进程序集中,这时候我们需要通过配置 UseFileServer 指定模块静态资源路径,如:

// 默认静态资源调用,wwwrootapp.UseStaticFiles();// 配置模块化静态资源app.UseFileServer(new FileServerOptions{    FileProvider = new EmbeddedFileProvider(模块程序集),    RequestPath = "/模块名称",  // 后续所有资源都是通过 /模块名称/xxx.css 调用    EnableDirectoryBrowsing = true});

31.6 文件上传下载

在应用开发中,文件上传下载属于非常常用的功能,这里贴出常见的文件上传下载示例。

31.6.1 文件下载

  • 文件路径的方式
[HttpGet, NonUnify]public IActionResult FileDownload(){    string filePath = "这里获取完整的文件下载路径";    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") {        FileDownloadName = fileName // 配置文件下载显示名    };}
  • byte[] 方式
[HttpGet, NonUnify]public IActionResult FileDownload(){    return new FileStreamResult(byte数组, "application/octet-stream") {        FileDownloadName = fileName // 配置文件下载显示名    };}
关于前端获取文件名

如果前端获取不到文件夹,可添加以下配置:

_httpContextAccessor.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename={文件名}");_httpContextAccessor.HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

31.6.2 文件上传

小提醒

IFormFile 类型对应前端的 Content-Type 为: multipart/form-data

  • 单文件 IFormFile 类型参数(存储到硬盘)
[HttpPost]public async Task<IActionResult> UploadFileAsync(IFormFile file){    // 如:保存到网站根目录下的 uploads 目录    var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");    if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);    //// 这里还可以获取文件的信息    // var size = file.Length / 1024.0;  // 文件大小 KB    // var clientFileName = file.FileName; // 客户端上传的文件名    // var contentType = file.ContentType; // 获取文件 ContentType 或解析 MIME 类型    // 避免文件名重复,采用 GUID 生成    var fileName = Guid.NewGuid().ToString("N") + Path.GetExtension(file.FileName);    var filePath = Path.Combine(savePath, fileName);    // 保存到指定路径    using (var stream = System.IO.File.Create(filePath))    {        await file.CopyToAsync(stream);    }    // 在动态 API 直接返回对象即可,无需 OK 和 IActionResult    return Ok(new { filename });}
  • 单文件 Base64 类型参数(存储到硬盘)
[HttpPost]public async Task UploadFileAsync([FromBody] string fileBase64, string clientFileName){    // 如:保存到网站根目录下的 uploads 目录    var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");    if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);    // 将 base64 字符串转 byte[]    var bytes = Convert.FromBase64String(fileBase64);    // 这里还可以获取文件的信息    // var size = bytes.Length / 1024.0;  // 文件大小 KB    // 避免文件名重复,采用 GUID 生成    var fileName = Guid.NewGuid().ToString("N") + Path.GetExtension(clientFileName);    var filePath = Path.Combine(savePath, fileName);    // 保存到指定路径    using (var fs = new FileStream(filePath, FileMode.Create))    {        await fs.WriteAsync(bytes);    }    // 在动态 API 直接返回对象即可,无需 OK 和 IActionResult    return Ok(new { fileName });}
特别注意

文件 Base64 字符串如果带 data:text/plain;base64, 开头则,需要手动去掉 , 之前(含逗号)的字符串。

  • 多文件 List<IFormFile> 类型参数(存储到硬盘)

代码和 单文件处理一致,只需 foreach 即可。

[HttpPost]public async Task<IActionResult> UploadFileAsync(List<IFormFile> files){    // 保存到网站根目录下的 uploads 目录    var savePath = Path.Combine(App.HostEnvironment.ContentRootPath, "uploads");    if(!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);    // 总上传大小    long size = files.Sum(f => f.Length);    // 遍历所有文件逐一上传    foreach (var formFile in files)    {        if (formFile.Length > 0)        {            // 避免文件名重复,采用 GUID 生成            var fileName = Guid.NewGuid().ToString("N") + Path.GetExtension(clientFileName);            var filePath = Path.Combine(savePath, fileName);            // 保存到指定路径            using (var stream = System.IO.File.Create(filePath))            {                await formFile.CopyToAsync(stream);            }        }    }    // 在动态 API 直接返回对象即可,无需 OK 和 IActionResult    return Ok(new { count = files.Count, size });}
  • 多文件 List<string> Base64 类型参数(存储到硬盘)

代码和 单文件处理一致,只需 foreach 即可(参上)。

31.6.3 将 IFormFilebyte[]

有时候我们需要将文件转换成 byte[] 存储到数据库,而不是存储到硬盘中。

[HttpPost]public async Task<IActionResult> UploadFileAsync(IFormFile file){    var fileLength = file.Length;    using var stream = file.OpenReadStream();    var bytes = new byte[fileLength];    stream.Read(bytes, 0, (int)fileLength);    // 这里将 bytes 存储到你想要的介质中即可}
便捷拓展方法

在 Furion v3.2.0 新增了 IFormFileToByteArray 拓展,如:

[HttpPost]public async Task<IActionResult> UploadFileAsync(IFormFile file){    var bytes = file.ToByteArray();    // 这里将 bytes 存储到你想要的介质中即可}

31.6.4 将 byte[] 输出为 Url 地址

由于一些项目直接将文件二进制存储在数据库中,读取到内存的时候都是 byte[] 数组,比如我们将图片文件存储在数据库中,然后前端通过 Url 链接进行访问,这个时候就需要将 byte[] 转换为有效的资源路径格式,如:

[NonUnify, HttpGet, AllowAnonymous]public async Task<IActionResult> attachment(string resourceId){    // 根据 resourceId 查询 byte[] 字节数组和 content-type    // 返回 FileContentResult 类型    return new FileContentResult(字节数组,content-type);}

之后我们就可以通过 https://localhost/attachment/资源id 访问文件或图片了。

31.7 请求大小控制(上传文件大小控制)

Web 项目中,KestrelHttpSys 都强制实施 30M (~28.6MiB) 的最大请求正文大小限制,如果请求正文大小超过配置的最大请求正文大小限制,则引发 Request body too large. The max request body size is xxxxx 异常,状态码为 413500

31.7.1 对特定的接口进行控制

可通过 [RequestSizeLimit] 特性进行特定限制

[HttpPost][RequestSizeLimit(100_000_000)]public IActionResult MyAction([FromBody] MyViewModel data){}

31.7.2 对特定接口取消限制

如果不需要对请求大小进行限制,也就是支持提交无限大小,则贴 [DisableRequestSizeLimit] 特性即可。

31.7.3 通用中间件进行控制

我们也可以通过中间件的方式在 Startup.cs 中进行配置:

app.Run(async context =>{    context.Features.Get<IHttpMaxRequestBodySizeFeature>().MaxRequestBodySize = 100_000_000; // 设置 null 就是不限制,具体值就是限制最大多少 M}

如果设置 MaxRequestBodySizenull ,则等同于取消限制,也就是 [DisableRequestSizeLimit] 的效果。

小注意

有时候配置了中间件效果发现没起作用,很有可能和中间件顺序有关,可以通过 .IsReadOnly 属性判断,如果为 true ,说明你的配置无效,只有 false 才有效。

31.7.4 全局配置

  • IIS 方式:
  1. 开发环境(IISExpress)

Web 启动层(通常是 XXX.Web.Entry)根目录下创建 web.config 文件,内容如下:

<?xml version="1.0" encoding="utf-8"?><configuration>    <system.webServer>        <security>            <requestFiltering>                <requestLimits maxAllowedContentLength="1073741824" />            </requestFiltering>        </security>    </system.webServer></configuration>
  1. 生产环境

通常生产环境 IIS 自动项目添加了 web.config 文件,这时候只需要在 <configuration> 节点下添加下面内容即可:

<system.webServer>    <security>        <requestFiltering>            <requestLimits maxAllowedContentLength="1073741824" />        </requestFiltering>    </security></system.webServer>
  • Kestrel 方式:
小知识

未使用 IIS 托管时,ASP.NET Core 默认使用 Kestrel 方式。

// .NET5 方式,在 .ConfigureWebHostDefaults 里面配置.UseStartup<Startup>().UseKestrel(options =>{    options.Limits.MaxRequestBodySize = null;   // 设置 null 就是不限制,具体值就是限制最大多少 M}// .NET6 方式,在 progame.cs 文件 var app = builder.Build(); 之后配置app.Configuration.Get<WebHostBuilder>().ConfigureKestrel(options =>{    options.Limits.MaxRequestBodySize = null;   // 设置 null 就是不限制,具体值就是限制最大多少 M});
  • HttpSys 方式:
小知识

HTTP.sys 是仅在 Windows 上运行的适用于 ASP.NET CoreWeb 服务器。 HTTP.sysKestrel 服务器的替代选择,提供了一些 Kestrel 不提供的功能。

// .NET5 方式同上.UseHttpSys(options =>{    options.MaxRequestBodySize = 100_000_000;   // 设置 null 就是不限制,具体值就是限制最大多少 M}// .NET6 方式同上

31.8 反馈与建议

与我们交流

给 Furion 提 Issue


演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/filter/index.html b/handbook/build/docs/filter/index.html index bda9025468..39b0a52759 100644 --- a/handbook/build/docs/filter/index.html +++ b/handbook/build/docs/filter/index.html @@ -2,22 +2,21 @@ - - - + +5.3 筛选器/拦截器/过滤器/AOP | Furion -5.3 筛选器/拦截器/过滤器/AOP | Furion - - + + +
-

5.3 筛选器/拦截器/过滤器/AOP

5.3.1 关于筛选器

筛选器又名过滤器,拦截器,在 ASP.NET Core 中,可在请求处理管道中特定阶段之前或之后运行代码。筛选器是非常经典的面向切面编程方式,也就是所谓的 AOP 操作。

通俗点说就是可以在控制器 Action 执行前后进行切面操作或返回 Result 结果前后操作。

5.3.2 应用场景

通过自定义筛选器可以实现错误处理,缓存处理,授权处理,日志记录,实现工作单元事务(Uow)等等切面操作,从而使业务逻辑和系统行为逻辑进行分离。

5.3.2.1 筛选器优点

  • 易拓展,易集成
  • 业务和系统逻辑分离,不干扰业务代码
  • 可实现接口多维度控制,如请求参数篡改,返回值篡改,限流,分布式事务支持
  • ...

5.3.3 支持拦截应用

  • Mvc/WebAPI 控制器/Action
  • Razor Pages 页面
  • 框架提供的 动态 WebAPI
  • 所有请求资源
  • 全局异常

5.3.4 筛选器类型

5.3.4.1 接口类型

  • 授权筛选器:该筛选器是最先运行,用于确定是否已针对请求为用户授权。 如果请求未获授权,授权筛选器可以让管道短路。
    • IAuthorizationFilter
    • IAsyncAuthorizationFilter
    • AuthorizeFilter
  • 资源筛选器:授权后运行,如果需要是大部分请求管道短路,它将会很有用
    • IResourceFilter
    • IAsyncResourceFilter
  • 操作筛选器:在调用操作方法之前和之后运行代码,可以更改传递的参数,返回结果等,不可在 Razor Pages 中使用
    • IActionFilter
    • IAsyncActionFilter
  • 异常筛选器:在向响应正文写入任何内容之前,对未经处理的异常应用全局策略。
    • IExceptionFilter
    • IAsyncExceptionFilter
  • 结果筛选器:在执行操作结果之前和之后立即运行代码,仅当操作方法成功执行时,它们才会运行。 对于必须围绕视图或格式化程序的执行的逻辑,它们很有用。
    • IResultFilter
    • IAsyncResultFilter
    • IAlwaysRunResultFilter:该接口主要针对所有操作结果运行拦截,也就是即使 IResourceFilter 设置了 Result 仍会执行并获取最终的 Result
    • IAsyncAlwaysRunReusltFilter
  • Razor Pages 筛选器:允许 Razor Pages 在运行 Razor 页面处理程序前后运行代码,和操作筛选器类似,但它们不能应用单个页面处理程序方法。
    • IPageFilter
    • IAsyncPageFilter

5.3.4.2 特性 Attribute 类型

  • 授权特性筛选器 (Attribute + IAsyncAuthorizationFilter):同上接口类型
  • 操作特性筛选器 (ActionFilterAttribute):同上接口类型
  • 异常特性筛选器 (ExceptionFilterAttribute):同上接口类型
  • 结果特性筛选器 (ResultFilterAttribute):同上接口类型
  • 服务特性筛选器 (ServiceFilterAttribute):支持依赖注入的服务筛选器特性
  • 类型特性筛选器 (TypeFilterAttribute):不支持依赖注入但可以传入自定义构造函数参数
  • 组合特性筛选器 (Attribute + 接口类型方式):可以通过派生自 Attribute 和 特定接口实现,如 Attribute, IActionFilter
筛选器选用技巧

关于选择哪种类型的筛选器有一个小技巧,当你不需要全局筛选器的时候使用特性筛选器,否则使用接口类型筛选器

另外尽可能的使用带 IAsync 开头的异步筛选器,这样无需分开多个方法,可在一个方法中操作,还能提高吞吐量。

同步异步筛选器

筛选器接口的同步和异步版本任意实现一个,而不是同时实现。

运行时会先查看筛选器是否实现了异步接口,如果是,则调用该接口。 如果不是,则调用同步接口的方法。

如果在一个类中同时实现异步和同步接口,则仅调用异步方法。 使用抽象类(如 ActionFilterAttribute)时,将为每种筛选器类型仅重写同步方法或仅重写异步方法。

5.3.5 筛选器注册

ASP.NET Core 提供了多种筛选器注册方式,通常情况下不同的注册方式执行顺序不同,服务类型注册最先执行,其次是 Mvc Filter 方式,最后是特性方式。相同的方式中又按照注册前后来决定执行顺序,先注册先执行。

同时也提供了 IOrderedFilter 接口重写执行顺序,其 Order 属性值越高的先执行。

5.3.5.1 在 Startup.cs 中注册

最常见的注册筛选器的方式就是在 Startup.cs 中注册,这种方式表示全局注册,应用所有控制器/Action

Startup.cs
public void ConfigureServices(IServiceCollection services){    // Mvc 方式注册一,全局执行    services.AddControllersWithViews(options =>    {       options.Filters.Add(new AddHeaderAttribute("GlobalAddHeader", "Result filter added to MvcOptions.Filters"));     // 手动创建实例,带构造参数       options.Filters.Add(typeof(MySampleActionFilter));   // 类型 Type 方式       options.Filters.Add(new SampleGlobalActionFilter()); // 手动创建实例,无构造参数    });    // Mvc 方式注册二,全局执行    services.Configure<MvcOptions>(options =>    {        options.Filters.Add<TFilter>();    });    // Mvc 注册方式三,全局执行,Furion 框架提供方式    services.AddMvcFilter<TFilter>();}

5.3.5.2 特性方式注册

如果筛选器派生自 特性,则可通过特性方式注册,这种方式表示局部注册,只作用于特定的控制器/Action

  • 直接贴方式
// 定义结果特性筛选器public class AddHeaderAttribute : ResultFilterAttribute{    // ...}// 直接贴方式,对于动态 WebAPI 也是一样的[AddHeader]public class SampleController : Controller{}
  • 通过 [ServiceFilter] 方式

这种方式适用于自定义的特性筛选器包含构造函数注入服务应用场景,这种方式必须在 ConfigureService 中通过 services.AddScoped<TFilter> 注册。

public class MyActionFilterAttribute : ActionFilterAttribute{    // 注入服务    private readonly PositionOptions _settings;    public MyActionFilterAttribute(IOptions<PositionOptions> options)    {    }}

需先在 Startup.cs 中注册筛选器

Startup.cs
services.AddScoped<MyActionFilterAttribute>();

使用:

public class SampleController : Controller{    // 通过 [ServiceFilter] 方式    [ServiceFilter(typeof(MyActionFilterAttribute))]    public IActionResult Index2()    {        // ...    }}
  • 通过 [TypeFilter] 方式

[TypeFilter][ServiceFilter] 类似,唯一的区别就是 [TypeFilter] 不支持构造函数注入服务,但可以传递基元类型构造函数参数

public class MyLogFilterAttribute : ActionFilterAttribute{    // 构造函数包含基元类型参数    public MyLogFilterAttribute(string message, int level)    {    }}public class SampleController : Controller{    // 通过 [TypeFilter] 方式    [TypeFilter(typeof(MyLogFilterAttribute), Arguments = new object[] { "Message", 10 })]    public IActionResult Index2()    {        // ...    }}

5.3.6 授权筛选器

通过授权筛选器可以实现在所有请求到达控制器/Action 之前进行验证,如果授权失败,直接跳转到登录或者返回 401

5.3.6.1 接口定义方式

using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.Authorization;using Microsoft.AspNetCore.Mvc.Controllers;using Microsoft.AspNetCore.Mvc.Filters;namespace WebApplication4.Filters;/// <summary>/// 自定义授权筛选器/// </summary>public class MyAuthorizationFilter : IAsyncAuthorizationFilter{    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)    {        Console.WriteLine("授权检查......");        // 获取控制器信息        var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;        // 获取控制器类型        var controllerType = actionDescriptor!.ControllerTypeInfo;        // 获取 Action 类型        var methodType = actionDescriptor.MethodInfo;        // 是否匿名访问        var allowAnonymouse = context.Filters.Any(u => u is IAllowAnonymousFilter)                        || controllerType.IsDefined(typeof(AllowAnonymousAttribute), true)                        || methodType.IsDefined(typeof(AllowAnonymousAttribute), true);        // 不是匿名才处理权限检查        if (!allowAnonymouse)        {            Console.Write("逻辑检查~~~~");            // 在 MVC 项目中,如果检查失败,则跳转到登录页            if (typeof(Controller).IsAssignableFrom(controllerType.AsType()))            {                context.Result = new RedirectResult("~/Login");            }            // WebAPI 或者其他类型            else            {                // 返回未授权                context.Result = new UnauthorizedResult();            }        }        // 否则直接跳过处理        else await Task.CompletedTask;    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyAuthorizationFilter>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyAuthorizationFilter>(),可使用它代替上面多行注册。

  • 局部特性方式

[TypeFilter]

[TypeFilter(typeof(MyAuthorizationFilter))]public IActionResult Get(){    // ...}

[ServiceFilter]

Starup.cs
services.AddScoped<MyAuthorizationFilter>();
[ServiceFilter(typeof(MyAuthorizationFilter))]public IActionResult Get(){    // ...}

5.3.6.2 特性定义方式(组合)

只需要上述接口方式中添加派生 Attribute 并设置 [AttributeUsage] 接口,如:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=false)]public class MyAuthorizationFilterAttribute : Attribute, IAsyncAuthorizationFilter{    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)    {        // 代码同上    }}

使用:

[MyAuthorizationFilter]public IActionResult Get(){    // ...}

5.3.7 资源筛选器

资源筛选器使用频率较少,通常用来处理资源缓存或者阻止模型(值)绑定操作。

5.3.7.1 接口定义方式

using Microsoft.AspNetCore.Mvc.Filters;using Microsoft.AspNetCore.Mvc.ModelBinding;namespace WebApplication4.Filters;public class MyResourceFilter : IAsyncResourceFilter{    public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)    {        // 获取所有资源提供器工厂        var valueProviderFactories = context.ValueProviderFactories;        // 比如这里判断如果是 Form 表单方式提交就就不给参数复制        var formValueProviderFactory = valueProviderFactories                .OfType<FormValueProviderFactory>()                .FirstOrDefault();        if (formValueProviderFactory != null)        {            // 移除 Form 表单绑定值提供器器            context.ValueProviderFactories.Remove(formValueProviderFactory);        }        // .... 更多操作        // 资源请求成功后        var resourceContext = await next();    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyResourceFilter>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyResourceFilter>(),可使用它代替上面多行注册。

  • 局部特性方式

[TypeFilter]

[TypeFilter(typeof(MyResourceFilter))]public IActionResult Get(){    // ...}

[ServiceFilter]

Starup.cs
services.AddScoped<MyResourceFilter>();
[ServiceFilter(typeof(MyResourceFilter))]public IActionResult Get(){    // ...}

5.3.7.2 特性定义方式(组合)

只需要上述接口方式中添加派生 Attribute 并设置 [AttributeUsage] 接口,如:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=false)]public class MyResourceFilterAttribute : Attribute, IAsyncResourceFilter{    public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)    {        // 代码同上    }}

使用:

[MyResourceFilter]public IActionResult Get(){    // ...}

5.3.8 操作筛选器

操作筛选器是使用频率最高的筛选器,通常用来控制进入 Action 之前(此时模型绑定已经完成)和 Action 执行之后(此时 Result 还未返回)。

可以使用操作筛选器实现各种骚操作,如篡改参数,篡改返回值,统一参数验证,审计日志,实现数据库事务自动开启关闭等等。

5.3.8.1 接口定义方式

using Microsoft.AspNetCore.Mvc.Controllers;using Microsoft.AspNetCore.Mvc.Filters;using System.Diagnostics;using System.Security.Claims;namespace WebApplication4.Filters;public class MyActionFilter : IAsyncActionFilter{    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)    {        //============== 这里是执行方法之前获取数据 ====================        // 获取控制器、路由信息        var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;        // 获取请求的方法        var method = actionDescriptor!.MethodInfo;        // 获取 HttpContext 和 HttpRequest 对象        var httpContext = context.HttpContext;        var httpRequest = httpContext.Request;        // 获取客户端 Ipv4 地址        var remoteIPv4 = httpContext.GetRemoteIpAddressToIPv4();        // 获取请求的 Url 地址        var requestUrl = httpRequest.GetRequestUrlAddress();        // 获取来源 Url 地址        var refererUrl = httpRequest.GetRefererUrlAddress();        // 获取请求参数(写入日志,需序列化成字符串后存储),可以自由篡改!!!!!!        var parameters = context.ActionArguments;        // 获取操作人(必须授权访问才有值)"userId" 为你存储的 claims type,jwt 授权对应的是 payload 中存储的键名        var userId = httpContext.User?.FindFirstValue("userId");        // 请求时间        var requestedTime = DateTimeOffset.Now;        //============== 这里是执行方法之后获取数据 ====================        var actionContext = await next();        // 获取返回的结果        var returnResult = actionContext.Result;        // 判断是否请求成功,没有异常就是请求成功        var isRequestSucceed = actionContext.Exception == null;        // 获取调用堆栈信息,提供更加简单明了的调用和异常堆栈        var stackTrace = EnhancedStackTrace.Current();        // 其他操作,如写入日志    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyActionFilter>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyActionFilter>(),可使用它代替上面多行注册。

  • 局部特性方式

[TypeFilter]

[TypeFilter(typeof(MyActionFilter))]public IActionResult Get(){    // ...}

[ServiceFilter]

Starup.cs
services.AddScoped<MyActionFilter>();
[ServiceFilter(typeof(MyActionFilter))]public IActionResult Get(){    // ...}

5.3.8.2 ActionFilterAttribute 方式

using Microsoft.AspNetCore.Mvc.Filters;namespace WebApplication4.Filters;public class MyActionAttribute : ActionFilterAttribute{    /// <summary>    /// 执行操作前后    /// </summary>    /// <param name="context"></param>    /// <param name="next"></param>    /// <returns></returns>    public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)    {        // 代码参考接口方式        return base.OnActionExecutionAsync(context, next);    }    /// <summary>    /// 返回结果前后    /// </summary>    /// <param name="context"></param>    /// <param name="next"></param>    /// <returns></returns>    public override Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)    {        // 代码参考接口方式        return base.OnResultExecutionAsync(context, next);    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyActionAttribute>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyActionAttribute>(),可使用它代替上面多行注册。

  • 局部特性方式
[MyAction]public IActionResult Get(){    // ...}

5.3.8.3 特性定义方式(组合)

只需要上述接口方式中添加派生 Attribute 并设置 [AttributeUsage] 接口,如:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=false)]public class MyActionFilterAttribute : Attribute, IAsyncActionFilter{    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)    {        // 代码同上    }}

使用:

[MyActionFilter]public IActionResult Get(){    // ...}

5.3.9 异常筛选器

异常筛选器使用频率仅次于操作筛选器,更多用于程序出现异常时记录日志或者返回统一的页面操作。

5.3.9.1 接口定义方式

using Microsoft.AspNetCore.Mvc.Controllers;using Microsoft.AspNetCore.Mvc.Filters;using System.Diagnostics;namespace WebApplication4.Filters;public class MyExceptionFilter : IAsyncExceptionFilter{    public async Task OnExceptionAsync(ExceptionContext context)    {        // 如果异常在其他地方被标记了处理,那么这里不再处理        if (context.ExceptionHandled) return;        // 获取控制器信息        ControllerActionDescriptor? actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;        // 获取请求的方法        var method = actionDescriptor!.MethodInfo;        // 获取异常对象        var exception = context.Exception;        // 获取调用堆栈信息,提供更加简单明了的调用和异常堆栈        var stackTrace = EnhancedStackTrace.Current();        // 其他处理~~~        // 1. MVC 直接返回自定义的错误页面,或者 BadPageResult 类型,如:context.Result = new BadPageResult(StatusCodes.Status500InternalServerError) { }        // 2. WebAPI 可以直接返回 context.Result = new JsonResult(.....);        // 3. 记录日志。。。。        await Task.CompletedTask;    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyExceptionFilter>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyExceptionFilter>(),可使用它代替上面多行注册。

  • 局部特性方式

[TypeFilter]

[TypeFilter(typeof(MyExceptionFilter))]public IActionResult Get(){    // ...}

[ServiceFilter]

Starup.cs
services.AddScoped<MyExceptionFilter>();
[ServiceFilter(typeof(MyExceptionFilter))]public IActionResult Get(){    // ...}

5.3.9.2 ExceptionFilterAttribute 方式

using Microsoft.AspNetCore.Mvc.Filters;namespace WebApplication4.Filters;public class MyExceptionAttribute : ExceptionFilterAttribute{    /// <summary>    /// 异常拦截器    /// </summary>    /// <param name="context"></param>    /// <returns></returns>    public override Task OnExceptionAsync(ExceptionContext context)    {        // 代码参考接口方式        return base.OnExceptionAsync(context);    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyExceptionAttribute>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyExceptionAttribute>(),可使用它代替上面多行注册。

  • 局部特性方式
[MyException]public IActionResult Get(){    // ...}

5.3.9.3 特性定义方式(组合)

只需要上述接口方式中添加派生 Attribute 并设置 [AttributeUsage] 接口,如:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=false)]public class MyExceptionFilterAttribute : Attribute, IAsyncExceptionFilter{    public async Task OnExceptionAsync(ExceptionContext context)    {        // 代码同上    }}

使用:

[MyExceptionFilter]public IActionResult Get(){    // ...}

5.3.10 结果筛选器

结果控制器常用于对返回的结果附加更多数据,比如 Mvc 中的 ViewBagViewData,换句话说主要用来控制输出到浏览器的界面视图对象。

5.3.10.1 接口定义方式

using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.Controllers;using Microsoft.AspNetCore.Mvc.Filters;namespace WebApplication4.Filters;public class MyResultFilter : IAsyncResultFilter{    public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)    {        // 获取控制器信息        ControllerActionDescriptor? actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;        // 获取路由表信息        var routeData = context.RouteData;        var controllerName = routeData.Values["controller"];        var actionName = routeData.Values["action"];        var areaName = routeData.DataTokens["area"];        // 判断如果是 MVC 视图,可以动态添加数据到页面中        if (context.Result is ViewResult viewResult)        {            // 动态添加数据,在 Razor 中就可以直接使用 @TempData["Name"] 获取数据了            viewResult.TempData["Name"] = "Furion";            // 动态添加数据,在 Razor 中就可以直接使用 @ViewBag.Version 或 @ViewData["Name"] 获取数据了            viewResult.ViewData["Version"] = 1;        }        // 这里还可以强制性换掉 Result        // context.Result = new ContentResult("....");        // 执行下一个结果过滤器,如果直接短路返回,可设置 context.Cancel = true; 这样就不会执行下一个过滤器,这个和下列代码是互斥的        var resultContext = await next();        // 获取返回的结果        var result = resultContext.Result;    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyResultFilter>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyResultFilter>(),可使用它代替上面多行注册。

  • 局部特性方式

[TypeFilter]

[TypeFilter(typeof(MyResultFilter))]public IActionResult Get(){    // ...}

[ServiceFilter]

Starup.cs
services.AddScoped<MyResultFilter>();
[ServiceFilter(typeof(MyResultFilter))]public IActionResult Get(){    // ...}

5.3.10.2 ResultFilterAttribute 方式

using Microsoft.AspNetCore.Mvc.Filters;namespace WebApplication4.Filters;public class MyResultAttribute : ResultFilterAttribute{    public override Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)    {        // 代码参考接口方式        return base.OnResultExecutionAsync(context, next);    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyResultAttribute>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyResultAttribute>(),可使用它代替上面多行注册。

  • 局部特性方式
[MyResult]public IActionResult Get(){    // ...}

5.3.10.3 特性定义方式(组合)

只需要上述接口方式中添加派生 Attribute 并设置 [AttributeUsage] 接口,如:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=false)]public class MyResultFilterAttribute : Attribute, IAsyncResultFilter{    public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)    {        // 代码同上    }}

使用:

[MyResultFilter]public IActionResult Get(){    // ...}

5.3.10.4 IAlwaysRunResultFilter

IAlwaysRunResultFilterIAsyncAlwaysRunResultFilter 接口声明了一个针对所有操作结果运行的 IResultFilter 实现。 这包括由以下对象生成的操作结果:

  • 设置短路的授权筛选器和资源筛选器。
  • 异常筛选器。

详细使用可查看微软官方文档 https://docs.microsoft.com/zh-cn/aspnet/core/mvc/controllers/filters?view=aspnetcore-6.0#ialwaysrunresultfilter-and-iasyncalwaysrunresultfilter

5.3.11 RazorPages 筛选器

Razor Pages 筛选器仅支持 Razor Pages 项目类型。

5.3.11.1 接口定义方式

using Microsoft.AspNetCore.Mvc.Filters;namespace WebApplication1;public class MyPageFilter : IAsyncPageFilter{    /// <summary>    /// 调用方法之前    /// </summary>    /// <param name="context"></param>    /// <param name="next"></param>    /// <returns></returns>    public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)    {        // 路由信息        var routeData = context.RouteData;        // 请求方法信息        var actionDescriptor = context.ActionDescriptor;        // 处理方法信息        var methodDescriptor = context.HandlerMethod;        await next.Invoke();    }    /// <summary>    /// 模型绑定之前    /// </summary>    /// <param name="context"></param>    /// <returns></returns>    public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)    {        return Task.CompletedTask;    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有 Page Handler

services.Configure<MvcOptions>(options =>{    options.Filters.Add(new MyPageFilter());});

5.3.11.2 ResultFilterAttribute 方式

using Microsoft.AspNetCore.Mvc.Filters;namespace WebApplication1.Filters;public class MyResultAttribute : ResultFilterAttribute{    public override Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)    {        // 代码参考接口方式        return base.OnResultExecutionAsync(context, next);    }}
  • 局部特性方式
[MyResult]public void OnGet(){    // ...}

5.3.12 筛选器取消和短路

通常筛选器支持多个,正常情况下,只要调用 await next() 方法都会进去下一个筛选器,但如果通过 context.Result = new XXXResult() 之后,就可以使其短路,也就是不会再执行下一个筛选器。

但也有例外

  • IResultFilter/IAsyncResultFilter 结果筛选器中,则使用标记 context.Cancel = true; 设置短路。
  • IExceptionFilter/IAsyncExceptionFilter 异常筛选器中,则使用标记 context.ExceptionHandled = true; 设置短路。

5.3.13 筛选器执行顺序控制

默认情况下,筛选器是按照以下执行顺序执行:

5.3.13.1 不同类型筛选器执行顺序

IAuthorizationFilter -> IResourceFilter -> IActionFilter -> IExceptionFilter -> IResultFilter -> IAlwaysRunResultFilter

异步也是如此。

5.3.13.2 相同类型筛选器执行顺序

默认情况下,通过 services.Configure<MvcOptions>(...) 方式先注册先执行,之后到特性方式,也是采用先注册先执行。

如果使用同一种方式,如 services.Configuration<MvcOptions>(...) 或同一种特性方式,也可以控制其执行顺序,如:

  • IOrderedFilter 方式:
public class MyActionFilter : IAsyncActionFilter, IOrderedFilter{    // 值越大,越优先执行    public int Order => 1000;    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)    {        // ....    }}
  • 特性 方式:
[MyActionFilter(Order = 1000)]public class ControllerFiltersController : Controller{    // ...}

5.3.4 筛选器依赖注入

筛选器是支持构造函数依赖注入服务的,使用它们的前提是在 Startup.cs 中注册,如:

Startup.cs
services.AddScoped<MyActionFilterAttribute>();

5.3.15 了解更多

想了解更多筛选器知识可查阅官方文档 https://docs.microsoft.com/zh-cn/aspnet/core/mvc/controllers/filters?view=aspnetcore-6.0

5.3.16 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

5.3 筛选器/拦截器/过滤器/AOP

5.3.1 关于筛选器

筛选器又名过滤器,拦截器,在 ASP.NET Core 中,可在请求处理管道中特定阶段之前或之后运行代码。筛选器是非常经典的面向切面编程方式,也就是所谓的 AOP 操作。

通俗点说就是可以在控制器 Action 执行前后进行切面操作或返回 Result 结果前后操作。

5.3.2 应用场景

通过自定义筛选器可以实现错误处理,缓存处理,授权处理,日志记录,实现工作单元事务(Uow)等等切面操作,从而使业务逻辑和系统行为逻辑进行分离。

5.3.2.1 筛选器优点

  • 易拓展,易集成
  • 业务和系统逻辑分离,不干扰业务代码
  • 可实现接口多维度控制,如请求参数篡改,返回值篡改,限流,分布式事务支持
  • ...

5.3.3 支持拦截应用

  • Mvc/WebAPI 控制器/Action
  • Razor Pages 页面
  • 框架提供的 动态 WebAPI
  • 所有请求资源
  • 全局异常

5.3.4 筛选器类型

5.3.4.1 接口类型

  • 授权筛选器:该筛选器是最先运行,用于确定是否已针对请求为用户授权。 如果请求未获授权,授权筛选器可以让管道短路。
    • IAuthorizationFilter
    • IAsyncAuthorizationFilter
    • AuthorizeFilter
  • 资源筛选器:授权后运行,如果需要是大部分请求管道短路,它将会很有用
    • IResourceFilter
    • IAsyncResourceFilter
  • 操作筛选器:在调用操作方法之前和之后运行代码,可以更改传递的参数,返回结果等,不可在 Razor Pages 中使用
    • IActionFilter
    • IAsyncActionFilter
  • 异常筛选器:在向响应正文写入任何内容之前,对未经处理的异常应用全局策略。
    • IExceptionFilter
    • IAsyncExceptionFilter
  • 结果筛选器:在执行操作结果之前和之后立即运行代码,仅当操作方法成功执行时,它们才会运行。 对于必须围绕视图或格式化程序的执行的逻辑,它们很有用。
    • IResultFilter
    • IAsyncResultFilter
    • IAlwaysRunResultFilter:该接口主要针对所有操作结果运行拦截,也就是即使 IResourceFilter 设置了 Result 仍会执行并获取最终的 Result
    • IAsyncAlwaysRunReusltFilter
  • Razor Pages 筛选器:允许 Razor Pages 在运行 Razor 页面处理程序前后运行代码,和操作筛选器类似,但它们不能应用单个页面处理程序方法。
    • IPageFilter
    • IAsyncPageFilter

5.3.4.2 特性 Attribute 类型

  • 授权特性筛选器 (Attribute + IAsyncAuthorizationFilter):同上接口类型
  • 操作特性筛选器 (ActionFilterAttribute):同上接口类型
  • 异常特性筛选器 (ExceptionFilterAttribute):同上接口类型
  • 结果特性筛选器 (ResultFilterAttribute):同上接口类型
  • 服务特性筛选器 (ServiceFilterAttribute):支持依赖注入的服务筛选器特性
  • 类型特性筛选器 (TypeFilterAttribute):不支持依赖注入但可以传入自定义构造函数参数
  • 组合特性筛选器 (Attribute + 接口类型方式):可以通过派生自 Attribute 和 特定接口实现,如 Attribute, IActionFilter
筛选器选用技巧

关于选择哪种类型的筛选器有一个小技巧,当你不需要全局筛选器的时候使用特性筛选器,否则使用接口类型筛选器

另外尽可能的使用带 IAsync 开头的异步筛选器,这样无需分开多个方法,可在一个方法中操作,还能提高吞吐量。

同步异步筛选器

筛选器接口的同步和异步版本任意实现一个,而不是同时实现。

运行时会先查看筛选器是否实现了异步接口,如果是,则调用该接口。 如果不是,则调用同步接口的方法。

如果在一个类中同时实现异步和同步接口,则仅调用异步方法。 使用抽象类(如 ActionFilterAttribute)时,将为每种筛选器类型仅重写同步方法或仅重写异步方法。

5.3.5 筛选器注册

ASP.NET Core 提供了多种筛选器注册方式,通常情况下不同的注册方式执行顺序不同,服务类型注册最先执行,其次是 Mvc Filter 方式,最后是特性方式。相同的方式中又按照注册前后来决定执行顺序,先注册先执行。

同时也提供了 IOrderedFilter 接口重写执行顺序,其 Order 属性值越高的先执行。

5.3.5.1 在 Startup.cs 中注册

最常见的注册筛选器的方式就是在 Startup.cs 中注册,这种方式表示全局注册,应用所有控制器/Action

Startup.cs
public void ConfigureServices(IServiceCollection services){    // Mvc 方式注册一,全局执行    services.AddControllersWithViews(options =>    {       options.Filters.Add(new AddHeaderAttribute("GlobalAddHeader", "Result filter added to MvcOptions.Filters"));     // 手动创建实例,带构造参数       options.Filters.Add(typeof(MySampleActionFilter));   // 类型 Type 方式       options.Filters.Add(new SampleGlobalActionFilter()); // 手动创建实例,无构造参数    });    // Mvc 方式注册二,全局执行    services.Configure<MvcOptions>(options =>    {        options.Filters.Add<TFilter>();    });    // Mvc 注册方式三,全局执行,Furion 框架提供方式    services.AddMvcFilter<TFilter>();}

5.3.5.2 特性方式注册

如果筛选器派生自 特性,则可通过特性方式注册,这种方式表示局部注册,只作用于特定的控制器/Action

  • 直接贴方式
// 定义结果特性筛选器public class AddHeaderAttribute : ResultFilterAttribute{    // ...}// 直接贴方式,对于动态 WebAPI 也是一样的[AddHeader]public class SampleController : Controller{}
  • 通过 [ServiceFilter] 方式

这种方式适用于自定义的特性筛选器包含构造函数注入服务应用场景,这种方式必须在 ConfigureService 中通过 services.AddScoped<TFilter> 注册。

public class MyActionFilterAttribute : ActionFilterAttribute{    // 注入服务    private readonly PositionOptions _settings;    public MyActionFilterAttribute(IOptions<PositionOptions> options)    {    }}

需先在 Startup.cs 中注册筛选器

Startup.cs
services.AddScoped<MyActionFilterAttribute>();

使用:

public class SampleController : Controller{    // 通过 [ServiceFilter] 方式    [ServiceFilter(typeof(MyActionFilterAttribute))]    public IActionResult Index2()    {        // ...    }}
  • 通过 [TypeFilter] 方式

[TypeFilter][ServiceFilter] 类似,唯一的区别就是 [TypeFilter] 不支持构造函数注入服务,但可以传递基元类型构造函数参数

public class MyLogFilterAttribute : ActionFilterAttribute{    // 构造函数包含基元类型参数    public MyLogFilterAttribute(string message, int level)    {    }}public class SampleController : Controller{    // 通过 [TypeFilter] 方式    [TypeFilter(typeof(MyLogFilterAttribute), Arguments = new object[] { "Message", 10 })]    public IActionResult Index2()    {        // ...    }}

5.3.6 授权筛选器

通过授权筛选器可以实现在所有请求到达控制器/Action 之前进行验证,如果授权失败,直接跳转到登录或者返回 401

5.3.6.1 接口定义方式

using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.Authorization;using Microsoft.AspNetCore.Mvc.Controllers;using Microsoft.AspNetCore.Mvc.Filters;namespace WebApplication4.Filters;/// <summary>/// 自定义授权筛选器/// </summary>public class MyAuthorizationFilter : IAsyncAuthorizationFilter{    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)    {        Console.WriteLine("授权检查......");        // 获取控制器信息        var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;        // 获取控制器类型        var controllerType = actionDescriptor!.ControllerTypeInfo;        // 获取 Action 类型        var methodType = actionDescriptor.MethodInfo;        // 是否匿名访问        var allowAnonymouse = context.Filters.Any(u => u is IAllowAnonymousFilter)                        || controllerType.IsDefined(typeof(AllowAnonymousAttribute), true)                        || methodType.IsDefined(typeof(AllowAnonymousAttribute), true);        // 不是匿名才处理权限检查        if (!allowAnonymouse)        {            Console.Write("逻辑检查~~~~");            // 在 MVC 项目中,如果检查失败,则跳转到登录页            if (typeof(Controller).IsAssignableFrom(controllerType.AsType()))            {                context.Result = new RedirectResult("~/Login");            }            // WebAPI 或者其他类型            else            {                // 返回未授权                context.Result = new UnauthorizedResult();            }        }        // 否则直接跳过处理        else await Task.CompletedTask;    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyAuthorizationFilter>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyAuthorizationFilter>(),可使用它代替上面多行注册。

  • 局部特性方式

[TypeFilter]

[TypeFilter(typeof(MyAuthorizationFilter))]public IActionResult Get(){    // ...}

[ServiceFilter]

Starup.cs
services.AddScoped<MyAuthorizationFilter>();
[ServiceFilter(typeof(MyAuthorizationFilter))]public IActionResult Get(){    // ...}

5.3.6.2 特性定义方式(组合)

只需要上述接口方式中添加派生 Attribute 并设置 [AttributeUsage] 接口,如:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=false)]public class MyAuthorizationFilterAttribute : Attribute, IAsyncAuthorizationFilter{    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)    {        // 代码同上    }}

使用:

[MyAuthorizationFilter]public IActionResult Get(){    // ...}

5.3.7 资源筛选器

资源筛选器使用频率较少,通常用来处理资源缓存或者阻止模型(值)绑定操作。

5.3.7.1 接口定义方式

using Microsoft.AspNetCore.Mvc.Filters;using Microsoft.AspNetCore.Mvc.ModelBinding;namespace WebApplication4.Filters;public class MyResourceFilter : IAsyncResourceFilter{    public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)    {        // 获取所有资源提供器工厂        var valueProviderFactories = context.ValueProviderFactories;        // 比如这里判断如果是 Form 表单方式提交就就不给参数复制        var formValueProviderFactory = valueProviderFactories                .OfType<FormValueProviderFactory>()                .FirstOrDefault();        if (formValueProviderFactory != null)        {            // 移除 Form 表单绑定值提供器器            context.ValueProviderFactories.Remove(formValueProviderFactory);        }        // .... 更多操作        // 资源请求成功后        var resourceContext = await next();    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyResourceFilter>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyResourceFilter>(),可使用它代替上面多行注册。

  • 局部特性方式

[TypeFilter]

[TypeFilter(typeof(MyResourceFilter))]public IActionResult Get(){    // ...}

[ServiceFilter]

Starup.cs
services.AddScoped<MyResourceFilter>();
[ServiceFilter(typeof(MyResourceFilter))]public IActionResult Get(){    // ...}

5.3.7.2 特性定义方式(组合)

只需要上述接口方式中添加派生 Attribute 并设置 [AttributeUsage] 接口,如:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=false)]public class MyResourceFilterAttribute : Attribute, IAsyncResourceFilter{    public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)    {        // 代码同上    }}

使用:

[MyResourceFilter]public IActionResult Get(){    // ...}

5.3.8 操作筛选器

操作筛选器是使用频率最高的筛选器,通常用来控制进入 Action 之前(此时模型绑定已经完成)和 Action 执行之后(此时 Result 还未返回)。

可以使用操作筛选器实现各种骚操作,如篡改参数,篡改返回值,统一参数验证,审计日志,实现数据库事务自动开启关闭等等。

5.3.8.1 接口定义方式

using Microsoft.AspNetCore.Mvc.Controllers;using Microsoft.AspNetCore.Mvc.Filters;using System.Diagnostics;using System.Security.Claims;namespace WebApplication4.Filters;public class MyActionFilter : IAsyncActionFilter{    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)    {        //============== 这里是执行方法之前获取数据 ====================        // 获取控制器、路由信息        var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;        // 获取请求的方法        var method = actionDescriptor!.MethodInfo;        // 获取 HttpContext 和 HttpRequest 对象        var httpContext = context.HttpContext;        var httpRequest = httpContext.Request;        // 获取客户端 Ipv4 地址        var remoteIPv4 = httpContext.GetRemoteIpAddressToIPv4();        // 获取请求的 Url 地址        var requestUrl = httpRequest.GetRequestUrlAddress();        // 获取来源 Url 地址        var refererUrl = httpRequest.GetRefererUrlAddress();        // 获取请求参数(写入日志,需序列化成字符串后存储),可以自由篡改!!!!!!        var parameters = context.ActionArguments;        // 获取操作人(必须授权访问才有值)"userId" 为你存储的 claims type,jwt 授权对应的是 payload 中存储的键名        var userId = httpContext.User?.FindFirstValue("userId");        // 请求时间        var requestedTime = DateTimeOffset.Now;        //============== 这里是执行方法之后获取数据 ====================        var actionContext = await next();        // 获取返回的结果        var returnResult = actionContext.Result;        // 判断是否请求成功,没有异常就是请求成功        var isRequestSucceed = actionContext.Exception == null;        // 获取调用堆栈信息,提供更加简单明了的调用和异常堆栈        var stackTrace = EnhancedStackTrace.Current();        // 其他操作,如写入日志    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyActionFilter>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyActionFilter>(),可使用它代替上面多行注册。

  • 局部特性方式

[TypeFilter]

[TypeFilter(typeof(MyActionFilter))]public IActionResult Get(){    // ...}

[ServiceFilter]

Starup.cs
services.AddScoped<MyActionFilter>();
[ServiceFilter(typeof(MyActionFilter))]public IActionResult Get(){    // ...}

5.3.8.2 ActionFilterAttribute 方式

using Microsoft.AspNetCore.Mvc.Filters;namespace WebApplication4.Filters;public class MyActionAttribute : ActionFilterAttribute{    /// <summary>    /// 执行操作前后    /// </summary>    /// <param name="context"></param>    /// <param name="next"></param>    /// <returns></returns>    public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)    {        // 代码参考接口方式        return base.OnActionExecutionAsync(context, next);    }    /// <summary>    /// 返回结果前后    /// </summary>    /// <param name="context"></param>    /// <param name="next"></param>    /// <returns></returns>    public override Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)    {        // 代码参考接口方式        return base.OnResultExecutionAsync(context, next);    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyActionAttribute>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyActionAttribute>(),可使用它代替上面多行注册。

  • 局部特性方式
[MyAction]public IActionResult Get(){    // ...}

5.3.8.3 特性定义方式(组合)

只需要上述接口方式中添加派生 Attribute 并设置 [AttributeUsage] 接口,如:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=false)]public class MyActionFilterAttribute : Attribute, IAsyncActionFilter{    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)    {        // 代码同上    }}

使用:

[MyActionFilter]public IActionResult Get(){    // ...}

5.3.9 异常筛选器

异常筛选器使用频率仅次于操作筛选器,更多用于程序出现异常时记录日志或者返回统一的页面操作。

5.3.9.1 接口定义方式

using Microsoft.AspNetCore.Mvc.Controllers;using Microsoft.AspNetCore.Mvc.Filters;using System.Diagnostics;namespace WebApplication4.Filters;public class MyExceptionFilter : IAsyncExceptionFilter{    public async Task OnExceptionAsync(ExceptionContext context)    {        // 如果异常在其他地方被标记了处理,那么这里不再处理        if (context.ExceptionHandled) return;        // 获取控制器信息        ControllerActionDescriptor? actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;        // 获取请求的方法        var method = actionDescriptor!.MethodInfo;        // 获取异常对象        var exception = context.Exception;        // 获取调用堆栈信息,提供更加简单明了的调用和异常堆栈        var stackTrace = EnhancedStackTrace.Current();        // 其他处理~~~        // 1. MVC 直接返回自定义的错误页面,或者 BadPageResult 类型,如:context.Result = new BadPageResult(StatusCodes.Status500InternalServerError) { }        // 2. WebAPI 可以直接返回 context.Result = new JsonResult(.....);        // 3. 记录日志。。。。        await Task.CompletedTask;    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyExceptionFilter>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyExceptionFilter>(),可使用它代替上面多行注册。

  • 局部特性方式

[TypeFilter]

[TypeFilter(typeof(MyExceptionFilter))]public IActionResult Get(){    // ...}

[ServiceFilter]

Starup.cs
services.AddScoped<MyExceptionFilter>();
[ServiceFilter(typeof(MyExceptionFilter))]public IActionResult Get(){    // ...}

5.3.9.2 ExceptionFilterAttribute 方式

using Microsoft.AspNetCore.Mvc.Filters;namespace WebApplication4.Filters;public class MyExceptionAttribute : ExceptionFilterAttribute{    /// <summary>    /// 异常拦截器    /// </summary>    /// <param name="context"></param>    /// <returns></returns>    public override Task OnExceptionAsync(ExceptionContext context)    {        // 代码参考接口方式        return base.OnExceptionAsync(context);    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyExceptionAttribute>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyExceptionAttribute>(),可使用它代替上面多行注册。

  • 局部特性方式
[MyException]public IActionResult Get(){    // ...}

5.3.9.3 特性定义方式(组合)

只需要上述接口方式中添加派生 Attribute 并设置 [AttributeUsage] 接口,如:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=false)]public class MyExceptionFilterAttribute : Attribute, IAsyncExceptionFilter{    public async Task OnExceptionAsync(ExceptionContext context)    {        // 代码同上    }}

使用:

[MyExceptionFilter]public IActionResult Get(){    // ...}

5.3.10 结果筛选器

结果控制器常用于对返回的结果附加更多数据,比如 Mvc 中的 ViewBagViewData,换句话说主要用来控制输出到浏览器的界面视图对象。

5.3.10.1 接口定义方式

using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.Controllers;using Microsoft.AspNetCore.Mvc.Filters;namespace WebApplication4.Filters;public class MyResultFilter : IAsyncResultFilter{    public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)    {        // 获取控制器信息        ControllerActionDescriptor? actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;        // 获取路由表信息        var routeData = context.RouteData;        var controllerName = routeData.Values["controller"];        var actionName = routeData.Values["action"];        var areaName = routeData.DataTokens["area"];        // 判断如果是 MVC 视图,可以动态添加数据到页面中        if (context.Result is ViewResult viewResult)        {            // 动态添加数据,在 Razor 中就可以直接使用 @TempData["Name"] 获取数据了            viewResult.TempData["Name"] = "Furion";            // 动态添加数据,在 Razor 中就可以直接使用 @ViewBag.Version 或 @ViewData["Name"] 获取数据了            viewResult.ViewData["Version"] = 1;        }        // 这里还可以强制性换掉 Result        // context.Result = new ContentResult("....");        // 执行下一个结果过滤器,如果直接短路返回,可设置 context.Cancel = true; 这样就不会执行下一个过滤器,这个和下列代码是互斥的        var resultContext = await next();        // 获取返回的结果        var result = resultContext.Result;    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyResultFilter>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyResultFilter>(),可使用它代替上面多行注册。

  • 局部特性方式

[TypeFilter]

[TypeFilter(typeof(MyResultFilter))]public IActionResult Get(){    // ...}

[ServiceFilter]

Starup.cs
services.AddScoped<MyResultFilter>();
[ServiceFilter(typeof(MyResultFilter))]public IActionResult Get(){    // ...}

5.3.10.2 ResultFilterAttribute 方式

using Microsoft.AspNetCore.Mvc.Filters;namespace WebApplication4.Filters;public class MyResultAttribute : ResultFilterAttribute{    public override Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)    {        // 代码参考接口方式        return base.OnResultExecutionAsync(context, next);    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有的控制器/ Action

services.Configure<MvcOptions>(options =>{    options.Filters.Add<MyResultAttribute>();});
更简易方式

Furion 框架中提供了 services.AddMvcFilter<MyResultAttribute>(),可使用它代替上面多行注册。

  • 局部特性方式
[MyResult]public IActionResult Get(){    // ...}

5.3.10.3 特性定义方式(组合)

只需要上述接口方式中添加派生 Attribute 并设置 [AttributeUsage] 接口,如:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true, AllowMultiple=false)]public class MyResultFilterAttribute : Attribute, IAsyncResultFilter{    public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)    {        // 代码同上    }}

使用:

[MyResultFilter]public IActionResult Get(){    // ...}

5.3.10.4 IAlwaysRunResultFilter

IAlwaysRunResultFilterIAsyncAlwaysRunResultFilter 接口声明了一个针对所有操作结果运行的 IResultFilter 实现。 这包括由以下对象生成的操作结果:

  • 设置短路的授权筛选器和资源筛选器。
  • 异常筛选器。

详细使用可查看微软官方文档 https://docs.microsoft.com/zh-cn/aspnet/core/mvc/controllers/filters?view=aspnetcore-6.0#ialwaysrunresultfilter-and-iasyncalwaysrunresultfilter

5.3.11 RazorPages 筛选器

Razor Pages 筛选器仅支持 Razor Pages 项目类型。

5.3.11.1 接口定义方式

using Microsoft.AspNetCore.Mvc.Filters;namespace WebApplication1;public class MyPageFilter : IAsyncPageFilter{    /// <summary>    /// 调用方法之前    /// </summary>    /// <param name="context"></param>    /// <param name="next"></param>    /// <returns></returns>    public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)    {        // 路由信息        var routeData = context.RouteData;        // 请求方法信息        var actionDescriptor = context.ActionDescriptor;        // 处理方法信息        var methodDescriptor = context.HandlerMethod;        await next.Invoke();    }    /// <summary>    /// 模型绑定之前    /// </summary>    /// <param name="context"></param>    /// <returns></returns>    public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)    {        return Task.CompletedTask;    }}
  • 全局注册

ConfigureService 中注册,该方式会作用所有 Page Handler

services.Configure<MvcOptions>(options =>{    options.Filters.Add(new MyPageFilter());});

5.3.11.2 ResultFilterAttribute 方式

using Microsoft.AspNetCore.Mvc.Filters;namespace WebApplication1.Filters;public class MyResultAttribute : ResultFilterAttribute{    public override Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)    {        // 代码参考接口方式        return base.OnResultExecutionAsync(context, next);    }}
  • 局部特性方式
[MyResult]public void OnGet(){    // ...}

5.3.12 筛选器取消和短路

通常筛选器支持多个,正常情况下,只要调用 await next() 方法都会进去下一个筛选器,但如果通过 context.Result = new XXXResult() 之后,就可以使其短路,也就是不会再执行下一个筛选器。

但也有例外

  • IResultFilter/IAsyncResultFilter 结果筛选器中,则使用标记 context.Cancel = true; 设置短路。
  • IExceptionFilter/IAsyncExceptionFilter 异常筛选器中,则使用标记 context.ExceptionHandled = true; 设置短路。

5.3.13 筛选器执行顺序控制

默认情况下,筛选器是按照以下执行顺序执行:

5.3.13.1 不同类型筛选器执行顺序

IAuthorizationFilter -> IResourceFilter -> IActionFilter -> IExceptionFilter -> IResultFilter -> IAlwaysRunResultFilter

异步也是如此。

5.3.13.2 相同类型筛选器执行顺序

默认情况下,通过 services.Configure<MvcOptions>(...) 方式先注册先执行,之后到特性方式,也是采用先注册先执行。

如果使用同一种方式,如 services.Configuration<MvcOptions>(...) 或同一种特性方式,也可以控制其执行顺序,如:

  • IOrderedFilter 方式:
public class MyActionFilter : IAsyncActionFilter, IOrderedFilter{    // 值越大,越优先执行    public int Order => 1000;    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)    {        // ....    }}
  • 特性 方式:
[MyActionFilter(Order = 1000)]public class ControllerFiltersController : Controller{    // ...}

5.3.4 筛选器依赖注入

筛选器是支持构造函数依赖注入服务的,使用它们的前提是在 Startup.cs 中注册,如:

Startup.cs
services.AddScoped<MyActionFilterAttribute>();

5.3.15 了解更多

想了解更多筛选器知识可查阅官方文档 https://docs.microsoft.com/zh-cn/aspnet/core/mvc/controllers/filters?view=aspnetcore-6.0

5.3.16 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/friendly-exception/index.html b/handbook/build/docs/friendly-exception/index.html index b3f1ba3c6e..b92275fece 100644 --- a/handbook/build/docs/friendly-exception/index.html +++ b/handbook/build/docs/friendly-exception/index.html @@ -2,22 +2,21 @@ - - - + +7. 友好异常处理 | Furion -7. 友好异常处理 | Furion - - + + +
-

7. 友好异常处理

7.1 什么是异常

异常一般是指运行期(此处特指 Exception 类)会发生的导致程序意外中止的问题,是一种对问题的描述后的封装对象。

在过去开发中,通常异常由系统运行时出错抛出,但现在的开发过程中,我们应在程序开发中合理的抛出异常,比如更新一条不存在的实体,或查询一个不存在的数据等等。

7.2 处理异常方式

  • 不处理,直接中断程序执行(不推荐)
  • 通过 try catch finally 处理(不推荐)
  • 全局统一处理,并记录异常信息(推荐)
  • 异常注解方式处理,支持本地化 (推荐)

7.3 什么是友好异常处理

7.3.1 非友好异常处理

在了解友好异常处理之前可以看看非友好异常处理:

  • 对终端用户抛出 500状态码 堆栈信息
  • 大量的 try catch 代码,污染正常业务逻辑
  • 没有规范化的异常状态码和异常消息管理
  • 没有异常日志收集记录
  • 不支持异常消息本地化处理
  • 不支持异常策略,失败后程序立即终止
  • 不支持分布式事务 CAP
  • 不支持异常传播
  • 返回的异常格式杂乱

7.3.2 友好异常处理

  • 对终端用户提示友好
  • 对后端开发人员提供详细的异常堆栈
  • 不干扰正常业务逻辑代码,如 没有 try catch 代码
  • 支持异常状态码多方设置
  • 支持异常消息本地化
  • 异常信息统一配置管理
  • 支持异常策略,如重试
  • 支持异常日志收集记录
  • 支持 CAP 分布式事务关联
  • 支持内部异常外部传播
  • 支持返回统一的异常格式数据

7.4 友好异常处理使用示例

Furion 框架提供了非常灵活的友好异常处理方式。

备注

.AddFriendlyException() 默认已经集成在 AddInject() 中了,无需再次注册。也就是 7.4.1 章节可不配置。

7.4.1 注册友好异常服务

Furion.Web.Core\FurWebCoreStartup.cs
using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Core{    [AppStartup(800)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddControllers()                    .AddFriendlyException();        }    }}
特别注意

.AddFriendlyException() 需在 services.AddControllers() 之后注册。

7.4.2 两个例子

简单抛个异常

using Furion.DynamicApiController;using Furion.FriendlyException;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public int Get(int id)        {            if (id < 3)            {                throw Oops.Oh($"{id} 不能小于3");            }            return id;        }    }}

如下图所示:

抛出特定类型异常

using Furion.DynamicApiController;using Furion.FriendlyException;using System;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public int Get(int id)        {            if (id < 3)            {                throw Oops.Oh($"{id} 不能小于3。", typeof(InvalidOperationException));            }            return id;        }    }}

如下图所示:

7.5 关于 Oops.Oh

通过上面的例子可以看出,Oops.Oh(errorMessage) 可以结合 throw 抛出异常。对于熟悉C#的人员来说,throw 后面只能 Exception 实例。Oops.Oh(...) 方法返回正是 Exception 实例。

7.5.1 为什么起这个名字?

这个名字来源于一个英语句子:Oh, Oops!,意思是 噢(哎),出错了!,所以就有了 Oops.Oh

7.5.2 Oops.Oh 重载方法

using System;namespace Furion.FriendlyException{    public static class Oops    {        /// <summary>        /// 抛出字符串异常        /// </summary>        /// <param name="errorMessage">异常消息</param>        /// <param name="args">String.Format 参数</param>        /// <returns>异常实例</returns>        public static Exception Oh(string errorMessage, params object[] args);        /// <summary>        /// 抛出字符串异常        /// </summary>        /// <param name="errorMessage">异常消息</param>        /// <param name="exceptionType">具体异常类型</param>        /// <param name="args">String.Format 参数</param>        /// <returns>异常实例</returns>        public static Exception Oh(string errorMessage, Type exceptionType, params object[] args);        /// <summary>        /// 抛出错误码异常        /// </summary>        /// <param name="errorCode">错误码</param>        /// <param name="args">String.Format 参数</param>        /// <returns>异常实例</returns>        public static Exception Oh(object errorCode, params object[] args);        /// <summary>        /// 抛出错误码异常        /// </summary>        /// <param name="errorCode">错误码</param>        /// <param name="exceptionType">具体异常类型</param>        /// <param name="args">String.Format 参数</param>        /// <returns>异常实例</returns>        public static Exception Oh(object errorCode, Type exceptionType, params object[] args);    }}

7.6 最佳实践 🤗

Furion 框架中,提供了非常灵活且规范化的友好异常处理方式,通过这个方式可以方便管理异常状态码、异常信息及异常本地化。

7.6.1 创建异常信息类型

实现自定义异常信息类型必须遵循以下配置:

  • 类型必须是公开且是 Enum 枚举类型
  • 枚举类型必须贴有 [ErrorCodeType] 特性
  • 枚举中每一项必须贴有 [ErrorCodeItemMetadata] 特性
using Furion.FriendlyException;namespace Furion.Application{    [ErrorCodeType]    public enum ErrorCodes    {        [ErrorCodeItemMetadata("{0} 不能小于 {1}")]        z1000,        [ErrorCodeItemMetadata("数据不存在")]        x1000,        [ErrorCodeItemMetadata("{0} 发现 {1} 个异常", "百小僧", 2)]        x1001,        [ErrorCodeItemMetadata("服务器运行异常", ErrorCode = "Error")]        SERVER_ERROR    }}
info

Furion 框架提供了 [ErrorCodeType] 特性和 IErrorCodeTypeProvider 提供器接口来提供异常信息扫描,这里用的是 [ErrorCodeType] 特性类。

7.6.2 关于 [ErrorCodeItemMetadata]

Furion 框架提供了[ErrorCodeItemMetadata] 特性用来标识枚举字段异常元数据,该特性支持传入 消息内容格式化参数。最终会使用 String.Format(消息内容,格式化参数) 进行格式化。

如果消息内容中包含格式化占位符但未指定格式化参数,那么会查找异常所在方法是否贴有 [IfException] 特性且含有格式化参数,接着就会查找 Oops.Oh 中指定的 格式化参数

7.6.3 静态异常类使用

using Furion.DynamicApiController;using Furion.FriendlyException;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public int Get(int id)        {            if (id < 3)            {                throw Oops.Oh(ErrorCodes.z1000, id, 3);            }            return id;        }    }}

如下图所示:

7.6.4 异常方法重试

调整说明

v2.17.0+ 版本下面方法请使用 Retry.Invoke() 替代。

Oops.Retry(() => {    // Do.....}, 3, 1000);// 带返回值var value = Oops.Retry<int>(() => {    // Do.....}, 3, 1000);// 只有特定异常才监听Oops.Retry(() => {}, 3, 1000, typeof(ArgumentNullException));

7.6.5 更多例子

throw Oops.Oh(1000);throw Oops.Oh(ErrorCodes.x1000);throw Oops.Oh("哈哈哈哈");throw Oops.Oh(errorCode: "x1001");throw Oops.Oh(1000, typeof(Exception));throw Oops.Oh(1000).StatusCode(400);    // 设置错误码throw Oops.Oh(1000).WithData(new Model {});    // 设置额外数据throw Oops.Bah("用户名或密码错误"); // 抛出业务异常,状态码为 400throw Oops.Bah(1000);

7.7 多个异常信息类型

using Furion.FriendlyException;namespace Furion.Application{    [ErrorCodeType]    public enum ErrorCodes    {        [ErrorCodeItemMetadata("{0} 不能小于 {1}")]        z1000,        [ErrorCodeItemMetadata("数据不存在")]        x1000,        [ErrorCodeItemMetadata("{0} 发现 {1} 个异常", "百小僧", 2)]        x1001,        [ErrorCodeItemMetadata("服务器运行异常", ErrorCode = "Error")]        SERVER_ERROR    }    [ErrorCodeType]    public enum UserErrorCodes    {        [ErrorCodeItemMetadata("用户数据不存在")]        u1000,        [ErrorCodeItemMetadata("其他异常")]        u1001    }}
特别注意

多个异常静态类中也必须保证常量值唯一性,不可重复。

7.8 IErrorCodeTypeProvider 提供器

Furion 框架中,还提供了 IErrorCodeTypeProvider 异常消息提供器接口,方便在不能贴 [ErrorCodeType] 特性情况下使用:

using Furion.FriendlyException;using System;namespace Furion.Application{    public class CustomErrorCodeTypeProvider : IErrorCodeTypeProvider    {        public Type[] Definitions => new[] {            typeof(ErrorCodes),            typeof(ErrorCodes2)        };    }}

启用 IErrorCodeTypeProvider 提供器:

Furion.Web.Core\FurWebCoreStartup.cs
using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Core{    [AppStartup(800)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddControllers()                    .AddFriendlyException<CustomErrorCodeTypeProvider>();        }    }}
小知识

只有使用 IErrorCodeTypeProvider 方式才需使用泛型方式注册。通过上面的方式注册可以同时支持 IErrorCodeTypeProvider[ErrorCodeType] 方式。

7.9 appsetting.json 中配置

Furion 框架还提供了非常灵活的配置文件配置异常,通过这种方式可以实现异常信息后期配置,也就是无需在开发阶段预先定义。

Furion.Web.Entry/appsettings.json
{  "ErrorCodeMessageSettings": {    "Definitions": [      ["5000", "{0} 不能小于 {1}"],      ["5001", "我叫 {0} 名字", "百小僧"],      ["5002", "Oops! 出错了"]    ]  }}

Definitions 类型为二维数组,二维数组中的每一个数组第一个参数为 ErrorCode 也就是错误码,第二个参数为 ErrorMessage 消息内容,剩余参数作为 ErrorMessage 的格式化参数。

使用示例

using Furion.DynamicApiController;using Furion.FriendlyException;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public int Get(int id)        {            if (id < 3)            {                throw Oops.Oh(5000, id, 3); // 可以将 5000作为常量配置起来            }            return id;        }    }}
小知识

[ErrorCodeType]IErrorCodeTypeProviderappsettings.json 可以同时使用。

7.10 [IfException] 使用

Furion 框架提供了 [IfException] 特性可以覆盖默认消息配置。也就是覆盖 异常消息类型appsettings.json 中的配置。

特别注意

[IfException] 只能贴在方法上,支持多个。

7.10.1 使用示例

  • 异常消息类定义
[ErrorCodeType]public enum ErrorCodes{   [ErrorCodeItemMetadata("{0} 不能小于 {1}")]   z1000}
  • 覆盖默认配置
using Furion.DynamicApiController;using Furion.FriendlyException;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [IfException(ErrorCodes.z1000, ErrorMessage = "我覆盖了默认的:{0} 不能小于 {1}")]        public int Get(int id)        {            if (id < 3)            {                throw Oops.Oh(ErrorCodes.z1000, id, 3);            }            return id;        }    }}

如下图所示:

7.10.2 更多例子

using Furion.DynamicApiController;using Furion.FriendlyException;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [IfException(typeof(ExceptionType), ErrorMessage = "特定异常类型全局拦截")]        [IfException(ErrorMessage = "全局异常拦截")]        [IfException(ErrorCodes.z1000, ErrorMessage = "我覆盖了默认的:{0} 不能小于 {1}")]        [IfException(ErrorCodes.x1001, "格式化参数1", "格式化参数2", ErrorMessage = "我覆盖了默认的:{0} 不能小于 {1}")]        [IfException(ErrorCodes.x1000, "格式化参数1", "格式化参数2")]        [IfException(ErrorCodes.SERVER_ERROR, "格式化参数1", "格式化参数2")]        public int Get(int id)        {            if (id < 3)            {                throw Oops.Oh(ErrorCodes.z1000, id, 3);            }            return id;        }    }}
格式化流程

如果消息内容中包含格式化占位符但未指定格式化参数,那么会查找异常所在方法是否贴有 [IfException] 特性且含有格式化参数,接着就会查找 Oops.Oh 中指定的 格式化参数

7.11 异常消息优先级

[ErrorCodeItemMetadata] -> appsettings.json -> [IfException](低 -> 高)

  • [IfException] 会覆盖 appsettings.json 定义的状态码消息。
  • appsettings.json 会覆盖 [ErrorCodeItemMetadata] 定义的消息。

7.12 多语言支持

参见 【全球化和本地化(多语言)】 章节

7.13 规范化结果异常处理

查看规范化结果文档

如需自定义规范化结果可查阅 【6.7 统一返回值模型

7.14 全局异常处理提供器

通常我们需要在异常捕获的时候写日志,这时候就需要使用到 IGlobalExceptionHandler 异常定义处理程序,如:

using Furion.DependencyInjection;using Furion.FriendlyException;using Microsoft.AspNetCore.Mvc.Filters;using System.Threading.Tasks;namespace Furion.Application{    public class LogExceptionHandler : IGlobalExceptionHandler, ISingleton    {        public Task OnExceptionAsync(ExceptionContext context)        {            // 写日志            return Task.CompletedTask;        }    }}

7.15 FriendlyExceptionSettings 配置

  • HideErrorCode:隐藏错误码,bool 类型,默认 false
  • DefaultErrorCode:默认错误码,string 类型
  • DefaultErrorMessage:默认错误消息,string 类型
  • ThrowBah:是否将 Oops.Oh 默认抛出为业务异常,bool 类型,默认 false,设置 true 之后 Oops.Oh 默认进入 OnValidateFailed 处理,而不是 OnException

配置示例

{  "FriendlyExceptionSettings": {    "DefaultErrorMessage": "系统异常,请联系管理员"  }}

7.16 BadPageResult 错误页

版本说明

以下内容仅限 Furion 3.6.1 + 版本使用。

Furion 在该版本之后内置了 BadPageResult 错误结果类型,该类型派生自 IActionResult,如需返回只需要在 Action 中返回即可。

using Furion.FriendlyException;public IActionResult Add(Person person){    if(!ModelState.IsValid)    {        return new BadPageResult();    }}
  • BadPageResult 更多配置
    • 构造函数 statusCode:状态码,int 类,默认 400
    • Title:页面标题,string 类型,默认 ModelState Invalid
    • Description:页面描述,string 类型,默认 User data verification failed. Please input it correctly.
    • Code:详细错误代码,string 类型,支持 代码,默认空字符串
    • CodeLang:详细错误代码语言,string 类型,默认 json
    • Base64Icon:页面图标,string 类型,带默认值,自定义必须是 base64 格式图标

7.17 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

7. 友好异常处理

7.1 什么是异常

异常一般是指运行期(此处特指 Exception 类)会发生的导致程序意外中止的问题,是一种对问题的描述后的封装对象。

在过去开发中,通常异常由系统运行时出错抛出,但现在的开发过程中,我们应在程序开发中合理的抛出异常,比如更新一条不存在的实体,或查询一个不存在的数据等等。

7.2 处理异常方式

  • 不处理,直接中断程序执行(不推荐)
  • 通过 try catch finally 处理(不推荐)
  • 全局统一处理,并记录异常信息(推荐)
  • 异常注解方式处理,支持本地化 (推荐)

7.3 什么是友好异常处理

7.3.1 非友好异常处理

在了解友好异常处理之前可以看看非友好异常处理:

  • 对终端用户抛出 500状态码 堆栈信息
  • 大量的 try catch 代码,污染正常业务逻辑
  • 没有规范化的异常状态码和异常消息管理
  • 没有异常日志收集记录
  • 不支持异常消息本地化处理
  • 不支持异常策略,失败后程序立即终止
  • 不支持分布式事务 CAP
  • 不支持异常传播
  • 返回的异常格式杂乱

7.3.2 友好异常处理

  • 对终端用户提示友好
  • 对后端开发人员提供详细的异常堆栈
  • 不干扰正常业务逻辑代码,如 没有 try catch 代码
  • 支持异常状态码多方设置
  • 支持异常消息本地化
  • 异常信息统一配置管理
  • 支持异常策略,如重试
  • 支持异常日志收集记录
  • 支持 CAP 分布式事务关联
  • 支持内部异常外部传播
  • 支持返回统一的异常格式数据

7.4 友好异常处理使用示例

Furion 框架提供了非常灵活的友好异常处理方式。

备注

.AddFriendlyException() 默认已经集成在 AddInject() 中了,无需再次注册。也就是 7.4.1 章节可不配置。

7.4.1 注册友好异常服务

Furion.Web.Core\FurWebCoreStartup.cs
using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Core{    [AppStartup(800)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddControllers()                    .AddFriendlyException();        }    }}
特别注意

.AddFriendlyException() 需在 services.AddControllers() 之后注册。

7.4.2 两个例子

简单抛个异常

using Furion.DynamicApiController;using Furion.FriendlyException;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public int Get(int id)        {            if (id < 3)            {                throw Oops.Oh($"{id} 不能小于3");            }            return id;        }    }}

如下图所示:

抛出特定类型异常

using Furion.DynamicApiController;using Furion.FriendlyException;using System;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public int Get(int id)        {            if (id < 3)            {                throw Oops.Oh($"{id} 不能小于3。", typeof(InvalidOperationException));            }            return id;        }    }}

如下图所示:

7.5 关于 Oops.Oh

通过上面的例子可以看出,Oops.Oh(errorMessage) 可以结合 throw 抛出异常。对于熟悉C#的人员来说,throw 后面只能 Exception 实例。Oops.Oh(...) 方法返回正是 Exception 实例。

7.5.1 为什么起这个名字?

这个名字来源于一个英语句子:Oh, Oops!,意思是 噢(哎),出错了!,所以就有了 Oops.Oh

7.5.2 Oops.Oh 重载方法

using System;namespace Furion.FriendlyException{    public static class Oops    {        /// <summary>        /// 抛出字符串异常        /// </summary>        /// <param name="errorMessage">异常消息</param>        /// <param name="args">String.Format 参数</param>        /// <returns>异常实例</returns>        public static Exception Oh(string errorMessage, params object[] args);        /// <summary>        /// 抛出字符串异常        /// </summary>        /// <param name="errorMessage">异常消息</param>        /// <param name="exceptionType">具体异常类型</param>        /// <param name="args">String.Format 参数</param>        /// <returns>异常实例</returns>        public static Exception Oh(string errorMessage, Type exceptionType, params object[] args);        /// <summary>        /// 抛出错误码异常        /// </summary>        /// <param name="errorCode">错误码</param>        /// <param name="args">String.Format 参数</param>        /// <returns>异常实例</returns>        public static Exception Oh(object errorCode, params object[] args);        /// <summary>        /// 抛出错误码异常        /// </summary>        /// <param name="errorCode">错误码</param>        /// <param name="exceptionType">具体异常类型</param>        /// <param name="args">String.Format 参数</param>        /// <returns>异常实例</returns>        public static Exception Oh(object errorCode, Type exceptionType, params object[] args);    }}

7.6 最佳实践 🤗

Furion 框架中,提供了非常灵活且规范化的友好异常处理方式,通过这个方式可以方便管理异常状态码、异常信息及异常本地化。

7.6.1 创建异常信息类型

实现自定义异常信息类型必须遵循以下配置:

  • 类型必须是公开且是 Enum 枚举类型
  • 枚举类型必须贴有 [ErrorCodeType] 特性
  • 枚举中每一项必须贴有 [ErrorCodeItemMetadata] 特性
using Furion.FriendlyException;namespace Furion.Application{    [ErrorCodeType]    public enum ErrorCodes    {        [ErrorCodeItemMetadata("{0} 不能小于 {1}")]        z1000,        [ErrorCodeItemMetadata("数据不存在")]        x1000,        [ErrorCodeItemMetadata("{0} 发现 {1} 个异常", "百小僧", 2)]        x1001,        [ErrorCodeItemMetadata("服务器运行异常", ErrorCode = "Error")]        SERVER_ERROR    }}
info

Furion 框架提供了 [ErrorCodeType] 特性和 IErrorCodeTypeProvider 提供器接口来提供异常信息扫描,这里用的是 [ErrorCodeType] 特性类。

7.6.2 关于 [ErrorCodeItemMetadata]

Furion 框架提供了[ErrorCodeItemMetadata] 特性用来标识枚举字段异常元数据,该特性支持传入 消息内容格式化参数。最终会使用 String.Format(消息内容,格式化参数) 进行格式化。

如果消息内容中包含格式化占位符但未指定格式化参数,那么会查找异常所在方法是否贴有 [IfException] 特性且含有格式化参数,接着就会查找 Oops.Oh 中指定的 格式化参数

7.6.3 静态异常类使用

using Furion.DynamicApiController;using Furion.FriendlyException;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public int Get(int id)        {            if (id < 3)            {                throw Oops.Oh(ErrorCodes.z1000, id, 3);            }            return id;        }    }}

如下图所示:

7.6.4 异常方法重试

调整说明

v2.17.0+ 版本下面方法请使用 Retry.Invoke() 替代。

Oops.Retry(() => {    // Do.....}, 3, 1000);// 带返回值var value = Oops.Retry<int>(() => {    // Do.....}, 3, 1000);// 只有特定异常才监听Oops.Retry(() => {}, 3, 1000, typeof(ArgumentNullException));

7.6.5 更多例子

throw Oops.Oh(1000);throw Oops.Oh(ErrorCodes.x1000);throw Oops.Oh("哈哈哈哈");throw Oops.Oh(errorCode: "x1001");throw Oops.Oh(1000, typeof(Exception));throw Oops.Oh(1000).StatusCode(400);    // 设置错误码throw Oops.Oh(1000).WithData(new Model {});    // 设置额外数据throw Oops.Bah("用户名或密码错误"); // 抛出业务异常,状态码为 400throw Oops.Bah(1000);

7.7 多个异常信息类型

using Furion.FriendlyException;namespace Furion.Application{    [ErrorCodeType]    public enum ErrorCodes    {        [ErrorCodeItemMetadata("{0} 不能小于 {1}")]        z1000,        [ErrorCodeItemMetadata("数据不存在")]        x1000,        [ErrorCodeItemMetadata("{0} 发现 {1} 个异常", "百小僧", 2)]        x1001,        [ErrorCodeItemMetadata("服务器运行异常", ErrorCode = "Error")]        SERVER_ERROR    }    [ErrorCodeType]    public enum UserErrorCodes    {        [ErrorCodeItemMetadata("用户数据不存在")]        u1000,        [ErrorCodeItemMetadata("其他异常")]        u1001    }}
特别注意

多个异常静态类中也必须保证常量值唯一性,不可重复。

7.8 IErrorCodeTypeProvider 提供器

Furion 框架中,还提供了 IErrorCodeTypeProvider 异常消息提供器接口,方便在不能贴 [ErrorCodeType] 特性情况下使用:

using Furion.FriendlyException;using System;namespace Furion.Application{    public class CustomErrorCodeTypeProvider : IErrorCodeTypeProvider    {        public Type[] Definitions => new[] {            typeof(ErrorCodes),            typeof(ErrorCodes2)        };    }}

启用 IErrorCodeTypeProvider 提供器:

Furion.Web.Core\FurWebCoreStartup.cs
using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Core{    [AppStartup(800)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddControllers()                    .AddFriendlyException<CustomErrorCodeTypeProvider>();        }    }}
小知识

只有使用 IErrorCodeTypeProvider 方式才需使用泛型方式注册。通过上面的方式注册可以同时支持 IErrorCodeTypeProvider[ErrorCodeType] 方式。

7.9 appsetting.json 中配置

Furion 框架还提供了非常灵活的配置文件配置异常,通过这种方式可以实现异常信息后期配置,也就是无需在开发阶段预先定义。

Furion.Web.Entry/appsettings.json
{  "ErrorCodeMessageSettings": {    "Definitions": [      ["5000", "{0} 不能小于 {1}"],      ["5001", "我叫 {0} 名字", "百小僧"],      ["5002", "Oops! 出错了"]    ]  }}

Definitions 类型为二维数组,二维数组中的每一个数组第一个参数为 ErrorCode 也就是错误码,第二个参数为 ErrorMessage 消息内容,剩余参数作为 ErrorMessage 的格式化参数。

使用示例

using Furion.DynamicApiController;using Furion.FriendlyException;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public int Get(int id)        {            if (id < 3)            {                throw Oops.Oh(5000, id, 3); // 可以将 5000作为常量配置起来            }            return id;        }    }}
小知识

[ErrorCodeType]IErrorCodeTypeProviderappsettings.json 可以同时使用。

7.10 [IfException] 使用

Furion 框架提供了 [IfException] 特性可以覆盖默认消息配置。也就是覆盖 异常消息类型appsettings.json 中的配置。

特别注意

[IfException] 只能贴在方法上,支持多个。

7.10.1 使用示例

  • 异常消息类定义
[ErrorCodeType]public enum ErrorCodes{   [ErrorCodeItemMetadata("{0} 不能小于 {1}")]   z1000}
  • 覆盖默认配置
using Furion.DynamicApiController;using Furion.FriendlyException;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [IfException(ErrorCodes.z1000, ErrorMessage = "我覆盖了默认的:{0} 不能小于 {1}")]        public int Get(int id)        {            if (id < 3)            {                throw Oops.Oh(ErrorCodes.z1000, id, 3);            }            return id;        }    }}

如下图所示:

7.10.2 更多例子

using Furion.DynamicApiController;using Furion.FriendlyException;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [IfException(typeof(ExceptionType), ErrorMessage = "特定异常类型全局拦截")]        [IfException(ErrorMessage = "全局异常拦截")]        [IfException(ErrorCodes.z1000, ErrorMessage = "我覆盖了默认的:{0} 不能小于 {1}")]        [IfException(ErrorCodes.x1001, "格式化参数1", "格式化参数2", ErrorMessage = "我覆盖了默认的:{0} 不能小于 {1}")]        [IfException(ErrorCodes.x1000, "格式化参数1", "格式化参数2")]        [IfException(ErrorCodes.SERVER_ERROR, "格式化参数1", "格式化参数2")]        public int Get(int id)        {            if (id < 3)            {                throw Oops.Oh(ErrorCodes.z1000, id, 3);            }            return id;        }    }}
格式化流程

如果消息内容中包含格式化占位符但未指定格式化参数,那么会查找异常所在方法是否贴有 [IfException] 特性且含有格式化参数,接着就会查找 Oops.Oh 中指定的 格式化参数

7.11 异常消息优先级

[ErrorCodeItemMetadata] -> appsettings.json -> [IfException](低 -> 高)

  • [IfException] 会覆盖 appsettings.json 定义的状态码消息。
  • appsettings.json 会覆盖 [ErrorCodeItemMetadata] 定义的消息。

7.12 多语言支持

参见 【全球化和本地化(多语言)】 章节

7.13 规范化结果异常处理

查看规范化结果文档

如需自定义规范化结果可查阅 【6.7 统一返回值模型

7.14 全局异常处理提供器

通常我们需要在异常捕获的时候写日志,这时候就需要使用到 IGlobalExceptionHandler 异常定义处理程序,如:

using Furion.DependencyInjection;using Furion.FriendlyException;using Microsoft.AspNetCore.Mvc.Filters;using System.Threading.Tasks;namespace Furion.Application{    public class LogExceptionHandler : IGlobalExceptionHandler, ISingleton    {        public Task OnExceptionAsync(ExceptionContext context)        {            // 写日志            return Task.CompletedTask;        }    }}

7.15 FriendlyExceptionSettings 配置

  • HideErrorCode:隐藏错误码,bool 类型,默认 false
  • DefaultErrorCode:默认错误码,string 类型
  • DefaultErrorMessage:默认错误消息,string 类型
  • ThrowBah:是否将 Oops.Oh 默认抛出为业务异常,bool 类型,默认 false,设置 true 之后 Oops.Oh 默认进入 OnValidateFailed 处理,而不是 OnException
  • LogError:是否输出异常日志,bool 类型,默认 true

配置示例

{  "FriendlyExceptionSettings": {    "DefaultErrorMessage": "系统异常,请联系管理员"  }}

7.16 BadPageResult 错误页

版本说明

以下内容仅限 Furion 3.6.1 + 版本使用。

Furion 在该版本之后内置了 BadPageResult 错误结果类型,该类型派生自 IActionResult,如需返回只需要在 Action 中返回即可。

using Furion.FriendlyException;public IActionResult Add(Person person){    if(!ModelState.IsValid)    {        return new BadPageResult();    }}
  • BadPageResult 更多配置
    • 构造函数 statusCode:状态码,int 类,默认 400
    • Title:页面标题,string 类型,默认 ModelState Invalid
    • Description:页面描述,string 类型,默认 User data verification failed. Please input it correctly.
    • Code:详细错误代码,string 类型,支持 代码,默认空字符串
    • CodeLang:详细错误代码语言,string 类型,默认 json
    • Base64Icon:页面图标,string 类型,带默认值,自定义必须是 base64 格式图标

7.17 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/get-start-net6/index.html b/handbook/build/docs/get-start-net6/index.html index 4b82663dfe..c3e2bfd8b7 100644 --- a/handbook/build/docs/get-start-net6/index.html +++ b/handbook/build/docs/get-start-net6/index.html @@ -2,22 +2,21 @@ - - - + +2.1 ASP.NET 6 集成 | Furion -2.1 ASP.NET 6 集成 | Furion - - + + +
-

2.1 ASP.NET 6 集成

推荐使用脚手架

Furion 官方提供了非常灵活方便的脚手架,可以快速的创建多层架构项目。

推荐使用 《2.2 官方脚手架》代替本章节功能。

入门条件

.NET Core/ASP.NET Core 有一定基础了解,还未接触的可先看 【ASP.NET Core 基础】

2.1 创建 Web 项目

环境要求

使用 Furion 之前先确保安装了最新的 .NET 6 SDK 并安装 Visual Studio 2022 最新版。

2.1.1 创建 ASP.NET Core Web 应用程序

  • 打开 Visual Studio 2022 并创建 Web 项目
  • 配置项目名称
  • 选择 WebAPI 项目
特别注意

Furion 已经内置了 Swagger 规范化库,所以创建时无需勾选 Enable OpenAPI support 选项。否则提示版本不一致产生冲突。

2.2 添加 Furion 依赖包

2.3 Furion 基本配置

2.3.1 Program.cs 添加 Inject()

var builder = WebApplication.CreateBuilder(args).Inject();builder.Services.AddControllers().AddInject();var app = builder.Build();app.UseHttpsRedirection();app.UseAuthorization();app.UseInject();app.MapControllers();app.Run();
小提醒

如果 app.UseInject() 不输入参数,则默认地址为 /api,如果输入 string.Empty 则为 / 目录。如果输入任意字符串,则为 /任意字符串 目录。

2.4 启动浏览器

启动浏览器查看效果。

小知识

默认情况下,通过 Visual Studio 2022 创建的项目会自动配置了启动页,如果使用 F5 运行,可能不会自动打开首页,这时候我们只需要配置 launchSettings.jsonlaunchUrl 即可:

2.5 WebApplication 说明 🎃

.NET6 版本新增了 WebApplication 对象,如果我们需要注册服务,只需要通过 builder.Services.AddXXX() 即可。如:

var builder = WebApplication.CreateBuilder(args).Inject();builder.Services.AddControllers().AddInject();builder.Services.AddRemoteRequest();
演练场
- - +

2.1 ASP.NET 6 集成

推荐使用脚手架

Furion 官方提供了非常灵活方便的脚手架,可以快速的创建多层架构项目。

推荐使用 《2.2 官方脚手架》代替本章节功能。

入门条件

.NET Core/ASP.NET Core 有一定基础了解,还未接触的可先看 【ASP.NET Core 基础】

2.1 创建 Web 项目

环境要求

使用 Furion 之前先确保安装了最新的 .NET 6 SDK 并安装 Visual Studio 2022 最新版。

2.1.1 创建 ASP.NET Core Web 应用程序

  • 打开 Visual Studio 2022 并创建 Web 项目
  • 配置项目名称
  • 选择 WebAPI 项目
特别注意

Furion 已经内置了 Swagger 规范化库,所以创建时无需勾选 Enable OpenAPI support 选项。否则提示版本不一致产生冲突。

2.2 添加 Furion 依赖包

2.3 Furion 基本配置

2.3.1 Program.cs 添加 Inject()

var builder = WebApplication.CreateBuilder(args).Inject();builder.Services.AddControllers().AddInject();var app = builder.Build();app.UseHttpsRedirection();app.UseAuthorization();app.UseInject();app.MapControllers();app.Run();
小提醒

如果 app.UseInject() 不输入参数,则默认地址为 /api,如果输入 string.Empty 则为 / 目录。如果输入任意字符串,则为 /任意字符串 目录。

2.4 启动浏览器

启动浏览器查看效果。

小知识

默认情况下,通过 Visual Studio 2022 创建的项目会自动配置了启动页,如果使用 F5 运行,可能不会自动打开首页,这时候我们只需要配置 launchSettings.jsonlaunchUrl 即可:

2.5 WebApplication 说明 🎃

.NET6 版本新增了 WebApplication 对象,如果我们需要注册服务,只需要通过 builder.Services.AddXXX() 即可。如:

var builder = WebApplication.CreateBuilder(args).Inject();builder.Services.AddControllers().AddInject();builder.Services.AddRemoteRequest();
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/get-start/index.html b/handbook/build/docs/get-start/index.html index 9bd5dbc852..147150598c 100644 --- a/handbook/build/docs/get-start/index.html +++ b/handbook/build/docs/get-start/index.html @@ -2,22 +2,21 @@ - - - + +2.1 ASP.NET 5 集成 | Furion -2.1 ASP.NET 5 集成 | Furion - - + + +
-

2.1 ASP.NET 5 集成

尽快升级

截至 2022 年 05 月 31 日,微软已经停止了 .NET5 的技术支持,所以请尽快升级到 .NET6 版本,详细升级可查阅 【.NET5 升级 .NET6

推荐使用脚手架

Furion 官方提供了非常灵活方便的脚手架,可以快速的创建多层架构项目。

推荐使用 《2.2 官方脚手架》代替本章节功能。

入门条件

.NET Core/ASP.NET Core 有一定基础了解,还未接触的可先看 【ASP.NET Core 基础】

2.1 创建 Web 项目

环境要求

使用 Furion 之前先确保安装了最新的 .NET 5 SDK 并升级 Visual Studio 2019 至最新版。

2.1.1 创建 ASP.NET Core Web 应用程序

  • 打开 Visual Studio 2019 并创建 Web 项目
  • 配置项目名称
  • 选择 WebAPI 项目
特别注意

Furion 已经内置了 Swagger 规范化库,所以创建时无需勾选 Enable OpenAPI support 选项。否则提示版本不一致产生冲突。

2.2 添加 Furion 依赖包

2.3 Furion 基本配置

2.3.1 Program.cs 添加 Inject()

using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.Hosting;namespace FurionStart{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args) =>            Host.CreateDefaultBuilder(args)                .ConfigureWebHostDefaults(webBuilder =>                {                    webBuilder                    .Inject()   // 添加这一行                    .UseStartup<Startup>();                });    }}

2.3.2 在 Startup.cs 中添加两个 Inject()

using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace FurionStart{    public class Startup    {        public Startup(IConfiguration configuration)        {            Configuration = configuration;        }        public IConfiguration Configuration { get; }        public void ConfigureServices(IServiceCollection services)        {            services.AddControllers().AddInject();  // 添加 AddInject();        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            if (env.IsDevelopment())            {                app.UseDeveloperExceptionPage();            }            app.UseHttpsRedirection();            app.UseRouting();            app.UseAuthorization();            // 添加这一行,如果是 MVC和API共存项目,无需添加 string.Empty            app.UseInject(string.Empty);            app.UseEndpoints(endpoints =>            {                endpoints.MapControllers();            });        }    }}
小提醒

如果 app.UseInject() 不输入参数,则默认地址为 /api,如果输入 string.Empty 则为 / 目录。如果输入任意字符串,则为 /任意字符串 目录。

2.4 启动浏览器

启动浏览器查看效果。

小知识

默认情况下,通过 Visual Studio 2019 创建的项目会自动配置了启动页,如果使用 F5 运行,可能不会自动打开首页,这时候我们只需要配置 launchSettings.jsonlaunchUrl 即可:

演练场
- - +

2.1 ASP.NET 5 集成

尽快升级

截至 2022 年 05 月 31 日,微软已经停止了 .NET5 的技术支持,所以请尽快升级到 .NET6 版本,详细升级可查阅 【.NET5 升级 .NET6

推荐使用脚手架

Furion 官方提供了非常灵活方便的脚手架,可以快速的创建多层架构项目。

推荐使用 《2.2 官方脚手架》代替本章节功能。

入门条件

.NET Core/ASP.NET Core 有一定基础了解,还未接触的可先看 【ASP.NET Core 基础】

2.1 创建 Web 项目

环境要求

使用 Furion 之前先确保安装了最新的 .NET 5 SDK 并升级 Visual Studio 2019 至最新版。

2.1.1 创建 ASP.NET Core Web 应用程序

  • 打开 Visual Studio 2019 并创建 Web 项目
  • 配置项目名称
  • 选择 WebAPI 项目
特别注意

Furion 已经内置了 Swagger 规范化库,所以创建时无需勾选 Enable OpenAPI support 选项。否则提示版本不一致产生冲突。

2.2 添加 Furion 依赖包

2.3 Furion 基本配置

2.3.1 Program.cs 添加 Inject()

using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.Hosting;namespace FurionStart{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args) =>            Host.CreateDefaultBuilder(args)                .ConfigureWebHostDefaults(webBuilder =>                {                    webBuilder                    .Inject()   // 添加这一行                    .UseStartup<Startup>();                });    }}

2.3.2 在 Startup.cs 中添加两个 Inject()

using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace FurionStart{    public class Startup    {        public Startup(IConfiguration configuration)        {            Configuration = configuration;        }        public IConfiguration Configuration { get; }        public void ConfigureServices(IServiceCollection services)        {            services.AddControllers().AddInject();  // 添加 AddInject();        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            if (env.IsDevelopment())            {                app.UseDeveloperExceptionPage();            }            app.UseHttpsRedirection();            app.UseRouting();            app.UseAuthorization();            // 添加这一行,如果是 MVC和API共存项目,无需添加 string.Empty            app.UseInject(string.Empty);            app.UseEndpoints(endpoints =>            {                endpoints.MapControllers();            });        }    }}
小提醒

如果 app.UseInject() 不输入参数,则默认地址为 /api,如果输入 string.Empty 则为 / 目录。如果输入任意字符串,则为 /任意字符串 目录。

2.4 启动浏览器

启动浏览器查看效果。

小知识

默认情况下,通过 Visual Studio 2019 创建的项目会自动配置了启动页,如果使用 F5 运行,可能不会自动打开首页,这时候我们只需要配置 launchSettings.jsonlaunchUrl 即可:

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/app/index.html b/handbook/build/docs/global/app/index.html index 1be9eb11b9..b0eb6fdfb3 100644 --- a/handbook/build/docs/global/app/index.html +++ b/handbook/build/docs/global/app/index.html @@ -2,22 +2,21 @@ - - - + +1. App 静态类 | Furion -1. App 静态类 | Furion - - + + +
-

1. App 静态类

1.1 获取全局配置

var settings = App.Settings;

1.2 获取配置对象

// 获取 IConfiguration 对象var configuration = App.Configuration;var value = configuration["xxx:xxx"];// 获取指定节点值并转成 T 类型var data = App.GetConfig<TConfig>("key:key2");// 重载/刷新配置(v2.17+ 版本已移除)App.Configuration.Reload();

1.3 获取环境对象

var webHostEnvironment = App.HostEnvironment;

1.4 获取项目所有程序集

var assemblies = App.Assemblies;

1.5 获取项目所有有效类型

var types = App.EffectiveTypes;

1.6 获取 HttpContext

var httpContext = App.HttpContext;

1.7 获取登录的 User 对象

var contextUser = App.User;// 获取 `Jwt` 存储的信息var userId = App.User?.FindFirstValue("键");

注意引入 System.Security.Claims 命名空间

1.8 获取服务提供器

var serviceProvider = App.ServiceProvider;// 获取根服务,通常用来解析单例和瞬时的,可优化性能var rootService = App.RootServices;

1.9 解析服务

var service = App.GetService<TService>([IServiceProvider]);var service2 = App.GetService(typeof(TService), [IServiceProvider]);var service3 = App.GetRequiredService<TService>([IServiceProvider]);var service4 = App.GetRequiredService(typeof(TService), [IServiceProvider]);

1.10 获取选项配置

var options = App.GetOptions<TOptions>([IServiceProvider]);var options2 = App.GetOptionsMonitor<TOptions>([IServiceProvider]);var options3 = App.GetOptionsSnapshot<TOptions>([IServiceProvider]);

1.11 打印数据到 MiniProfiler

App.PrintToMiniProfiler("分类", "状态", "要打印的消息");

1.12 获取应用名称

var applicationName = App.HostEnvironment.ApplicationName;

1.13 获取启动项目根目录

var webRootPath = App.HostEnvironment.ContentRootPath;

1.14 获取网站根目录 wwwroot 目录

var wwwroot = App.WebHostEnvironment.WebRootPath;

1.15 获取启动项目所在程序集

var webAssembly = Assembly.GetEntryAssembly();

1.16 获取启动项目 bin 目录

var binPath = AppContext.BaseDirectory;

1.17 获取环境变量名

var environmentName = App.HostEnvironment.EnvironmentName;

1.18 判断系统环境

// 判断是否开发环境var isDevelopment = App.HostEnvironment.IsDevelopment();// 判断是否生产环境var isProduction = App.HostEnvironment.IsProduction();// 判断是否 Stage 环境var isStaging = App.HostEnvironment.IsStaging();// 判断是否是特定环境,比如自定义测试环境var isTest = App.HostEnvironment.IsEnvironment("TestEnvironment");

注意,需引用 Microsoft.Extensions.Hosting 命名空间

1.19 获取服务器信息

// 获取系统架构var osArchitecture = RuntimeInformation.OSArchitecture; // => X64// 获取系统名称var osDescription = RuntimeInformation.OSDescription;   // => Windows 10 企业版// 获取进程架构var processArchitecture = RuntimeInformation.ProcessArchitecture;   // => X64// 是否是64位操作系统var is64BitOperatingSystem = Environment.Is64BitOperatingSystem;    // => True

1.20 获取框架底层所有未托管对象

var objs = App.UnmanagedObjects;

1.21 手动释放非托管对象

App.DisposeUnmanagedObjects();  // 通常在非 `Web` 环境中手动处理释放时机

1.22 判断是否是单文件环境

版本说明

以下内容仅限 Furion 3.6.8 + 版本使用。

bool isSingleFileEnviroment = App.SingleFileEnvironment;
演练场
- - +

1. App 静态类

1.1 获取全局配置

var settings = App.Settings;

1.2 获取配置对象

// 获取 IConfiguration 对象var configuration = App.Configuration;var value = configuration["xxx:xxx"];// 获取指定节点值并转成 T 类型var data = App.GetConfig<TConfig>("key:key2");// 重载/刷新配置(v2.17+ 版本已移除)App.Configuration.Reload();

1.3 获取环境对象

var webHostEnvironment = App.HostEnvironment;

1.4 获取项目所有程序集

var assemblies = App.Assemblies;

1.5 获取项目所有有效类型

var types = App.EffectiveTypes;

1.6 获取 HttpContext

var httpContext = App.HttpContext;

1.7 获取登录的 User 对象

var contextUser = App.User;// 获取 `Jwt` 存储的信息var userId = App.User?.FindFirstValue("键");

注意引入 System.Security.Claims 命名空间

1.8 获取服务提供器

var serviceProvider = App.ServiceProvider;// 获取根服务,通常用来解析单例和瞬时的,可优化性能var rootService = App.RootServices;

1.9 解析服务

var service = App.GetService<TService>([IServiceProvider]);var service2 = App.GetService(typeof(TService), [IServiceProvider]);var service3 = App.GetRequiredService<TService>([IServiceProvider]);var service4 = App.GetRequiredService(typeof(TService), [IServiceProvider]);

1.10 获取选项配置

var options = App.GetOptions<TOptions>([IServiceProvider]);var options2 = App.GetOptionsMonitor<TOptions>([IServiceProvider]);var options3 = App.GetOptionsSnapshot<TOptions>([IServiceProvider]);

1.11 打印数据到 MiniProfiler

App.PrintToMiniProfiler("分类", "状态", "要打印的消息");

1.12 获取应用名称

var applicationName = App.HostEnvironment.ApplicationName;

1.13 获取启动项目根目录

var webRootPath = App.HostEnvironment.ContentRootPath;

1.14 获取网站根目录 wwwroot 目录

var wwwroot = App.WebHostEnvironment.WebRootPath;

1.15 获取启动项目所在程序集

var webAssembly = Assembly.GetEntryAssembly();

1.16 获取启动项目 bin 目录

var binPath = AppContext.BaseDirectory;

1.17 获取环境变量名

var environmentName = App.HostEnvironment.EnvironmentName;

1.18 判断系统环境

// 判断是否开发环境var isDevelopment = App.HostEnvironment.IsDevelopment();// 判断是否生产环境var isProduction = App.HostEnvironment.IsProduction();// 判断是否 Stage 环境var isStaging = App.HostEnvironment.IsStaging();// 判断是否是特定环境,比如自定义测试环境var isTest = App.HostEnvironment.IsEnvironment("TestEnvironment");

注意,需引用 Microsoft.Extensions.Hosting 命名空间

1.19 获取服务器信息

// 获取系统架构var osArchitecture = RuntimeInformation.OSArchitecture; // => X64// 获取系统名称var osDescription = RuntimeInformation.OSDescription;   // => Windows 10 企业版// 获取进程架构var processArchitecture = RuntimeInformation.ProcessArchitecture;   // => X64// 是否是64位操作系统var is64BitOperatingSystem = Environment.Is64BitOperatingSystem;    // => True

1.20 获取框架底层所有未托管对象

var objs = App.UnmanagedObjects;

1.21 手动释放非托管对象

App.DisposeUnmanagedObjects();  // 通常在非 `Web` 环境中手动处理释放时机

1.22 判断是否是单文件环境

版本说明

以下内容仅限 Furion 3.6.8 + 版本使用。

bool isSingleFileEnviroment = App.SingleFileEnvironment;
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/datavalidator/index.html b/handbook/build/docs/global/datavalidator/index.html index 6a80f3a69e..80aefacd34 100644 --- a/handbook/build/docs/global/datavalidator/index.html +++ b/handbook/build/docs/global/datavalidator/index.html @@ -2,22 +2,21 @@ - - - + +3. DataValidator 静态类 | Furion -3. DataValidator 静态类 | Furion - - + + +
-

3. DataValidator 静态类

3.1 验证对象数据

var result = DataValidator.TryValidateObject(obj);

3.2 验证单个值

var result = DataValidator.TryValidateValue(value, typeof(RequiredAttribure), typeof(RangeAttribute));

3.3 正则表达式验证单个值

var result = DataValidator.TryValidateValue(value,"正则表达式");

3.4 验证类型验证单个值

var result = DataValidator.TryValidateValue(value, ValidationTypes.Number);var result2 = DataValidator.TryValidateValue(value, ValidationPattern.AllOfThem, ValidationTypes.Number, ValidationTypes.Required);
演练场
- - +

3. DataValidator 静态类

3.1 验证对象数据

var result = DataValidator.TryValidateObject(obj);

3.2 验证单个值

var result = DataValidator.TryValidateValue(value, typeof(RequiredAttribure), typeof(RangeAttribute));

3.3 正则表达式验证单个值

var result = DataValidator.TryValidateValue(value,"正则表达式");

3.4 验证类型验证单个值

var result = DataValidator.TryValidateValue(value, ValidationTypes.Number);var result2 = DataValidator.TryValidateValue(value, ValidationPattern.AllOfThem, ValidationTypes.Number, ValidationTypes.Required);
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/db/index.html b/handbook/build/docs/global/db/index.html index 4066b684f4..488dccaef2 100644 --- a/handbook/build/docs/global/db/index.html +++ b/handbook/build/docs/global/db/index.html @@ -2,22 +2,21 @@ - - - + +2. Db 静态类 | Furion -2. Db 静态类 | Furion - - + + +
-

2. Db 静态类

2.1 获取非泛型仓储

var repository = Db.GetRepository();

2.2 获取泛型仓储

var entityRepository = Db.GetRepository<TEntity>();

2.3 获取带定位器泛型仓储

var locatorRepository = Db.GetRepository<TEntity, TDbContextLocator>();

2.4 获取 Sql 仓储

var sqlRepository = Db.GetSqlRepository();

2.5 获取 Sql 定位器仓储

var sqlLocatorRepository = Db.GetSqlRepository<TDbContextLocator>();

2.6 获取 Sql 代理对象

var sqlProxy= Db.GetSqlProxy<TSqlDispatchProxy>();

2.7 获取默认数据库上下文

var dbContext = Db.GetDbContext();

2.8 获取定位器数据库上下文

var locatorDbContext = Db.GetDbContext<TDbContextLocator>();var locatorDbContext2 = Db.GetDbContext(typeof(TDbContextLocator));

2.9 创建新的默认数据库上下文

var dbContext = Db.GetNewDbContext();

2.10 创建新的定位器数据库上下文

var locatorDbContext = Db.GetNewDbContext<TDbContextLocator>();var locatorDbContext2 = Db.GetNewDbContext(typeof(TDbContextLocator));

2.11 根据定位器类型获取仓储

var repository = Db.GetRepository<TEntity>(dbContextLocatorType);

2.12 获取 主从库 仓储

var msRepository = Db.GetMSRepository();

2.13 获取 Sql 主库定位器仓储

var msLocatorRepository = Db.GetMSRepository<TMasterDbContextLocator>();

2.14 获取特定定位器仓储

var msLocatorRepository = Db.GetDbRepository<TDbContextLocator>();
演练场
- - +

2. Db 静态类

2.1 获取非泛型仓储

var repository = Db.GetRepository();

2.2 获取泛型仓储

var entityRepository = Db.GetRepository<TEntity>();

2.3 获取带定位器泛型仓储

var locatorRepository = Db.GetRepository<TEntity, TDbContextLocator>();

2.4 获取 Sql 仓储

var sqlRepository = Db.GetSqlRepository();

2.5 获取 Sql 定位器仓储

var sqlLocatorRepository = Db.GetSqlRepository<TDbContextLocator>();

2.6 获取 Sql 代理对象

var sqlProxy= Db.GetSqlProxy<TSqlDispatchProxy>();

2.7 获取默认数据库上下文

var dbContext = Db.GetDbContext();

2.8 获取定位器数据库上下文

var locatorDbContext = Db.GetDbContext<TDbContextLocator>();var locatorDbContext2 = Db.GetDbContext(typeof(TDbContextLocator));

2.9 创建新的默认数据库上下文

var dbContext = Db.GetNewDbContext();

2.10 创建新的定位器数据库上下文

var locatorDbContext = Db.GetNewDbContext<TDbContextLocator>();var locatorDbContext2 = Db.GetNewDbContext(typeof(TDbContextLocator));

2.11 根据定位器类型获取仓储

var repository = Db.GetRepository<TEntity>(dbContextLocatorType);

2.12 获取 主从库 仓储

var msRepository = Db.GetMSRepository();

2.13 获取 Sql 主库定位器仓储

var msLocatorRepository = Db.GetMSRepository<TMasterDbContextLocator>();

2.14 获取特定定位器仓储

var msLocatorRepository = Db.GetDbRepository<TDbContextLocator>();
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/fs/index.html b/handbook/build/docs/global/fs/index.html index cc798e468d..b48116cc85 100644 --- a/handbook/build/docs/global/fs/index.html +++ b/handbook/build/docs/global/fs/index.html @@ -2,22 +2,21 @@ - - - + +13. FS 静态类 | Furion -13. FS 静态类 | Furion - - + + +
-

13. FS 静态类

13.1 获取物理文件提供器

var fileProvider = FS.GetPhysicalFileProvider(@"c:/test");

13.2 获取嵌入资源文件提供器

var fileProvider = FS.GetEmbeddedFileProvider(Assembly.GetEntryAssembly());

13.3 获取文件提供器

var fileProvider = FS.GetFileProvider(FileProviderTypes.Physical, @"c:/test");

13.4 特别注意

使用该功能需确保 services.AddVirtualFileServer() 已注册。框架提供两种方式控制该服务注册:

  • AppSettings 配置(推荐方式)
{  "AppSettings": {    "EnabledVirtualFileServer": true  }}

以上配置默认开启,无需配置。

  • `手动注册
services.AddVirtualFileServer();

13.5 获取文件 ContentTypeMime

版本说明

以下内容仅限 Furion 3.3.1 + 版本使用。

var success = FS.TryGetContentType("image.png", out var contentType);  // image/png

13.6 初始化文件 ContentType 提供器

var provider = FS.InitialContentTypeProvider();// 可以在 Startup.cs 中添加静态配置app.UseStaticFiles(new StaticFileOptions {  ContentTypeProvider = provider})
演练场
- - +

13. FS 静态类

13.1 获取物理文件提供器

var fileProvider = FS.GetPhysicalFileProvider(@"c:/test");

13.2 获取嵌入资源文件提供器

var fileProvider = FS.GetEmbeddedFileProvider(Assembly.GetEntryAssembly());

13.3 获取文件提供器

var fileProvider = FS.GetFileProvider(FileProviderTypes.Physical, @"c:/test");

13.4 特别注意

使用该功能需确保 services.AddVirtualFileServer() 已注册。框架提供两种方式控制该服务注册:

  • AppSettings 配置(推荐方式)
{  "AppSettings": {    "EnabledVirtualFileServer": true  }}

以上配置默认开启,无需配置。

  • `手动注册
services.AddVirtualFileServer();

13.5 获取文件 ContentTypeMime

版本说明

以下内容仅限 Furion 3.3.1 + 版本使用。

var success = FS.TryGetContentType("image.png", out var contentType);  // image/png

13.6 初始化文件 ContentType 提供器

var provider = FS.InitialContentTypeProvider();// 可以在 Startup.cs 中添加静态配置app.UseStaticFiles(new StaticFileOptions {  ContentTypeProvider = provider})
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/json/index.html b/handbook/build/docs/global/json/index.html index 14362f75c3..10ed9c6964 100644 --- a/handbook/build/docs/global/json/index.html +++ b/handbook/build/docs/global/json/index.html @@ -2,22 +2,21 @@ - - - + +10. JSON 静态类 | Furion -10. JSON 静态类 | Furion - - + + +
-

10. JSON 静态类

版本说明

以下内容仅限 Furion 1.16.0 + 版本使用。

10.1 获取序列化提供器

var serializer = JSON.GetJsonSerializer();

10.2 序列化

var str = JSON.Serialize(obj, [options]);

10.3 反序列化

var obj = JSON.Deserialize<T>(str, [options]);

10.4 获取全局配置

var options = JSON.GetSerializerOptions<TOption>();
演练场
- - +

10. JSON 静态类

版本说明

以下内容仅限 Furion 1.16.0 + 版本使用。

10.1 获取序列化提供器

var serializer = JSON.GetJsonSerializer();

10.2 序列化

var str = JSON.Serialize(obj, [options]);

10.3 反序列化

var obj = JSON.Deserialize<T>(str, [options]);

10.4 获取全局配置

var options = JSON.GetSerializerOptions<TOption>();
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/jsonserializer/index.html b/handbook/build/docs/global/jsonserializer/index.html index d9a24c79c8..ecfbade751 100644 --- a/handbook/build/docs/global/jsonserializer/index.html +++ b/handbook/build/docs/global/jsonserializer/index.html @@ -2,22 +2,21 @@ - - - + +7. JsonSerializerUtility 静态类 | Furion -7. JsonSerializerUtility 静态类 | Furion - - + + +
-

7. JsonSerializerUtility 静态类

重要声明

以下内容在 Furion 1.16.0 + 版本中已移除。请使用 【23. JSON 序列化章节】

7.1 序列化

var str = JsonSerializerUtility.Serialize(obj, [options]);

7.2 反序列化

var obj = JsonSerializerUtility.Deserialize<T>(str, [options]);

7.3 获取默认序列化配置

var options = JsonSerializerUtility.GetDefaultJsonSerializerOptions();

7.4 设置序列化属性首字母大写

services.AddControllersWithViews()        .AddJsonSerializerPascalPropertyNaming();

7.5 设置时间输出统一格式化

services.AddControllersWithViews()        .AddDateTimeJsonConverter("yyyy-MM-dd HH:mm:ss");
演练场
- - +

7. JsonSerializerUtility 静态类

重要声明

以下内容在 Furion 1.16.0 + 版本中已移除。请使用 【23. JSON 序列化章节】

7.1 序列化

var str = JsonSerializerUtility.Serialize(obj, [options]);

7.2 反序列化

var obj = JsonSerializerUtility.Deserialize<T>(str, [options]);

7.3 获取默认序列化配置

var options = JsonSerializerUtility.GetDefaultJsonSerializerOptions();

7.4 设置序列化属性首字母大写

services.AddControllersWithViews()        .AddJsonSerializerPascalPropertyNaming();

7.5 设置时间输出统一格式化

services.AddControllersWithViews()        .AddDateTimeJsonConverter("yyyy-MM-dd HH:mm:ss");
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/jwt/index.html b/handbook/build/docs/global/jwt/index.html index 42643a0744..8802891df0 100644 --- a/handbook/build/docs/global/jwt/index.html +++ b/handbook/build/docs/global/jwt/index.html @@ -2,22 +2,21 @@ - - - + +14. JWTEncryption 静态类 | Furion -14. JWTEncryption 静态类 | Furion - - + + +
-

14. JWTEncryption 静态类

14.1 生成 Token

// 读取配置信息生成 Tokenvar token = JWTEncryption.Encrypt(new Dictionary<string, object> { { "UserId", 1 }  });// 配置 Token 过期时间var token = JWTEncryption.Encrypt(new Dictionary<string, object> { { "UserId", 1 }  }, 20);// 配置 Token 密钥var token = JWTEncryption.Encrypt("monksoul@outlook.com", new Dictionary<string, object> { { "UserId", 1 }  });// 配置算法var token = JWTEncryption.Encrypt("monksoul@outlook.com", new Dictionary<string, object> { { "UserId", 1 }  }, SecurityAlgorithms.HmacSha256);

14.2 生成刷新 Token

var refreshToken = JWTEncryption.GenerateRefreshToken("token", 43200);

14.3 根据过期 Token 交换新 Token

var newToken = JWTEncryption.Exchange("过期 token", "与之匹配的刷新 token", [新的token过期时间], [容错值]);

14.4 授权处理程序自动刷新 Token

JWTEncryption.AutoRefreshToken(context, httpContext);

14.5 验证 Token 有效性

var (isVaild, tokenInfo) = JWTEncryption.Validate("token");

14.6 验证请求中 Token 有效性

var isValid = JWTEncryption.ValidateJwtBearerToken(httpContext, out tokenInfo);

14.7 读取 Token 信息(不含验证)

var tokenInfo = JWTEncryption.ReadJwtToken("token");// 3.8.2+ 之后支持更强大的读取var securityToken = JWTEncryption.SecurityReadJwtToken("token");
演练场
- - +

14. JWTEncryption 静态类

14.1 生成 Token

// 读取配置信息生成 Tokenvar token = JWTEncryption.Encrypt(new Dictionary<string, object> { { "UserId", 1 }  });// 配置 Token 过期时间var token = JWTEncryption.Encrypt(new Dictionary<string, object> { { "UserId", 1 }  }, 20);// 配置 Token 密钥var token = JWTEncryption.Encrypt("monksoul@outlook.com", new Dictionary<string, object> { { "UserId", 1 }  });// 配置算法var token = JWTEncryption.Encrypt("monksoul@outlook.com", new Dictionary<string, object> { { "UserId", 1 }  }, SecurityAlgorithms.HmacSha256);

14.2 生成刷新 Token

var refreshToken = JWTEncryption.GenerateRefreshToken("token", 43200);

14.3 根据过期 Token 交换新 Token

var newToken = JWTEncryption.Exchange("过期 token", "与之匹配的刷新 token", [新的token过期时间], [容错值]);

14.4 授权处理程序自动刷新 Token

JWTEncryption.AutoRefreshToken(context, httpContext);

14.5 验证 Token 有效性

var (isVaild, tokenInfo) = JWTEncryption.Validate("token");

14.6 验证请求中 Token 有效性

var isValid = JWTEncryption.ValidateJwtBearerToken(httpContext, out tokenInfo);

14.7 读取 Token 信息(不含验证)

var tokenInfo = JWTEncryption.ReadJwtToken("token");// 3.8.2+ 之后支持更强大的读取var securityToken = JWTEncryption.SecurityReadJwtToken("token");
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/l/index.html b/handbook/build/docs/global/l/index.html index 217f32fd58..346cd130e2 100644 --- a/handbook/build/docs/global/l/index.html +++ b/handbook/build/docs/global/l/index.html @@ -2,22 +2,21 @@ - - - + +8. L 静态类 | Furion -8. L 静态类 | Furion - - + + + - - +
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/linqexpression/index.html b/handbook/build/docs/global/linqexpression/index.html index 099109c548..68c22ead6d 100644 --- a/handbook/build/docs/global/linqexpression/index.html +++ b/handbook/build/docs/global/linqexpression/index.html @@ -2,22 +2,21 @@ - - - + +5. LinqExpression 静态类 | Furion -5. LinqExpression 静态类 | Furion - - + + +
-

5. LinqExpression 静态类

5.1 创建一个表达式

var expression = LinqExpression.Create<T>(u => u.Id == 1);var expression2 = LinqExpression.Create<T>((u,i) => u.Id == 1 && i > 0);

5.2 拼接两个表达式

// 创建一个初始化的表达式var expression = LinqExpression.And();var expression2 = LinqExpression.IndexAnd();var expression3 = LinqExpression.Or();var expression4 = LinqExpression.IndexOr();// 拼接表达式var expression5 = expression.And(expression2);var expression6 = expression.AndIf(age > 18, expression2);var expression7 = expression.Or(expression2);var expression8 = expression.OrIf(age > 18, expression2);// 获取表达式属性名var properyName = expression.GetExpressionPropertyName(u => u.Name);    // Name
演练场
- - +

5. LinqExpression 静态类

5.1 创建一个表达式

var expression = LinqExpression.Create<T>(u => u.Id == 1);var expression2 = LinqExpression.Create<T>((u,i) => u.Id == 1 && i > 0);

5.2 拼接两个表达式

// 创建一个初始化的表达式var expression = LinqExpression.And();var expression2 = LinqExpression.IndexAnd();var expression3 = LinqExpression.Or();var expression4 = LinqExpression.IndexOr();// 拼接表达式var expression5 = expression.And(expression2);var expression6 = expression.AndIf(age > 18, expression2);var expression7 = expression.Or(expression2);var expression8 = expression.OrIf(age > 18, expression2);// 获取表达式属性名var properyName = expression.GetExpressionPropertyName(u => u.Name);    // Name
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/messagecenter/index.html b/handbook/build/docs/global/messagecenter/index.html index 27326dae18..dd01145dd4 100644 --- a/handbook/build/docs/global/messagecenter/index.html +++ b/handbook/build/docs/global/messagecenter/index.html @@ -2,22 +2,21 @@ - - - + +9. MessageCenter 静态类 | Furion -9. MessageCenter 静态类 | Furion - - + + +
-

9. MessageCenter 静态类

9.1 动态订阅消息

MessageCenter.Subscribe("messageId", async (ctx) => {    Console.WriteLine("我是动态的");    await Task.CompletedTask;});

9.2 发送消息

await MessageCenter.PublishAsync("messageId", new {});// 诸多重载

9.3 取消订阅

MessageCenter.Unsubscribe("messageId");
演练场
- - +

9. MessageCenter 静态类

9.1 动态订阅消息

MessageCenter.Subscribe("messageId", async (ctx) => {    Console.WriteLine("我是动态的");    await Task.CompletedTask;});

9.2 发送消息

await MessageCenter.PublishAsync("messageId", new {});// 诸多重载

9.3 取消订阅

MessageCenter.Unsubscribe("messageId");
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/oops/index.html b/handbook/build/docs/global/oops/index.html index ebd444794d..87c8374cb1 100644 --- a/handbook/build/docs/global/oops/index.html +++ b/handbook/build/docs/global/oops/index.html @@ -2,22 +2,21 @@ - - - + +4. Oops 静态类 | Furion -4. Oops 静态类 | Furion - - + + +
-

4. Oops 静态类

4.1 抛出字符串异常

throw Oops.Oh("异常消息");throw Oops.Oh("异常消息:{0}", "出错了");

4.2 指定类型的异常

throw Oops.Oh("异常消息", typeof(ArgumentNullException));throw Oops.Oh("异常消息:{0}", typeof(ArgumentNullException), "出错了");

4.3 状态码异常

throw Oops.Oh(1000);throw Oops.Oh(1000, "出错了");

4.4 状态码异常

throw Oops.Oh(1000, typeof(ArgumentNullException));throw Oops.Oh(1000, typeof(ArgumentNullException), "出错了");

4.5 异常方法重试

调整说明

v2.17.0+ 版本下面方法请使用 Retry.Invoke()/Retry.InvokeAsync() 替代。

Oops.Retry(() => {    // Do.....}, 3, 1000);// 带返回值var value = Oops.Retry<int>(() => {    // Do.....}, 3, 1000);// 只有特定异常才监听Oops.Retry(() => {}, 3, 1000, typeof(ArgumentNullException));

4.6 抛出业务异常

throw Oops.Bah("用户名或密码错误");throw Oops.Bah(1000);
演练场
- - +

4. Oops 静态类

4.1 抛出字符串异常

throw Oops.Oh("异常消息");throw Oops.Oh("异常消息:{0}", "出错了");

4.2 指定类型的异常

throw Oops.Oh("异常消息", typeof(ArgumentNullException));throw Oops.Oh("异常消息:{0}", typeof(ArgumentNullException), "出错了");

4.3 状态码异常

throw Oops.Oh(1000);throw Oops.Oh(1000, "出错了");

4.4 状态码异常

throw Oops.Oh(1000, typeof(ArgumentNullException));throw Oops.Oh(1000, typeof(ArgumentNullException), "出错了");

4.5 异常方法重试

调整说明

v2.17.0+ 版本下面方法请使用 Retry.Invoke()/Retry.InvokeAsync() 替代。

Oops.Retry(() => {    // Do.....}, 3, 1000);// 带返回值var value = Oops.Retry<int>(() => {    // Do.....}, 3, 1000);// 只有特定异常才监听Oops.Retry(() => {}, 3, 1000, typeof(ArgumentNullException));

4.6 抛出业务异常

throw Oops.Bah("用户名或密码错误");throw Oops.Bah(1000);
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/scoped/index.html b/handbook/build/docs/global/scoped/index.html index 4bbd834d55..86177baacf 100644 --- a/handbook/build/docs/global/scoped/index.html +++ b/handbook/build/docs/global/scoped/index.html @@ -2,22 +2,21 @@ - - - + +11. Scoped 静态类 | Furion -11. Scoped 静态类 | Furion - - + + +
-

11. Scoped 静态类

11.1 创建一个依赖注入作用域范围

// 同步Scoped.Create((factory, scope) => {     var services = scope.ServiceProvider;});// 异步await Scope.CreateAsync(async (factory, scope) => {     var services = scope.ServiceProvider;     await _calcService.GetAsync();     // ...})
数据库操作注意

如果作用域中对数据库有任何变更操作,需手动调用 SaveChanges 或带 Now 结尾的方法。也可以使用 Scoped.CreateUow(handler) 代替。

11.2 创建一个带工作单元的作用域

// 同步Scoped.CreateUow((factory, scope) => {     var services = scope.ServiceProvider;});// 异步await Scope.CreateUowAsync(await (factory, scope) => {     var services = scope.ServiceProvider;     await _calcService.GetAsync();     // ...});

此方法将在执行完毕之后自动调用 SaveChanges()

11.3 创建一个依赖注入作用域范围(带返回值)

移除声明

Furion v2.18+ 版本移除带返回值的作用域(该方法属于多余操作)

var obj = Scoped.CreateRef<string>((factory, scope) => {     var services = scope.ServiceProvider;     return "返回值";});

11.4 创建一个带工作单元的作用域(带返回值)

移除声明

Furion v2.18+ 版本移除带返回值的作用域(该方法属于多余操作)

var obj = Scoped.CreateUowRef<string>((factory, scope) => {     var services = scope.ServiceProvider;     return "返回值";});
演练场
- - +

11. Scoped 静态类

11.1 创建一个依赖注入作用域范围

// 同步Scoped.Create((factory, scope) => {     var services = scope.ServiceProvider;});// 异步await Scoped.CreateAsync(async (factory, scope) => {     var services = scope.ServiceProvider;     await _calcService.GetAsync();     // ...})
数据库操作注意

如果作用域中对数据库有任何变更操作,需手动调用 SaveChanges 或带 Now 结尾的方法。也可以使用 Scoped.CreateUow(handler) 代替。

11.2 创建一个带工作单元的作用域

// 同步Scoped.CreateUow((factory, scope) => {     var services = scope.ServiceProvider;});// 异步await Scope.CreateUowAsync(await (factory, scope) => {     var services = scope.ServiceProvider;     await _calcService.GetAsync();     // ...});

此方法将在执行完毕之后自动调用 SaveChanges()

11.3 创建一个依赖注入作用域范围(带返回值)

移除声明

Furion v2.18+ 版本移除带返回值的作用域(该方法属于多余操作)

var obj = Scoped.CreateRef<string>((factory, scope) => {     var services = scope.ServiceProvider;     return "返回值";});

11.4 创建一个带工作单元的作用域(带返回值)

移除声明

Furion v2.18+ 版本移除带返回值的作用域(该方法属于多余操作)

var obj = Scoped.CreateUowRef<string>((factory, scope) => {     var services = scope.ServiceProvider;     return "返回值";});
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/shttp/index.html b/handbook/build/docs/global/shttp/index.html index 902d2b7ddc..b883f04702 100644 --- a/handbook/build/docs/global/shttp/index.html +++ b/handbook/build/docs/global/shttp/index.html @@ -2,22 +2,21 @@ - - - + +6. Http 静态类 | Furion -6. Http 静态类 | Furion - - + + + - - +
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/sparetime/index.html b/handbook/build/docs/global/sparetime/index.html index cff27d4c4c..2027c70851 100644 --- a/handbook/build/docs/global/sparetime/index.html +++ b/handbook/build/docs/global/sparetime/index.html @@ -2,22 +2,21 @@ - - - + +12. SpareTime 静态类 | Furion -12. SpareTime 静态类 | Furion - - + + +
-

12. SpareTime 静态类

SpareTime 静态类提供了一些方法方便初始化和管理任务

12.1 初始化任务

// 开启间隔任务SpareTime.Do(interval, [options]);// 开启 Cron 表达式任务SpareTime.Do(expression, [options]);// 只执行一次任务SpareTime.DoOnce(interval, [options]);// 实现自定义任务SpareTime.Do(()=>{    return DateTime.Now.AddMinutes(10);},[options]);

12.2 实现后台执行

// 实现后台执行SpareTime.DoIt(()=>{});

12.3 开始一个任务

SpareTime.Start("任务标识");

12.4 暂停一个任务

SpareTime.Stop("任务标识");// 还可以标记一个任务执行失败SpareTime.Stop("任务标识", true);

12.5 取消一个任务

SpareTime.Cancel("任务名称");

12.6 销毁所有任务

SpareTime.Dispose();

12.7 获取所有任务

var workers = SpareTime.GetWorkers();

12.8 获取单个任务

var worker = SpareTime.GetWorker("workerName");

12.9 解析 Cron 表达式

var nextTime = SpareTime.GetCronNextOccurrence("* * * * *");

12.10 BackgroundService 间隔定时任务

// 间隔执行任务await SpareTime.DoAsync(1000, () =>{    _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);}, stoppingToken);

12.11 BackgroundService Cron 定时任务

 // 执行 Cron 表达式任务await SpareTime.DoAsync("*/5 * * * * *", () =>{    _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);}, stoppingToken, CronFormat.IncludeSeconds);
演练场
- - +

12. SpareTime 静态类

SpareTime 静态类提供了一些方法方便初始化和管理任务

12.1 初始化任务

// 开启间隔任务SpareTime.Do(interval, [options]);// 开启 Cron 表达式任务SpareTime.Do(expression, [options]);// 只执行一次任务SpareTime.DoOnce(interval, [options]);// 实现自定义任务SpareTime.Do(()=>{    return DateTime.Now.AddMinutes(10);},[options]);

12.2 实现后台执行

// 实现后台执行SpareTime.DoIt(()=>{});

12.3 开始一个任务

SpareTime.Start("任务标识");

12.4 暂停一个任务

SpareTime.Stop("任务标识");// 还可以标记一个任务执行失败SpareTime.Stop("任务标识", true);

12.5 取消一个任务

SpareTime.Cancel("任务名称");

12.6 销毁所有任务

SpareTime.Dispose();

12.7 获取所有任务

var workers = SpareTime.GetWorkers();

12.8 获取单个任务

var worker = SpareTime.GetWorker("workerName");

12.9 解析 Cron 表达式

var nextTime = SpareTime.GetCronNextOccurrence("* * * * *");

12.10 BackgroundService 间隔定时任务

// 间隔执行任务await SpareTime.DoAsync(1000, () =>{    _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);}, stoppingToken);

12.11 BackgroundService Cron 定时任务

 // 执行 Cron 表达式任务await SpareTime.DoAsync("*/5 * * * * *", () =>{    _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);}, stoppingToken, CronFormat.IncludeSeconds);
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/global/tp/index.html b/handbook/build/docs/global/tp/index.html index 22d29233ef..3f4c3d0f04 100644 --- a/handbook/build/docs/global/tp/index.html +++ b/handbook/build/docs/global/tp/index.html @@ -2,22 +2,21 @@ - - - + +15. TP 静态类 | Furion -15. TP 静态类 | Furion - - + + +
-

15. TP 静态类

版本说明

以下内容仅限 Furion 3.5.3 + 版本使用。

15.1 生成规范的日志模板

// 生成模板字符串var template = TP.Wrapper("Furion 框架", "让 .NET 开发更简单,更通用,更流行。",    "##作者## 百小僧",    "##当前版本## v3.5.3",    "##文档地址## https://furion.icu",    "##Copyright## 百小僧, Baiqian Co.,Ltd.");Console.WriteLine(template);

日志打印模板如下:

┏━━━━━━━━━━━  Furion 框架 ━━━━━━━━━━━┣ 让 .NET 开发更简单,更通用,更流行。┣ 作者:        百小僧┣ 当前版本:    v3.5.3┣ 文档地址:    https://furion.icu┣ Copyright:   百小僧, Baiqian Co.,Ltd.┗━━━━━━━━━━━  Furion 框架 ━━━━━━━━━━━
关于属性生成

如果列表项以 ##属性名## 开头,自动生成 属性名: 作为行首且自动等宽对齐。

Furion 3.9.1 之前版本使用 [属性名] 开头。

演练场
- - +

15. TP 静态类

版本说明

以下内容仅限 Furion 3.5.3 + 版本使用。

15.1 生成规范的日志模板

// 生成模板字符串var template = TP.Wrapper("Furion 框架", "让 .NET 开发更简单,更通用,更流行。",    "##作者## 百小僧",    "##当前版本## v3.5.3",    "##文档地址## https://furion.icu",    "##Copyright## 百小僧, Baiqian Co.,Ltd.");Console.WriteLine(template);

日志打印模板如下:

┏━━━━━━━━━━━  Furion 框架 ━━━━━━━━━━━┣ 让 .NET 开发更简单,更通用,更流行。┣ 作者:        百小僧┣ 当前版本:    v3.5.3┣ 文档地址:    https://furion.icu┣ Copyright:   百小僧, Baiqian Co.,Ltd.┗━━━━━━━━━━━  Furion 框架 ━━━━━━━━━━━
关于属性生成

如果列表项以 ##属性名## 开头,自动生成 属性名: 作为行首且自动等宽对齐。

Furion 3.9.1 之前版本使用 [属性名] 开头。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/globalusing/index.html b/handbook/build/docs/globalusing/index.html index f7e90fa787..c783d17168 100644 --- a/handbook/build/docs/globalusing/index.html +++ b/handbook/build/docs/globalusing/index.html @@ -2,22 +2,21 @@ - - - + +2.6 GlobalUsing 使用 | Furion -2.6 GlobalUsing 使用 | Furion - - + + +
-

2.6 GlobalUsing 使用

2.6.1 关于 GlobalUsing

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

2.6.2 必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

2.6.3 基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Furion.Logging;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件(注意 20192022 版本)哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

2.6.3.1 默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

2.6.4 .NET5 项目开启支持

默认情况下,.NET5 采用 C# 9.0 编译,而 GlobalUsing 是从 C# 10.0 开始,这时候只需要编辑项目的 .csproj 并添加 <LangVersion>10.0</LangVersion> 即可:

<PropertyGroup>    <TargetFramework>net5.0</TargetFramework>    <LangVersion>10.0</LangVersion>    <!-- 其他配置 --></PropertyGroup>

如需使用最新版可配置为 <LangVersion>latest</LangVersion>

2.6.5 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

2.6 GlobalUsing 使用

2.6.1 关于 GlobalUsing

.NET6/C#10 之后,微软新增了 GlobalUsings 机制,可以在项目的根目录下创建一个 GlobalUsings.cs 文件,把常用的 using 放置其中。

这样 GlobalUsings.cs 所在的项目 .cs 文件就无需重复 using 了,大大的提高开发效率,也让代码变的更加简洁。

2.6.2 必要配置

启用 GlobalUsings 机制需要以下两个步骤:

  1. 在你需要全局 using 的项目层根目录创建 GlobalUsings.cs 文件,如果多个项目层需要,则每个层都应该有一个 GlobalUsings.cs
  2. 编辑项目的 .csproj 文件,添加 <ImplicitUsings>enable</ImplicitUsings>,注意是在 <PropertyGroup> 中添加,通常和 <TargetFramework> 同父同级

2.6.3 基本使用

配置之后,现在就可以把常用的 using 放到 GlobalUsings.cs 中了,写法如下:

Furion 推荐的全局命名空间
global using Furion;global using Furion.DatabaseAccessor;global using Furion.DataEncryption;global using Furion.DataValidation;global using Furion.DependencyInjection;global using Furion.DynamicApiController;global using Furion.Extensions;global using Furion.FriendlyException;global using Furion.Logging;global using Mapster;global using Microsoft.AspNetCore.Authorization;global using Microsoft.AspNetCore.Http;global using Microsoft.AspNetCore.Mvc;global using Microsoft.CodeAnalysis;global using Microsoft.EntityFrameworkCore;global using System.ComponentModel.DataAnnotations;

注意必须以 global 开头!

小知识

一般推荐把实体类的命名空间也放进去,因为仓储 IRepository<T> 使用的频率非常高。

另外推荐大家在 Visual Studio 中安装 CodeMaid 插件(注意 20192022 版本)哦,自动清理解决方案所有无用的 using,结合 GlobalUsings.cs 非常棒!

个别情况

可能由于 Visual Studio 版本的问题,导致 GlobalUsings.cs 定义出错,这时候需要在 using 后面加 global::,如:

global using global::Furion;

接下来在代码中使用:

// 无需 using Furion 的命名空间了哦,清爽了不少namespace Your.Application;public class DefaultAppService : IDynamicApiController{    private readonly IRepository<BoardCard> _boardCardRepository;    private readonly IRepository<BoardGroup> _boardGroupRepository;    private readonly IRepository<BoardCardAttachment> _boardCardAttachmentRepository;    private readonly IRepository<BoardCardUser> _boardCardUserRepository;}// ....

2.6.3.1 默认全局 using

实际上微软已经自动把一些常用的 using 在编译后的代码中自动补上了,路径在 项目/obj/Debug/net6.0/项目.GlobalUsings.cs 文件中,文件内容如下:

// <auto-generated/>global using global::System;global using global::System.Collections.Generic;global using global::System.IO;global using global::System.Linq;global using global::System.Net.Http;global using global::System.Threading;global using global::System.Threading.Tasks;

也就是以上的 using 无需写在你创建的 GlobalUsings.cs 中了,微软会在编译时自动合并。

2.6.4 .NET5 项目开启支持

默认情况下,.NET5 采用 C# 9.0 编译,而 GlobalUsing 是从 C# 10.0 开始,这时候只需要编辑项目的 .csproj 并添加 <LangVersion>10.0</LangVersion> 即可:

<PropertyGroup>    <TargetFramework>net5.0</TargetFramework>    <LangVersion>10.0</LangVersion>    <!-- 其他配置 --></PropertyGroup>

如需使用最新版可配置为 <LangVersion>latest</LangVersion>

2.6.5 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/http/index.html b/handbook/build/docs/http/index.html index 30e4d07a9a..82832fe6aa 100644 --- a/handbook/build/docs/http/index.html +++ b/handbook/build/docs/http/index.html @@ -2,24 +2,23 @@ - - - + +19. 远程请求 | Furion -19. 远程请求 | Furion - - + + +
-

19. 远程请求

版本说明

以下内容仅限 Furion 1.16.0 + 版本使用。

19.1 关于远程请求

在互联网大数据的驱动下,平台或系统免不了需要和第三方进行数据交互,而第三方往往提供了 RESTful API 接口规范,这个时候就需要通过 Http 请求第三方接口进行数据传输交互。

也就是本章节所说的远程请求。

19.2 远程请求的作用

  • 跨系统、跨设备通信
  • 实现多个系统数据传输交互
  • 跨编程语言协同开发

19.3 基础使用

19.3.1 注册服务

使用之前需在 Startup.cs 注册 远程请求服务

public void ConfigureServices(IServiceCollection services){    services.AddRemoteRequest();}

19.3.2 使用方式

Furion 提供两种方式访问发送远程请求。

定义代理请求的 接口 并继承 IHttpDispatchProxy 接口

public interface IHttp : IHttpDispatchProxy{    [Get("https://www.furion.icu/get")]    Task<Result> GetXXXAsync();    [Post("https://www.furion.icu/post")]    Task<Result> PostXXXAsync();    [Put("https://www.furion.icu/put")]    Task<Result> PutXXXAsync();    [Delete("https://www.furion.icu/delete")]    Task<Result> DeleteXXXAsync();    [Patch("https://www.furion.icu/patch")]    Task<Result> PatchXXXAsync();    [Head("https://www.furion.icu/head")]    Task<Result> HeadXXXAsync();}

通过构造函数注入 接口

using Furion.DynamicApiController;using Furion.RemoteRequest.Extensions;namespace Furion.Application{    public class RemoteRequestService : IDynamicApiController    {        private readonly IHttp _http;        public RemoteRequestService(IHttp http)        {            _http = http;        }        public async Task GetData()        {            var data = await _http.GetXXXAsync();        }    }}

19.4 字符串方式使用示例

19.4.1 内置请求方式

// 发送 Get 请求var response = await "https://www.furion.icu/get".GetAsync();// 发送 Post 请求var response = await "https://www.furion.icu/post".PostAsync();// 发送 Put 请求var response = await "https://www.furion.icu/put".PutAsync();// 发送 Delete 请求var response = await "https://www.furion.icu/delete".DeleteAsync();// 发送 Patch 请求var response = await "https://www.furion.icu/patch".PatchAsync();// 发送 Head 请求var response = await "https://www.furion.icu/head".HeadAsync();// 手动指定发送特定请求var response = await "https://www.furion.icu/post".SetHttpMethod(HttpMethod.Post)                                                  .SendAsync();

19.4.2 设置请求地址

// 该方式在 Furion v3.0.0 已移除,多此一举了await "".SetRequestUrl("https://www.furion.icu/");

19.4.3 设置请求方式

await "https://www.furion.icu/post".SetHttpMethod(HttpMethod.Get);

19.4.4 设置地址模板

// 字典方式await "https://www.furion.icu/post/{id}?name={name}&id={p.Id}".SetTemplates(new Dictionary<string , object> {    { "id", 1 },    { "name", "Furion" },    { "p.Id", new Person { Id = 1 } }});// 对象/匿名对象方式await "https://www.furion.icu/post/{id}?name={name}".SetTemplates(new {    id = 1,    name = "Furion"});

注:模板替换区分大小写。

19.4.5 设置请求报文头

// 字典方式await "https://www.furion.icu/post".SetHeaders(new Dictionary<string , object> {    { "Authorization", "Bearer 你的token"},    { "X-Authorization", "Bearer 你的刷新token"}});// 对象/匿名对象方式await "https://www.furion.icu/post".SetHeaders(new {    Authorization = "Bearer 你的token"});

19.4.6 设置 URL 地址参数

// 字典方式await "https://www.furion.icu/get".SetQueries(new Dictionary<string , object> {    { "id", 1 },    { "name", "Furion"}});// 对象/匿名对象方式await "https://www.furion.icu/get".SetQueries(new {    id = 1,    name = "Furion"});

最终输出格式为:https://www.furion.icu/get?id=1&name=Furion

19.4.7 设置请求客户端

  • 全局配置方式
services.AddRemoteRequest(options=>{    // 配置 Github 基本信息    options.AddHttpClient("github", c =>    {        c.BaseAddress = new Uri("https://api.github.com/");        c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");        c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");    });});await "get".SetClient("github");

最终生成请求地址为:https://api.github.com/get

  • 局部配置方式
版本说明

以下内容仅限 Furion 4.3.8 + 版本使用。

await "https://www.furion.icu".SetClient(() => new HttpClient());

19.4.8 设置 Body 参数

// 传入对象await "https://www.furion.icu/api/user/add".SetBody(new User { Id = 1, Name = "Furion" });// 配置 Content-Typeawait "https://www.furion.icu/api/user/add".SetBody(new { Id = 1, Name = "Furion" }, "application/json");// 设置 Encoding 编码await  "https://www.furion.icu/api/user/add".SetBody(new User { Id = 1, Name = "Furion" }, "application/json", Encoding.UTF8);// 处理 application/x-www-form-urlencoded 请求await "https://www.furion.icu/api/user/add".SetBody(new Dictionary<string , object> {    { "Id", 1 },    { "Name", "Furion"}}, "application/x-www-form-urlencoded");// 处理 application/xml、text/xmlawait "https://www.furion.icu/api/user/add".SetBody("<SomeDto><SomeTag>somevalue</SomeTag></SomeDto>", "application/xml");
特别注意

如果请求 Content-Type 设置为 application/x-www-form-urlencoded 类型,那么底层自动将数据进行 UrlEncode 编码处理,无需外部处理。

19.4.9 设置 Content-Type

await "https://www.furion.icu/post".SetContentType("application/json");

19.4.10 设置内容编码

await "https://www.furion.icu/post".SetContentEncoding(Encoding.UTF8);

19.4.11 设置 JSON 序列化提供程序

Furion 默认情况下采用 System.Text.Json 进行 JSON 序列化处理,如需设置第三方 JSON 提供器,则可以通过以下配置:

// 泛型方式await "https://www.furion.icu/api/user/add".SetJsonSerialization<NewtonsoftJsonSerializerProvider>();// 非泛型方式await "https://www.furion.icu/api/user/add".SetJsonSerialization(typeof(NewtonsoftJsonSerializerProvider));// 添加更多配置await "https://www.furion.icu/api/user/add".SetJsonSerialization<NewtonsoftJsonSerializerProvider>(new JsonSerializerSettings {});
关于 JSON 序列化提供器

如需了解更多 JSON 序列化知识可查阅 23. JSON 序列化 章节

19.4.12 启用 Body 参数验证

await "https://www.furion.icu/api/user/add".SetValidationState();// 设置不验证 null 值await "https://www.furion.icu/api/user/add".SetValidationState(includeNull: true);

支持类中 [Required] 等完整模型验证特性。

19.4.13 请求拦截

await "https://www.furion.icu/".OnRequesting((client, req) => {    // req 为 HttpRequestMessage 对象    // 追加更多参数    req.AppendQueries(new Dictionary<string, object> {        { "access_token", "xxxx"}    });});

支持多次拦截

19.4.14 HttpClient 拦截

await "https://www.furion.icu/".OnClientCreating(client => {    // client 为 HttpClient 对象    client.Timeout = 30000; // 设置超时时间});

支持多次拦截

19.4.15 请求之前拦截

await "https://www.furion.icu/".OnRequesting((client, req) => {    // req 为 HttpRequestMessage 对象});

支持多次拦截

19.4.16 成功请求拦截

await "https://www.furion.icu/".OnResponsing((client, res) => {    // res 为 HttpResponseMessage 对象});

支持多次拦截

19.4.17 请求异常拦截

await "https://www.furion.icu/".OnException((client, res, errors) => {    // res 为 HttpResponseMessage 对象});

支持多次拦截

19.4.18 各种返回值处理

Furion 远程请求默认提供四种返回值类型:

  • HttpResponseMessage:请求响应消息类型
  • Stream:流类型
  • T:泛型 T 类型
  • String:字符串类型,也就是直接将网络请求结果内容字符串化
  • Byte[]:字节数组类型

如:

// HttpResponseMessagevar res = await "https://www.furion.icu/".GetAsync();// Streamvar stream = await "https://www.furion.icu/".GetAsStreamAsync();// Tvar user = await "https://www.furion.icu/".GetAsAsync<User>();// Stringvar str = await "https://www.baidu.com".GetAsStringAsync();

19.4.19 设置 Byte[] 类型/上传文件

有时候我们需要上传文件,需要设置 Content-Typemultipart/form-data 类型,如:

// bytes 可以通过 File.ReadAllBytes(文件路径) 获取var res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")                                               .SetBodyBytes(("键", bytes, "文件名")).PostAsync();// 支持多个文件var res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")                                               .SetBodyBytes(("键", bytes, "文件名"),("键", bytes, "文件名")).PostAsync();
关于微信上传接口

如果遇到微信上传出现问题,则可设置 Content-Type 为:application/octet-stream,如:

var result = await $"https://api.weixin.qq.com/wxa/img_sec_check?access_token={token}"                .SetBodyBytes(("media", bytes, Path.GetFileName(imgPath)))                .SetContentType("application/octet-stream")                .PostAsStringAsync();

19.4.20 设置 IServiceProvider

有时候我们需要构建一个作用域的 IServiceProvider,这时只需要设置即可:

var res = await "https://www.furion.icu/upload".SetRequestScoped(services);

19.4.21 设置 Timeout 超时时间

var res = await "https://www.furion.icu/upload".SetClientTimeout(10); // 单位秒

19.4.22 支持模板配置

模板格式为:#(配置路径)

var res = await "#(Furion:Address)/upload".GetAsync();
{  "Furion": {    "Address": "https://www.furion.icu"  }}

19.4.23 重试策略

Furion v2.18+ 版本支持配置重试策略,如:

var res = await "https://www.furion.icu".SetRetryPolicy(3, 1000).GetAsync();

以上代码表示请求失败重试 3 次,每次延迟 1000ms

19.4.24 支持 GZip 压缩

Furion v3.2.0+ 版本支持GZip 压缩,如:

var res = await "https://www.furion.icu".WithGZip().GetAsync();

19.4.25 设置 Url 转码

过去版本会对所有的 Url 进行 Uri.EscapeDataString 转码,在 Furion v3.8.0+ 版本支持 Url 转码设置,如:

var res = await "https://www.furion.icu".WithEncodeUrl(false).GetAsync();

19.5 IHttpDispatchProxy 代理方式

19.5.1 支持多种代理方式

public interface IHttp : IHttpDispatchProxy{    // 发送 Get 请求    [Get("https://www.furion.icu/get")]    Task<HttpResponseMessage> GetXXXAsync();    // 发送 Post 请求    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync();    // 发送 Put 请求    [Put("https://www.furion.icu/put")]    Task<HttpResponseMessage> PutXXXAsync();    // 发送 Delete 请求    [Delete("https://www.furion.icu/delete")]    Task<HttpResponseMessage> DeleteXXXAsync();    // 发送 Patch 请求    [Patch("https://www.furion.icu/patch")]    Task<HttpResponseMessage> PatchXXXAsync();    // 发送 Head 请求    [Head("https://www.furion.icu/head")]    Task<HttpResponseMessage> HeadXXXAsync();}

19.5.2 设置地址模板

public interface IHttp : IHttpDispatchProxy{    [Get("https://www.furion.icu/get/{id}?name={name}&number={p.PersonDetail.PhonNumber}")]    Task<HttpResponseMessage> GetXXXAsync(int id, string name, Person p);}

注:模板替换区分大小写。

19.5.3 设置请求报文头

Furion 框架远程请求代理模式提供三种方式设置请求报文头:

  • 支持在接口中声明
  • 支持在方法中声明
  • 支持在参数中声明
[Headers("key","value")][Headers("key1","value2")] // 设置多个public interface IHttp : IHttpDispatchProxy{    [Get("https://www.furion.icu/get/{id}?name={name}"), Headers("key2","value2")]    Task<HttpResponseMessage> GetXXXAsync(int id, string name);    [Get("https://www.furion.icu")]    Task<HttpResponseMessage> GetXXX2Async(int id, [Headers]string token = default);    [Get("https://www.furion.icu")]    Task<HttpResponseMessage> GetXXX2Async(int id, string name, [Headers("别名")]string token = default);}

19.5.4 设置 URL 地址参数

public interface IHttp : IHttpDispatchProxy{    [Get("https://www.furion.icu/get/{id}?name={name}")]    Task<HttpResponseMessage> GetXXXAsync(int id, string name);    [Get("https://www.furion.icu/get/{p.Id}?name={p.Name}")]    Task<HttpResponseMessage> GetXXXAsync(Person p);    [Get("https://www.furion.icu/get")]    Task<HttpResponseMessage> GetXXXAsync([QueryString]int id, [QueryString]string name);    [Get("https://www.furion.icu/get")]    Task<HttpResponseMessage> GetXXXAsync([QueryString]int id, [QueryString("别名")]string name);}

最终输出格式为:https://www.furion.icu/get?id=1&name=Furion

19.5.5 设置请求客户端

  • 全局配置方式
services.AddRemoteRequest(options=>{    // 配置 Github 基本信息    options.AddHttpClient("github", c =>    {        c.BaseAddress = new Uri("https://api.github.com/");        c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");        c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");    });});public interface IHttp : IHttpDispatchProxy{    [Get("get"), Client("github")]    Task<HttpResponseMessage> GetXXXAsync();}

最终生成请求地址为:https://api.github.com/get

  • 局部配置方式
版本说明

以下内容仅限 Furion 4.3.8 + 版本使用。

public interface IHttp : IHttpDispatchProxy{    // 局部方式    [Get("get")]    Task<HttpResponseMessage> GetXXXAsync([Interceptor(InterceptorTypes.Initiate)]Func<HttpClient> clientProvider);    // 全局静态方式    [Interceptor(InterceptorTypes.Initiate)]    static HttpClient CreateHttpClient()    {        return new HttpClient(...);    }}

19.5.6 设置 Body 参数

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Body]User user);    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Body("application/x-www-form-urlencoded")]User user);    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Body("application/x-www-form-urlencoded", "UTF-8")]User user);}

19.5.7 设置 JSON 序列化提供程序

Furion 默认情况下采用 System.Text.Json 进行 JSON 序列化处理,如需设置第三方 JSON 提供器,则可以通过以下配置:

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu/post"), JsonSerialization(typeof(NewtonsoftJsonSerializerProvider))]    Task<HttpResponseMessage> PostXXXAsync([Body]User user);    [Post("https://www.furion.icu/post"), JsonSerialization(typeof(NewtonsoftJsonSerializerProvider))]    Task<HttpResponseMessage> PostXXXAsync([Body]User user, [JsonSerializerOptions]object jsonSerializerOptions = default);    /// <summary>    /// 缺省序列化配置    /// </summary>    /// <returns></returns>    [JsonSerializerOptions]    static object GetJsonSerializerOptions()    {        // 这里也可以通过 JSON.GetSerializerOptions<JsonSerializerOptions>() 获取 Startup.cs 中的配置        return new JsonSerializerOptions        {        };    }}

[JsonSerializerOptions] 可以标记参数是一个 JSON 序列化配置参数。

关于 JSON 序列化提供器

如需了解更多 JSON 序列化知识可查阅 23. JSON 序列化 章节

19.5.8 参数验证

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Range(1,10)]int id, [Required, MaxLength(10)]string name);    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Required]User user);  // 对象类型支持属性配置特性验证}

19.5.9 请求拦截

Furion 远程请求代理方式提供两种拦截方式:

  • 接口静态方法拦截
  • 参数标记拦截
public interface IHttp : IHttpDispatchProxy{    // 通过参数拦截    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Request)] Action<HttpClient, HttpRequestMessage> action = default);    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Request)]    static void OnRequesting1(HttpClient client, HttpRequestMessage req)    {        // 追加更多参数        req.AppendQueries(new Dictionary<string, object> {            { "access_token", "xxxx"}        });    }    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Request)]    static void OnRequesting2(HttpClient client, HttpRequestMessage req)    {    }}

支持多次拦截

19.5.10 HttpClient 拦截

Furion 远程请求代理方式提供两种拦截方式:

  • 接口静态方法拦截
  • 参数标记拦截
public interface IHttp : IHttpDispatchProxy{    // 通过参数拦截    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Client)] Action<HttpClient> action = default);    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Client)]    static void onClientCreating1(HttpClient client)    {    }    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Client)]    static void onClientCreating2(HttpClient client)    {    }}

支持多次拦截

19.5.11 请求之前拦截

Furion 远程请求代理方式提供两种拦截方式:

  • 接口静态方法拦截
  • 参数标记拦截
public interface IHttp : IHttpDispatchProxy{    // 通过参数拦截    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Request)] Action<HttpClient, HttpRequestMessage> action = default);    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Request)]    static void OnRequest1(HttpClient client, HttpRequestMessage req)    {    }    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Request)]    static void OnRequest2(HttpClient client, HttpRequestMessage req)    {    }}

支持多次拦截

19.5.12 成功请求拦截

Furion 远程请求代理方式提供两种拦截方式:

  • 接口静态方法拦截
  • 参数标记拦截
public interface IHttp : IHttpDispatchProxy{    // 通过参数拦截    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Response)] Action<HttpClient, HttpResponseMessage> action = default);    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Response)]    static void OnResponsing1(HttpClien client, HttpResponseMessage res)    {    }    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Response)]    static void OnResponsing2(HttpClien client, HttpResponseMessage res)    {    }}

支持多次拦截

19.5.13 请求异常拦截

Furion 远程请求代理方式提供两种拦截方式:

  • 接口静态方法拦截
  • 参数标记拦截
public interface IHttp : IHttpDispatchProxy{    // 通过参数拦截    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Exception)] Action<HttpClient, HttpResponseMessage, string> action = default);    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Exception)]    static void OnException1(HttpClient client, HttpResponseMessage res, string errors)    {    }    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Exception)]    static void OnException2(HttpClient client, HttpResponseMessage res, string errors)    {    }}

支持多次拦截

19.5.14 各种返回值处理

Furion 远程请求默认提供四种返回值类型:

  • HttpResponseMessage:请求响应消息类型
  • Stream:流类型
  • T:泛型 T 类型
  • String:字符串类型,也就是直接将网络请求结果内容字符串化

如:

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync();    [Post("https://www.furion.icu/post")]    Task<Stream> PostXXXAsync();    [Post("https://www.furion.icu/post")]    Task<User> PostXXXAsync();    [Post("https://www.furion.icu/post")]    Task<string> PostXXXAsync();}

19.5.15 设置 Byte[] 类型/上传文件

有时候我们需要上传文件,需要设置 Content-Typemultipart/form-data 类型,如:

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")] // bytes 可以通过 File.ReadAllBytes(文件路径) 获取    Task<HttpResponseMessage> PostXXXAsync([BodyBytes("键","文件名")]Byte[] bytes);    // 支持多个文件    [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")] // bytes 可以通过 File.ReadAllBytes(文件路径) 获取    Task<HttpResponseMessage> PostXXXAsync([BodyBytes("键","文件名")]Byte[] bytes,[BodyBytes("键","文件名")]Byte[] bytes2);}

19.5.16 设置 Timeout 超时时间

[Timeout(1000)]public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu/upload"), Timeout(500)]   // 单位秒    Task<HttpResponseMessage> PostXXXAsync([Body]User user);}

19.5.17 支持模板配置

模板格式为:#(配置路径)

public interface IHttp : IHttpDispatchProxy{    [Post("#(Furion:Address)/upload")]    Task<HttpResponseMessage> PostXXXAsync([Body]User user);}
{  "Furion": {    "Address": "https://www.furion.icu"  }}

方法的优先级高于接口定义的优先级。

19.5.18 重试策略

Furion v2.18+ 版本支持配置重试策略,如:

[RetryPolicy(3, 1000)] // 支持全局public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu"), RetryPolicy(3, 1000)]    // 支持局部    Task<HttpResponseMessage> PostXXXAsync([Body]User user);}

以上代码表示请求失败重试 3 次,每次延迟 1000ms

19.5.19 支持 GZip

Furion v3.2.0+ 版本支持 GZip,如:

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu", WithGZip = true)]    Task<HttpResponseMessage> PostXXXAsync([Body]User user);}

19.5.20 设置 Url 转码

过去版本会对所有的 Url 进行 Uri.EscapeDataString 转码,在 Furion v3.8.0+ 版本支持 Url 转码设置,如:

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu", WithEncodeUrl = false)]    Task<HttpResponseMessage> PostXXXAsync([Body]User user);}

19.6 请求客户端配置

Furion 框架也提供了多个请求客户端配置,可以为多个客户端请求配置默认请求信息,目前支持四种模式进行配置。

19.6.1 Startup.cs 统一配置

services.AddRemoteRequest(options=>{    // 配置默认 HttpClient    options.AddHttpClient(string.Empty, c => {        // 其他配置    });    // 配置特定客户端    options.AddHttpClient("github", c =>    {        c.BaseAddress = new Uri("https://api.github.com/");        c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");        c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");    });})

配置了命名客户端后,每次请求都会自动加上这些配置。

  • 代理请求 使用
[Get("api/getdata"), Client("github")]Task<User> GetData();[Put("api/getdata"), Client("facebook")]Task<User> GetData();
  • 字符串拓展 使用
// 设置请求拦截var response = await "http://47.100.247.61/api/sysdata/categories".SetClient("github").PostAsync();
  • IHttpClientFactory 中使用
public class ValuesController : Controller{    private readonly IHttpClientFactory _httpClientFactory;    public ValuesController(IHttpClientFactory httpClientFactory)    {        _httpClientFactory = httpClientFactory;    }    [HttpGet]    public async Task<ActionResult> Get()    {        var client = _httpClientFactory.CreateClient("github");        string result = await client.GetStringAsync("/");        return Ok(result);    }}

19.6.2 自定义 Client 类方式

我们可以按照一定的规则编写特定服务的请求客户端,如:

public class GitHubClient{    public HttpClient Client { get; private set; }    public GitHubClient(HttpClient httpClient)    {        httpClient.BaseAddress = new Uri("https://api.github.com/");        httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");        httpClient.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");        Client = httpClient;    }}

然后在 Startup.cs 中注册:

services.AddHttpClient<GitHubClient>();

使用如下:

public class ValuesController : Controller{    private readonly GitHubClient _gitHubClient;;    public ValuesController(GitHubClient gitHubClient)    {        _gitHubClient = gitHubClient;    }    [HttpGet]    public async Task<ActionResult> Get()    {        string result = await _gitHubClient.Client.GetStringAsync("/");        return Ok(result);    }}

19.6.3 自定义 Client 类 + 接口方式

我们也可以定义接口,通过接口的提供具体的服务 API 操作,无需手动配置 Url,如上面的 GetStringAsync("/")

public interface IGitHubClient{    Task<string> GetData();}public class GitHubClient : IGitHubClient{    private readonly HttpClient _client;    public GitHubClient(HttpClient httpClient)    {        httpClient.BaseAddress = new Uri("https://api.github.com/");        httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");        httpClient.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");        _client = httpClient;    }    public async Task<string> GetData()    {        return await _client.GetStringAsync("/");    }}

然后在 Startup.cs 中注册:

services.AddHttpClient<IGitHubClient, GitHubClient>();

使用:

public class ValuesController : Controller{    private readonly IGitHubClient _gitHubClient;;    public ValuesController(IGitHubClient gitHubClient)    {        _gitHubClient = gitHubClient;    }    [HttpGet]    public async Task<ActionResult> Get()    {        string result = await _gitHubClient.GetData();        return Ok(result);    }}

19.7 SSL/https 证书配置

有时候我们请求远程接口时会遇到 The SSL connection could not be established, see inner exception. 这样的错误,原因是证书配置不正确问题,下面有几种解决方法。

19.7.1 忽略特定客户端 SSL 证书检查

services.AddRemoteRequest(options=>{    // 默认 HttpClient 在 Furion 框架内部已经配置了该操作    options.AddHttpClient(string.Empty)            .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler            {                ServerCertificateCustomValidationCallback = (_, _, _, _) => true,            });    // 配置特定客户端    options.AddHttpClient("github", c => { /*其他配置*/ })           .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler            {                ServerCertificateCustomValidationCallback = (_, _, _, _) => true,            });});
关于 HttpClientHandlerSocketsHttpHandler

.NET6 之后默认使用 SocketsHttpHandler 作为默认底层网络通信,但比 HttpClientHandler 提供了更多平台无差异的功能,对 HttpClientHandler 的任何设置都会转发到 SocketsHttpHandler 中,如需使用 SocketsHttpHandler 配置可参考:

// 忽略 SSL 不安全检查,或 https 不安全或 https 证书有误options.AddHttpClient(string.Empty)       .ConfigurePrimaryHttpMessageHandler(u => new SocketsHttpHandler        {            SslOptions = new SslClientAuthenticationOptions            {                RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true            }    });

19.7.2 手动指定 SSL 证书

services.AddRemoteRequest(options=>{    // 配置特定客户端    options.AddHttpClient("github", c => { /*其他配置*/ })           .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler           {                // 手动配置证书                ClientCertificateOptions = ClientCertificateOption.Manual,                ClientCertificates = {                    new X509Certificate2("...","..."),                    new X509Certificate2("...","..."),                    new X509Certificate2("...","...")                }            });});

19.7.3 忽略所有客户端证书检查

版本说明

以下内容仅限 Furion v3.6.6+ 版本使用。

services.AddRemoteRequest(options=>{    // 需在所有客户端注册之前注册    options.ApproveAllCerts();});

19.8 关于返回值非 200 时忽略 Http状态

Furion 提供了非常方便的请求并且序列化请求结果 PostAsAsync<T> +

19. 远程请求

版本说明

以下内容仅限 Furion 1.16.0 + 版本使用。

19.1 关于远程请求

在互联网大数据的驱动下,平台或系统免不了需要和第三方进行数据交互,而第三方往往提供了 RESTful API 接口规范,这个时候就需要通过 Http 请求第三方接口进行数据传输交互。

也就是本章节所说的远程请求。

19.2 远程请求的作用

  • 跨系统、跨设备通信
  • 实现多个系统数据传输交互
  • 跨编程语言协同开发

19.3 基础使用

19.3.1 注册服务

使用之前需在 Startup.cs 注册 远程请求服务

public void ConfigureServices(IServiceCollection services){    services.AddRemoteRequest();}

19.3.2 使用方式

Furion 提供两种方式访问发送远程请求。

定义代理请求的 接口 并继承 IHttpDispatchProxy 接口

public interface IHttp : IHttpDispatchProxy{    [Get("https://www.furion.icu/get")]    Task<Result> GetXXXAsync();    [Post("https://www.furion.icu/post")]    Task<Result> PostXXXAsync();    [Put("https://www.furion.icu/put")]    Task<Result> PutXXXAsync();    [Delete("https://www.furion.icu/delete")]    Task<Result> DeleteXXXAsync();    [Patch("https://www.furion.icu/patch")]    Task<Result> PatchXXXAsync();    [Head("https://www.furion.icu/head")]    Task<Result> HeadXXXAsync();}

通过构造函数注入 接口

using Furion.DynamicApiController;using Furion.RemoteRequest.Extensions;namespace Furion.Application{    public class RemoteRequestService : IDynamicApiController    {        private readonly IHttp _http;        public RemoteRequestService(IHttp http)        {            _http = http;        }        public async Task GetData()        {            var data = await _http.GetXXXAsync();        }    }}

19.4 字符串方式使用示例

19.4.1 内置请求方式

// 发送 Get 请求var response = await "https://www.furion.icu/get".GetAsync();// 发送 Post 请求var response = await "https://www.furion.icu/post".PostAsync();// 发送 Put 请求var response = await "https://www.furion.icu/put".PutAsync();// 发送 Delete 请求var response = await "https://www.furion.icu/delete".DeleteAsync();// 发送 Patch 请求var response = await "https://www.furion.icu/patch".PatchAsync();// 发送 Head 请求var response = await "https://www.furion.icu/head".HeadAsync();// 手动指定发送特定请求var response = await "https://www.furion.icu/post".SetHttpMethod(HttpMethod.Post)                                                  .SendAsync();

19.4.2 设置请求地址

// 该方式在 Furion v3.0.0 已移除,多此一举了await "".SetRequestUrl("https://www.furion.icu/");

19.4.3 设置请求方式

await "https://www.furion.icu/post".SetHttpMethod(HttpMethod.Get);

19.4.4 设置地址模板

// 字典方式await "https://www.furion.icu/post/{id}?name={name}&id={p.Id}".SetTemplates(new Dictionary<string , object> {    { "id", 1 },    { "name", "Furion" },    { "p.Id", new Person { Id = 1 } }});// 对象/匿名对象方式await "https://www.furion.icu/post/{id}?name={name}".SetTemplates(new {    id = 1,    name = "Furion"});

注:模板替换区分大小写。

19.4.5 设置请求报文头

// 字典方式await "https://www.furion.icu/post".SetHeaders(new Dictionary<string , object> {    { "Authorization", "Bearer 你的token"},    { "X-Authorization", "Bearer 你的刷新token"}});// 对象/匿名对象方式await "https://www.furion.icu/post".SetHeaders(new {    Authorization = "Bearer 你的token"});

19.4.6 设置 URL 地址参数

// 字典方式await "https://www.furion.icu/get".SetQueries(new Dictionary<string , object> {    { "id", 1 },    { "name", "Furion"}});// 对象/匿名对象方式await "https://www.furion.icu/get".SetQueries(new {    id = 1,    name = "Furion"});

最终输出格式为:https://www.furion.icu/get?id=1&name=Furion

19.4.7 设置请求客户端

  • 全局配置方式
services.AddRemoteRequest(options=>{    // 配置 Github 基本信息    options.AddHttpClient("github", c =>    {        c.BaseAddress = new Uri("https://api.github.com/");        c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");        c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");    });});await "get".SetClient("github");

最终生成请求地址为:https://api.github.com/get

  • 局部配置方式
版本说明

以下内容仅限 Furion 4.3.8 + 版本使用。

await "https://www.furion.icu".SetClient(() => new HttpClient());

19.4.8 设置 Body 参数

// 传入对象await "https://www.furion.icu/api/user/add".SetBody(new User { Id = 1, Name = "Furion" });// 配置 Content-Typeawait "https://www.furion.icu/api/user/add".SetBody(new { Id = 1, Name = "Furion" }, "application/json");// 设置 Encoding 编码await  "https://www.furion.icu/api/user/add".SetBody(new User { Id = 1, Name = "Furion" }, "application/json", Encoding.UTF8);// 处理 application/x-www-form-urlencoded 请求await "https://www.furion.icu/api/user/add".SetBody(new Dictionary<string , object> {    { "Id", 1 },    { "Name", "Furion"}}, "application/x-www-form-urlencoded");// 处理 application/xml、text/xmlawait "https://www.furion.icu/api/user/add".SetBody("<SomeDto><SomeTag>somevalue</SomeTag></SomeDto>", "application/xml");
特别注意

如果请求 Content-Type 设置为 application/x-www-form-urlencoded 类型,那么底层自动将数据进行 UrlEncode 编码处理,无需外部处理。

19.4.9 设置 Content-Type

await "https://www.furion.icu/post".SetContentType("application/json");

19.4.10 设置内容编码

await "https://www.furion.icu/post".SetContentEncoding(Encoding.UTF8);

19.4.11 设置 JSON 序列化提供程序

Furion 默认情况下采用 System.Text.Json 进行 JSON 序列化处理,如需设置第三方 JSON 提供器,则可以通过以下配置:

// 泛型方式await "https://www.furion.icu/api/user/add".SetJsonSerialization<NewtonsoftJsonSerializerProvider>();// 非泛型方式await "https://www.furion.icu/api/user/add".SetJsonSerialization(typeof(NewtonsoftJsonSerializerProvider));// 添加更多配置await "https://www.furion.icu/api/user/add".SetJsonSerialization<NewtonsoftJsonSerializerProvider>(new JsonSerializerSettings {});
关于 JSON 序列化提供器

如需了解更多 JSON 序列化知识可查阅 23. JSON 序列化 章节

19.4.12 启用 Body 参数验证

await "https://www.furion.icu/api/user/add".SetValidationState();// 设置不验证 null 值await "https://www.furion.icu/api/user/add".SetValidationState(includeNull: true);

支持类中 [Required] 等完整模型验证特性。

19.4.13 请求拦截

await "https://www.furion.icu/".OnRequesting((client, req) => {    // req 为 HttpRequestMessage 对象    // 追加更多参数    req.AppendQueries(new Dictionary<string, object> {        { "access_token", "xxxx"}    });});

支持多次拦截

19.4.14 HttpClient 拦截

await "https://www.furion.icu/".OnClientCreating(client => {    // client 为 HttpClient 对象    client.Timeout = 30000; // 设置超时时间});

支持多次拦截

19.4.15 请求之前拦截

await "https://www.furion.icu/".OnRequesting((client, req) => {    // req 为 HttpRequestMessage 对象});

支持多次拦截

19.4.16 成功请求拦截

await "https://www.furion.icu/".OnResponsing((client, res) => {    // res 为 HttpResponseMessage 对象});

支持多次拦截

19.4.17 请求异常拦截

await "https://www.furion.icu/".OnException((client, res, errors) => {    // res 为 HttpResponseMessage 对象});

支持多次拦截

19.4.18 各种返回值处理

Furion 远程请求默认提供四种返回值类型:

  • HttpResponseMessage:请求响应消息类型
  • Stream:流类型
  • T:泛型 T 类型
  • String:字符串类型,也就是直接将网络请求结果内容字符串化
  • Byte[]:字节数组类型

如:

// HttpResponseMessagevar res = await "https://www.furion.icu/".GetAsync();// Streamvar stream = await "https://www.furion.icu/".GetAsStreamAsync();// Tvar user = await "https://www.furion.icu/".GetAsAsync<User>();// Stringvar str = await "https://www.baidu.com".GetAsStringAsync();

19.4.19 设置 Byte[] 类型/上传文件

Furion 4.4.0 以下版本

Furion 4.4.0+ 版本移除了 .SetBodyBytes 方式,原因是拓展性太差,新版本请使用 .SetFiles 方式

有时候我们需要上传文件,需要设置 Content-Typemultipart/form-data 类型,如:

// bytes 可以通过 File.ReadAllBytes(文件路径) 获取var res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")                                               .SetBodyBytes(("键", bytes, "文件名")).PostAsync();// 支持多个文件var res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")                                               .SetBodyBytes(("键", bytes, "文件名"),("键", bytes, "文件名")).PostAsync();
关于微信上传接口

如果遇到微信上传出现问题,则可设置 Content-Type 为:application/octet-stream,如:

var result = await $"https://api.weixin.qq.com/wxa/img_sec_check?access_token={token}"                .SetBodyBytes(("media", bytes, Path.GetFileName(imgPath)))                .SetContentType("application/octet-stream")                .PostAsStringAsync();
Furion 4.4.0+ 版本

如果使用 Furion 4.4.0+ 版本,请使用以下的 .SetFiles 替代 .SetBodyBytes 操作。

// bytes 可以通过 File.ReadAllBytes(文件路径) 获取var res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")                                               .SetFiles(HttpFile.Create("file", bytes, "image.png")).PostAsync();// 支持多个文件var res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")                                               .SetFiles(HttpFile.CreateMultiple("files", (bytes, "image1.png"), (bytes, "image2.png"))).PostAsync();

19.4.20 设置 IServiceProvider

有时候我们需要构建一个作用域的 IServiceProvider,这时只需要设置即可:

var res = await "https://www.furion.icu/upload".SetRequestScoped(services);

19.4.21 设置 Timeout 超时时间

var res = await "https://www.furion.icu/upload".SetClientTimeout(10); // 单位秒

19.4.22 支持模板配置

模板格式为:#(配置路径)

var res = await "#(Furion:Address)/upload".GetAsync();
{  "Furion": {    "Address": "https://www.furion.icu"  }}

19.4.23 重试策略

Furion v2.18+ 版本支持配置重试策略,如:

var res = await "https://www.furion.icu".SetRetryPolicy(3, 1000).GetAsync();

以上代码表示请求失败重试 3 次,每次延迟 1000ms

19.4.24 支持 GZip 压缩

Furion v3.2.0+ 版本支持GZip 压缩,如:

var res = await "https://www.furion.icu".WithGZip().GetAsync();

19.4.25 设置 Url 转码

过去版本会对所有的 Url 进行 Uri.EscapeDataString 转码,在 Furion v3.8.0+ 版本支持 Url 转码设置,如:

var res = await "https://www.furion.icu".WithEncodeUrl(false).GetAsync();

19.5 IHttpDispatchProxy 代理方式

19.5.1 支持多种代理方式

public interface IHttp : IHttpDispatchProxy{    // 发送 Get 请求    [Get("https://www.furion.icu/get")]    Task<HttpResponseMessage> GetXXXAsync();    // 发送 Post 请求    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync();    // 发送 Put 请求    [Put("https://www.furion.icu/put")]    Task<HttpResponseMessage> PutXXXAsync();    // 发送 Delete 请求    [Delete("https://www.furion.icu/delete")]    Task<HttpResponseMessage> DeleteXXXAsync();    // 发送 Patch 请求    [Patch("https://www.furion.icu/patch")]    Task<HttpResponseMessage> PatchXXXAsync();    // 发送 Head 请求    [Head("https://www.furion.icu/head")]    Task<HttpResponseMessage> HeadXXXAsync();}

19.5.2 设置地址模板

public interface IHttp : IHttpDispatchProxy{    [Get("https://www.furion.icu/get/{id}?name={name}&number={p.PersonDetail.PhonNumber}")]    Task<HttpResponseMessage> GetXXXAsync(int id, string name, Person p);}

注:模板替换区分大小写。

19.5.3 设置请求报文头

Furion 框架远程请求代理模式提供三种方式设置请求报文头:

  • 支持在接口中声明
  • 支持在方法中声明
  • 支持在参数中声明
[Headers("key","value")][Headers("key1","value2")] // 设置多个public interface IHttp : IHttpDispatchProxy{    [Get("https://www.furion.icu/get/{id}?name={name}"), Headers("key2","value2")]    Task<HttpResponseMessage> GetXXXAsync(int id, string name);    [Get("https://www.furion.icu")]    Task<HttpResponseMessage> GetXXX2Async(int id, [Headers]string token = default);    [Get("https://www.furion.icu")]    Task<HttpResponseMessage> GetXXX2Async(int id, string name, [Headers("别名")]string token = default);}

19.5.4 设置 URL 地址参数

public interface IHttp : IHttpDispatchProxy{    [Get("https://www.furion.icu/get/{id}?name={name}")]    Task<HttpResponseMessage> GetXXXAsync(int id, string name);    [Get("https://www.furion.icu/get/{p.Id}?name={p.Name}")]    Task<HttpResponseMessage> GetXXXAsync(Person p);    [Get("https://www.furion.icu/get")]    Task<HttpResponseMessage> GetXXXAsync([QueryString]int id, [QueryString]string name);    [Get("https://www.furion.icu/get")]    Task<HttpResponseMessage> GetXXXAsync([QueryString]int id, [QueryString("别名")]string name);}

最终输出格式为:https://www.furion.icu/get?id=1&name=Furion

19.5.5 设置请求客户端

  • 全局配置方式
services.AddRemoteRequest(options=>{    // 配置 Github 基本信息    options.AddHttpClient("github", c =>    {        c.BaseAddress = new Uri("https://api.github.com/");        c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");        c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");    });});public interface IHttp : IHttpDispatchProxy{    [Get("get"), Client("github")]    Task<HttpResponseMessage> GetXXXAsync();}

最终生成请求地址为:https://api.github.com/get

  • 局部配置方式
版本说明

以下内容仅限 Furion 4.3.8 + 版本使用。

public interface IHttp : IHttpDispatchProxy{    // 局部方式    [Get("get")]    Task<HttpResponseMessage> GetXXXAsync([Interceptor(InterceptorTypes.Initiate)]Func<HttpClient> clientProvider);    // 全局静态方式    [Interceptor(InterceptorTypes.Initiate)]    static HttpClient CreateHttpClient()    {        return new HttpClient(...);    }}

19.5.6 设置 Body 参数

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Body]User user);    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Body("application/x-www-form-urlencoded")]User user);    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Body("application/x-www-form-urlencoded", "UTF-8")]User user);}

19.5.7 设置 JSON 序列化提供程序

Furion 默认情况下采用 System.Text.Json 进行 JSON 序列化处理,如需设置第三方 JSON 提供器,则可以通过以下配置:

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu/post"), JsonSerialization(typeof(NewtonsoftJsonSerializerProvider))]    Task<HttpResponseMessage> PostXXXAsync([Body]User user);    [Post("https://www.furion.icu/post"), JsonSerialization(typeof(NewtonsoftJsonSerializerProvider))]    Task<HttpResponseMessage> PostXXXAsync([Body]User user, [JsonSerializerOptions]object jsonSerializerOptions = default);    /// <summary>    /// 缺省序列化配置    /// </summary>    /// <returns></returns>    [JsonSerializerOptions]    static object GetJsonSerializerOptions()    {        // 这里也可以通过 JSON.GetSerializerOptions<JsonSerializerOptions>() 获取 Startup.cs 中的配置        return new JsonSerializerOptions        {        };    }}

[JsonSerializerOptions] 可以标记参数是一个 JSON 序列化配置参数。

关于 JSON 序列化提供器

如需了解更多 JSON 序列化知识可查阅 23. JSON 序列化 章节

19.5.8 参数验证

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Range(1,10)]int id, [Required, MaxLength(10)]string name);    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Required]User user);  // 对象类型支持属性配置特性验证}

19.5.9 请求拦截

Furion 远程请求代理方式提供两种拦截方式:

  • 接口静态方法拦截
  • 参数标记拦截
public interface IHttp : IHttpDispatchProxy{    // 通过参数拦截    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Request)] Action<HttpClient, HttpRequestMessage> action = default);    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Request)]    static void OnRequesting1(HttpClient client, HttpRequestMessage req)    {        // 追加更多参数        req.AppendQueries(new Dictionary<string, object> {            { "access_token", "xxxx"}        });    }    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Request)]    static void OnRequesting2(HttpClient client, HttpRequestMessage req)    {    }}

支持多次拦截

19.5.10 HttpClient 拦截

Furion 远程请求代理方式提供两种拦截方式:

  • 接口静态方法拦截
  • 参数标记拦截
public interface IHttp : IHttpDispatchProxy{    // 通过参数拦截    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Client)] Action<HttpClient> action = default);    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Client)]    static void onClientCreating1(HttpClient client)    {    }    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Client)]    static void onClientCreating2(HttpClient client)    {    }}

支持多次拦截

19.5.11 请求之前拦截

Furion 远程请求代理方式提供两种拦截方式:

  • 接口静态方法拦截
  • 参数标记拦截
public interface IHttp : IHttpDispatchProxy{    // 通过参数拦截    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Request)] Action<HttpClient, HttpRequestMessage> action = default);    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Request)]    static void OnRequest1(HttpClient client, HttpRequestMessage req)    {    }    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Request)]    static void OnRequest2(HttpClient client, HttpRequestMessage req)    {    }}

支持多次拦截

19.5.12 成功请求拦截

Furion 远程请求代理方式提供两种拦截方式:

  • 接口静态方法拦截
  • 参数标记拦截
public interface IHttp : IHttpDispatchProxy{    // 通过参数拦截    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Response)] Action<HttpClient, HttpResponseMessage> action = default);    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Response)]    static void OnResponsing1(HttpClien client, HttpResponseMessage res)    {    }    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Response)]    static void OnResponsing2(HttpClien client, HttpResponseMessage res)    {    }}

支持多次拦截

19.5.13 请求异常拦截

Furion 远程请求代理方式提供两种拦截方式:

  • 接口静态方法拦截
  • 参数标记拦截
public interface IHttp : IHttpDispatchProxy{    // 通过参数拦截    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync([Interceptor(InterceptorTypes.Exception)] Action<HttpClient, HttpResponseMessage, string> action = default);    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Exception)]    static void OnException1(HttpClient client, HttpResponseMessage res, string errors)    {    }    // 全局拦截,类中每一个方法都会触发    [Interceptor(InterceptorTypes.Exception)]    static void OnException2(HttpClient client, HttpResponseMessage res, string errors)    {    }}

支持多次拦截

19.5.14 各种返回值处理

Furion 远程请求默认提供四种返回值类型:

  • HttpResponseMessage:请求响应消息类型
  • Stream:流类型
  • T:泛型 T 类型
  • String:字符串类型,也就是直接将网络请求结果内容字符串化

如:

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu/post")]    Task<HttpResponseMessage> PostXXXAsync();    [Post("https://www.furion.icu/post")]    Task<Stream> PostXXXAsync();    [Post("https://www.furion.icu/post")]    Task<User> PostXXXAsync();    [Post("https://www.furion.icu/post")]    Task<string> PostXXXAsync();}

19.5.15 设置 Byte[] 类型/上传文件

Furion 4.4.0 以下版本

Furion 4.4.0+ 版本移除了 [BodyBytes] 方式,原因是拓展性太差,新版本请使用 HttpFile 方式

有时候我们需要上传文件,需要设置 Content-Typemultipart/form-data 类型,如:

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")] // bytes 可以通过 File.ReadAllBytes(文件路径) 获取    Task<HttpResponseMessage> PostXXXAsync([BodyBytes("键","文件名")]Byte[] bytes);    // 支持多个文件    [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")] // bytes 可以通过 File.ReadAllBytes(文件路径) 获取    Task<HttpResponseMessage> PostXXXAsync([BodyBytes("键","文件名")]Byte[] bytes,[BodyBytes("键","文件名")]Byte[] bytes2);}
Furion 4.4.0+ 版本

如果使用 Furion 4.4.0+ 版本,请使用以下的 HttpFile 替代 [BodyBytes] 操作。

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")]     Task<HttpResponseMessage> PostXXXAsync(HttpFile file);    // 支持多个文件    [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")]     Task<HttpResponseMessage> PostXXXAsync(HttpFile[] files);        // 支持多个文件    [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")]     Task<HttpResponseMessage> PostXXXAsync(IList<HttpFile> files);}

19.5.16 设置 Timeout 超时时间

[Timeout(1000)]public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu/upload"), Timeout(500)]   // 单位秒    Task<HttpResponseMessage> PostXXXAsync([Body]User user);}

19.5.17 支持模板配置

模板格式为:#(配置路径)

public interface IHttp : IHttpDispatchProxy{    [Post("#(Furion:Address)/upload")]    Task<HttpResponseMessage> PostXXXAsync([Body]User user);}
{  "Furion": {    "Address": "https://www.furion.icu"  }}

方法的优先级高于接口定义的优先级。

19.5.18 重试策略

Furion v2.18+ 版本支持配置重试策略,如:

[RetryPolicy(3, 1000)] // 支持全局public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu"), RetryPolicy(3, 1000)]    // 支持局部    Task<HttpResponseMessage> PostXXXAsync([Body]User user);}

以上代码表示请求失败重试 3 次,每次延迟 1000ms

19.5.19 支持 GZip

Furion v3.2.0+ 版本支持 GZip,如:

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu", WithGZip = true)]    Task<HttpResponseMessage> PostXXXAsync([Body]User user);}

19.5.20 设置 Url 转码

过去版本会对所有的 Url 进行 Uri.EscapeDataString 转码,在 Furion v3.8.0+ 版本支持 Url 转码设置,如:

public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu", WithEncodeUrl = false)]    Task<HttpResponseMessage> PostXXXAsync([Body]User user);}

19.6 请求客户端配置

Furion 框架也提供了多个请求客户端配置,可以为多个客户端请求配置默认请求信息,目前支持四种模式进行配置。

19.6.1 Startup.cs 统一配置

services.AddRemoteRequest(options=>{    // 配置默认 HttpClient    options.AddHttpClient(string.Empty, c => {        // 其他配置    });    // 配置特定客户端    options.AddHttpClient("github", c =>    {        c.BaseAddress = new Uri("https://api.github.com/");        c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");        c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");    });})

配置了命名客户端后,每次请求都会自动加上这些配置。

  • 代理请求 使用
[Get("api/getdata"), Client("github")]Task<User> GetData();[Put("api/getdata"), Client("facebook")]Task<User> GetData();
  • 字符串拓展 使用
// 设置请求拦截var response = await "http://47.100.247.61/api/sysdata/categories".SetClient("github").PostAsync();
  • IHttpClientFactory 中使用
public class ValuesController : Controller{    private readonly IHttpClientFactory _httpClientFactory;    public ValuesController(IHttpClientFactory httpClientFactory)    {        _httpClientFactory = httpClientFactory;    }    [HttpGet]    public async Task<ActionResult> Get()    {        var client = _httpClientFactory.CreateClient("github");        string result = await client.GetStringAsync("/");        return Ok(result);    }}

19.6.2 自定义 Client 类方式

我们可以按照一定的规则编写特定服务的请求客户端,如:

public class GitHubClient{    public HttpClient Client { get; private set; }    public GitHubClient(HttpClient httpClient)    {        httpClient.BaseAddress = new Uri("https://api.github.com/");        httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");        httpClient.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");        Client = httpClient;    }}

然后在 Startup.cs 中注册:

services.AddHttpClient<GitHubClient>();

使用如下:

public class ValuesController : Controller{    private readonly GitHubClient _gitHubClient;;    public ValuesController(GitHubClient gitHubClient)    {        _gitHubClient = gitHubClient;    }    [HttpGet]    public async Task<ActionResult> Get()    {        string result = await _gitHubClient.Client.GetStringAsync("/");        return Ok(result);    }}

19.6.3 自定义 Client 类 + 接口方式

我们也可以定义接口,通过接口的提供具体的服务 API 操作,无需手动配置 Url,如上面的 GetStringAsync("/")

public interface IGitHubClient{    Task<string> GetData();}public class GitHubClient : IGitHubClient{    private readonly HttpClient _client;    public GitHubClient(HttpClient httpClient)    {        httpClient.BaseAddress = new Uri("https://api.github.com/");        httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");        httpClient.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");        _client = httpClient;    }    public async Task<string> GetData()    {        return await _client.GetStringAsync("/");    }}

然后在 Startup.cs 中注册:

services.AddHttpClient<IGitHubClient, GitHubClient>();

使用:

public class ValuesController : Controller{    private readonly IGitHubClient _gitHubClient;;    public ValuesController(IGitHubClient gitHubClient)    {        _gitHubClient = gitHubClient;    }    [HttpGet]    public async Task<ActionResult> Get()    {        string result = await _gitHubClient.GetData();        return Ok(result);    }}

19.7 SSL/https 证书配置

有时候我们请求远程接口时会遇到 The SSL connection could not be established, see inner exception. 这样的错误,原因是证书配置不正确问题,下面有几种解决方法。

19.7.1 忽略特定客户端 SSL 证书检查

services.AddRemoteRequest(options=>{    // 默认 HttpClient 在 Furion 框架内部已经配置了该操作    options.AddHttpClient(string.Empty)            .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler            {                ServerCertificateCustomValidationCallback = (_, _, _, _) => true,            });    // 配置特定客户端    options.AddHttpClient("github", c => { /*其他配置*/ })           .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler            {                ServerCertificateCustomValidationCallback = (_, _, _, _) => true,            });});
关于 HttpClientHandlerSocketsHttpHandler

.NET6 之后默认使用 SocketsHttpHandler 作为默认底层网络通信,但比 HttpClientHandler 提供了更多平台无差异的功能,对 HttpClientHandler 的任何设置都会转发到 SocketsHttpHandler 中,如需使用 SocketsHttpHandler 配置可参考:

// 忽略 SSL 不安全检查,或 https 不安全或 https 证书有误options.AddHttpClient(string.Empty)       .ConfigurePrimaryHttpMessageHandler(u => new SocketsHttpHandler        {            SslOptions = new SslClientAuthenticationOptions            {                RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true            }    });

19.7.2 手动指定 SSL 证书

services.AddRemoteRequest(options=>{    // 配置特定客户端    options.AddHttpClient("github", c => { /*其他配置*/ })           .ConfigurePrimaryHttpMessageHandler(u => new HttpClientHandler           {                // 手动配置证书                ClientCertificateOptions = ClientCertificateOption.Manual,                ClientCertificates = {                    new X509Certificate2("...","..."),                    new X509Certificate2("...","..."),                    new X509Certificate2("...","...")                }            });});

19.7.3 忽略所有客户端证书检查

版本说明

以下内容仅限 Furion v3.6.6+ 版本使用。

services.AddRemoteRequest(options=>{    // 需在所有客户端注册之前注册    options.ApproveAllCerts();});

19.8 关于返回值非 200 时忽略 Http状态

Furion 提供了非常方便的请求并且序列化请求结果 PostAsAsync<T>2.8.8 及以下版本,当返回结果的 Http 状态为非 200 时,会直接截断。考虑到请求接口的多样性,在 2.8.9 及以上版本增加忽略返回 Http 状态,直接序列化结果的方式。

//请求并且序列化请求结果var result = await "https://api.facebook.com/"    //如果不加OnException,则会直接截断    .OnException((res,errors)=> {        //激活异步拦截 此处可以做记录日志操作 也可保持现状    })    .PostAsAsync<T>();

PostAsStringAsync() 也使用同样的 OnException 操作使得忽略返回 Http 状态,原样返回 Http 请求结果

特别说明

如果不加 OnException,则会直接截断。 -如果需要复杂的 Http Post 请求,建议直接使用 PostAsync,返回值为 HttpResponseMessage,可以更灵活的控制结果。

19.9 关于同步请求

Furion 框架内部默认不提供同步请求操作,建议总是使用异步的方式请求。如在不能使用异步的情况下,可自行转换为同步执行。

19.10 多线程共享作用域

默认情况下,所有的 字符串实体 拓展都有自己独立维护的 ServiceProvider 作用域。

Web 请求中,默认是 HttpContext.RequestServices,但在 非 Web,如多线程操作,后台任务,事件总线等场景下会自动创建新的作用域,实际上这是非常不必要的内存开销。

这时,我们只需要通过 .SetXXXScoped(service) 共享当前服务提供器作用域即可,如:

Scoped.Create(async (fac, scope) => {   var response = await "https://www.furion.icu".SetRequestScoped(scope.ServiceProvider).PostAsync();});

19.11 静态 Default 方式构建

await HttpRequestPart.Default.SetRequestUrl("https://www.baidu.com").GetAsStringAsync();

19.12 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 HttpClient 知识可查阅 ASP.NET Core - HTTP 请求 章节

演练场
- - +如果需要复杂的 Http Post 请求,建议直接使用 PostAsync,返回值为 HttpResponseMessage,可以更灵活的控制结果。

19.9 关于同步请求

Furion 框架内部默认不提供同步请求操作,建议总是使用异步的方式请求。如在不能使用异步的情况下,可自行转换为同步执行。

19.10 多线程共享作用域

默认情况下,所有的 字符串实体 拓展都有自己独立维护的 ServiceProvider 作用域。

Web 请求中,默认是 HttpContext.RequestServices,但在 非 Web,如多线程操作,后台任务,事件总线等场景下会自动创建新的作用域,实际上这是非常不必要的内存开销。

这时,我们只需要通过 .SetXXXScoped(service) 共享当前服务提供器作用域即可,如:

Scoped.Create(async (fac, scope) => {   var response = await "https://www.furion.icu".SetRequestScoped(scope.ServiceProvider).PostAsync();});

19.11 静态 Default 方式构建

await HttpRequestPart.Default.SetRequestUrl("https://www.baidu.com").GetAsStringAsync();

19.12 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 HttpClient 知识可查阅 ASP.NET Core - HTTP 请求 章节

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/httpcontext/index.html b/handbook/build/docs/httpcontext/index.html index 98f3daac25..3f3f4e0b89 100644 --- a/handbook/build/docs/httpcontext/index.html +++ b/handbook/build/docs/httpcontext/index.html @@ -2,22 +2,21 @@ - - - + +5.2 HttpContext | Furion -5.2 HttpContext | Furion - - + + +
-

5.2 HttpContext

5.2.1 关于 HttpContext

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

5.2.2 获取 HttpContext

ASP.NET CoreFurion 提供了多种访问 HttpContext 的方式。

5.2.2.1 在 ControllerBase 派生类中

ControllerBase 派生类中,我们可以直接通过 HttpContext 属性获取 HttpContext 对象。

public class HomeController : Controller{    public IActionResult Index()    {        // 在这里HttpContext 是 Controller/ControllerBase 对象的属性        var httpContext = HttpContext;        return View();    }}

5.2.2.2 注入 IHttpContextAccessor

Furion 框架中,默认已经注册了 IHttpContextAccessor 服务,所以我们可以通过构造函数注入该接口获取。

public class AppService{    public AppService(IHttpContextAccessor httpContextAccessor)    {        var httpContext = httpContextAccessor.HttpContext;    }}

5.2.2.3 通过 App.HttpContext

App 静态类也提供了 App.HttpContext 获取 HttpContext 对象。

var request = App.HttpContext.Request;
Web 中访问

Web 完整的生命周期内,App.HttpContext 都是有效的,但在非 Web 中返回 null,避免在多线程,事件总线,定时任务等中使用。

5.2.3 HttpContext 拓展方法

Furion 框架基于 HttpContext 提供了一些常用的拓展方法。

5.2.3.1 获取当前请求的特性 Attribute

下列代码通常用于授权 Handler 中。

var attribute = httpContext.GetMetadata<SomeAttribute>();
Middleware 中间件获取特性方式

Middleware 中间件中获取有所区别,主要通过 HttpContextFeatures 获取,如:

var endpointFeature = httpContext.Features.Get<IEndpointFeature>();var attribute =  endpointFeature?.Endpoint?.Metadata?.GetMetadata<SomeAttribute>();

5.2.3.2 设置 Swagger 自动授权

Swagger 默认不能记住授权信息,一旦刷新浏览器就自动清空,所以 Furion 提供了该拓展,即使刷新浏览器也能保持授权状态。

// 检查用户登录和生成 token 代码...// .....// 之后调用该拓展,这样就可以实现 Swagger 刷新也能记住登录了httpContext.SigninToSwagger("你的token");

5.2.3.3 退出 Swagger 授权

通过后端代码强制性让 Swagger 授权实现,只针对下一次请求有效!

httpContext.SignoutToSwagger();

5.2.3.4 获取本地 IP 地址

// ipv4var ipv4 = httpContext.GetLocalIpAddressToIPv4();// ipv6var ipv6 = httpContext.GetLocalIpAddressToIPv6();

5.2.3.5 获取客户端 IP 地址

// ipv4var ipv4 = httpContext.GetRemoteIpAddressToIPv4();// ipv6var ipv6 = httpContext.GetRemoteIpAddressToIPv6();
Nginx 无法获取正确客户端 IP 问题

如果服务器端使用了 nginx 等反向代理工具,可添加以下代码配置:

Startup.cs
services.Configure<ForwardedHeadersOptions>(options =>{    options.ForwardedHeaders = ForwardedHeaders.All;});// 注意在 Configure 最前面配置app.UseForwardedHeaders();

5.2.4 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

5.2 HttpContext

5.2.1 关于 HttpContext

ASP.NET 的时代,我们通常通过 HttpContext 全局静态类获取请求上下文,但在 ASP.NET Core 中,HttpContext 是一个非静态的抽象类,无法手动创建,也无法通过静态获取。

虽然在 ASP.NET Core 中无法直接获取 HttpContext 对象。但是微软也提供了注入 IHttpContextAccessor 方式获取。

5.2.2 获取 HttpContext

ASP.NET CoreFurion 提供了多种访问 HttpContext 的方式。

5.2.2.1 在 ControllerBase 派生类中

ControllerBase 派生类中,我们可以直接通过 HttpContext 属性获取 HttpContext 对象。

public class HomeController : Controller{    public IActionResult Index()    {        // 在这里HttpContext 是 Controller/ControllerBase 对象的属性        var httpContext = HttpContext;        return View();    }}

5.2.2.2 注入 IHttpContextAccessor

Furion 框架中,默认已经注册了 IHttpContextAccessor 服务,所以我们可以通过构造函数注入该接口获取。

public class AppService{    public AppService(IHttpContextAccessor httpContextAccessor)    {        var httpContext = httpContextAccessor.HttpContext;    }}

5.2.2.3 通过 App.HttpContext

App 静态类也提供了 App.HttpContext 获取 HttpContext 对象。

var request = App.HttpContext.Request;
Web 中访问

Web 完整的生命周期内,App.HttpContext 都是有效的,但在非 Web 中返回 null,避免在多线程,事件总线,定时任务等中使用。

5.2.3 HttpContext 拓展方法

Furion 框架基于 HttpContext 提供了一些常用的拓展方法。

5.2.3.1 获取当前请求的特性 Attribute

下列代码通常用于授权 Handler 中。

var attribute = httpContext.GetMetadata<SomeAttribute>();
Middleware 中间件获取特性方式

Middleware 中间件中获取有所区别,主要通过 HttpContextFeatures 获取,如:

var endpointFeature = httpContext.Features.Get<IEndpointFeature>();var attribute =  endpointFeature?.Endpoint?.Metadata?.GetMetadata<SomeAttribute>();

5.2.3.2 设置 Swagger 自动授权

Swagger 默认不能记住授权信息,一旦刷新浏览器就自动清空,所以 Furion 提供了该拓展,即使刷新浏览器也能保持授权状态。

// 检查用户登录和生成 token 代码...// .....// 之后调用该拓展,这样就可以实现 Swagger 刷新也能记住登录了httpContext.SigninToSwagger("你的token");

5.2.3.3 退出 Swagger 授权

通过后端代码强制性让 Swagger 授权实现,只针对下一次请求有效!

httpContext.SignoutToSwagger();

5.2.3.4 获取本地 IP 地址

// ipv4var ipv4 = httpContext.GetLocalIpAddressToIPv4();// ipv6var ipv6 = httpContext.GetLocalIpAddressToIPv6();

5.2.3.5 获取客户端 IP 地址

// ipv4var ipv4 = httpContext.GetRemoteIpAddressToIPv4();// ipv6var ipv6 = httpContext.GetRemoteIpAddressToIPv6();
Nginx 无法获取正确客户端 IP 问题

如果服务器端使用了 nginx 等反向代理工具,可添加以下代码配置:

Startup.cs
services.Configure<ForwardedHeadersOptions>(options =>{    options.ForwardedHeaders = ForwardedHeaders.All;});// 注意在 Configure 最前面配置app.UseForwardedHeaders();

5.2.4 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/idgenerator/index.html b/handbook/build/docs/idgenerator/index.html index 536615e49c..3a32aba099 100644 --- a/handbook/build/docs/idgenerator/index.html +++ b/handbook/build/docs/idgenerator/index.html @@ -2,22 +2,21 @@ - - - + +27. 分布式 ID 生成 | Furion -27. 分布式 ID 生成 | Furion - - + + +
-

27. 分布式 ID 生成

27.1 为什么需要分布式 ID

  • 全局唯一性: 不能出现重复的 ID 号, 既然是唯一标识, 这是最基本的要求。

  • 趋势递增: 在 MySQL InnoDB 引擎中使用的是聚集索引, 由于多数 RDBMS 使用 B-tree 的数据结构来存储索引数据, 在主键的选择上面我们应该尽量使用有序的主键保证写入性能。

  • 单调递增: 保证下一个 ID 一定大于上一个 ID, 例如事务版本号, IM 增量消息, 排序等特殊需求。

  • 信息安全: 如果 ID 是连续的, 恶意用户的扒取工作就非常容易做了, 直接按照顺序下载指定 URL 即可; 如果是订单号就更危险了, 竞对可以直接知道我们一天的单量。 所以在一些应用场景下, 会需要 ID 无规则, 不规则。

27.2 分布式 ID 有哪些

常见的分布式 ID 有 连续 GUID短 ID雪花算法 ID

27.3 如何使用

27.3.1 连续 GUID 方式

  • 静态 IDGen 方式
var guid = IDGen.NextID();// 还可以配置更多参数var guid2 = IDGen.NextID(new SequentialGuidSettings { LittleEndianBinary16Format = true }));    // SequentialGuidSettings 参数取决于你的分布式ID的实现
特别提醒

如果在循环中使用 IDGen 静态类方式,性能最差,原因是底层不断解析服务。如果非循环中,性能等于下面两种用法。

  • IDistributedIDGenerator 注入方式 推荐
private readonly IDistributedIDGenerator _idGenerator;public AppServices(IDistributedIDGenerator idGenerator){    _idGenerator = idGenerator;    var guidObject =  _idGenerator.Create();}
  • SequentialGuidIDGenerator 方式
var idGen = new SequentialGuidIDGenerator();var guid = idGen.Create();// 更多参数var idGen2 = new SequentialGuidIDGenerator();var guid2 = idGen2.Create(new SequentialGuidSettings { LittleEndianBinary16Format = true });

27.3.2 短 ID

短 ID 按道理不应该放在分布式 ID 生成这个章节,它的作用用途常用于并发不强的内部系统中,比如 任务IDIssue 编号 等等。

var shortid = ShortIDGen.NextID(); // 生成一个包含数字,字母,不包含特殊符号的 8 位短id// 添加更多配置var shortid = ShortIDGen.NextID(new GenerationOptions {    UseNumbers = false, // 不包含数字    UseSpecialCharacters = true, // 包含特殊符号    Length = 8// 设置长度,注意:不设置次长度是随机长度!!!!!!!});// 自定义生成短 ID 参与运算字符string characters = "ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ①②③④⑤⑥⑦⑧⑨⑩⑪⑫"; //whatever you want;ShortIDGen.SetCharacters(characters);// 自定义随机数(for)步长int seed = 1939048828;ShortIDGen.SetSeed(seed);// 重载所有自定义配置ShortIDGen.Reset();

27.3.3 雪花算法 ID

Furion 在最新的 2.1 + 版本移除了雪花算法 ID 功能,原因是:

目前,雪花算法 ID 使用频率不高,而且实现 雪花算法 ID 的方式也是千差万别,所以框架移除该功能,采用拓展或自集成方式。

27.4 反馈与建议

与我们交流

给 Furion 提 Issue


演练场
- - +

27. 分布式 ID 生成

27.1 为什么需要分布式 ID

  • 全局唯一性: 不能出现重复的 ID 号, 既然是唯一标识, 这是最基本的要求。

  • 趋势递增: 在 MySQL InnoDB 引擎中使用的是聚集索引, 由于多数 RDBMS 使用 B-tree 的数据结构来存储索引数据, 在主键的选择上面我们应该尽量使用有序的主键保证写入性能。

  • 单调递增: 保证下一个 ID 一定大于上一个 ID, 例如事务版本号, IM 增量消息, 排序等特殊需求。

  • 信息安全: 如果 ID 是连续的, 恶意用户的扒取工作就非常容易做了, 直接按照顺序下载指定 URL 即可; 如果是订单号就更危险了, 竞对可以直接知道我们一天的单量。 所以在一些应用场景下, 会需要 ID 无规则, 不规则。

27.2 分布式 ID 有哪些

常见的分布式 ID 有 连续 GUID短 ID雪花算法 ID

27.3 如何使用

27.3.1 连续 GUID 方式

  • 静态 IDGen 方式
var guid = IDGen.NextID();// 还可以配置更多参数var guid2 = IDGen.NextID(new SequentialGuidSettings { LittleEndianBinary16Format = true }));    // SequentialGuidSettings 参数取决于你的分布式ID的实现
特别提醒

如果在循环中使用 IDGen 静态类方式,性能最差,原因是底层不断解析服务。如果非循环中,性能等于下面两种用法。

  • IDistributedIDGenerator 注入方式 推荐
private readonly IDistributedIDGenerator _idGenerator;public AppServices(IDistributedIDGenerator idGenerator){    _idGenerator = idGenerator;    var guidObject =  _idGenerator.Create();}
  • SequentialGuidIDGenerator 方式
var idGen = new SequentialGuidIDGenerator();var guid = idGen.Create();// 更多参数var idGen2 = new SequentialGuidIDGenerator();var guid2 = idGen2.Create(new SequentialGuidSettings { LittleEndianBinary16Format = true });

27.3.2 短 ID

短 ID 按道理不应该放在分布式 ID 生成这个章节,它的作用用途常用于并发不强的内部系统中,比如 任务IDIssue 编号 等等。

var shortid = ShortIDGen.NextID(); // 生成一个包含数字,字母,不包含特殊符号的 8 位短id// 添加更多配置var shortid = ShortIDGen.NextID(new GenerationOptions {    UseNumbers = false, // 不包含数字    UseSpecialCharacters = true, // 包含特殊符号    Length = 8// 设置长度,注意:不设置次长度是随机长度!!!!!!!});// 自定义生成短 ID 参与运算字符string characters = "ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ①②③④⑤⑥⑦⑧⑨⑩⑪⑫"; //whatever you want;ShortIDGen.SetCharacters(characters);// 自定义随机数(for)步长int seed = 1939048828;ShortIDGen.SetSeed(seed);// 重载所有自定义配置ShortIDGen.Reset();

27.3.3 雪花算法 ID

Furion 在最新的 2.1 + 版本移除了雪花算法 ID 功能,原因是:

目前,雪花算法 ID 使用频率不高,而且实现 雪花算法 ID 的方式也是千差万别,所以框架移除该功能,采用拓展或自集成方式。

27.4 反馈与建议

与我们交流

给 Furion 提 Issue


演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/index.html b/handbook/build/docs/index.html index 37618bb600..aa59597f59 100644 --- a/handbook/build/docs/index.html +++ b/handbook/build/docs/index.html @@ -2,22 +2,21 @@ - - - + +1.1 介绍 | Furion -1.1 介绍 | Furion - - + + +
-

1.1 介绍

star fork GitHub stars GitHub forks GitHub license nuget

让 .NET 开发更简单,更通用,更流行。

💐 序言

无私奉献不是天方夜谭,有时候,我们也可以做到。

🍕 名字的由来

故事是这样子的:

自微软宣布 .NET 5 平台消息之后,就琢磨着开发一个基于 .NET 5 平台的开发框架,想做第一个吃 .NET 5 螃蟹尝鲜之人。

一开始想到了 Lazier 作为框架的名称,中文有 更懒 的意思。符合我的 “一切从简,只为了更懒” 的开发理念。

但是 更懒更烂 中文读音相近且没有特色,而且寓意也不是很好,对此换名问题苦恼了好些天。

刚好有一次在 QQ 群中无意间刷到了群友发的 “先知” 单词:Furion [fu:rɪən],就那一刻,就认定它了!

Furion 中文有 先知 的意思,恰好符合我创造框架的初衷。所以,Furion 就诞生了。

🍟 文档地址

🌭 开源地址

🥥 框架拓展包

包类型名称版本描述
nugetFurionnugetFurion 核心包
nugetFurion.PurenugetFurion 纯净版包(不含 EFCore)
nugetFurion.Extras.Authentication.JwtBearernugetFurion Jwt 拓展包
nugetFurion.Extras.DependencyModel.CodeAnalysisnugetFurion CodeAnalysis 拓展包
nugetFurion.Extras.ObjectMapper.MapsternugetFurion Mapster 拓展包
nugetFurion.Extras.DatabaseAccessor.SqlSugarnugetFurion SqlSugar 拓展包
nugetFurion.Extras.DatabaseAccessor.DappernugetFurion Dapper 拓展包
nugetFurion.Extras.DatabaseAccessor.MongoDBnugetFurion MongoDB 拓展包
nugetFurion.Extras.Logging.SerilognugetFurion Serilog 拓展包
nugetFurion.XunitnugetFurion Xunit 单元测试拓展包
nugetFurion.Pure.XunitnugetFurion 纯净版包 Xunit 单元测试拓展包(不含 EFCore)
nugetFurion.Tools.CommandLinenugetFurion Tools 命令行参数解析

🍄 框架脚手架

Furion + EFCore

模板类型名称版本描述
nugetFurion.Template.MvcnugetMvc 模板
nugetFurion.Template.ApinugetWebApi 模板
nugetFurion.Template.AppnugetMvc/WebApi 模板
nugetFurion.Template.RazornugetRazorPages 模板
nugetFurion.Template.RazorWithWebApinugetRazorPages/WebApi 模板
nugetFurion.Template.BlazornugetBlazor 模板
nugetFurion.Template.BlazorWithWebApinugetBlazor/WebApi 模板

Furion + SqlSugar

模板类型名称版本描述
nugetFurion.SqlSugar.Template.MvcnugetMvc 模板
nugetFurion.SqlSugar.Template.ApinugetWebApi 模板
nugetFurion.SqlSugar.Template.AppnugetMvc/WebApi 模板
nugetFurion.SqlSugar.Template.RazornugetRazorPages 模板
nugetFurion.SqlSugar.Template.RazorWithWebApinugetRazorPages/WebApi 模板
nugetFurion.SqlSugar.Template.BlazornugetBlazor 模板
nugetFurion.SqlSugar.Template.BlazorWithWebApinugetBlazor/WebApi 模板

如何使用脚手架

🍎 框架特点

  • 全新面貌:基于 .NET5+ 平台,没有历史包袱
  • 极少依赖:框架只依赖两个第三方包
  • 极易入门:只需要一个 Inject() 即可完成配置
  • 极速开发:内置丰富的企业应用开发功能
  • 极其灵活:轻松面对多变复杂的需求
  • 极易维护:采用独特的架构思想,只为长久维护设计
  • 完整文档:提供完善的开发文档
  • 跨全平台:支持所有主流操作系统及 .NET 全部项目类型

🥝 功能模块

🥐 框架依赖

Furion 为了追求极速入门,极致性能,尽可能的不使用或减少第三方依赖。目前 Furion 仅集成了以下两个依赖:

麻雀虽小五脏俱全。Furion 即使只集成了这两个依赖,但是主流的 依赖注入/控制反转AOP 面向切面编程,事件总线数据验证数据库操作 等等一个都不少。

🥗 环境要求

  • Visual Studio 2019 16.8 +
  • .NET 5 SDK +
  • .Net Standard 2.1 +

🥪 支持平台

  • 运行环境
    • Windows
    • Linux
    • MacOS/MacOS M1 CPU
    • Docker/K8S/K3S/Rancher
    • Xamarin/MAUI
  • 数据库
    • SqlServer
    • Sqlite
    • Azure Cosmos
    • MySql
    • MariaDB
    • PostgreSQL
    • InMemoryDatabase
    • Oracle
    • Firebird
    • 达梦数据库
    • MongoDB
  • 应用部署
    • Kestrel
    • Nginx
    • Jexus
    • IIS
    • Apache
    • PM2
    • Supervisor
    • 独立发布/单文件
    • 容器(Docker/K8S/K3S/Rancher/PodMan)

🍖 关于性能

Furion 目前采用 Visual Studio 2019 16.8 自带性能测试和 JMeter 进行测试,由于篇幅有限,只贴部分测试图,测试结果如下:

🍻 贡献代码

Furion 遵循 MIT 开源协议,欢迎大家提交 PRIssue

如果要为项目做出贡献,请查看 贡献指南。感谢每一位为 Furion 贡献代码的朋友。

演练场
- - +

1.1 介绍

star fork GitHub stars GitHub forks GitHub license nuget

让 .NET 开发更简单,更通用,更流行。

💐 序言

无私奉献不是天方夜谭,有时候,我们也可以做到。

🍕 名字的由来

故事是这样子的:

自微软宣布 .NET 5 平台消息之后,就琢磨着开发一个基于 .NET 5 平台的开发框架,想做第一个吃 .NET 5 螃蟹尝鲜之人。

一开始想到了 Lazier 作为框架的名称,中文有 更懒 的意思。符合我的 “一切从简,只为了更懒” 的开发理念。

但是 更懒更烂 中文读音相近且没有特色,而且寓意也不是很好,对此换名问题苦恼了好些天。

刚好有一次在 QQ 群中无意间刷到了群友发的 “先知” 单词:Furion [fu:rɪən],就那一刻,就认定它了!

Furion 中文有 先知 的意思,恰好符合我创造框架的初衷。所以,Furion 就诞生了。

🍟 文档地址

🌭 开源地址

🥥 框架拓展包

包类型名称版本描述
nugetFurionnugetFurion 核心包
nugetFurion.PurenugetFurion 纯净版包(不含 EFCore)
nugetFurion.Extras.Authentication.JwtBearernugetFurion Jwt 拓展包
nugetFurion.Extras.DependencyModel.CodeAnalysisnugetFurion CodeAnalysis 拓展包
nugetFurion.Extras.ObjectMapper.MapsternugetFurion Mapster 拓展包
nugetFurion.Extras.DatabaseAccessor.SqlSugarnugetFurion SqlSugar 拓展包
nugetFurion.Extras.DatabaseAccessor.DappernugetFurion Dapper 拓展包
nugetFurion.Extras.DatabaseAccessor.MongoDBnugetFurion MongoDB 拓展包
nugetFurion.Extras.Logging.SerilognugetFurion Serilog 拓展包
nugetFurion.XunitnugetFurion Xunit 单元测试拓展包
nugetFurion.Pure.XunitnugetFurion 纯净版包 Xunit 单元测试拓展包(不含 EFCore)
nugetFurion.Tools.CommandLinenugetFurion Tools 命令行参数解析

🍄 框架脚手架

Furion + EFCore

模板类型名称版本描述
nugetFurion.Template.MvcnugetMvc 模板
nugetFurion.Template.ApinugetWebApi 模板
nugetFurion.Template.AppnugetMvc/WebApi 模板
nugetFurion.Template.RazornugetRazorPages 模板
nugetFurion.Template.RazorWithWebApinugetRazorPages/WebApi 模板
nugetFurion.Template.BlazornugetBlazor 模板
nugetFurion.Template.BlazorWithWebApinugetBlazor/WebApi 模板

Furion + SqlSugar

模板类型名称版本描述
nugetFurion.SqlSugar.Template.MvcnugetMvc 模板
nugetFurion.SqlSugar.Template.ApinugetWebApi 模板
nugetFurion.SqlSugar.Template.AppnugetMvc/WebApi 模板
nugetFurion.SqlSugar.Template.RazornugetRazorPages 模板
nugetFurion.SqlSugar.Template.RazorWithWebApinugetRazorPages/WebApi 模板
nugetFurion.SqlSugar.Template.BlazornugetBlazor 模板
nugetFurion.SqlSugar.Template.BlazorWithWebApinugetBlazor/WebApi 模板

如何使用脚手架

🍎 框架特点

  • 全新面貌:基于 .NET5+ 平台,没有历史包袱
  • 极少依赖:框架只依赖两个第三方包
  • 极易入门:只需要一个 Inject() 即可完成配置
  • 极速开发:内置丰富的企业应用开发功能
  • 极其灵活:轻松面对多变复杂的需求
  • 极易维护:采用独特的架构思想,只为长久维护设计
  • 完整文档:提供完善的开发文档
  • 跨全平台:支持所有主流操作系统及 .NET 全部项目类型

🥝 功能模块

🥐 框架依赖

Furion 为了追求极速入门,极致性能,尽可能的不使用或减少第三方依赖。目前 Furion 仅集成了以下两个依赖:

麻雀虽小五脏俱全。Furion 即使只集成了这两个依赖,但是主流的 依赖注入/控制反转AOP 面向切面编程,事件总线数据验证数据库操作 等等一个都不少。

🥗 环境要求

  • Visual Studio 2019 16.8 +
  • .NET 5 SDK +
  • .Net Standard 2.1 +

🥪 支持平台

  • 运行环境
    • Windows
    • Linux
    • MacOS/MacOS M1 CPU
    • Docker/K8S/K3S/Rancher
    • Xamarin/MAUI
  • 数据库
    • SqlServer
    • Sqlite
    • Azure Cosmos
    • MySql
    • MariaDB
    • PostgreSQL
    • InMemoryDatabase
    • Oracle
    • Firebird
    • 达梦数据库
    • MongoDB
  • 应用部署
    • Kestrel
    • Nginx
    • Jexus
    • IIS
    • Apache
    • PM2
    • Supervisor
    • 独立发布/单文件
    • 容器(Docker/K8S/K3S/Rancher/PodMan)

🍖 关于性能

Furion 目前采用 Visual Studio 2019 16.8 自带性能测试和 JMeter 进行测试,由于篇幅有限,只贴部分测试图,测试结果如下:

🍻 贡献代码

Furion 遵循 MIT 开源协议,欢迎大家提交 PRIssue

如果要为项目做出贡献,请查看 贡献指南。感谢每一位为 Furion 贡献代码的朋友。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/inject/index.html b/handbook/build/docs/inject/index.html index 6368a5787e..1b623ded5b 100644 --- a/handbook/build/docs/inject/index.html +++ b/handbook/build/docs/inject/index.html @@ -2,22 +2,21 @@ - - - + +2.4 神奇的 Inject | Furion -2.4 神奇的 Inject | Furion - - + + +
-

2.4 神奇的 Inject

2.4.1 Inject 设计

Inject [ɪnˈdʒekt] 意思是 注入,注射 的意思,在这里意为使用最小的侵入式对应用进行机能改造。

Inject() 方法是 Furion 框架提供的最小侵入式的方法,可以让任何 ASP.NET Core Web 后端项目瞬间支持所有 Furion 框架特性。

2.4.2 Inject 方法有哪些

  • Inject():在 Program.cs 中注册
  • AddInject():在 Startup.csConfigureServices 中注册
  • AddInjectBase():在 Startup.csConfigureServices 中注册
  • AddInjectWithUnifyResult()/ AddInjectWithUnifyResult<T>():在 Startup.csConfigureServices 中注册
  • AddInjectMini():支持 Minimal API
  • UseInject():在 Startup.csConfigure 中注册
  • UseInjectBase():在 Startup.csConfigure 中注册

2.4.3 在 Program.cs 中使用

2.4.3.1 Inject() 方法

Inject() 是在启动程序 Program.cs 中使用的,集成 Furion 框架唯一方法,如:

Furion.Web.Entry\Program.cs
using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.Hosting;namespace Furion.Web.Entry{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args)        {            return Host.CreateDefaultBuilder(args)                .ConfigureWebHostDefaults(webBuilder =>                {                    webBuilder.Inject()                              .UseStartup<Startup>();                });        }    }}

2.4.4 Startup.ConfigureServices 使用

2.4.4.1 AddInject() 方法

AddInject() 方法是在 Startup.csConfigureServices 中提供最基础功能的注册。

AddInject() 包含以下基础功能注册:

services.AddSpecificationDocuments([options])        .AddDynamicApiControllers()        .AddDataValidation()        .AddFriendlyException();

使用如下:

namespace Furion.Web.Entry{    public class Startup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddInject();   // 支持直接注册(和下面代码二选一,不能同时注册两次)            services.AddControllers()                    .AddInject();   // 支持链式注册(和上面代码二选一,不能同时注册两次)        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            // 其他代码        }    }}

2.4.4.2 AddInjectBase() 方法

AddInjectBase() 方法是在 Startup.csConfigureServices 中提供最基础功能的注册。

AddInjectBase() 包含以下基础功能注册:

services.AddDataValidation()        .AddFriendlyException();

使用同上 AddInject()

2.4.4.3 AddInjectMini() 方法

版本说明

以下内容仅限 Furion 3.7.6 + 版本使用。

支持 .NET6 最新的 Minimal API 模式:

builder.Services.AddInjectMini();

2.4.4.4 AddInjectWithUnifyResult() 方法

AddInjectWithUnifyResult() 方法实际上等同于:

services.AddInject([swaggerGen])        .AddUnifyResult();

使用同上 AddInject()

特别注意

所有 .AddInject****() 方法不能同时注册,只能取其一。

2.4.5 Startup.Configure 使用

2.4.5.1 UseInject() 方法

UseInject() 方法是在 Startup.csConfigure 中提供最基础功能的注册。

UseInject() 包含以下基础功能注册:

app.UseSpecificationDocuments();

使用如下:

namespace Furion.Web.Entry{    public class Startup    {        public void ConfigureServices(IServiceCollection services)        {            // 其他代码        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            app.UseInject();    // 包含最小 Swagger 注册        }    }}

2.4.5.2 UseInjectBase() 方法

UseInjectBase() 方法是在 Startup.csConfigure 中提供最基础功能的注册。

UseInjectBase() 实际上是个空方法,为了规范化代码特意建立的。

使用同上 UseInject()

2.4.6 配置 Inject() 默认注册服务

所有 .Inject 方法都可以传入委托,通过委托可以进一步去配置默认行为。如:

.AddInject(options =>{    options.DataValidation = (d) =>    {        d.GlobalEnabled = false;    };    // ....});

2.4.7 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

2.4 神奇的 Inject

2.4.1 Inject 设计

Inject [ɪnˈdʒekt] 意思是 注入,注射 的意思,在这里意为使用最小的侵入式对应用进行机能改造。

Inject() 方法是 Furion 框架提供的最小侵入式的方法,可以让任何 ASP.NET Core Web 后端项目瞬间支持所有 Furion 框架特性。

2.4.2 Inject 方法有哪些

  • Inject():在 Program.cs 中注册
  • AddInject():在 Startup.csConfigureServices 中注册
  • AddInjectBase():在 Startup.csConfigureServices 中注册
  • AddInjectWithUnifyResult()/ AddInjectWithUnifyResult<T>():在 Startup.csConfigureServices 中注册
  • AddInjectMini():支持 Minimal API
  • UseInject():在 Startup.csConfigure 中注册
  • UseInjectBase():在 Startup.csConfigure 中注册

2.4.3 在 Program.cs 中使用

2.4.3.1 Inject() 方法

Inject() 是在启动程序 Program.cs 中使用的,集成 Furion 框架唯一方法,如:

Furion.Web.Entry\Program.cs
using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.Hosting;namespace Furion.Web.Entry{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args)        {            return Host.CreateDefaultBuilder(args)                .ConfigureWebHostDefaults(webBuilder =>                {                    webBuilder.Inject()                              .UseStartup<Startup>();                });        }    }}

2.4.4 Startup.ConfigureServices 使用

2.4.4.1 AddInject() 方法

AddInject() 方法是在 Startup.csConfigureServices 中提供最基础功能的注册。

AddInject() 包含以下基础功能注册:

services.AddSpecificationDocuments([options])        .AddDynamicApiControllers()        .AddDataValidation()        .AddFriendlyException();

使用如下:

namespace Furion.Web.Entry{    public class Startup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddInject();   // 支持直接注册(和下面代码二选一,不能同时注册两次)            services.AddControllers()                    .AddInject();   // 支持链式注册(和上面代码二选一,不能同时注册两次)        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            // 其他代码        }    }}

2.4.4.2 AddInjectBase() 方法

AddInjectBase() 方法是在 Startup.csConfigureServices 中提供最基础功能的注册。

AddInjectBase() 包含以下基础功能注册:

services.AddDataValidation()        .AddFriendlyException();

使用同上 AddInject()

2.4.4.3 AddInjectMini() 方法

版本说明

以下内容仅限 Furion 3.7.6 + 版本使用。

支持 .NET6 最新的 Minimal API 模式:

builder.Services.AddInjectMini();

2.4.4.4 AddInjectWithUnifyResult() 方法

AddInjectWithUnifyResult() 方法实际上等同于:

services.AddInject([swaggerGen])        .AddUnifyResult();

使用同上 AddInject()

特别注意

所有 .AddInject****() 方法不能同时注册,只能取其一。

2.4.5 Startup.Configure 使用

2.4.5.1 UseInject() 方法

UseInject() 方法是在 Startup.csConfigure 中提供最基础功能的注册。

UseInject() 包含以下基础功能注册:

app.UseSpecificationDocuments();

使用如下:

namespace Furion.Web.Entry{    public class Startup    {        public void ConfigureServices(IServiceCollection services)        {            // 其他代码        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            app.UseInject();    // 包含最小 Swagger 注册        }    }}

2.4.5.2 UseInjectBase() 方法

UseInjectBase() 方法是在 Startup.csConfigure 中提供最基础功能的注册。

UseInjectBase() 实际上是个空方法,为了规范化代码特意建立的。

使用同上 UseInject()

2.4.6 配置 Inject() 默认注册服务

所有 .Inject 方法都可以传入委托,通过委托可以进一步去配置默认行为。如:

.AddInject(options =>{    options.DataValidation = (d) =>    {        d.GlobalEnabled = false;    };    // ....});

2.4.7 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/ipc/index.html b/handbook/build/docs/ipc/index.html index 6c66783cc3..1063cbd5da 100644 --- a/handbook/build/docs/ipc/index.html +++ b/handbook/build/docs/ipc/index.html @@ -2,22 +2,21 @@ - - - + +33. IPC 进程通信 | Furion -33. IPC 进程通信 | Furion - - + + +
-

33. IPC 进程通信

33.1 什么是 IPC

引用百度百科

IPC(Inter-Process Communication,进程间通信)。进程间通信是指两个进程的数据之间产生交互。

通俗点说,IPC 可以实现不同应用程序间通信(交互数据)。

33.2 实现 IPC 通信方式

  • 半双工 Unix 管道
  • FIFOs(命名管道)
  • 消息队列(常用模式)
  • 信号量
  • 共享内存(常用模式,Furion 框架默认实现方式)
  • 网络 Socket(常用模式)

33.3 IPC 通信模式

IPC 本身指的是 进程间 通信,但 Furion 框架将内置 进程间/内 两种进程通信模式。

  • 进程内通信Furion 采用 Channel 管道提供进程内通信
  • 进程外通信Furion 采用 MemoryMapperFile 共享内存方式实现进程外通信(后续版本完善)

33.4 进程内通信(线程间)

进程内通信俗称线程间通信,Furion 框架采用 C# 提供的 Channel(管道) + Lazy + Task.Factory 实现长时间高性能的线程间通信机制。Channel 管道也是目前 .NET/C# 实现 生产者-订阅者 模式最简易且最为强大的实现。

33.4.1 了解 Channel

Channel 是在 .NET Core 2.1+ 版本之后加入。Channel 底层实现是一个高效的、线程安全的队列,可以在线程之间传递数据。

Channel 的主要应用场景是 发布/订阅、观察者模式 中使用,如:事件总线 就是最好的实现方式。通过 Channel 实现 生产-消费 机制可以减少项目间的耦合,提高应用吞吐量。

Furion 框架提供了 ChannelContext<TMessage, THandler> 密封类,提供 UnBoundedChannelBoundedChannel 两种管道通信模式。

  • UnBoundedChannel:具有无限容量的 Channel, 生产者可以全速进行生产数据,但如果消费者的消费速度低于生产者,Channel 的资源使用会无限增加,会有服务器资源耗尽的可能。
  • BoundedChannel:具有有限容量的 ChannelFurion 框架默认为 1000,到达上限后,生产者进入等待写入直到有空闲,好处是可以控制生产的速度,控制系统资源的使用。(推荐)

33.4.2 常规使用

创建 ChannelHandler<TMessage> 管道处理程序

using Furion.IPCChannel;using System;using System.Threading.Tasks;namespace Furion.Core{    /// <summary>    /// 创建管道处理程序(处理 String 类型消息)    /// </summary>    public class MyChannelHandler : ChannelHandler<string>    {        /// <summary>        /// 接受到管道消息后处理程序        /// </summary>        /// <param name="message"></param>        /// <returns></returns>        public override Task InvokeAsync(string message)        {            Console.WriteLine(message);            return Task.CompletedTask;        }    }}
note

ChannelHandler<TMessage> 泛型类型决定了你要接受那种类型的消息,不同类型消息将会自动过滤筛选。

使用 ChannelContext<TMessage, THandler> 发送消息

public async Task SendAsync(){    for (int i = 0; i < 100; i++)    {        // 使用有限容量生产数据        await ChannelContext<string, MyChannelHandler>.BoundedChannel.Writer.WriteAsync($"Loop {i} times.");    }}

以上代码也可以通过 ChannelContext<string, MyChannelHandler>.BoundedChannel.Writer.TryWrite() 同步写入。

33.4.3 实现多订阅

默认情况下,Furion 初始化了一个长时间的 Task 任务进行数据检查及订阅,如需实现多订阅模式,可创建新的订阅任务即可:

var reader = ChannelContext<string, MyChannelHandler>.BoundedChannel.Reader;// 创建长时间线程管道读取器_ = Task.Factory.StartNew(async () =>  {      while (await reader.WaitToReadAsync())      {          if (!reader.TryRead(out var message)) continue;          // 默认重试 3 次(每次间隔 1s)          await Retry.Invoke(async () => await Activator.CreateInstance<MyChannelHandler>().InvokeAsync(message), 3, 1000, finalThrow: false);      }  }, TaskCreationOptions.LongRunning);

33.4.4 更多 Channel 知识

可查阅 Dotnet Core 下的 Channel, 你用了吗? 博客教程(😃 写的不错)

33.4.5 CallContext 方式

Furion v2.18+ 版本提供了 CallContext 静态类,内部使用 AsyncLocal<T> 实现,也可以实现线程间通信,如:

CallContext.SetLocalValue("name", "Furion");CallContext.GetLocalValue("name");CallContext<int>.SetLocalValue("count", 1);CallContext<int>.GetLocalValue("count");

34.5 进程外通信(共享内存)

Furion 目前暂未提供的进程外通信功能,将在后续版本实现(主要是模块设计还未想好,技术已实现)。

主要是通过 MemoryMapperFile 实现共享内存达到进程外通信功能,了解更多 MemoryMapperFile

33.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

33. IPC 进程通信

33.1 什么是 IPC

引用百度百科

IPC(Inter-Process Communication,进程间通信)。进程间通信是指两个进程的数据之间产生交互。

通俗点说,IPC 可以实现不同应用程序间通信(交互数据)。

33.2 实现 IPC 通信方式

  • 半双工 Unix 管道
  • FIFOs(命名管道)
  • 消息队列(常用模式)
  • 信号量
  • 共享内存(常用模式,Furion 框架默认实现方式)
  • 网络 Socket(常用模式)

33.3 IPC 通信模式

IPC 本身指的是 进程间 通信,但 Furion 框架将内置 进程间/内 两种进程通信模式。

  • 进程内通信Furion 采用 Channel 管道提供进程内通信
  • 进程外通信Furion 采用 MemoryMapperFile 共享内存方式实现进程外通信(后续版本完善)

33.4 进程内通信(线程间)

进程内通信俗称线程间通信,Furion 框架采用 C# 提供的 Channel(管道) + Lazy + Task.Factory 实现长时间高性能的线程间通信机制。Channel 管道也是目前 .NET/C# 实现 生产者-订阅者 模式最简易且最为强大的实现。

33.4.1 了解 Channel

Channel 是在 .NET Core 2.1+ 版本之后加入。Channel 底层实现是一个高效的、线程安全的队列,可以在线程之间传递数据。

Channel 的主要应用场景是 发布/订阅、观察者模式 中使用,如:事件总线 就是最好的实现方式。通过 Channel 实现 生产-消费 机制可以减少项目间的耦合,提高应用吞吐量。

Furion 框架提供了 ChannelContext<TMessage, THandler> 密封类,提供 UnBoundedChannelBoundedChannel 两种管道通信模式。

  • UnBoundedChannel:具有无限容量的 Channel, 生产者可以全速进行生产数据,但如果消费者的消费速度低于生产者,Channel 的资源使用会无限增加,会有服务器资源耗尽的可能。
  • BoundedChannel:具有有限容量的 ChannelFurion 框架默认为 1000,到达上限后,生产者进入等待写入直到有空闲,好处是可以控制生产的速度,控制系统资源的使用。(推荐)

33.4.2 常规使用

创建 ChannelHandler<TMessage> 管道处理程序

using Furion.IPCChannel;using System;using System.Threading.Tasks;namespace Furion.Core{    /// <summary>    /// 创建管道处理程序(处理 String 类型消息)    /// </summary>    public class MyChannelHandler : ChannelHandler<string>    {        /// <summary>        /// 接受到管道消息后处理程序        /// </summary>        /// <param name="message"></param>        /// <returns></returns>        public override Task InvokeAsync(string message)        {            Console.WriteLine(message);            return Task.CompletedTask;        }    }}
note

ChannelHandler<TMessage> 泛型类型决定了你要接受那种类型的消息,不同类型消息将会自动过滤筛选。

使用 ChannelContext<TMessage, THandler> 发送消息

public async Task SendAsync(){    for (int i = 0; i < 100; i++)    {        // 使用有限容量生产数据        await ChannelContext<string, MyChannelHandler>.BoundedChannel.Writer.WriteAsync($"Loop {i} times.");    }}

以上代码也可以通过 ChannelContext<string, MyChannelHandler>.BoundedChannel.Writer.TryWrite() 同步写入。

33.4.3 实现多订阅

默认情况下,Furion 初始化了一个长时间的 Task 任务进行数据检查及订阅,如需实现多订阅模式,可创建新的订阅任务即可:

var reader = ChannelContext<string, MyChannelHandler>.BoundedChannel.Reader;// 创建长时间线程管道读取器_ = Task.Factory.StartNew(async () =>  {      while (await reader.WaitToReadAsync())      {          if (!reader.TryRead(out var message)) continue;          // 默认重试 3 次(每次间隔 1s)          await Retry.Invoke(async () => await Activator.CreateInstance<MyChannelHandler>().InvokeAsync(message), 3, 1000, finalThrow: false);      }  }, TaskCreationOptions.LongRunning);

33.4.4 更多 Channel 知识

可查阅 Dotnet Core 下的 Channel, 你用了吗? 博客教程(😃 写的不错)

33.4.5 CallContext 方式

Furion v2.18+ 版本提供了 CallContext 静态类,内部使用 AsyncLocal<T> 实现,也可以实现线程间通信,如:

CallContext.SetLocalValue("name", "Furion");CallContext.GetLocalValue("name");CallContext<int>.SetLocalValue("count", 1);CallContext<int>.GetLocalValue("count");

34.5 进程外通信(共享内存)

Furion 目前暂未提供的进程外通信功能,将在后续版本实现(主要是模块设计还未想好,技术已实现)。

主要是通过 MemoryMapperFile 实现共享内存达到进程外通信功能,了解更多 MemoryMapperFile

33.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/job/index.html b/handbook/build/docs/job/index.html index 2bc9ad9d04..51359b78f3 100644 --- a/handbook/build/docs/job/index.html +++ b/handbook/build/docs/job/index.html @@ -2,22 +2,21 @@ - - - + +26. 定时任务/后台任务 | Furion -26. 定时任务/后台任务 | Furion - - + + +
-

26. 定时任务/后台任务

版本说明

以下内容仅限 Furion 2.0.0 + 版本使用。

IIS 部署说明

由于 IIS 有回收的机制,所以定时任务应该采用独立部署,不然经常出现不能触发的情况。查看【Worker Service 章节

26.1 关于定时任务

顾名思义,定时任务就是在特定的时间或符合某种时间规律执行的任务。通常定时任务有四种时间调度方式:

  • 缓隔时间 方式:延迟多少时间后调配任务,这种方式任务只会被调用一次。
  • 间隔时间 方式:每隔一段固定时间调配任务,无间断调用任务。
  • Cron 表达式 方法:通过 Cron 表达式计算下一次执行时间进行调配任务,可以配置特定时间范围内执行,也可以无间断执行。
  • 自定义下次执行时间:可以通过各种逻辑运算返回下一次执行时间

26.2 如何实现

Furion 框架提供了两种方式实现定时任务:

  • SpareTime 静态类:SpareTime 静态类提供 SpareTime.Do([options]) 方式调用。
  • ISpareTimeWorker 依赖方式:通过自定义类实现 ISpareTimeWorker 接口并编写一定规则的方法即可。需要在 Startup.cs 中注册 services.AddTaskScheduler()

26.3 缓隔方式使用

26.3.1 特定时间后执行

这里演示 3s 后执行

Console.WriteLine("当前时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));// timer 是定时器的对象,包含定时器相关信息// count 表示执行次数,这里只有一次SpareTime.DoOnce(3000, (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));});

26.3.2 配置任务信息

SpareTime.DoOnce(3000, (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));}, "jobName", "描述一下这个任务是干什么的");

jobName 标识任务的唯一标识,通过这个标识可以启动、暂停、销毁任务。

26.3.3 手动启动执行

默认情况下,任务初始化后就立即启动,等待符合的时间就执行,有些时候我们仅仅想初始化时间,不希望立即执行,只需要配置 startNow 即可:

SpareTime.DoOnce(3000, (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));},"jobName", startNow: false);// 手动启动执行SpareTime.Start("jobName");

26.3.4 模拟后台执行

有些时候,我们只需要开启新线程去执行一个任务,比如发短信,发邮件,无需配置。

// 此方法无需主线程等待即可返回,可大大提高性能SpareTime.DoIt(() => {    // 这里发送短信,发送邮件或记录访问记录});

还可以指定多长时间后触发,建议 10-1000 毫秒之间:

SpareTime.DoIt(() => {    // 发送短信}, 100);

26.3.5 ISpareTimeWorker 方式

public class JobWorker : ISpareTimeWorker{    /// <summary>    /// 3s 后执行    /// </summary>    /// <param name="timer"></param>    /// <param name="count"></param>    [SpareTime(3000, "jobName", DoOnce = true, StartNow = true)]    public void DoSomething(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    }    /// <summary>    /// 3s 后执行(支持异步)    /// </summary>    /// <param name="timer"></param>    /// <param name="count"></param>    [SpareTime(3000, "jobName", DoOnce = true, StartNow = true)]    public async Task DoSomethingAsync(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        await Task.CompletedTask;    }}

需要在 Startup.cs 中注册 services.AddTaskScheduler()

26.4 间隔方式使用

26.4.1 每隔一段时间执行

// 每隔 1s 执行SpareTime.Do(1000, (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");});

26.4.2 配置任务信息

SpareTime.Do(1000, (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");}, "jobName", "这是一个计时器任务");

26.4.3 手动启动执行

SpareTime.Do(1000, (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");}, "jobName", startNow:false);SpareTime.Start("jobName");

26.4.4 ISpareTimeWorker 方式

public class JobWorker : ISpareTimeWorker{    /// <summary>    /// 每隔 3s 执行    /// </summary>    /// <param name="timer"></param>    /// <param name="count"></param>    [SpareTime(3000, "jobName", StartNow = true)]    public void DoSomething(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }}

需要在 Startup.cs 中注册 services.AddTaskScheduler()

26.5 Cron 表达式使用

26.5.1 什么是 Cron 表达式

Cron 表达式是一个字符串,字符串以 56 个空格隔开,分为 6 或 7 个域,每一个域代表一个含义,Cron 有如下两种语法格式:

(1) Seconds Minutes Hours DayofMonth Month DayofWeek Year

(2)Seconds Minutes Hours DayofMonth Month DayofWeek

Cron 从左到右(用空格隔开): 小时 月份中的日期 月份 星期中的日期 年份

字段允许值允许的特殊字符
秒(Seconds)0~59 的整数, - \* / 四个字符
分(Minutes)0~59 的整数, - \* / 四个字符
小时(Hours)0~23 的整数, - \* / 四个字符
日期(DayofMonth)1~31 的整数(但是你需要考虑平闰月的天数),- \* ? / L W C 八个字符
月份(Month)1~12 的整数或者 JAN-DEC, - \* / 四个字符
星期(DayofWeek)1~7 的整数或者 SUN-SAT (1=SUN), - \* ? / L C # 八个字符
年(可选,留空)(Year)1970~2099, - \* / 四个字符

每一个域都使用数字,但还可以出现如下特殊字符,它们的含义是:

(1)_:表示匹配该域的任意值。假如在 Minutes 域使用 \_, 即表示每分钟都会触发事件。

(2)?:只能用在 DayofMonthDayofWeek 两个域。它也匹配域的任意值,但实际不会。因为 DayofMonthDayofWeek 会相互影响。例如想在每月的 20 日触发调度,不管 20 日到底是星期几,则只能使用如下写法: 13 13 15 20 _ ?, 其中最后一位只能用,而不能使用_,如果使用*表示不管星期几都会触发,实际上并不是这样。

(3)-:表示范围。例如在 Minutes 域使用 5-20,表示从 5 分到 20 分钟每分钟触发一次

(4)/:表示起始时间开始触发,然后每隔固定时间触发一次。例如在 Minutes 域使用 5/20,则意味着 5 分钟触发一次,而 25,45 等分别触发一次.

(5),:表示列出枚举值。例如:在 Minutes 域使用 5,20,则意味着在 520 分每分钟触发一次。

(6)L:表示最后,只能出现在 DayofWeekDayofMonth 域。如果在 DayofWeek 域使用 5L,意味着在最后的一个星期四触发。

(7)W:表示有效工作日(周一到周五) 只能出现在 DayofMonth 域,系统将在离指定日期的最近的有效工作日触发事件。例如:在 DayofMonth 使用 5W,如果 5 日是星期六,则将在最近的工作日:星期五,即 4 日触发。如果 5 日是星期天,则在 6 日(周一)触发;如果 5 日在星期一到星期五中的一天,则就在 5 日触发。另外一点,W 的最近寻找不会跨过月份 。

(8)LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。

(9)#:用于确定每个月第几个星期几,只能出现在 DayofMonth 域。例如在 4#2,表示某月的第二个星期三。

26.5.2 常见 Cron 表达式

表达式表达式代表含义格式化
* * * * *每分钟CronFormat.Standard
*/1 * * * *每分钟CronFormat.Standard
0 0/1 * * * ?每分钟CronFormat.IncludeSeconds
0 0 * * * ?每小时CronFormat.IncludeSeconds
0 0 0/1 * * ?每小时CronFormat.IncludeSeconds
0 23 ? * MON-FRI晚上 11:00,周一至周五CronFormat.Standard
* * * * * *每秒CronFormat.IncludeSeconds
*/45 * * * * *每 45 秒CronFormat.IncludeSeconds
*/5 * * * *每 5 分钟CronFormat.Standard
0 0/10 * * * ?每 10 分钟CronFormat.IncludeSeconds
0 */5 * * * *每 5 分钟CronFormat.IncludeSeconds
30 11 * * 1-5周一至周五上午 11:30CronFormat.Standard
30 11 * * *11:30CronFormat.Standard
0-10 11 * * *上午 11:00 至 11:10 之间的每一分钟CronFormat.Standard
* * * 3 *每分钟,只在 3 月份CronFormat.Standard
* * * 3,6 *每分钟,只在 3 月和 6 月CronFormat.Standard
30 14,16 * * *下午 02:30 分和 04:30 分CronFormat.Standard
30 6,14,16 * * *早上 06:30,下午 02:30 和 04:30CronFormat.Standard
46 9 * * 1早上 09:46,只在星期一CronFormat.Standard
23 12 15 * *下午 12:23,在本月的第 15 天CronFormat.Standard
23 12 * JAN *下午 12:23,只在 1 月份CronFormat.Standard
23 12 ? JAN *下午 12:23,只在 1 月份CronFormat.Standard
23 12 * JAN-FEB *下午 12:23,1 月至 2 月CronFormat.Standard
23 12 * JAN-MAR *下午 12:23,1 月至 3 月CronFormat.Standard
23 12 * * SUN下午 12:23,仅在星期天CronFormat.Standard
*/5 15 * * MON-FRI每 5 分钟,下午 0:00 至 03:59,周一至周五CronFormat.Standard
* * * * MON#3每分钟,在月的第三个星期一CronFormat.Standard
* * * * 4L每一分钟,在本月的最后一天CronFormat.Standard
*/5 * L JAN *每月一次每月 5 分钟,只在 1 月份CronFormat.Standard
30 02 14 * * *下午在 02:02:30CronFormat.IncludeSeconds
5-10 * * * * *每分钟的 5-10 秒CronFormat.IncludeSeconds
5-10 30-35 10-12 * * *10:00 至 12:00 之间的每分钟 5-10 秒,每小时 30-35 分钟CronFormat.IncludeSeconds
30 */5 * * * *每分钟的 30 秒,每五分钟CronFormat.IncludeSeconds
0 30 10-13 ? * WED,FRI每小时的 30 分钟,下午 10:00 至 01:00 之间,仅在周三和周五CronFormat.IncludeSeconds
10 0/5 * * * ?每分钟的 10 秒,每 05 分钟CronFormat.IncludeSeconds
0 0 6 1/1 * ?下午 06:00CronFormat.IncludeSeconds
0 5 0/1 * * ?一个小时的 05 分CronFormat.IncludeSeconds
0 0 L * *每月最后一天上午 00:00CronFormat.Standard
0 0 L-1 * *每月最后一天的凌晨 00:00CronFormat.Standard
0 0 3W * *每月第 3 个工作日上午 00:00CronFormat.Standard
0 0 LW * *在每月的最后一个工作日,上午 00:00CronFormat.Standard
0 0 * * 2L本月最后一个星期二上午 00:00CronFormat.Standard
0 0 * * 6#3每月第三个星期六上午 00:00CronFormat.Standard
0 0 ? 1 MON#11 月第一个星期一上午 00:00CronFormat.Standard
0 0 3 * * ?每天几点执行一次CronFormat.IncludeSeconds

26.5.3 在线生成 Cron 表达式

https://cron.qqe2.com/

26.5.4 Macro 标识符

为了方便定义 Cron 表达式,Furion 框架也提供了非常方便的占位符实现常用的时间格式:

占位符对应表达式占位符代表含义
@every_second* * * * * *一秒钟跑一次
@every_minute* * * * *在分钟开始时每分钟运行一次
@hourly0 * * * *在小时开始时每小时运行一次
@daily0 0 * * *每天午夜运行一次
@midnight0 0 * * *每天午夜运行一次
@weekly0 0 * * 0周日上午午夜每周运行一次
@monthly0 0 1 * *每月在每月第一天的午夜运行一次
@yearly0 0 1 1 *每年 1 月 1 日午夜运行一次
@annually0 0 1 1 *每年 1 月 1 日午夜运行一次

26.5.5 使用 Cron 表达式

// 每隔 1s 执行SpareTime.Do("* * * * * *", (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");}, cronFormat: CronFormat.IncludeSeconds);
关于 CronFormat

默认情况下,Furion 框架未启用对 的支持,如需开启,则设置 cronFormat: CronFormat.IncludeSeconds 即可。默认值是 cronFormat: CronFormat.Standard

26.5.6 使用 Macro 占位符

// 每隔 1s 执行SpareTime.Do("@every_second", (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");});

26.5.7 配置任务信息

SpareTime.Do("* * * * *", (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");}, "cronName", "每分钟执行一次");

26.5.8 手动启动执行

SpareTime.Do("* * * * *", (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");}, "cronName", "每分钟执行一次", startNow: false);SpareTime.Start("cronName");

26.5.9 ISpareTimeWorker 方式

public class JobWorker : ISpareTimeWorker{    /// <summary>    /// 每分钟执行    /// </summary>    /// <param name="timer"></param>    /// <param name="count"></param>    [SpareTime("* * * * *", "jobName", StartNow = true)]    public void DoSomething(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }    /// <summary>    /// 每分钟执行(支持异步)    /// </summary>    /// <param name="timer"></param>    /// <param name="count"></param>    [SpareTime("* * * * *", "jobName", StartNow = true)]    public async Task DoSomethingAsync(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");        await Task.Completed;    }}

26.6 自定义下次执行时间

有些时候我们需要进行一些业务逻辑,比如数据库查询等操作返回下一次执行时间,这个时候我们可以通过高级自定义方式。

26.6.1 高级自定义间隔方式

SpareTime.Do(()=>{    // 这里可以查询数据库或进行或进行任何业务逻辑    if(符合逻辑){        return 1000; // 每秒执行    }    else return -1; // 不符合逻辑取消任务},(timer,count)=>{    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");});
配置是否持续检查

默认情况下,该自定义会在返回 小于或等于0 时终止任务的执行。但是我们希望该任务不要终止,只要符合条件都一直执行,只需要配置 cancelInNoneNextTime: false 即可

26.6.2 高级自定义 Cron 表达式

SpareTime.Do(()=>{    // 这里可以查询数据库或进行或进行任何业务逻辑    if(符合逻辑){        return DateTimeOffset.Now.AddMinutes(10);  // 十分钟后再执行    }    else return null; // 不符合逻辑取消任务},(timer,count) => {    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");});
配置是否持续检查

默认情况下,该自定义会在返回 null 时终止任务的执行。但是我们希望该任务不要终止,只要符合条件都一直执行,只需要配置 cancelInNoneNextTime: false 即可,如:

SpareTime.Do(()=>{    // 这里可以查询数据库或进行或进行任何业务逻辑    if(符合逻辑){        return SpareTime.GetCronNextOccurrence("cron 表达式");    }    else return null; // 不符合逻辑继续检查},(timer,count) => {    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");}, cancelInNoneNextTime: false);

26.7 ISpareTimeWorker 说明

除了上面的 SpareTime 静态类方式,Furion 框架还提供了 ISpareTimeWorker 方式,使用该方式非常简单,只需要自定义一个公开且非抽象非静态类并实现 ISpareTimeWorker 即可。

在该类中定义的任务方法需满足以下规则:

  • 必须是公开且实例方法
  • 该方法必须返回 void 且提供 SpareTimerlong 两个参数
  • 必须贴有 [SpareTime] 特性

如:

public class JobWorker : ISpareTimeWorker{    // 每隔一秒执行,且立即启动    [SpareTime(1000, "jobName1", StartNow = true)]    public void DoSomething1(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }    // 每分钟执行,且立即启动    [SpareTime("* * * * *", "jobName2", StartNow = true)]    public void DoSomething2(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }    // 每秒执行,且等待启动    [SpareTime("* * * * * *", "jobName3",CronFormat = CronFormat.IncludeSeconds, StartNow = false)]    public void DoSomething3(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }    // 每秒执行一次,每分钟也执行一次    [SpareTime(1000, "jobName4", StartNow = true)]    [SpareTime("* * * * *", "jobName5", StartNow = true)]    public void DoSomething4(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }    // 只执行一次    [SpareTime(1000, "jobName5", StartNow = true, DoOnce = true)]    public void DoSomething5(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }    // 读取配置文件,通过 #(配置路径)    [SpareTime("#(MyJob:Time)", "jobName6", StartNow = true, DoOnce = true)]    public void DoSomething5(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }    // 支持异步    [SpareTime(1000, "jobName1", StartNow = true)]    public async Task DoSomethingAsync(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");        await Task.Completed;    }}
关于依赖注入

ISpareTimeWorker 接口主要是用来查找定时器对象的,也就是它的实现类并未提供依赖注入功能,所以在实现类并不支持构造函数注入依赖项。

26.7.1 [SpareTime] 特性

[SpareTime] 支持以下配置属性

  • Interval:间隔时间, double 类型
  • CronExpressionCron 表达式,string 类型
  • WorkerName:任务唯一标识,string 类型,必填
  • Description:任务描述,string 类型
  • DoOnce:是否只执行一次,bool 类型,默认 false
  • StartNow:是否立即启动,默认 false
  • CronFormatCron 表达式格式化方式,CronFormat 枚举类型,默认 CronFormat.Standard
  • ExecuteType:配置任务执行方式,SpareTimeExecuteTypes 枚举类型,默认 SpareTimeExecuteTypes.Parallel

26.8 SpareTime 静态类

SpareTime 静态类提供了一些方法方便初始化和管理任务

26.8.1 初始化任务

// 开启间隔任务SpareTime.Do(interval, [options]);// 开启 Cron 表达式任务SpareTime.Do(expression, [options]);// 只执行一次任务SpareTime.DoOnce(interval, [options]);// 实现自定义任务SpareTime.Do(()=>{    return DateTime.Now.AddMinutes(10);},[options]);

26.8.2 实现后台执行

// 实现后台执行SpareTime.DoIt(()=>{});

26.8.3 开始一个任务

SpareTime.Start("任务标识");

26.8.4 暂停一个任务

SpareTime.Stop("任务标识");// 还可以标记一个任务执行失败SpareTime.Stop("任务标识", true);

26.8.5 取消一个任务

SpareTime.Cancel("任务名称");

26.8.6 销毁所有任务

SpareTime.Dispose();

26.8.7 获取所有任务

var workers = SpareTime.GetWorkers();

26.8.8 获取单个任务

var worker = SpareTime.GetWorker("workerName");

26.8.9 解析 Cron 表达式

var nextTime = SpareTime.GetCronNextOccurrence("* * * * *");

26.9 并行串行执行方式

Furion 框架提供了任务两种执行方式 并行串行

  • 并行:无需等待上一次任务完成,默认值
  • 串行:需等待上一次任务完成

26.9.1 SpareTime 静态方式指定

SpareTime.Do(1000, (t, i) =>{    Thread.Sleep(5000); // 模拟执行耗时任务    Console.WriteLine($"{t.WorkerName} -{t.Description} - {DateTime.Now:yyyy-MM-dd HH:mm:ss} - {i}");}, "serialName", "模拟串行任务", executeType: SpareTimeExecuteTypes.Serial);

26.9.2 ISpareTimeWorker 方式

[SpareTime(1000, "jobName1", StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]public void DoSomething1(SpareTimer timer, long count){    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");}

26.10 任务异常处理

有些时候我们可能在执行任务过程中出现异常,Furion 也提供了属性判断是否有异常和异常信息,方便记录到日志中,如:

SpareTime.Do(1000, (t, c) =>{    // 判断是否有异常    if (t.Exception.Any())    {        Console.WriteLine(t.Exception.Values.LastOrDefault()?.Message);    }    // 执行第三次抛异常    if (c > 2)    {        throw Oops.Oh("抛异常" + c);    }    else    {        Console.WriteLine($"{t.WorkerName} -{t.Description} - {DateTime.Now:yyyy-MM-dd HH:mm:ss} - {c}");    }}, "exceptionJob");
特别说明

如果一个任务连续错误次数达 10次 则任务将自动停止,并标记任务状态为 Failed

26.11 如何在任务中解析对象

有些时候我们需要在任务中进行数据库操作或解析服务,这时候我们只需要创建一个新的作用域即可

26.11.1 SpareTime 静态类中

SpareTime.Do(1000, (timer,count) => {    Scoped.Create((_, scope) =>    {        var services = scope.ServiceProvider;        // 获取数据库上下文        var dbContext = Db.GetDbContext(services);        // 获取仓储        var respository = Db.GetRepository<Person>(services);        // 解析其他服务        var otherService = services.GetService<XXX>();        var otherService2 = App.GetService<XXX>(services);    });}, "任务标识");

26.11.2 ISpareTimeWorker 方式

[SpareTime(1000, "jobName1", StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]public void DoSomething1(SpareTimer timer, long count){    Scoped.Create((_, scope) =>    {        var services = scope.ServiceProvider;        // 获取数据库上下文        var dbContext = Db.GetDbContext(services);        // 获取仓储        var respository = Db.GetRepository<Person>(services);        // 解析其他服务        var otherService = services.GetService<XXX>();        var otherService2 = App.GetService<XXX>(services);    });}
数据库操作注意

如果作用域中对数据库有任何变更操作,需手动调用 SaveChanges 或带 Now 结尾的方法。也可以使用 Scoped.CreateUow(handler) 代替。

26.12 在 BackgroundService 中使用

BackgroundService.NET Core 3 之后提供的轻量级后台任务,同时可以发布到 Windows 服务和 Linux 守护进程中。

26.12.1 间隔执行方式

namespace WorkerService;public class Worker : BackgroundService{    private readonly ILogger<Worker> _logger;    private const int delay = 1000;    public Worker(ILogger<Worker> logger)    {        _logger = logger;    }    protected override async Task ExecuteAsync(CancellationToken stoppingToken)    {        while (!stoppingToken.IsCancellationRequested)        {            var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);            await taskFactory.StartNew(async () =>            {                // 你的业务代码写到这里面                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);                await Task.CompletedTask;            }, stoppingToken);            await Task.Delay(delay, stoppingToken);        }    }}

26.12.2 Cron 表达式执行方式

using Furion.TimeCrontab;namespace WorkerService;public class Worker : BackgroundService{    private readonly ILogger<Worker> _logger;    private readonly Crontab _crontab;    public Worker(ILogger<Worker> logger)    {        _logger = logger;        _crontab = Crontab.Parse("* * * * * *", CronStringFormat.WithSeconds);    }    protected override async Task ExecuteAsync(CancellationToken stoppingToken)    {        while (!stoppingToken.IsCancellationRequested)        {            var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);            await taskFactory.StartNew(async () =>            {                // 你的业务代码写到这里面                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);                await Task.CompletedTask;            }, stoppingToken);            await Task.Delay(_crontab.GetSleepMilliseconds(DateTime.UtcNow), stoppingToken);        }    }}

26.13 定时任务监听器

Furion v2.18+ 版本之后新增了定时任务监听器 ISpareTimeListener,通过监听器可以实现所有定时任务的状态。如,创建一个 单例 的监听器 SpareTimeListener

using Furion.DependencyInjection;using Furion.TaskScheduler;using System;using System.Threading.Tasks;namespace Furion.Core{    public class SpareTimeListener : ISpareTimeListener, ISingleton    {        /// <summary>        /// 监听所有任务        /// </summary>        /// <param name="executer"></param>        /// <returns></returns>        public Task OnListener(SpareTimerExecuter executer)        {            switch (executer.Status)            {                // 执行开始通知                case 0:                    Console.WriteLine($"{executer.Timer.WorkerName} 任务开始通知");                    break;                // 任务执行之前通知                case 1:                    Console.WriteLine($"{executer.Timer.WorkerName} 执行之前通知");                    break;                // 执行成功通知                case 2:                    Console.WriteLine($"{executer.Timer.WorkerName} 执行成功通知");                    break;                // 任务执行失败通知                case 3:                    Console.WriteLine($"{executer.Timer.WorkerName} 执行失败通知");                    break;                // 任务执行停止通知                case -1:                    Console.WriteLine($"{executer.Timer.WorkerName} 执行停止通知");                    break;                // 任务执行取消通知                case -2:                    Console.WriteLine($"{executer.Timer.WorkerName} 执行取消通知");                    break;                default:                    break;            }            return Task.CompletedTask;        }    }}

26.13.1 SpareTimerExecuter 属性说明

  • TimerSpareTimer 定时器对象
  • Status:监听状态
    • 0:任务开始
    • 1:执行之前
    • 2:执行成功
    • 3:执行失败
    • -1:任务停止
    • -2:任务取消

26.14 IIS 部署回收设置

如果在项目中使用了定时任务且部署到 IIS 中,那么需要设置 IIS 禁止回收,如:

部署建议

建议定时任务采用 Worker Service 独立部署方式,不应依托 Web 项目进程中。查看【 Worker Service】章节

26.15 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

26. 定时任务/后台任务

版本说明

以下内容仅限 Furion 2.0.0 + 版本使用。

IIS 部署说明

由于 IIS 有回收的机制,所以定时任务应该采用独立部署,不然经常出现不能触发的情况。查看【Worker Service 章节

26.1 关于定时任务

顾名思义,定时任务就是在特定的时间或符合某种时间规律执行的任务。通常定时任务有四种时间调度方式:

  • 缓隔时间 方式:延迟多少时间后调配任务,这种方式任务只会被调用一次。
  • 间隔时间 方式:每隔一段固定时间调配任务,无间断调用任务。
  • Cron 表达式 方法:通过 Cron 表达式计算下一次执行时间进行调配任务,可以配置特定时间范围内执行,也可以无间断执行。
  • 自定义下次执行时间:可以通过各种逻辑运算返回下一次执行时间

26.2 如何实现

Furion 框架提供了两种方式实现定时任务:

  • SpareTime 静态类:SpareTime 静态类提供 SpareTime.Do([options]) 方式调用。
  • ISpareTimeWorker 依赖方式:通过自定义类实现 ISpareTimeWorker 接口并编写一定规则的方法即可。需要在 Startup.cs 中注册 services.AddTaskScheduler()

26.3 缓隔方式使用

26.3.1 特定时间后执行

这里演示 3s 后执行

Console.WriteLine("当前时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));// timer 是定时器的对象,包含定时器相关信息// count 表示执行次数,这里只有一次SpareTime.DoOnce(3000, (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));});

26.3.2 配置任务信息

SpareTime.DoOnce(3000, (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));}, "jobName", "描述一下这个任务是干什么的");

jobName 标识任务的唯一标识,通过这个标识可以启动、暂停、销毁任务。

26.3.3 手动启动执行

默认情况下,任务初始化后就立即启动,等待符合的时间就执行,有些时候我们仅仅想初始化时间,不希望立即执行,只需要配置 startNow 即可:

SpareTime.DoOnce(3000, (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));},"jobName", startNow: false);// 手动启动执行SpareTime.Start("jobName");

26.3.4 模拟后台执行

有些时候,我们只需要开启新线程去执行一个任务,比如发短信,发邮件,无需配置。

// 此方法无需主线程等待即可返回,可大大提高性能SpareTime.DoIt(() => {    // 这里发送短信,发送邮件或记录访问记录});

还可以指定多长时间后触发,建议 10-1000 毫秒之间:

SpareTime.DoIt(() => {    // 发送短信}, 100);

26.3.5 ISpareTimeWorker 方式

public class JobWorker : ISpareTimeWorker{    /// <summary>    /// 3s 后执行    /// </summary>    /// <param name="timer"></param>    /// <param name="count"></param>    [SpareTime(3000, "jobName", DoOnce = true, StartNow = true)]    public void DoSomething(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    }    /// <summary>    /// 3s 后执行(支持异步)    /// </summary>    /// <param name="timer"></param>    /// <param name="count"></param>    [SpareTime(3000, "jobName", DoOnce = true, StartNow = true)]    public async Task DoSomethingAsync(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        await Task.CompletedTask;    }}

需要在 Startup.cs 中注册 services.AddTaskScheduler()

26.4 间隔方式使用

26.4.1 每隔一段时间执行

// 每隔 1s 执行SpareTime.Do(1000, (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");});

26.4.2 配置任务信息

SpareTime.Do(1000, (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");}, "jobName", "这是一个计时器任务");

26.4.3 手动启动执行

SpareTime.Do(1000, (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");}, "jobName", startNow:false);SpareTime.Start("jobName");

26.4.4 ISpareTimeWorker 方式

public class JobWorker : ISpareTimeWorker{    /// <summary>    /// 每隔 3s 执行    /// </summary>    /// <param name="timer"></param>    /// <param name="count"></param>    [SpareTime(3000, "jobName", StartNow = true)]    public void DoSomething(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }}

需要在 Startup.cs 中注册 services.AddTaskScheduler()

26.5 Cron 表达式使用

26.5.1 什么是 Cron 表达式

Cron 表达式是一个字符串,字符串以 56 个空格隔开,分为 6 或 7 个域,每一个域代表一个含义,Cron 有如下两种语法格式:

(1) Seconds Minutes Hours DayofMonth Month DayofWeek Year

(2)Seconds Minutes Hours DayofMonth Month DayofWeek

Cron 从左到右(用空格隔开): 小时 月份中的日期 月份 星期中的日期 年份

字段允许值允许的特殊字符
秒(Seconds)0~59 的整数, - \* / 四个字符
分(Minutes)0~59 的整数, - \* / 四个字符
小时(Hours)0~23 的整数, - \* / 四个字符
日期(DayofMonth)1~31 的整数(但是你需要考虑平闰月的天数),- \* ? / L W C 八个字符
月份(Month)1~12 的整数或者 JAN-DEC, - \* / 四个字符
星期(DayofWeek)1~7 的整数或者 SUN-SAT (1=SUN), - \* ? / L C # 八个字符
年(可选,留空)(Year)1970~2099, - \* / 四个字符

每一个域都使用数字,但还可以出现如下特殊字符,它们的含义是:

(1)_:表示匹配该域的任意值。假如在 Minutes 域使用 \_, 即表示每分钟都会触发事件。

(2)?:只能用在 DayofMonthDayofWeek 两个域。它也匹配域的任意值,但实际不会。因为 DayofMonthDayofWeek 会相互影响。例如想在每月的 20 日触发调度,不管 20 日到底是星期几,则只能使用如下写法: 13 13 15 20 _ ?, 其中最后一位只能用,而不能使用_,如果使用*表示不管星期几都会触发,实际上并不是这样。

(3)-:表示范围。例如在 Minutes 域使用 5-20,表示从 5 分到 20 分钟每分钟触发一次

(4)/:表示起始时间开始触发,然后每隔固定时间触发一次。例如在 Minutes 域使用 5/20,则意味着 5 分钟触发一次,而 25,45 等分别触发一次.

(5),:表示列出枚举值。例如:在 Minutes 域使用 5,20,则意味着在 520 分每分钟触发一次。

(6)L:表示最后,只能出现在 DayofWeekDayofMonth 域。如果在 DayofWeek 域使用 5L,意味着在最后的一个星期四触发。

(7)W:表示有效工作日(周一到周五) 只能出现在 DayofMonth 域,系统将在离指定日期的最近的有效工作日触发事件。例如:在 DayofMonth 使用 5W,如果 5 日是星期六,则将在最近的工作日:星期五,即 4 日触发。如果 5 日是星期天,则在 6 日(周一)触发;如果 5 日在星期一到星期五中的一天,则就在 5 日触发。另外一点,W 的最近寻找不会跨过月份 。

(8)LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。

(9)#:用于确定每个月第几个星期几,只能出现在 DayofMonth 域。例如在 4#2,表示某月的第二个星期三。

26.5.2 常见 Cron 表达式

表达式表达式代表含义格式化
* * * * *每分钟CronFormat.Standard
*/1 * * * *每分钟CronFormat.Standard
0 0/1 * * * ?每分钟CronFormat.IncludeSeconds
0 0 * * * ?每小时CronFormat.IncludeSeconds
0 0 0/1 * * ?每小时CronFormat.IncludeSeconds
0 23 ? * MON-FRI晚上 11:00,周一至周五CronFormat.Standard
* * * * * *每秒CronFormat.IncludeSeconds
*/45 * * * * *每 45 秒CronFormat.IncludeSeconds
*/5 * * * *每 5 分钟CronFormat.Standard
0 0/10 * * * ?每 10 分钟CronFormat.IncludeSeconds
0 */5 * * * *每 5 分钟CronFormat.IncludeSeconds
30 11 * * 1-5周一至周五上午 11:30CronFormat.Standard
30 11 * * *11:30CronFormat.Standard
0-10 11 * * *上午 11:00 至 11:10 之间的每一分钟CronFormat.Standard
* * * 3 *每分钟,只在 3 月份CronFormat.Standard
* * * 3,6 *每分钟,只在 3 月和 6 月CronFormat.Standard
30 14,16 * * *下午 02:30 分和 04:30 分CronFormat.Standard
30 6,14,16 * * *早上 06:30,下午 02:30 和 04:30CronFormat.Standard
46 9 * * 1早上 09:46,只在星期一CronFormat.Standard
23 12 15 * *下午 12:23,在本月的第 15 天CronFormat.Standard
23 12 * JAN *下午 12:23,只在 1 月份CronFormat.Standard
23 12 ? JAN *下午 12:23,只在 1 月份CronFormat.Standard
23 12 * JAN-FEB *下午 12:23,1 月至 2 月CronFormat.Standard
23 12 * JAN-MAR *下午 12:23,1 月至 3 月CronFormat.Standard
23 12 * * SUN下午 12:23,仅在星期天CronFormat.Standard
*/5 15 * * MON-FRI每 5 分钟,下午 0:00 至 03:59,周一至周五CronFormat.Standard
* * * * MON#3每分钟,在月的第三个星期一CronFormat.Standard
* * * * 4L每一分钟,在本月的最后一天CronFormat.Standard
*/5 * L JAN *每月一次每月 5 分钟,只在 1 月份CronFormat.Standard
30 02 14 * * *下午在 02:02:30CronFormat.IncludeSeconds
5-10 * * * * *每分钟的 5-10 秒CronFormat.IncludeSeconds
5-10 30-35 10-12 * * *10:00 至 12:00 之间的每分钟 5-10 秒,每小时 30-35 分钟CronFormat.IncludeSeconds
30 */5 * * * *每分钟的 30 秒,每五分钟CronFormat.IncludeSeconds
0 30 10-13 ? * WED,FRI每小时的 30 分钟,下午 10:00 至 01:00 之间,仅在周三和周五CronFormat.IncludeSeconds
10 0/5 * * * ?每分钟的 10 秒,每 05 分钟CronFormat.IncludeSeconds
0 0 6 1/1 * ?下午 06:00CronFormat.IncludeSeconds
0 5 0/1 * * ?一个小时的 05 分CronFormat.IncludeSeconds
0 0 L * *每月最后一天上午 00:00CronFormat.Standard
0 0 L-1 * *每月最后一天的凌晨 00:00CronFormat.Standard
0 0 3W * *每月第 3 个工作日上午 00:00CronFormat.Standard
0 0 LW * *在每月的最后一个工作日,上午 00:00CronFormat.Standard
0 0 * * 2L本月最后一个星期二上午 00:00CronFormat.Standard
0 0 * * 6#3每月第三个星期六上午 00:00CronFormat.Standard
0 0 ? 1 MON#11 月第一个星期一上午 00:00CronFormat.Standard
0 0 3 * * ?每天几点执行一次CronFormat.IncludeSeconds

26.5.3 在线生成 Cron 表达式

https://cron.qqe2.com/

26.5.4 Macro 标识符

为了方便定义 Cron 表达式,Furion 框架也提供了非常方便的占位符实现常用的时间格式:

占位符对应表达式占位符代表含义
@every_second* * * * * *一秒钟跑一次
@every_minute* * * * *在分钟开始时每分钟运行一次
@hourly0 * * * *在小时开始时每小时运行一次
@daily0 0 * * *每天午夜运行一次
@midnight0 0 * * *每天午夜运行一次
@weekly0 0 * * 0周日上午午夜每周运行一次
@monthly0 0 1 * *每月在每月第一天的午夜运行一次
@yearly0 0 1 1 *每年 1 月 1 日午夜运行一次
@annually0 0 1 1 *每年 1 月 1 日午夜运行一次

26.5.5 使用 Cron 表达式

// 每隔 1s 执行SpareTime.Do("* * * * * *", (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");}, cronFormat: CronFormat.IncludeSeconds);
关于 CronFormat

默认情况下,Furion 框架未启用对 的支持,如需开启,则设置 cronFormat: CronFormat.IncludeSeconds 即可。默认值是 cronFormat: CronFormat.Standard

26.5.6 使用 Macro 占位符

// 每隔 1s 执行SpareTime.Do("@every_second", (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");});

26.5.7 配置任务信息

SpareTime.Do("* * * * *", (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");}, "cronName", "每分钟执行一次");

26.5.8 手动启动执行

SpareTime.Do("* * * * *", (timer, count) => {    Console.WriteLine("现在时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");}, "cronName", "每分钟执行一次", startNow: false);SpareTime.Start("cronName");

26.5.9 ISpareTimeWorker 方式

public class JobWorker : ISpareTimeWorker{    /// <summary>    /// 每分钟执行    /// </summary>    /// <param name="timer"></param>    /// <param name="count"></param>    [SpareTime("* * * * *", "jobName", StartNow = true)]    public void DoSomething(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }    /// <summary>    /// 每分钟执行(支持异步)    /// </summary>    /// <param name="timer"></param>    /// <param name="count"></param>    [SpareTime("* * * * *", "jobName", StartNow = true)]    public async Task DoSomethingAsync(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");        await Task.Completed;    }}

26.6 自定义下次执行时间

有些时候我们需要进行一些业务逻辑,比如数据库查询等操作返回下一次执行时间,这个时候我们可以通过高级自定义方式。

26.6.1 高级自定义间隔方式

SpareTime.Do(()=>{    // 这里可以查询数据库或进行或进行任何业务逻辑    if(符合逻辑){        return 1000; // 每秒执行    }    else return -1; // 不符合逻辑取消任务},(timer,count)=>{    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");});
配置是否持续检查

默认情况下,该自定义会在返回 小于或等于0 时终止任务的执行。但是我们希望该任务不要终止,只要符合条件都一直执行,只需要配置 cancelInNoneNextTime: false 即可

26.6.2 高级自定义 Cron 表达式

SpareTime.Do(()=>{    // 这里可以查询数据库或进行或进行任何业务逻辑    if(符合逻辑){        return DateTimeOffset.Now.AddMinutes(10);  // 十分钟后再执行    }    else return null; // 不符合逻辑取消任务},(timer,count) => {    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");});
配置是否持续检查

默认情况下,该自定义会在返回 null 时终止任务的执行。但是我们希望该任务不要终止,只要符合条件都一直执行,只需要配置 cancelInNoneNextTime: false 即可,如:

SpareTime.Do(()=>{    // 这里可以查询数据库或进行或进行任何业务逻辑    if(符合逻辑){        return SpareTime.GetCronNextOccurrence("cron 表达式");    }    else return null; // 不符合逻辑继续检查},(timer,count) => {    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");}, cancelInNoneNextTime: false);

26.7 ISpareTimeWorker 说明

除了上面的 SpareTime 静态类方式,Furion 框架还提供了 ISpareTimeWorker 方式,使用该方式非常简单,只需要自定义一个公开且非抽象非静态类并实现 ISpareTimeWorker 即可。

在该类中定义的任务方法需满足以下规则:

  • 必须是公开且实例方法
  • 该方法必须返回 void 且提供 SpareTimerlong 两个参数
  • 必须贴有 [SpareTime] 特性

如:

public class JobWorker : ISpareTimeWorker{    // 每隔一秒执行,且立即启动    [SpareTime(1000, "jobName1", StartNow = true)]    public void DoSomething1(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }    // 每分钟执行,且立即启动    [SpareTime("* * * * *", "jobName2", StartNow = true)]    public void DoSomething2(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }    // 每秒执行,且等待启动    [SpareTime("* * * * * *", "jobName3",CronFormat = CronFormat.IncludeSeconds, StartNow = false)]    public void DoSomething3(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }    // 每秒执行一次,每分钟也执行一次    [SpareTime(1000, "jobName4", StartNow = true)]    [SpareTime("* * * * *", "jobName5", StartNow = true)]    public void DoSomething4(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }    // 只执行一次    [SpareTime(1000, "jobName5", StartNow = true, DoOnce = true)]    public void DoSomething5(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }    // 读取配置文件,通过 #(配置路径)    [SpareTime("#(MyJob:Time)", "jobName6", StartNow = true, DoOnce = true)]    public void DoSomething5(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");    }    // 支持异步    [SpareTime(1000, "jobName1", StartNow = true)]    public async Task DoSomethingAsync(SpareTimer timer, long count)    {        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));        Console.WriteLine($"一共执行了:{count} 次");        await Task.Completed;    }}
关于依赖注入

ISpareTimeWorker 接口主要是用来查找定时器对象的,也就是它的实现类并未提供依赖注入功能,所以在实现类并不支持构造函数注入依赖项。

26.7.1 [SpareTime] 特性

[SpareTime] 支持以下配置属性

  • Interval:间隔时间, double 类型
  • CronExpressionCron 表达式,string 类型
  • WorkerName:任务唯一标识,string 类型,必填
  • Description:任务描述,string 类型
  • DoOnce:是否只执行一次,bool 类型,默认 false
  • StartNow:是否立即启动,默认 false
  • CronFormatCron 表达式格式化方式,CronFormat 枚举类型,默认 CronFormat.Standard
  • ExecuteType:配置任务执行方式,SpareTimeExecuteTypes 枚举类型,默认 SpareTimeExecuteTypes.Parallel

26.8 SpareTime 静态类

SpareTime 静态类提供了一些方法方便初始化和管理任务

26.8.1 初始化任务

// 开启间隔任务SpareTime.Do(interval, [options]);// 开启 Cron 表达式任务SpareTime.Do(expression, [options]);// 只执行一次任务SpareTime.DoOnce(interval, [options]);// 实现自定义任务SpareTime.Do(()=>{    return DateTime.Now.AddMinutes(10);},[options]);

26.8.2 实现后台执行

// 实现后台执行SpareTime.DoIt(()=>{});

26.8.3 开始一个任务

SpareTime.Start("任务标识");

26.8.4 暂停一个任务

SpareTime.Stop("任务标识");// 还可以标记一个任务执行失败SpareTime.Stop("任务标识", true);

26.8.5 取消一个任务

SpareTime.Cancel("任务名称");

26.8.6 销毁所有任务

SpareTime.Dispose();

26.8.7 获取所有任务

var workers = SpareTime.GetWorkers();

26.8.8 获取单个任务

var worker = SpareTime.GetWorker("workerName");

26.8.9 解析 Cron 表达式

var nextTime = SpareTime.GetCronNextOccurrence("* * * * *");

26.9 并行串行执行方式

Furion 框架提供了任务两种执行方式 并行串行

  • 并行:无需等待上一次任务完成,默认值
  • 串行:需等待上一次任务完成

26.9.1 SpareTime 静态方式指定

SpareTime.Do(1000, (t, i) =>{    Thread.Sleep(5000); // 模拟执行耗时任务    Console.WriteLine($"{t.WorkerName} -{t.Description} - {DateTime.Now:yyyy-MM-dd HH:mm:ss} - {i}");}, "serialName", "模拟串行任务", executeType: SpareTimeExecuteTypes.Serial);

26.9.2 ISpareTimeWorker 方式

[SpareTime(1000, "jobName1", StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]public void DoSomething1(SpareTimer timer, long count){    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    Console.WriteLine($"一共执行了:{count} 次");}

26.10 任务异常处理

有些时候我们可能在执行任务过程中出现异常,Furion 也提供了属性判断是否有异常和异常信息,方便记录到日志中,如:

SpareTime.Do(1000, (t, c) =>{    // 判断是否有异常    if (t.Exception.Any())    {        Console.WriteLine(t.Exception.Values.LastOrDefault()?.Message);    }    // 执行第三次抛异常    if (c > 2)    {        throw Oops.Oh("抛异常" + c);    }    else    {        Console.WriteLine($"{t.WorkerName} -{t.Description} - {DateTime.Now:yyyy-MM-dd HH:mm:ss} - {c}");    }}, "exceptionJob");
特别说明

如果一个任务连续错误次数达 10次 则任务将自动停止,并标记任务状态为 Failed

26.11 如何在任务中解析对象

有些时候我们需要在任务中进行数据库操作或解析服务,这时候我们只需要创建一个新的作用域即可

26.11.1 SpareTime 静态类中

SpareTime.Do(1000, (timer,count) => {    Scoped.Create((_, scope) =>    {        var services = scope.ServiceProvider;        // 获取数据库上下文        var dbContext = Db.GetDbContext(services);        // 获取仓储        var respository = Db.GetRepository<Person>(services);        // 解析其他服务        var otherService = services.GetService<XXX>();        var otherService2 = App.GetService<XXX>(services);    });}, "任务标识");

26.11.2 ISpareTimeWorker 方式

[SpareTime(1000, "jobName1", StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]public void DoSomething1(SpareTimer timer, long count){    Scoped.Create((_, scope) =>    {        var services = scope.ServiceProvider;        // 获取数据库上下文        var dbContext = Db.GetDbContext(services);        // 获取仓储        var respository = Db.GetRepository<Person>(services);        // 解析其他服务        var otherService = services.GetService<XXX>();        var otherService2 = App.GetService<XXX>(services);    });}
数据库操作注意

如果作用域中对数据库有任何变更操作,需手动调用 SaveChanges 或带 Now 结尾的方法。也可以使用 Scoped.CreateUow(handler) 代替。

26.12 在 BackgroundService 中使用

BackgroundService.NET Core 3 之后提供的轻量级后台任务,同时可以发布到 Windows 服务和 Linux 守护进程中。

26.12.1 间隔执行方式

namespace WorkerService;public class Worker : BackgroundService{    private readonly ILogger<Worker> _logger;    private const int delay = 1000;    public Worker(ILogger<Worker> logger)    {        _logger = logger;    }    protected override async Task ExecuteAsync(CancellationToken stoppingToken)    {        while (!stoppingToken.IsCancellationRequested)        {            var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);            await taskFactory.StartNew(async () =>            {                // 你的业务代码写到这里面                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);                await Task.CompletedTask;            }, stoppingToken);            await Task.Delay(delay, stoppingToken);        }    }}

26.12.2 Cron 表达式执行方式

using Furion.TimeCrontab;namespace WorkerService;public class Worker : BackgroundService{    private readonly ILogger<Worker> _logger;    private readonly Crontab _crontab;    public Worker(ILogger<Worker> logger)    {        _logger = logger;        _crontab = Crontab.Parse("* * * * * *", CronStringFormat.WithSeconds);    }    protected override async Task ExecuteAsync(CancellationToken stoppingToken)    {        while (!stoppingToken.IsCancellationRequested)        {            var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);            await taskFactory.StartNew(async () =>            {                // 你的业务代码写到这里面                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);                await Task.CompletedTask;            }, stoppingToken);            await Task.Delay(_crontab.GetSleepMilliseconds(DateTime.UtcNow), stoppingToken);        }    }}

26.13 定时任务监听器

Furion v2.18+ 版本之后新增了定时任务监听器 ISpareTimeListener,通过监听器可以实现所有定时任务的状态。如,创建一个 单例 的监听器 SpareTimeListener

using Furion.DependencyInjection;using Furion.TaskScheduler;using System;using System.Threading.Tasks;namespace Furion.Core{    public class SpareTimeListener : ISpareTimeListener, ISingleton    {        /// <summary>        /// 监听所有任务        /// </summary>        /// <param name="executer"></param>        /// <returns></returns>        public Task OnListener(SpareTimerExecuter executer)        {            switch (executer.Status)            {                // 执行开始通知                case 0:                    Console.WriteLine($"{executer.Timer.WorkerName} 任务开始通知");                    break;                // 任务执行之前通知                case 1:                    Console.WriteLine($"{executer.Timer.WorkerName} 执行之前通知");                    break;                // 执行成功通知                case 2:                    Console.WriteLine($"{executer.Timer.WorkerName} 执行成功通知");                    break;                // 任务执行失败通知                case 3:                    Console.WriteLine($"{executer.Timer.WorkerName} 执行失败通知");                    break;                // 任务执行停止通知                case -1:                    Console.WriteLine($"{executer.Timer.WorkerName} 执行停止通知");                    break;                // 任务执行取消通知                case -2:                    Console.WriteLine($"{executer.Timer.WorkerName} 执行取消通知");                    break;                default:                    break;            }            return Task.CompletedTask;        }    }}

26.13.1 SpareTimerExecuter 属性说明

  • TimerSpareTimer 定时器对象
  • Status:监听状态
    • 0:任务开始
    • 1:执行之前
    • 2:执行成功
    • 3:执行失败
    • -1:任务停止
    • -2:任务取消

26.14 IIS 部署回收设置

如果在项目中使用了定时任务且部署到 IIS 中,那么需要设置 IIS 禁止回收,如:

部署建议

建议定时任务采用 Worker Service 独立部署方式,不应依托 Web 项目进程中。查看【 Worker Service】章节

26.15 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/json-serialization/index.html b/handbook/build/docs/json-serialization/index.html index d9b347fbbe..f3df8415b1 100644 --- a/handbook/build/docs/json-serialization/index.html +++ b/handbook/build/docs/json-serialization/index.html @@ -2,22 +2,21 @@ - - - + +23. JSON 序列化 | Furion -23. JSON 序列化 | Furion - - + + +
-

23. JSON 序列化

版本说明

以下内容仅限 Furion 1.16.0 + 版本使用。

23.1 什么是 JSON

JSON (JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。它基于 ECMAScript (w3c 制定的 js 规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

简单来说,JSON,是一种数据格式,在与后端的数据交互中有较为广泛的应用。

23.2 关于序列化库

目前在 C# 语言中有两个主流的 JSON 序列化操作库:

  • System.Text.Json.NET Core 内置 JSON 序列化库,也是 Furion 框架默认实现
  • Newtonsoft.Json:目前使用人数最多的 JSON 序列化库,需要安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson 拓展包

由于目前 System.Text.Json 相比 Newtonsoft.Json 功能和稳定性有许多不足之处,比如循环引用问题在 System.Text.Json 无解。但在 .NET 6 之后得到解决。

Furion 框架为了解决多种序列化工具配置和用法上的差异问题,抽象出了 IJsonSerializerProvider 接口。

23.3 IJsonSerializerProvider 接口

Furion 框架提供了 IJsonSerializerProvider 接口规范,同时要求实现该接口的实体都必须采用单例模式,该接口定义代码如下:

namespace Furion.JsonSerialization{    /// <summary>    /// Json 序列化提供器    /// </summary>    public interface IJsonSerializerProvider    {        /// <summary>        /// 序列化对象        /// </summary>        /// <param name="value"></param>        /// <param name="jsonSerializerOptions"></param>        /// <returns></returns>        string Serialize(object value, object jsonSerializerOptions = default);        /// <summary>        /// 反序列化字符串        /// </summary>        /// <typeparam name="T"></typeparam>        /// <param name="json"></param>        /// <param name="jsonSerializerOptions"></param>        /// <returns></returns>        T Deserialize<T>(string json, object jsonSerializerOptions = default);        /// <summary>        /// 返回读取全局配置的 JSON 选项        /// </summary>        /// <returns></returns>        object GetSerializerOptions();    }}
默认实现

SystemTextJsonSerializerProvider 类是 IJsonSerializerProvider 接口的默认实现,在应用启动时已默认注册。

23.4 如何使用

23.4.1 获取序列化对象

Furion 框架提供了两种方式获取 IJsonSerializerProvider 实例:

  • 构造函数注入 IJsonSerializerProvider
  • 静态类 JSON.GetJsonSerializer() 方式,查看 JSON 静态类

如:

using Furion.DynamicApiController;using Furion.JsonSerialization;namespace Furion.Application{    public class JsonDemo : IDynamicApiController    {        private readonly IJsonSerializerProvider _jsonSerializer;        private readonly IJsonSerializerProvider _jsonSerializer2;        public JsonDemo(IJsonSerializerProvider jsonSerializer)        {            _jsonSerializer = jsonSerializer;            _jsonSerializer2 = JSON.GetJsonSerializer();        }    }}

23.4.2 序列化对象

public string GetText(){    return _jsonSerializer.Serialize(new    {        Id = 1,        Name = "Furion"    });}

23.4.3 反序列化字符串

public object GetObject(){    var json = "{\"Id\":1,\"Name\":\"Furion\"}";    var obj = _jsonSerializer.Deserialize<object>(json);    return obj;}
特别注意

System.Text.Json 默认反序列化大小写敏感,也就是不完全匹配的属性名称不会自动赋值。这时候我们可以全局配置或单独配置。

  • 全局配置
services.AddControllersWithViews()        .AddJsonOptions(options => {            options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;        });
  • 单独配置
var obj = _jsonSerializer.Deserialize<object>(json, new JsonSerializerOptions   {       PropertyNameCaseInsensitive = true   });

23.4.4 序列化更多配置

Furion 框架不推荐一个框架中有多种序列化实现类,也就是说使用 System.Text.Json 就不要使用 Newtonsoft.Json,反之亦然。

如需配置更多选项,只需创建 JsonSerializerOptions 配置对象即可,如:

var json =  _jsonSerializer.Serialize(new            {                Id = 1,                Name = "Furion"            }, new JsonSerializerOptions {                WriteIndented = true            });

23.5 高级用法

23.5.1 自定义序列化提供器

正如上文所说,Furion 默认的 IJsonSerializerProvider 实现方式是 System.Text.Json 库,如需替换为 Newtonsoft.Json,只需以下步骤即可:

  1. 安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson 拓展,并在 Startup.cs 中注册
services.AddControllersWithViews()        .AddNewtonsoftJson();
  1. 实现 IJsonSerializerProvider 提供器
using Furion.DependencyInjection;using Furion.JsonSerialization;using Newtonsoft.Json;namespace Furion.Core{    /// <summary>    /// Newtonsoft.Json 实现    /// </summary>    public class NewtonsoftJsonSerializerProvider : IJsonSerializerProvider, ISingleton    {        /// <summary>        /// 序列化对象        /// </summary>        /// <param name="value"></param>        /// <param name="jsonSerializerOptions"></param>        /// <returns></returns>        public string Serialize(object value, object jsonSerializerOptions = null)        {            return JsonConvert.SerializeObject(value, (jsonSerializerOptions ?? GetSerializerOptions()) as JsonSerializerSettings);        }        /// <summary>        /// 反序列化字符串        /// </summary>        /// <typeparam name="T"></typeparam>        /// <param name="json"></param>        /// <param name="jsonSerializerOptions"></param>        /// <returns></returns>        public T Deserialize<T>(string json, object jsonSerializerOptions = null)        {            return JsonConvert.DeserializeObject<T>(json, (jsonSerializerOptions ?? GetSerializerOptions()) as JsonSerializerSettings);        }        /// <summary>        /// 返回读取全局配置的 JSON 选项        /// </summary>        /// <returns></returns>        public object GetSerializerOptions()        {            return App.GetOptions<MvcNewtonsoftJsonOptions>()?.SerializerSettings;        }    }}

23.5.2 序列化属性名大写(属性原样输出)

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options => {            options.JsonSerializerOptions.PropertyNamingPolicy = null;            // options.JsonSerializerOptions.DictionaryKeyPolicy = null;    // 配置 Dictionary 类型序列化输出        });
  • Newtonsoft.Json 方式
services.AddControllersWithViews()        .AddNewtonsoftJson(options =>        {            options.SerializerSettings.ContractResolver = new DefaultContractResolver();        });
特别注意

采用 Newtonsoft.Json 方式接口返回值能够正常输出,但是 Swagger 界面中的 Example Values 依然显示小写字母开头的属性,这时只需要再添加 System.Text.Json 配置即可,如:

.AddJsonOptions(options => {            options.JsonSerializerOptions.PropertyNamingPolicy = null;        });

主要原因是 Swagger 拓展包底层依赖了 System.Text.Json

23.5.3 时间格式化

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options =>        {            options.JsonSerializerOptions.Converters.AddDateFormatString("yyyy-MM-dd HH:mm:ss");        });
小提示

如果使用使用了 DateTimeOffset 类型,那么可以设置 .AddDateFormatString("yyyy-MM-dd HH:mm:ss", true) 第二个参数为 true,自动转换成本地时间。

如果使用了 Mysql 数据库,且使用了 Pomelo.EntityFrameworkCore.MySql 包,那么会出现时区问题,比如少 8 小时,可以尝试配置第二个参数为 true

需引用 System.Text.Json 命名空间。

  • Newtonsoft.Json 方式
services.AddControllersWithViews()        .AddNewtonsoftJson(options =>        {            options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";        });

23.5.4 忽略循环引用

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options =>        {            options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;        });
特别说明

.NET 5 中,System.Text.Json 并不支持处理循环引用问题,以上的解决方案仅限用于 .NET 6 Preview 2+。😂

需引用 System.Text.Json 命名空间。

  • Newtonsoft.Json 方式
services.AddControllersWithViews()        .AddNewtonsoftJson(options =>        {            options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;        });

23.5.5 包含成员字段序列化

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options =>        {            options.JsonSerializerOptions.IncludeFields = true;        });

需引用 System.Text.Json 命名空间。

  • Newtonsoft.Json 方式

无需配置。

23.5.6 允许尾随逗号

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options =>        {            options.JsonSerializerOptions.AllowTrailingCommas = true;        });

需引用 System.Text.Json 命名空间。

  • Newtonsoft.Json 方式

无需配置。

23.5.7 允许注释

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options =>        {            options.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip;        });

需引用 System.Text.Json 命名空间。

  • Newtonsoft.Json 方式

无需配置。

23.5.8 处理乱码问题

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options =>        {            options.JsonSerializerOptions.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping;        });

需引用 System.Text.Json 命名空间。

  • Newtonsoft.Json 方式

无需配置。

23.5.9 不区分大小写

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options =>        {            options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;        });

需引用 System.Text.Json 命名空间。

  • Newtonsoft.Json 方式
更多序列化配置

这里只列举常用见的序列化配置,如需查看更多配置,可查阅 System.Text.Json 文档

23.5.10 忽略特定属性序列化

有时候我们不希望对象中某个对象被序列化出来或者不想在 Swagger 中显示,这时候只需要在属性贴该特性即可:

[Newtonsoft.Json.JsonIgnore]    // 针对 Newtonsoft[System.Text.Json.Serialization.JsonIgnore] // 针对 System.Text.Jsonpublic string PropertyName {get; set;}

23.5.11 动态对象属性名大写问题

有时候使用了动态对象后发现属性名出现了大写情况(首字母),这个时候可以尝试使用以下方法解决:

.AddNewtonsoftJson(options =>{    options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();})

23.6 DataTableDataSetTuple 元组等序列化问题

由于默认 Furion 采用 System.Text.Json 进行序列化,但是不支持复杂类型,如 DataTableDataSetTuple 元组,所以需要更换成 NewtonsoftJson 即可,见 JSON 序列化 - 23.5.1 自定义序列化提供器

23.7 System.Text.JsonNewtonsoft.Json 完整差异化对比

https://docs.microsoft.com/zh-cn/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to?pivots=dotnet-5-0

23.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

23. JSON 序列化

版本说明

以下内容仅限 Furion 1.16.0 + 版本使用。

23.1 什么是 JSON

JSON (JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。它基于 ECMAScript (w3c 制定的 js 规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

简单来说,JSON,是一种数据格式,在与后端的数据交互中有较为广泛的应用。

23.2 关于序列化库

目前在 C# 语言中有两个主流的 JSON 序列化操作库:

  • System.Text.Json.NET Core 内置 JSON 序列化库,也是 Furion 框架默认实现
  • Newtonsoft.Json:目前使用人数最多的 JSON 序列化库,需要安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson 拓展包

由于目前 System.Text.Json 相比 Newtonsoft.Json 功能和稳定性有许多不足之处,比如循环引用问题在 System.Text.Json 无解。但在 .NET 6 之后得到解决。

Furion 框架为了解决多种序列化工具配置和用法上的差异问题,抽象出了 IJsonSerializerProvider 接口。

23.3 IJsonSerializerProvider 接口

Furion 框架提供了 IJsonSerializerProvider 接口规范,同时要求实现该接口的实体都必须采用单例模式,该接口定义代码如下:

namespace Furion.JsonSerialization{    /// <summary>    /// Json 序列化提供器    /// </summary>    public interface IJsonSerializerProvider    {        /// <summary>        /// 序列化对象        /// </summary>        /// <param name="value"></param>        /// <param name="jsonSerializerOptions"></param>        /// <returns></returns>        string Serialize(object value, object jsonSerializerOptions = default);        /// <summary>        /// 反序列化字符串        /// </summary>        /// <typeparam name="T"></typeparam>        /// <param name="json"></param>        /// <param name="jsonSerializerOptions"></param>        /// <returns></returns>        T Deserialize<T>(string json, object jsonSerializerOptions = default);        /// <summary>        /// 返回读取全局配置的 JSON 选项        /// </summary>        /// <returns></returns>        object GetSerializerOptions();    }}
默认实现

SystemTextJsonSerializerProvider 类是 IJsonSerializerProvider 接口的默认实现,在应用启动时已默认注册。

23.4 如何使用

23.4.1 获取序列化对象

Furion 框架提供了两种方式获取 IJsonSerializerProvider 实例:

  • 构造函数注入 IJsonSerializerProvider
  • 静态类 JSON.GetJsonSerializer() 方式,查看 JSON 静态类

如:

using Furion.DynamicApiController;using Furion.JsonSerialization;namespace Furion.Application{    public class JsonDemo : IDynamicApiController    {        private readonly IJsonSerializerProvider _jsonSerializer;        private readonly IJsonSerializerProvider _jsonSerializer2;        public JsonDemo(IJsonSerializerProvider jsonSerializer)        {            _jsonSerializer = jsonSerializer;            _jsonSerializer2 = JSON.GetJsonSerializer();        }    }}

23.4.2 序列化对象

public string GetText(){    return _jsonSerializer.Serialize(new    {        Id = 1,        Name = "Furion"    });}

23.4.3 反序列化字符串

public object GetObject(){    var json = "{\"Id\":1,\"Name\":\"Furion\"}";    var obj = _jsonSerializer.Deserialize<object>(json);    return obj;}
特别注意

System.Text.Json 默认反序列化大小写敏感,也就是不完全匹配的属性名称不会自动赋值。这时候我们可以全局配置或单独配置。

  • 全局配置
services.AddControllersWithViews()        .AddJsonOptions(options => {            options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;        });
  • 单独配置
var obj = _jsonSerializer.Deserialize<object>(json, new JsonSerializerOptions   {       PropertyNameCaseInsensitive = true   });

23.4.4 序列化更多配置

Furion 框架不推荐一个框架中有多种序列化实现类,也就是说使用 System.Text.Json 就不要使用 Newtonsoft.Json,反之亦然。

如需配置更多选项,只需创建 JsonSerializerOptions 配置对象即可,如:

var json =  _jsonSerializer.Serialize(new            {                Id = 1,                Name = "Furion"            }, new JsonSerializerOptions {                WriteIndented = true            });

23.5 高级用法

23.5.1 自定义序列化提供器

正如上文所说,Furion 默认的 IJsonSerializerProvider 实现方式是 System.Text.Json 库,如需替换为 Newtonsoft.Json,只需以下步骤即可:

  1. 安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson 拓展,并在 Startup.cs 中注册
services.AddControllersWithViews()        .AddNewtonsoftJson();
  1. 实现 IJsonSerializerProvider 提供器
using Furion.DependencyInjection;using Furion.JsonSerialization;using Newtonsoft.Json;namespace Furion.Core{    /// <summary>    /// Newtonsoft.Json 实现    /// </summary>    public class NewtonsoftJsonSerializerProvider : IJsonSerializerProvider, ISingleton    {        /// <summary>        /// 序列化对象        /// </summary>        /// <param name="value"></param>        /// <param name="jsonSerializerOptions"></param>        /// <returns></returns>        public string Serialize(object value, object jsonSerializerOptions = null)        {            return JsonConvert.SerializeObject(value, (jsonSerializerOptions ?? GetSerializerOptions()) as JsonSerializerSettings);        }        /// <summary>        /// 反序列化字符串        /// </summary>        /// <typeparam name="T"></typeparam>        /// <param name="json"></param>        /// <param name="jsonSerializerOptions"></param>        /// <returns></returns>        public T Deserialize<T>(string json, object jsonSerializerOptions = null)        {            return JsonConvert.DeserializeObject<T>(json, (jsonSerializerOptions ?? GetSerializerOptions()) as JsonSerializerSettings);        }        /// <summary>        /// 返回读取全局配置的 JSON 选项        /// </summary>        /// <returns></returns>        public object GetSerializerOptions()        {            return App.GetOptions<MvcNewtonsoftJsonOptions>()?.SerializerSettings;        }    }}

23.5.2 序列化属性名大写(属性原样输出)

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options => {            options.JsonSerializerOptions.PropertyNamingPolicy = null;            // options.JsonSerializerOptions.DictionaryKeyPolicy = null;    // 配置 Dictionary 类型序列化输出        });
  • Newtonsoft.Json 方式
services.AddControllersWithViews()        .AddNewtonsoftJson(options =>        {            options.SerializerSettings.ContractResolver = new DefaultContractResolver();        });
特别注意

采用 Newtonsoft.Json 方式接口返回值能够正常输出,但是 Swagger 界面中的 Example Values 依然显示小写字母开头的属性,这时只需要再添加 System.Text.Json 配置即可,如:

.AddJsonOptions(options => {            options.JsonSerializerOptions.PropertyNamingPolicy = null;        });

主要原因是 Swagger 拓展包底层依赖了 System.Text.Json

23.5.3 时间格式化

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options =>        {            options.JsonSerializerOptions.Converters.AddDateFormatString("yyyy-MM-dd HH:mm:ss");        });
小提示

如果使用使用了 DateTimeOffset 类型,那么可以设置 .AddDateFormatString("yyyy-MM-dd HH:mm:ss", true) 第二个参数为 true,自动转换成本地时间。

如果使用了 Mysql 数据库,且使用了 Pomelo.EntityFrameworkCore.MySql 包,那么会出现时区问题,比如少 8 小时,可以尝试配置第二个参数为 true

需引用 System.Text.Json 命名空间。

  • Newtonsoft.Json 方式
services.AddControllersWithViews()        .AddNewtonsoftJson(options =>        {            options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";        });

23.5.4 忽略循环引用

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options =>        {            options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;        });
特别说明

.NET 5 中,System.Text.Json 并不支持处理循环引用问题,以上的解决方案仅限用于 .NET 6 Preview 2+。😂

需引用 System.Text.Json 命名空间。

  • Newtonsoft.Json 方式
services.AddControllersWithViews()        .AddNewtonsoftJson(options =>        {            options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;        });

23.5.5 包含成员字段序列化

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options =>        {            options.JsonSerializerOptions.IncludeFields = true;        });

需引用 System.Text.Json 命名空间。

  • Newtonsoft.Json 方式

无需配置。

23.5.6 允许尾随逗号

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options =>        {            options.JsonSerializerOptions.AllowTrailingCommas = true;        });

需引用 System.Text.Json 命名空间。

  • Newtonsoft.Json 方式

无需配置。

23.5.7 允许注释

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options =>        {            options.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip;        });

需引用 System.Text.Json 命名空间。

  • Newtonsoft.Json 方式

无需配置。

23.5.8 处理乱码问题

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options =>        {            options.JsonSerializerOptions.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping;        });

需引用 System.Text.Json 命名空间。

  • Newtonsoft.Json 方式

无需配置。

23.5.9 不区分大小写

  • System.Text.Json 方式
services.AddControllersWithViews()        .AddJsonOptions(options =>        {            options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;        });

需引用 System.Text.Json 命名空间。

  • Newtonsoft.Json 方式
更多序列化配置

这里只列举常用见的序列化配置,如需查看更多配置,可查阅 System.Text.Json 文档

23.5.10 忽略特定属性序列化

有时候我们不希望对象中某个对象被序列化出来或者不想在 Swagger 中显示,这时候只需要在属性贴该特性即可:

[Newtonsoft.Json.JsonIgnore]    // 针对 Newtonsoft[System.Text.Json.Serialization.JsonIgnore] // 针对 System.Text.Jsonpublic string PropertyName {get; set;}

23.5.11 动态对象属性名大写问题

有时候使用了动态对象后发现属性名出现了大写情况(首字母),这个时候可以尝试使用以下方法解决:

.AddNewtonsoftJson(options =>{    options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();})

23.6 DataTableDataSetTuple 元组等序列化问题

由于默认 Furion 采用 System.Text.Json 进行序列化,但是不支持复杂类型,如 DataTableDataSetTuple 元组,所以需要更换成 NewtonsoftJson 即可,见 JSON 序列化 - 23.5.1 自定义序列化提供器

23.7 System.Text.JsonNewtonsoft.Json 完整差异化对比

https://docs.microsoft.com/zh-cn/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to?pivots=dotnet-5-0

23.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/jsonschema/index.html b/handbook/build/docs/jsonschema/index.html index b153d3f7d4..cb626f1e2e 100644 --- a/handbook/build/docs/jsonschema/index.html +++ b/handbook/build/docs/jsonschema/index.html @@ -2,22 +2,21 @@ - - - + +2.7 JSON Schema 使用 | Furion -2.7 JSON Schema 使用 | Furion - - + + +
-

2.7 JSON Schema 使用

2.7.1 关于 JSON Schema

JSON Schema 是用于验证 JSON 数据结构的强大工具,Schema 可以理解为模式或者规则。

有了 JSON Schema 再也不怕配置写错的情况了!

2.7.2 学习 JSON Schema 编写

作为一个框架提供 JSON Schema 是非常有必要的,可以让开发者在添加配置的时候能够有智能提示和校验功能,如果想学习 JSON Schema 编写可以查看以下文档:

这里也提供一个非常便捷的创建 JSON Schema 的在线网站,可以根据 json 文件内容自动生成 JSON Schema,之后进行小量修改即可:

https://hellosean1025.github.io/json-schema-visual-editor/

2.7.3 框架提供

Furion 框架提供了完整的 FurionASP.NET CoreJSON Schema 文件,通过该文件可以在编写配置文件时提供完整的智能提示和校验。

查看 JSON Schema 源码地址

2.7.4 如何使用

使用方式非常简单,只需要在 .json 文件的头部添加 "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json", 即可,如:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json",  "Logging": {    "LogLevel": {      "Default": "Information",      "Microsoft": "Warning",      "Microsoft.Hosting.Lifetime": "Information",      "Microsoft.EntityFrameworkCore": "Information",      "Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"    }  },  "AllowedHosts": "*"}

2.7.5 JSON Schema 失效解决

如果添加了 "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json", 依然无法进行智能提示校验,可尝试关闭 .json 文件再重新打开。

如果上面步骤依然无效,那么还可以通过下面方式:

2.7.5.1 Visual Studio

2.7.5.2 Visual Studio Code

重启 Visual Studio Code 即可。

2.7.6 如何更新 JSON Schema

默认情况下,JSON Schema 在第一次获取之后会自动缓存起来,可能会导致 .json 文件提示错误,这个时候只需要删除缓存即可。

2.7.6.1 Visual Studio

打开电脑的 运行 并输入 %AppData%,之后进入 C:\Users\你的电脑用户名\AppData\Local\Microsoft\VisualStudio

之后删除 http/https 开头的文件即可。

2.7.6.2 Visual Studio Code

同上,运行进入 %AppData%,之后进入下列路径:C:\Users\你的电脑用户名\AppData\Roaming\Code\User\globalStorage\vscode.json-language-features\json-schema-cache

之后删除这些文件即可。

2.7.7 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

2.7 JSON Schema 使用

2.7.1 关于 JSON Schema

JSON Schema 是用于验证 JSON 数据结构的强大工具,Schema 可以理解为模式或者规则。

有了 JSON Schema 再也不怕配置写错的情况了!

2.7.2 学习 JSON Schema 编写

作为一个框架提供 JSON Schema 是非常有必要的,可以让开发者在添加配置的时候能够有智能提示和校验功能,如果想学习 JSON Schema 编写可以查看以下文档:

这里也提供一个非常便捷的创建 JSON Schema 的在线网站,可以根据 json 文件内容自动生成 JSON Schema,之后进行小量修改即可:

https://hellosean1025.github.io/json-schema-visual-editor/

2.7.3 框架提供

Furion 框架提供了完整的 FurionASP.NET CoreJSON Schema 文件,通过该文件可以在编写配置文件时提供完整的智能提示和校验。

查看 JSON Schema 源码地址

2.7.4 如何使用

使用方式非常简单,只需要在 .json 文件的头部添加 "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json", 即可,如:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json",  "Logging": {    "LogLevel": {      "Default": "Information",      "Microsoft": "Warning",      "Microsoft.Hosting.Lifetime": "Information",      "Microsoft.EntityFrameworkCore": "Information",      "Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"    }  },  "AllowedHosts": "*"}

2.7.5 JSON Schema 失效解决

如果添加了 "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json", 依然无法进行智能提示校验,可尝试关闭 .json 文件再重新打开。

如果上面步骤依然无效,那么还可以通过下面方式:

2.7.5.1 Visual Studio

2.7.5.2 Visual Studio Code

重启 Visual Studio Code 即可。

2.7.6 如何更新 JSON Schema

默认情况下,JSON Schema 在第一次获取之后会自动缓存起来,可能会导致 .json 文件提示错误,这个时候只需要删除缓存即可。

2.7.6.1 Visual Studio

打开电脑的 运行 并输入 %AppData%,之后进入 C:\Users\你的电脑用户名\AppData\Local\Microsoft\VisualStudio

之后删除 http/https 开头的文件即可。

2.7.6.2 Visual Studio Code

同上,运行进入 %AppData%,之后进入下列路径:C:\Users\你的电脑用户名\AppData\Roaming\Code\User\globalStorage\vscode.json-language-features\json-schema-cache

之后删除这些文件即可。

2.7.7 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/local-language/index.html b/handbook/build/docs/local-language/index.html index d481c8e5b3..5d023644c0 100644 --- a/handbook/build/docs/local-language/index.html +++ b/handbook/build/docs/local-language/index.html @@ -2,22 +2,21 @@ - - - + +21. 全球化和本地化 | Furion -21. 全球化和本地化 | Furion - - + + +
-

21. 全球化和本地化

21.1 全球化和本地化

全球化 是设计支持不同区域性的应用程序的过程。 全球化添加了对一组有关特定地理区域的已定义语言脚本的输入、显示和输出支持。

本地化 是将已经针对可本地化性进行处理的全球化应用调整为特定的区域性/区域设置的过程。

通俗来说,就是使应用或系统支持多语言切换。Furion 框架提供了完整支持多语言处理的服务。

21.2 注册服务

在使用多语言服务之前,必须先注册服务,如:

public void ConfigureServices(IServiceCollection services){    services.AddControllersWithViews()            .AddAppLocalization();  // 注册多语言}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){    if (env.IsDevelopment())    {        app.UseDeveloperExceptionPage();    }    // 配置多语言,必须在 路由注册之前    app.UseAppLocalization();    app.UseStaticFiles();    app.UseRouting();    // 其他中间件}
特别注意

app.UseAppLocalization(); 必须在 app.UseRouting(); 之前注册。

21.3 如何使用

21.3.1 配置 LocalizationSettings

添加 LocalizationSettings 配置选项:

{  "LocalizationSettings": {    "SupportedCultures": ["zh-CN", "en-US"], // 配置支持的语言列表    "DefaultCulture": "zh-CN" // 配置默认语言,如果不配置,取 SupportedCultures 的第一项  }}

21.3.2 创建 Resources 文件夹

接下来在 Web启动项目层 添加 Resources 文件夹,如图:(可配置放置任意层,见配置 AssemblyName

21.4 L 静态类

Furion 框架主要通过 L 静态类完成多语言转换,该静态类有以下属性和方法:

  • L.Text[文本]:转换文本多语言
  • L.Html[HTML代码, 格式化]:转换 Html 多语言
  • L.SetCulture(区域码):设置当前语言区域
  • L.GetSelectCulture():获取当前的语言区域
  • L.GetCultures():获取系统支持的多语言列表

21.5 使用例子

通过上面的配置步骤之后,我们就可以通过 L 静态类在代码任何位置使用了,如:

21.5.1 在类中使用

// 文本多语言var apiInterface = L.Text["API 接口"];var sourceCode = L.Text["源码地址"];// HTML 标记多语言var name = L.Html["<b>Hello</b><i> {0}</i>", name];

21.5.2 在视图中使用

@using Furion.Localization<div style="text-align:center;margin-top:50px;">  <p>让 .NET 开发更简单,更通用,更流行。</p>  <p>    <a href="/api">@L.Text["API 接口"]</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a      href="https://gitee.com/dotnetchina/Furion"      target="_blank"      >@L.Text["源码地址"]</a    >  </p></div>

21.5.3 在验证特性中使用

[Required(ErrorMessage = "必填消息")]

所有验证特性已经自动支持多语言配置了,无需通过 L.Text[] 调用。

21.5.4 在异常消息中使用

using Furion.FriendlyException;namespace Furion.Application{    [ErrorCodeType]    public enum ErrorCodes    {        [ErrorCodeItemMetadata("用户名不能为空")]        z1000    }}

所有异常消息特性已经自动支持多语言配置了,无需通过 L.Text[] 调用。

throw Oops.Oh(ErrorCodes.z1000);    // 自动应用多语言

21.5.5 SharedResource 模式

版本说明

以下内容仅限 Furion 4.3.7 + 版本使用。

正常情况下,我们都是通过 L.Text["Hello"] 方式输出 Hello 在不同的区域语言的翻译,但是会导致 Hello 硬编码字符串散落到处都是。

所以 Furion 提供了 SharedResource 模式,只需要创建一个 SharedResource.cs 类(可以任何名字)并添加对应的属性即可,如:

namespace Furion.Core;public class SharedResource{    public string Hello { get; set; }    public string Name { get; set; }}

使用如下:

var hello = L.GetString<SharedResource>(u => u.Hello);  // 比 L.Text["Hello"]; 容易维护var name = L.GetString<SharedResource>(u => u.Name);  // 比 L.Text["Name"]; 容易维护

当然也有更简单的方式,就是使用 nameof,如:

var hello = L.Text[nameof(SharedResource.Hello)];  // 比 L.Text["Hello"]; 容易维护var name = L.Text[nameof(SharedResource.Name)];  // 比 L.Text["Name"]; 容易维护

21.6 创建语言翻译文件

Furion 框架中,如果没找到对应的语言翻译文件,则自动显示字符串文本,如:

L.Text["没找到"];   // => 如果设置为英文,但是没有文件,则直接输出 “没找到”

21.6.1 在 Resources 文件夹中创建语言文件

接下来,我们只需要在刚刚的 Resources 文件夹中添加 资源文件 即可,资源文件命名规则:Lang.区域码.resx,如:Lang.en-US.resx

接下来,只需要把对应语言版本的键值对填写即可。

自定义资源文件名或存放程序集

默认情况下,资源文件名必须以 Lang 开头,且只能放在启动层,如果需要自定义,添加配置文件即可

{  "LocalizationSettings": {    "LanguageFilePrefix": "MyLang"    // "AssemblyName": "你的其他层程序集名称"  }}

之后,就可以:MyLang.区域码.resx

21.7 切换语言

Furion 提供了三种语言切换方式进行切换语言:

  • URL 参数 方式: ?culture=en-US此方式优先级最高,格式为:culture=区域码
  • Cookies 方式:调用 L.SetCulture(区域码) 方式切换
  • 客户端浏览器语言自动匹配:如果前面两种方式都没有设置,支持自动根据客户端浏览器语言进行匹配。

21.7.1 URL 参数 方式

21.7.2 Cookies 方式

此方式只需要提供一个 api 或设置代码即可:

L.SetCulture("en-US");  // en-US 也可以通过前端传递过来,这样就可以不用 `culture` 参数了,可以自定义参数。

这样就可以直接根据客户端存储的 cookies 自动切换了。

21.7.3 客户端浏览器语言自动切换

推荐此方式,可以自动根据浏览器的语言自动配置:

21.8 依赖注入方式使用

Furion 框架也兼容 .NET Core 自带的依赖注入方式,如:

 public class TestController : Controller {     private readonly IStringLocalizer _localizer;     public TestController(IStringLocalizerFactory factory)     {         _localizer = factory.Create();     }     public IActionResult About()     {         ViewData["Message"] = _localizer["Your application description page."];     } }

21.9 LocalizationSettings 配置

  • LocalizationSettings 多语言配置根节点
    • ResourcesPath:资源目录,string 类型,默认 Resources
    • SupportedCultures:支持的语言区域码类别,string[] 类型
    • DefaultCulture:默认语言区域码,如果为空,则取 SupportedCultures 第一项
    • LanguageFilePrefix:配置资源文件前缀,string 类型,默认 Lang
    • AssemblyName:配置资源文件存放程序集名,string 类型,默认 启动层 名称

21.10 关于中文不能切换问题

若通过 dotnet build 命令行编译后发布的代码(比如 jenkins 以及其他 devops 工具),无法生成 zh-CN 资源文件,会出现中文无法显示的问题,这时候只需要将 Lang.zh-CN.resx 修改为:Lang.zh-Hans.resxLang.zh-Hant.resxLang.zh.resx 即可。

相关文档说明 https://docs.microsoft.com/zh-cn/dotnet/api/system.globalization.cultureinfo?view=net-6.0

21.11 Json数据库 多语言实现

asp.net core 本地化 文档中微软推荐了三个拓展开源项目:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/localization-extensibility?view=aspnetcore-6.0#localization-resources

选择自己合适的即可。

21.12 区域码列表

  • af 公用荷兰语
  • af-ZA 公用荷兰语 - 南非
  • sq 阿尔巴尼亚
  • sq-AL 阿尔巴尼亚 -阿尔巴尼亚
  • ar 阿拉伯语
  • ar-DZ 阿拉伯语 -阿尔及利亚
  • ar-BH 阿拉伯语 -巴林
  • ar-EG 阿拉伯语 -埃及
  • ar-IQ 阿拉伯语 -伊拉克
  • ar-JO 阿拉伯语 -约旦
  • ar-KW 阿拉伯语 -科威特
  • ar-LB 阿拉伯语 -黎巴嫩
  • ar-LY 阿拉伯语 -利比亚
  • ar-MA 阿拉伯语 -摩洛哥
  • ar-OM 阿拉伯语 -阿曼
  • ar-QA 阿拉伯语 -卡塔尔
  • ar-SA 阿拉伯语 - 沙特阿拉伯
  • ar-SY 阿拉伯语 -叙利亚共和国
  • ar-TN 阿拉伯语 -北非的共和国
  • ar-AE 阿拉伯语 - 阿拉伯联合酋长国
  • ar-YE 阿拉伯语 -也门
  • hy 亚美尼亚
  • hy-AM 亚美尼亚的 -亚美尼亚
  • az Azeri
  • az-AZ-Cyrl Azeri-(西里尔字母的) 阿塞拜疆
  • az-AZ-Latn Azeri(拉丁文)- 阿塞拜疆
  • eu 巴斯克
  • eu-ES 巴斯克 -巴斯克
  • be Belarusian
  • be-BY Belarusian-白俄罗斯
  • bg 保加利亚
  • bg-BG 保加利亚 -保加利亚
  • ca 嘉泰罗尼亚
  • ca-ES 嘉泰罗尼亚 -嘉泰罗尼亚
  • zh-HK 华 - 香港的 SAR
  • zh-MO 华 - 澳门的 SAR
  • zh-CN 华 -中国
  • zh-CHS 华 (单一化)
  • zh-SG 华 -新加坡
  • zh-TW 华 -台湾
  • zh-CHT 华 (传统的)
  • hr 克罗埃西亚
  • hr-HR 克罗埃西亚 -克罗埃西亚
  • cs 捷克
  • cs-CZ 捷克 - 捷克
  • da 丹麦文
  • da-DK 丹麦文 -丹麦
  • div Dhivehi
  • div-MV Dhivehi-马尔代夫
  • nl 荷兰
  • nl-BE 荷兰 -比利时
  • nl-NL 荷兰 - 荷兰
  • en 英国
  • en-AU 英国 -澳洲
  • en-BZ 英国 -伯利兹
  • en-CA 英国 -加拿大
  • en-CB 英国 -加勒比海
  • en-IE 英国 -爱尔兰
  • en-JM 英国 -牙买加
  • en-NZ 英国 - 新西兰
  • en-PH 英国 -菲律宾共和国
  • en-ZA 英国 - 南非
  • en-TT 英国 - 千里达托贝哥共和国
  • en-GB 英国 - 英国
  • en-US 英国 - 美国
  • en-ZW 英国 -津巴布韦
  • et 爱沙尼亚
  • et-EE 爱沙尼亚的 -爱沙尼亚
  • fo Faroese
  • fo-FO Faroese- 法罗群岛
  • fa 波斯语
  • fa-IR 波斯语 -伊朗王国
  • fi 芬兰语
  • fi-FI 芬兰语 -芬兰
  • fr 法国
  • fr-BE 法国 -比利时
  • fr-CA 法国 -加拿大
  • fr-FR 法国 -法国
  • fr-LU 法国 -卢森堡
  • fr-MC 法国 -摩纳哥
  • fr-CH 法国 -瑞士
  • gl 加利西亚
  • gl-ES 加利西亚 -加利西亚
  • ka 格鲁吉亚州
  • ka-GE 格鲁吉亚州 -格鲁吉亚州
  • de 德国
  • de-AT 德国 -奥地利
  • de-DE 德国 -德国
  • de-LI 德国 -列支敦士登
  • de-LU 德国 -卢森堡
  • de-CH 德国 -瑞士
  • el 希腊
  • el-GR 希腊 -希腊
  • gu Gujarati
  • gu-IN Gujarati-印度
  • he 希伯来
  • he-IL 希伯来 -以色列
  • hi 北印度语
  • hi-IN 北印度的 -印度
  • hu 匈牙利
  • hu-HU 匈牙利的 -匈牙利
  • is 冰岛语
  • is-IS 冰岛的 -冰岛
  • id 印尼
  • id-ID 印尼 -印尼
  • it 意大利
  • it-IT 意大利 -意大利
  • it-CH 意大利 -瑞士
  • ja 日本
  • ja-JP 日本 -日本
  • kn 卡纳达语
  • kn-IN 卡纳达语 -印度
  • kk Kazakh
  • kk-KZ Kazakh-哈萨克
  • kok Konkani
  • kok-IN Konkani-印度
  • ko 韩国
  • ko-KR 韩国 -韩国
  • ky Kyrgyz
  • ky-KZ Kyrgyz-哈萨克
  • lv 拉脱维亚
  • lv-LV 拉脱维亚的 -拉脱维亚
  • lt 立陶宛
  • lt-LT 立陶宛 -立陶宛
  • mk 马其顿
  • mk-MK 马其顿 -FYROM
  • ms 马来
  • ms-BN 马来 -汶莱
  • ms-MY 马来 -马来西亚
  • mr 马拉地语
  • mr-IN 马拉地语 -印度
  • mn 蒙古
  • mn-MN 蒙古 -蒙古
  • no 挪威
  • nb-NO 挪威 (Bokm?l) - 挪威
  • nn-NO 挪威 (Nynorsk)- 挪威
  • pl 波兰
  • pl-PL 波兰 -波兰
  • pt 葡萄牙
  • pt-BR 葡萄牙 -巴西
  • pt-PT 葡萄牙 -葡萄牙
  • pa Punjab 语
  • pa-IN Punjab 语 -印度
  • ro 罗马尼亚语
  • ro-RO 罗马尼亚语 -罗马尼亚
  • ru 俄国
  • ru-RU 俄国 -俄国
  • sa 梵文
  • sa-IN 梵文 -印度
  • sr-SP-Cyrl 塞尔维亚 -(西里尔字母的) 塞尔维亚共和国
  • sr-SP-Latn 塞尔维亚 (拉丁文)- 塞尔维亚共和国
  • sk 斯洛伐克
  • sk-SK 斯洛伐克 -斯洛伐克
  • sl 斯洛文尼亚
  • sl-SI 斯洛文尼亚 -斯洛文尼亚
  • es 西班牙
  • es-AR 西班牙 -阿根廷
  • es-BO 西班牙 -玻利维亚
  • es-CL 西班牙 -智利
  • es-CO 西班牙 -哥伦比亚
  • es-CR 西班牙 - 哥斯达黎加
  • es-DO 西班牙 - 多米尼加共和国
  • es-EC 西班牙 -厄瓜多尔
  • es-SV 西班牙 - 萨尔瓦多
  • es-GT 西班牙 -危地马拉
  • es-HN 西班牙 -洪都拉斯
  • es-MX 西班牙 -墨西哥
  • es-NI 西班牙 -尼加拉瓜
  • es-PA 西班牙 -巴拿马
  • es-PY 西班牙 -巴拉圭
  • es-PE 西班牙 -秘鲁
  • es-PR 西班牙 - 波多黎各
  • es-ES 西班牙 -西班牙
  • es-UY 西班牙 -乌拉圭
  • es-VE 西班牙 -委内瑞拉
  • sw Swahili
  • sw-KE Swahili-肯尼亚
  • sv 瑞典
  • sv-FI 瑞典 -芬兰
  • sv-SE 瑞典 -瑞典
  • syr Syriac
  • syr-SY Syriac-叙利亚共和国
  • ta 坦米尔
  • ta-IN 坦米尔 -印度
  • tt Tatar
  • tt-RU Tatar-俄国
  • te Telugu
  • te-IN Telugu-印度
  • th 泰国
  • th-TH 泰国 -泰国
  • tr 土耳其语
  • tr-TR 土耳其语 -土耳其
  • uk 乌克兰
  • uk-UA 乌克兰 -乌克兰
  • ur Urdu
  • ur-PK Urdu-巴基斯坦
  • uz Uzbek
  • uz-UZ-Cyrl Uzbek-(西里尔字母的) 乌兹别克斯坦
  • uz-UZ-Latn Uzbek(拉丁文)- 乌兹别克斯坦
  • vi 越南
  • vi-VN 越南 -越南

21.13 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 多语言 知识可查阅 ASP.NET Core - 全局化和本地化 章节。

演练场
- - +

21. 全球化和本地化

21.1 全球化和本地化

全球化 是设计支持不同区域性的应用程序的过程。 全球化添加了对一组有关特定地理区域的已定义语言脚本的输入、显示和输出支持。

本地化 是将已经针对可本地化性进行处理的全球化应用调整为特定的区域性/区域设置的过程。

通俗来说,就是使应用或系统支持多语言切换。Furion 框架提供了完整支持多语言处理的服务。

21.2 注册服务

在使用多语言服务之前,必须先注册服务,如:

public void ConfigureServices(IServiceCollection services){    services.AddControllersWithViews()            .AddAppLocalization();  // 注册多语言}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){    if (env.IsDevelopment())    {        app.UseDeveloperExceptionPage();    }    // 配置多语言,必须在 路由注册之前    app.UseAppLocalization();    app.UseStaticFiles();    app.UseRouting();    // 其他中间件}
特别注意

app.UseAppLocalization(); 必须在 app.UseRouting(); 之前注册。

21.3 如何使用

21.3.1 配置 LocalizationSettings

添加 LocalizationSettings 配置选项:

{  "LocalizationSettings": {    "SupportedCultures": ["zh-CN", "en-US"], // 配置支持的语言列表    "DefaultCulture": "zh-CN" // 配置默认语言,如果不配置,取 SupportedCultures 的第一项  }}

21.3.2 创建 Resources 文件夹

接下来在 Web启动项目层 添加 Resources 文件夹,如图:(可配置放置任意层,见配置 AssemblyName

21.4 L 静态类

Furion 框架主要通过 L 静态类完成多语言转换,该静态类有以下属性和方法:

  • L.Text[文本]:转换文本多语言
  • L.Html[HTML代码, 格式化]:转换 Html 多语言
  • L.SetCulture(区域码):设置当前语言区域
  • L.GetSelectCulture():获取当前的语言区域
  • L.GetCultures():获取系统支持的多语言列表

21.5 使用例子

通过上面的配置步骤之后,我们就可以通过 L 静态类在代码任何位置使用了,如:

21.5.1 在类中使用

// 文本多语言var apiInterface = L.Text["API 接口"];var sourceCode = L.Text["源码地址"];// HTML 标记多语言var name = L.Html["<b>Hello</b><i> {0}</i>", name];

21.5.2 在视图中使用

@using Furion.Localization<div style="text-align:center;margin-top:50px;">  <p>让 .NET 开发更简单,更通用,更流行。</p>  <p>    <a href="/api">@L.Text["API 接口"]</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a      href="https://gitee.com/dotnetchina/Furion"      target="_blank"      >@L.Text["源码地址"]</a    >  </p></div>

21.5.3 在验证特性中使用

[Required(ErrorMessage = "必填消息")]

所有验证特性已经自动支持多语言配置了,无需通过 L.Text[] 调用。

21.5.4 在异常消息中使用

using Furion.FriendlyException;namespace Furion.Application{    [ErrorCodeType]    public enum ErrorCodes    {        [ErrorCodeItemMetadata("用户名不能为空")]        z1000    }}

所有异常消息特性已经自动支持多语言配置了,无需通过 L.Text[] 调用。

throw Oops.Oh(ErrorCodes.z1000);    // 自动应用多语言

21.5.5 SharedResource 模式

版本说明

以下内容仅限 Furion 4.3.7 + 版本使用。

正常情况下,我们都是通过 L.Text["Hello"] 方式输出 Hello 在不同的区域语言的翻译,但是会导致 Hello 硬编码字符串散落到处都是。

所以 Furion 提供了 SharedResource 模式,只需要创建一个 SharedResource.cs 类(可以任何名字)并添加对应的属性即可,如:

namespace Furion.Core;public class SharedResource{    public string Hello { get; set; }    public string Name { get; set; }}

使用如下:

var hello = L.GetString<SharedResource>(u => u.Hello);  // 比 L.Text["Hello"]; 容易维护var name = L.GetString<SharedResource>(u => u.Name);  // 比 L.Text["Name"]; 容易维护

当然也有更简单的方式,就是使用 nameof,如:

var hello = L.Text[nameof(SharedResource.Hello)];  // 比 L.Text["Hello"]; 容易维护var name = L.Text[nameof(SharedResource.Name)];  // 比 L.Text["Name"]; 容易维护

21.6 创建语言翻译文件

Furion 框架中,如果没找到对应的语言翻译文件,则自动显示字符串文本,如:

L.Text["没找到"];   // => 如果设置为英文,但是没有文件,则直接输出 “没找到”

21.6.1 在 Resources 文件夹中创建语言文件

接下来,我们只需要在刚刚的 Resources 文件夹中添加 资源文件 即可,资源文件命名规则:Lang.区域码.resx,如:Lang.en-US.resx

接下来,只需要把对应语言版本的键值对填写即可。

自定义资源文件名或存放程序集

默认情况下,资源文件名必须以 Lang 开头,且只能放在启动层,如果需要自定义,添加配置文件即可

{  "LocalizationSettings": {    "LanguageFilePrefix": "MyLang"    // "AssemblyName": "你的其他层程序集名称"  }}

之后,就可以:MyLang.区域码.resx

21.7 切换语言

Furion 提供了三种语言切换方式进行切换语言:

  • URL 参数 方式: ?culture=en-US此方式优先级最高,格式为:culture=区域码
  • Cookies 方式:调用 L.SetCulture(区域码) 方式切换
  • 客户端浏览器语言自动匹配:如果前面两种方式都没有设置,支持自动根据客户端浏览器语言进行匹配。

21.7.1 URL 参数 方式

21.7.2 Cookies 方式

此方式只需要提供一个 api 或设置代码即可:

L.SetCulture("en-US");  // en-US 也可以通过前端传递过来,这样就可以不用 `culture` 参数了,可以自定义参数。

这样就可以直接根据客户端存储的 cookies 自动切换了。

21.7.3 客户端浏览器语言自动切换

推荐此方式,可以自动根据浏览器的语言自动配置:

21.8 依赖注入方式使用

Furion 框架也兼容 .NET Core 自带的依赖注入方式,如:

 public class TestController : Controller {     private readonly IStringLocalizer _localizer;     public TestController(IStringLocalizerFactory factory)     {         _localizer = factory.Create();     }     public IActionResult About()     {         ViewData["Message"] = _localizer["Your application description page."];     } }

21.9 LocalizationSettings 配置

  • LocalizationSettings 多语言配置根节点
    • ResourcesPath:资源目录,string 类型,默认 Resources
    • SupportedCultures:支持的语言区域码类别,string[] 类型
    • DefaultCulture:默认语言区域码,如果为空,则取 SupportedCultures 第一项
    • LanguageFilePrefix:配置资源文件前缀,string 类型,默认 Lang
    • AssemblyName:配置资源文件存放程序集名,string 类型,默认 启动层 名称

21.10 关于中文不能切换问题

若通过 dotnet build 命令行编译后发布的代码(比如 jenkins 以及其他 devops 工具),无法生成 zh-CN 资源文件,会出现中文无法显示的问题,这时候只需要将 Lang.zh-CN.resx 修改为:Lang.zh-Hans.resxLang.zh-Hant.resxLang.zh.resx 即可。

相关文档说明 https://docs.microsoft.com/zh-cn/dotnet/api/system.globalization.cultureinfo?view=net-6.0

21.11 Json数据库 多语言实现

asp.net core 本地化 文档中微软推荐了三个拓展开源项目:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/localization-extensibility?view=aspnetcore-6.0#localization-resources

选择自己合适的即可。

21.12 区域码列表

  • af 公用荷兰语
  • af-ZA 公用荷兰语 - 南非
  • sq 阿尔巴尼亚
  • sq-AL 阿尔巴尼亚 -阿尔巴尼亚
  • ar 阿拉伯语
  • ar-DZ 阿拉伯语 -阿尔及利亚
  • ar-BH 阿拉伯语 -巴林
  • ar-EG 阿拉伯语 -埃及
  • ar-IQ 阿拉伯语 -伊拉克
  • ar-JO 阿拉伯语 -约旦
  • ar-KW 阿拉伯语 -科威特
  • ar-LB 阿拉伯语 -黎巴嫩
  • ar-LY 阿拉伯语 -利比亚
  • ar-MA 阿拉伯语 -摩洛哥
  • ar-OM 阿拉伯语 -阿曼
  • ar-QA 阿拉伯语 -卡塔尔
  • ar-SA 阿拉伯语 - 沙特阿拉伯
  • ar-SY 阿拉伯语 -叙利亚共和国
  • ar-TN 阿拉伯语 -北非的共和国
  • ar-AE 阿拉伯语 - 阿拉伯联合酋长国
  • ar-YE 阿拉伯语 -也门
  • hy 亚美尼亚
  • hy-AM 亚美尼亚的 -亚美尼亚
  • az Azeri
  • az-AZ-Cyrl Azeri-(西里尔字母的) 阿塞拜疆
  • az-AZ-Latn Azeri(拉丁文)- 阿塞拜疆
  • eu 巴斯克
  • eu-ES 巴斯克 -巴斯克
  • be Belarusian
  • be-BY Belarusian-白俄罗斯
  • bg 保加利亚
  • bg-BG 保加利亚 -保加利亚
  • ca 嘉泰罗尼亚
  • ca-ES 嘉泰罗尼亚 -嘉泰罗尼亚
  • zh-HK 华 - 香港的 SAR
  • zh-MO 华 - 澳门的 SAR
  • zh-CN 华 -中国
  • zh-CHS 华 (单一化)
  • zh-SG 华 -新加坡
  • zh-TW 华 -台湾
  • zh-CHT 华 (传统的)
  • hr 克罗埃西亚
  • hr-HR 克罗埃西亚 -克罗埃西亚
  • cs 捷克
  • cs-CZ 捷克 - 捷克
  • da 丹麦文
  • da-DK 丹麦文 -丹麦
  • div Dhivehi
  • div-MV Dhivehi-马尔代夫
  • nl 荷兰
  • nl-BE 荷兰 -比利时
  • nl-NL 荷兰 - 荷兰
  • en 英国
  • en-AU 英国 -澳洲
  • en-BZ 英国 -伯利兹
  • en-CA 英国 -加拿大
  • en-CB 英国 -加勒比海
  • en-IE 英国 -爱尔兰
  • en-JM 英国 -牙买加
  • en-NZ 英国 - 新西兰
  • en-PH 英国 -菲律宾共和国
  • en-ZA 英国 - 南非
  • en-TT 英国 - 千里达托贝哥共和国
  • en-GB 英国 - 英国
  • en-US 英国 - 美国
  • en-ZW 英国 -津巴布韦
  • et 爱沙尼亚
  • et-EE 爱沙尼亚的 -爱沙尼亚
  • fo Faroese
  • fo-FO Faroese- 法罗群岛
  • fa 波斯语
  • fa-IR 波斯语 -伊朗王国
  • fi 芬兰语
  • fi-FI 芬兰语 -芬兰
  • fr 法国
  • fr-BE 法国 -比利时
  • fr-CA 法国 -加拿大
  • fr-FR 法国 -法国
  • fr-LU 法国 -卢森堡
  • fr-MC 法国 -摩纳哥
  • fr-CH 法国 -瑞士
  • gl 加利西亚
  • gl-ES 加利西亚 -加利西亚
  • ka 格鲁吉亚州
  • ka-GE 格鲁吉亚州 -格鲁吉亚州
  • de 德国
  • de-AT 德国 -奥地利
  • de-DE 德国 -德国
  • de-LI 德国 -列支敦士登
  • de-LU 德国 -卢森堡
  • de-CH 德国 -瑞士
  • el 希腊
  • el-GR 希腊 -希腊
  • gu Gujarati
  • gu-IN Gujarati-印度
  • he 希伯来
  • he-IL 希伯来 -以色列
  • hi 北印度语
  • hi-IN 北印度的 -印度
  • hu 匈牙利
  • hu-HU 匈牙利的 -匈牙利
  • is 冰岛语
  • is-IS 冰岛的 -冰岛
  • id 印尼
  • id-ID 印尼 -印尼
  • it 意大利
  • it-IT 意大利 -意大利
  • it-CH 意大利 -瑞士
  • ja 日本
  • ja-JP 日本 -日本
  • kn 卡纳达语
  • kn-IN 卡纳达语 -印度
  • kk Kazakh
  • kk-KZ Kazakh-哈萨克
  • kok Konkani
  • kok-IN Konkani-印度
  • ko 韩国
  • ko-KR 韩国 -韩国
  • ky Kyrgyz
  • ky-KZ Kyrgyz-哈萨克
  • lv 拉脱维亚
  • lv-LV 拉脱维亚的 -拉脱维亚
  • lt 立陶宛
  • lt-LT 立陶宛 -立陶宛
  • mk 马其顿
  • mk-MK 马其顿 -FYROM
  • ms 马来
  • ms-BN 马来 -汶莱
  • ms-MY 马来 -马来西亚
  • mr 马拉地语
  • mr-IN 马拉地语 -印度
  • mn 蒙古
  • mn-MN 蒙古 -蒙古
  • no 挪威
  • nb-NO 挪威 (Bokm?l) - 挪威
  • nn-NO 挪威 (Nynorsk)- 挪威
  • pl 波兰
  • pl-PL 波兰 -波兰
  • pt 葡萄牙
  • pt-BR 葡萄牙 -巴西
  • pt-PT 葡萄牙 -葡萄牙
  • pa Punjab 语
  • pa-IN Punjab 语 -印度
  • ro 罗马尼亚语
  • ro-RO 罗马尼亚语 -罗马尼亚
  • ru 俄国
  • ru-RU 俄国 -俄国
  • sa 梵文
  • sa-IN 梵文 -印度
  • sr-SP-Cyrl 塞尔维亚 -(西里尔字母的) 塞尔维亚共和国
  • sr-SP-Latn 塞尔维亚 (拉丁文)- 塞尔维亚共和国
  • sk 斯洛伐克
  • sk-SK 斯洛伐克 -斯洛伐克
  • sl 斯洛文尼亚
  • sl-SI 斯洛文尼亚 -斯洛文尼亚
  • es 西班牙
  • es-AR 西班牙 -阿根廷
  • es-BO 西班牙 -玻利维亚
  • es-CL 西班牙 -智利
  • es-CO 西班牙 -哥伦比亚
  • es-CR 西班牙 - 哥斯达黎加
  • es-DO 西班牙 - 多米尼加共和国
  • es-EC 西班牙 -厄瓜多尔
  • es-SV 西班牙 - 萨尔瓦多
  • es-GT 西班牙 -危地马拉
  • es-HN 西班牙 -洪都拉斯
  • es-MX 西班牙 -墨西哥
  • es-NI 西班牙 -尼加拉瓜
  • es-PA 西班牙 -巴拿马
  • es-PY 西班牙 -巴拉圭
  • es-PE 西班牙 -秘鲁
  • es-PR 西班牙 - 波多黎各
  • es-ES 西班牙 -西班牙
  • es-UY 西班牙 -乌拉圭
  • es-VE 西班牙 -委内瑞拉
  • sw Swahili
  • sw-KE Swahili-肯尼亚
  • sv 瑞典
  • sv-FI 瑞典 -芬兰
  • sv-SE 瑞典 -瑞典
  • syr Syriac
  • syr-SY Syriac-叙利亚共和国
  • ta 坦米尔
  • ta-IN 坦米尔 -印度
  • tt Tatar
  • tt-RU Tatar-俄国
  • te Telugu
  • te-IN Telugu-印度
  • th 泰国
  • th-TH 泰国 -泰国
  • tr 土耳其语
  • tr-TR 土耳其语 -土耳其
  • uk 乌克兰
  • uk-UA 乌克兰 -乌克兰
  • ur Urdu
  • ur-PK Urdu-巴基斯坦
  • uz Uzbek
  • uz-UZ-Cyrl Uzbek-(西里尔字母的) 乌兹别克斯坦
  • uz-UZ-Latn Uzbek(拉丁文)- 乌兹别克斯坦
  • vi 越南
  • vi-VN 越南 -越南

21.13 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 多语言 知识可查阅 ASP.NET Core - 全局化和本地化 章节。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/logging/index.html b/handbook/build/docs/logging/index.html index d322cc1114..5bf385d06d 100644 --- a/handbook/build/docs/logging/index.html +++ b/handbook/build/docs/logging/index.html @@ -2,22 +2,21 @@ - - - + +18. 日志记录 | Furion -18. 日志记录 | Furion - - + + +
-

18. 日志记录

18.1 关于日志

通常日志指的是系统日志程序日志

系统日志 是记录系统中硬件、软件和系统问题的信息,同时还可以监视系统中发生的事件。用户可以通过它来检查错误发生的原因,或者寻找受到攻击时攻击者留下的痕迹。系统日志包括系统日志、应用程序日志和安全日志。

程序日志 是程序运行中产生的日志,通常由框架运行时或开发者提供的日志。包括请求日志,异常日志、审计日志、行为日志等。

18.2 日志作用

在项目开发中,都不可避免的使用到日志。没有日志虽然不会影响项目的正确运行,但是没有日志的项目可以说是不完整的。日志在调试,错误或者异常定位,数据分析中的作用是不言而喻的。

  • 调试

在项目调试时,查看栈信息可以方便地知道当前程序的运行状态,输出的日志便于记录程序在之前的运行结果。

  • 错误定位

不要以为项目能正确跑起来就可以高枕无忧,项目在运行一段时候后,可能由于数据问题,网络问题,内存问题等出现异常。这时日志可以帮助开发或者运维人员快速定位错误位置,提出解决方案。

  • 数据分析

大数据的兴起,使得大量的日志分析成为可能,ELK 也让日志分析门槛降低了很多。日志中蕴含了大量的用户数据,包括点击行为,兴趣偏好等,用户画像对于公司下一步的战略方向有一定指引作用。

18.3 日志级别

日志级别可以有效的对日志信息进行归类,方便准确的查看特定日志内容。通常日志类别有以下级别:

级别方法描述
Trace(跟踪)0LogTrace包含最详细的消息。 这些消息可能包含敏感的应用数据。 这些消息默认情况下处于禁用状态,并且不应在生产中启用。
Debug(调试)1LogDebug用于调试和开发。 由于量大,请在生产中小心使用。
Information(信息)2LogInformation跟踪应用的常规流。 可能具有长期值。
Warning(警告)3LogWarning对于异常事件或意外事件。 通常包括不会导致应用失败的错误或情况。
Error(错误)4LogError表示无法处理的错误和异常。 这些消息表示当前操作或请求失败,而不是整个应用失败。
Critical(严重)5LogCritical需要立即关注的失败。 例如数据丢失、磁盘空间不足。

18.4 如何使用

.NET 5 框架中,微软已经为我们内置了 日志组件,正常情况下,无需我们引用第三方包进行日志记录。.NET 5 框架为我们提供了两种日志对象创建方式。

18.4.1 ILogger<T> 泛型方式

使用非常简单,可以通过 ILogger<T> 对象进行注入,如:

public class PrivacyModel : PageModel{    private readonly ILogger<PrivacyModel> _logger;    public PrivacyModel(ILogger<PrivacyModel> logger)    {        _logger = logger;    }    public void OnGet()    {        _logger.LogInformation("GET Pages.PrivacyModel called.");    }}
小知识

通过泛型 ILogger<T> 方式写入日志,那么默认将 T 类型完整类型名称作为 日志类别

18.4.2 ILoggerFactory 工厂方式

使用工厂方式,需手动传入 日志类别,如:

public class ContactModel : PageModel{    private readonly ILogger _logger;    public ContactModel(ILoggerFactory logger)    {        _logger = logger.CreateLogger("MyCategory");    }    public void OnGet()    {        _logger.LogInformation("GET Pages.ContactModel called.");    }}

18.4.3 Log 静态类方式

版本说明

以下内容仅限 Furion 4.2.1 + 版本使用。

// 创建日志对象var logger = Log.CreateLogger("日志名称");// 创建日志工厂using var loggerFactory = Log.CreateLoggerFactory(builder => {    // ....});// 日志记录Log.Information("Information");Log.Warning("Warning");Log.Error("Error");Log.Debug("Debug");Log.Trace("Trace");Log.Critical("Critical");

18.4.4 懒人模式 😁

Furion 框架中,提供了更懒的方式写入日志,也就是通过字符串拓展的方式写入,如:

"简单日志".LogInformation();"百小僧 新增了一条记录".LogInformation<HomeController>();"程序出现异常啦".LogError<HomeController>();"这是自定义类别日志".SetCategory("类别").LogInformation();

通过字符串拓展方式可以在任何时候方便记录日志,专门为懒人提供的。

18.5 配置日志输出介质

版本说明

以下小节仅在 Furion 3.9.0+ 版本提供。

ASP.NET Core 应用程序中,主机启动时默认注册了 ConsoleLoggerProvider 提供器,也就是控制台日志输出提供器,所以无需任何注册服务即可在控制台输出。

18.5.1 输出到控制台

info: Furion.EventBus.EventBusHostedService[0]      EventBus Hosted Service is running.info: Microsoft.Hosting.Lifetime[14]      Now listening on: https://localhost:5001info: Microsoft.Hosting.Lifetime[14]      Now listening on: http://localhost:5000info: Microsoft.Hosting.Lifetime[0]      Application started. Press Ctrl+C to shut down.info: Microsoft.Hosting.Lifetime[0]      Hosting environment: Developmentinfo: Microsoft.Hosting.Lifetime[0]      Content root path: C:\Workplaces\Furion\samples\Furion.Web.Entry\
  • 控制台输出过滤

.NET5 版本:

Host.CreateDefaultBuilder(args)    .ConfigureLogging(logging =>    {        logging.AddFilter((provider, category, logLevel) =>        {            // .....        });    })

.NET6+ 版本:

var builder = WebApplication.CreateBuilder(args);builder.Logging.AddFilter((provider, category, logLevel) =>{    // .....});

如需其他配置可在 appsettings.json 配置即可:

{  "Logging": {    "Console": {      "IncludeScopes": true,      "LogLevel": {        "Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",        "Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",        "Microsoft.AspNetCore.Mvc.Razor": "Error",        "Default": "Information"      }    }  }}

如需自定义控制台日志模板可查看微软官方文档 https://docs.microsoft.com/zh-cn/dotnet/core/extensions/console-log-formatter#implement-a-custom-formatter

这里也提供相关 Issue 参考:#I5JJJH

18.5.2 输出到文件

  • 基础使用
// 例子一:启动层根目录输出services.AddFileLogging("application.log");// 例子二:支持路径services.AddFileLogging("logs/application.log");// 例子三:支持日志追加还是覆盖,设置 true 为追加,false 为覆盖services.AddFileLogging("application.log", true);
  • 从配置文件读取配置
特别注意

只有不在 .AddFile 第一个参数配置文件名才会自动加载配置,也就是文件名应该配置在配置文件中。

文件日志配置说明:

{  "Logging": {    "LogLevel": {      "Default": "Information"      // .... appsettings 默认配置    },    "File": {      "FileName": "application.log", // 日志文件完整路径或文件名,推荐 .log 作为拓展名      "Append": true, // 追加到已存在日志文件或覆盖它们      "MinimumLevel": "Information", // 最低日志记录级别      "FileSizeLimitBytes": 0, // 控制每一个日志文件最大存储大小,默认无限制,如果指定了该值,那么日志文件大小超出了该配置就会创建新的日志文件,新创建的日志文件命名规则:文件名+[递增序号].log      "MaxRollingFiles": 0 // 控制最大创建的日志文件数量,默认无限制,配合 FileSizeLimitBytes 使用,如果指定了该值,那么超出该值将从最初日志文件中从头写入覆盖    }  },  // 自定义配置节点  "MyLogger": {    "FileName": "application.log",    "Append": true,    "MinimumLevel": "Information",    "FileSizeLimitBytes": 0,    "MaxRollingFiles": 0  }}
// 例子一:默认读取 Logging:File 节点services.AddFileLogging();// 例子二:默认读取 Logging:File 节点,支持更多配置services.AddFileLogging(options =>{    options.MinimumLevel = LogLevel.Warning;    // 其他配置...});// 例子三:自定义配置节点services.AddFileLogging(() => "MyLogger");// 例子四:自定义配置节点,支持更多配置services.AddFileLogging(() => "MyLogger", options =>{    options.MinimumLevel = LogLevel.Warning;    // 其他配置...});
  • 自定义日志文件名规则
// 例子一:支持系统环境变量,如%SystemDrive%,%SystemRoot%services.AddFileLogging("application%SystemDrive%-%SystemRoot%.log");// 例子二:每天创建一个日志文件services.AddFileLogging("application-{0:yyyy}-{0:MM}-{0:dd}.log", options =>{    options.FileNameRule = fileName =>    {        return string.Format(fileName, DateTime.UtcNow);    };});// 例子三,任何自己喜欢的命名规则services.AddFileLogging("application-{0:yyyy}-{0:MM}-{0:dd}.log", options =>{    options.FileNameRule = fileName =>    {        // your rule...    };});// 例子四,批量设置多个Array.ForEach(new[] { LogLevel.Information, LogLevel.Warning, LogLevel.Error }, logLevel =>{    services.AddFileLogging("application-{1}-{0:yyyy}-{0:MM}-{0:dd}.log", options =>    {        options.FileNameRule = fileName => string.Format(fileName, DateTime.UtcNow, logLevel.ToString());        options.WriteFilter = logMsg => logMsg.LogLevel == logLevel;    });});
  • 日志过滤器/筛选器

通过日志筛选器可以对日志进行归类写入

// 例子一:根据日志级别输出services.AddFileLogging("infomation.log", options =>{    options.WriteFilter = (logMsg) =>    {        return logMsg.LogLevel == LogLevel.Information;    };});services.AddFileLogging("error.log", options =>{    options.WriteFilter = (logMsg) =>    {        return logMsg.LogLevel == LogLevel.Error;    };});// 例子二,根据任何规则,比如特定的类名services.AddFileLogging("someclass.log", options =>{    options.WriteFilter = (logMsg) =>    {        return logMsg.LogName.Contains("SomeClassName");    };});
  • 自定义日志模板

默认情况下,Furion 提供了标准的日志输出模板,如:

2022-07-23T20:16:29.3459053+08:00   [INF]   [Furion.EventBus.EventBusHostedService] [0] EventBus Hosted Service is running.2022-07-23T20:16:29.5827366+08:00   [INF]   [Microsoft.Hosting.Lifetime]    [0] Application started. Press Ctrl+C to shut down.2022-07-23T20:16:29.5828798+08:00   [INF]   [Microsoft.Hosting.Lifetime]    [0] Hosting environment: Development2022-07-23T20:16:29.5829377+08:00   [INF]   [Microsoft.Hosting.Lifetime]    [0] Content root path: C:\Workplaces\Furion\samples\Furion.Web.Entry\

如需自定义:

// 例子一,自定义日志模板(常用)services.AddFileLogging("mytemplate.log", options =>{    options.MessageFormat = (logMsg) =>    {        var stringBuilder = new StringBuilder();        stringBuilder.Append(DateTime.Now.ToString("o"));        // 其他的。。。自己组装        return stringBuilder.ToString();    };});// 例子二,需要输出 json 格式,比如对接阿里云日志,kibana第三方日志使用这个services.AddFileLogging("mytemplate.log", options =>{    options.MessageFormat = (logMsg) =>    {        // 高性能写入        return logMsg.WriteArray(writer =>        {            writer.WriteStringValue(DateTime.Now.ToString("o"));            writer.WriteStringValue(logMsg.LogLevel.ToString());            writer.WriteStringValue(logMsg.LogName);            writer.WriteNumberValue(logMsg.EventId.Id);            writer.WriteStringValue(logMsg.Message);            writer.WriteStringValue(logMsg.Exception?.ToString());        });    };});// 例子二,需要输出 json (自定义)格式,比如对接阿里云日志,kibana第三方日志使用这个services.AddFileLogging("mytemplate.log", options =>{    options.MessageFormat = (logMsg) =>    {        // 高性能写入        return logMsg.Write(writer =>        {            // write 对象为 Utf8JsonWriter,可通过流写入,性能极高        });    };});
  • 日志写入失败处理

有时候可能因为日志文件被打开或者其他应用程序占用了,那么就会导致日志写入失败,这时候可以进行其他相关处理:

// 例子一:其他处理services.AddFileLogging("template-obj.log", options =>{    options.HandleWriteError = (writeError) =>    {        // ~~    };});// 例子二,启用备用日志文件功能,也就是如果文件被占用了,可以创建新的备用日志继续写入,推荐!!!services.AddFileLogging("template-obj.log", options =>{    options.HandleWriteError = (writeError) =>    {        writeError.UseRollbackFileName(Path.GetFileNameWithoutExtension(writeError.CurrentFileName) + "-oops" + Path.GetExtension(writeError.CurrentFileName));    };});

18.5.3 输出到数据库/其他存储介质

将日志输出到数据库中也是非常常见的需求,Furion 把该功能做到了非常简单,支持任何存储介质。

在写入数据库/其他存储介质之前需创建数据库日志写入器并实现 IDatabaseLoggingWriter 接口,支持多个,如:

using Furion.Logging;namespace Your.Core;public class DatabaseLoggingWriter : IDatabaseLoggingWriter{    // 支持构造函数注入任何实例,会自动释放任何服务,比如注入 IRepository,或者 SqlSugarClient    public DatabaseLoggingWriter()    {    }    public void Write(LogMessage logMsg, bool flush)    {        // 这里写你任何插入数据库的操作,无需 try catch    }}

你没看错,就这么简单!!

  • 基础使用
// 例子一,默认配置services.AddDatabaseLogging<DatabaseLoggingWriter>(options => {});// 例子二:自定义配置services.AddDatabaseLogging<DatabaseLoggingWriter>(options =>{    options.MinimumLevel = LogLevel.Warning;    // 其他配置...});
  • 从配置文件中读取
特别注意

只有不在 .AddDatabase 第一个参数为空才会自动加载配置。

数据库日志配置说明:

{  "Logging": {    "LogLevel": {      "Default": "Information"      // .... appsettings 默认配置    },    "Database": {      "MinimumLevel": "Information" // 最低日志记录级别    }  },  // 自定义配置节点  "MyLogger": {    "MinimumLevel": "Information"  }}
// 例子一:默认读取 Logging:Database 节点services.AddDatabaseLogging<DatabaseLoggingWriter>();// 例子二:默认读取 Logging:Database 节点,支持更多配置services.AddDatabaseLogging<DatabaseLoggingWriter>(default(string), options =>{    options.MinimumLevel = LogLevel.Warning;    // 其他配置...});// 例子三:自定义配置节点services.AddDatabaseLogging<DatabaseLoggingWriter>("MyLogger");// 或services.AddDatabaseLogging<DatabaseLoggingWriter>(() => "MyLogger");// 例子四:自定义配置节点,支持更多配置services.AddDatabaseLogging<DatabaseLoggingWriter>("MyLogger", options =>{    options.MinimumLevel = LogLevel.Warning;    // 其他配置...});// 或services.AddDatabaseLogging<DatabaseLoggingWriter>(() => "MyLogger", options =>{    options.MinimumLevel = LogLevel.Warning;    // 其他配置...});
  • 日志过滤器/筛选器

通过日志筛选器可以对日志进行归类写入

// 例子一:根据日志级别输出,可以分别定义 IDatabaseLoggingWriter,也可以用同一个底层进行判断services.AddDatabaseLogging<InfomationLoggingWriter>(options =>{    options.WriteFilter = (logMsg) =>    {        return logMsg.LogLevel == LogLevel.Information;    };});// 可以分别定义 IDatabaseLoggingWriter,也可以用同一个底层进行判断services.AddDatabaseLogging<ErrorLoggingWriter>(options =>{    options.WriteFilter = (logMsg) =>    {        return logMsg.LogLevel == LogLevel.Error;    };});// 例子二,根据任何规则,比如特定的类名services.AddDatabaseLogging<DatabaseLoggingWriter>(options =>{    options.WriteFilter = (logMsg) =>    {        return logMsg.LogName.Contains("SomeClassName");    };});
  • 日志写入失败处理

有时候可能因为数据库连接异常或其他原因连接池满,那么就会导致日志写入失败,这时候可以进行其他相关处理:

// 例子一:其他处理services.AddDatabaseLogging<DatabaseLoggingWriter>(options =>{    options.HandleWriteError = (writeError) =>    {        // ~~    };});

18.5.4 ILoggerFactory 方式

Furion 也提供了运行时动态创建日志提供器并写入:

public class ContactModel : PageModel{    private readonly ILogger _logger;    public ContactModel(ILoggerFactory logger)    {        // 支持所有 AddLoggingFile 和 AddDatabaseFile 配置        _logger = logger.AddFile(....).CreateLogger("MyCategory");    }    public void OnGet()    {        _logger.LogInformation("GET Pages.ContactModel called.");    }}

18.5.5 ILoggingBuilder 方式

Furion 也提供了原生 services.AddLogging(builder => {}) 方式配置,如

services.AddLogging(builder =>{    builder.AddFile("applicaion.log");    builder.AddDatabase<DatabaseLoggingWriter>();    //....});

18.5.6 记录请求日志

ASP.NET 6 中,框架默认提供了 app.UseHttpLogging() 记录 HTTP 请求日志功能,详细了解可查看官方文档 ASP.NET Core - HTTP 日志记录

当然也可以自定义中间件的方式写,只需要注入 ILogger<> 接口即可。

18.5.7 DebugTrace 默认不输出问题

默认情况下,微软在 appsettings.jsonappsettings.Development.json 中配置了 Default 日志级别,如需自定义:

{  "Logging": {    "LogLevel": {      "Default": "Information"    }  }}

这时候只需要修改 DefaultDebugTrace 即可,注意不同环境加载不同的配置文件。开发环境应修改 appsettings.Development.json 下的配置。

18.6 [LoggingMonitor] 监听日志

Furion 3.9.1 版本新增了 [LoggingMonitor] 特性,支持在控制器或操作中贴该特性,可以实现强大的请求日志监听,方便测试,如:

18.6.1 特性配置

using Furion.Logging;namespace Furion.Application;public class TestLoggerServices : IDynamicApiController{    [LoggingMonitor]    public PersonDto GetPerson(int id)    {        return new PersonDto        {            Id = id        };    }}
  • [LoggingMonitor] 支持以下配置:
    • Title:配置标题,string 类型,默认 Logging Monitor
    • WithReturnValue:是否包含返回值打印,bool 类型,默认 trueFurion 4.3.9+ 有效
    • ReturnValueThreshold:配置返回值字符串阈值,int 类型,默认 0 全量输出,Furion 4.3.9+ 有效

输出日志为:

┏━━━━━━━━━━━  Logging Monitor ━━━━━━━━━━━┣ Furion.Application.TestLoggerServices.GetPerson (Furion.Application)┣ 控制器名称:              TestLoggerServices┣ 操作名称:                GetPerson┣ 路由信息:                [area]: ; [controller]: test-logger; [action]: person┣ 请求方式:                POST┣ 请求地址:                https://localhost:44316/api/test-logger/person/11┣ 来源地址:                https://localhost:44316/api/index.html┣ 浏览器标识:              Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62┣ 客户端 IP 地址:          0.0.0.1┣ 服务端 IP 地址:          0.0.0.1┣ 服务端运行环境:          Development┣ 执行耗时:                31ms┣ ━━━━━━━━━━━━━━━  授权信息 ━━━━━━━━━━━━━━━┣ JWT Token:               Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjEsIkFjY291bnQiOiJhZG1pbiIsImlhdCI6MTY1ODcxNjc5NywibmJmIjoxNjU4NzE2Nzk3LCJleHAiOjE2NTg3MTc5OTcsImlzcyI6ImRvdG5ldGNoaW5hIiwiYXVkIjoicG93ZXJieSBGdXJpb24ifQ.VYZkwwqCwlUy3aJjuL-og62I0rkxNQ96kSjEm3VgXtg┣ UserId (integer)1┣ Account (string):        admin┣ iat (integer)1658716797┣ nbf (integer)1658716797┣ exp (integer)1658717997┣ iss (string):            dotnetchina┣ aud (string):            powerby Furion┣ ━━━━━━━━━━━━━━━  参数列表 ━━━━━━━━━━━━━━━┣ Content-Type:id (Int32)11┣ ━━━━━━━━━━━━━━━  返回信息 ━━━━━━━━━━━━━━━┣ 类型:                    Furion.Application.Persons.PersonDto┣ 返回值:                  {"Id":11,"Name":null,"Age":0,"Address":null,"PhoneNumber":null,"QQ":null,"CreatedTime":"0001-01-01T00:00:00+00:00","Childrens":null,"Posts":null}┗━━━━━━━━━━━  Logging Monitor ━━━━━━━━━━━

18.6.2 全局配置

如需全局启用 LoggingMonitor 功能,无需在每个控制器或者方法中贴,全局注册如下:

services.AddMvcFilter<LoggingMonitorAttribute>();
Furion 4.0.2 新推荐配置

Furion 4.0.2 版本中新增了非常灵活方便的 services.AddMonitorLogging() 服务配置,可在配置中随意控制哪个类哪个方法启用或不启用。

  • 注册服务
services.AddMonitorLogging();   // 默认读取 Logging:Monitor 下配置,支持传入参数自定义
  • 添加配置
{  "Logging": {    "Monitor": {      "GlobalEnabled": false, // 是否启用全局拦截,默认 `false`      "IncludeOfMethods": [], // 是否指定拦截特定方法,当 GlobalEnabled: false 有效      "ExcludeOfMethods": [], // 是否指定排除特定方法,当 GlobalEnabled: true 有效      "BahLogLevel": "Information", // 配置 Oops.Oh 和 Oops.Bah 业务日志输出级别,默认 Information      "WithReturnValue": true, // 配置是否包含返回值,默认 `true`,Furion 4.3.9+ 有效      "ReturnValueThreshold": 0, // 配置返回值字符串阈值,默认 0,全量输出,Furion 4.3.9+ 有效      "MethodsSettings": [        // 配置被监视方法更多信息,Furion 4.3.9+ 有效        {          "FullName": "Furion.Application.TestLoggerServices.MethodName", // 方法完全限定名          "WithReturnValue": true, // 配置是否包含返回值,默认 `true`,Furion 4.3.9+ 有效          "ReturnValueThreshold": 0 // 配置返回值字符串阈值,默认 0,全量输出,Furion 4.3.9+ 有效        }      ]    }  }}

IncludeOfMethodsExcludeOfMethods 方法签名格式为:类完全限定名.方法名,如:Furion.Application.TestNamedServices.GetNameFurion.Application.TestNamedServices 是类名,GetName 是方法名。

如果配置了全局请求监视日志,对个别不需要监视的接口方法只需要贴 [SuppressMonitor] 特性即可。

18.6.3 更多配置

版本说明

以下内容仅限 Furion 4.3.9 + 版本使用。

支持 LoggingMonitor 写入日志拦截,如添加额外数据:

services.AddMonitorLogging(options =>{    options.ConfigureLogger((logger, logContext, context) =>    {        var httpContext = context.HttpContext;        logContext.Set("extra", "其他数据");    });});

除此之外,还支持配置 json 路径:

services.AddMonitorLogging(jsonKey: "YourKey:Monitor");

18.7 打印日志到 Swagger

Furion 框架中默认集成了 MiniProfiler 组件并与 Swagger 进行了结合,如需打印日志或调试代码,只需调用以下方法即可:

App.PrintToMiniProfiler("分类", "状态", "要打印的消息");

18.8 在后台任务中使用

由于 DbContext 默认注册为 Scoped 生存周期,所以在后台任务中使用 IServiceScopeFactory 获取所有服务,如:

public class JobService : BackgroundService{    // 日志对象    private readonly ILogger<JobService> _logger;    // 服务工厂    private readonly IServiceScopeFactory _scopeFactory;    public JobService(ILogger<JobService> logger        , IServiceScopeFactory scopeFactory)    {        _logger = logger;        _scopeFactory = scopeFactory;    }    protected override Task ExecuteAsync(CancellationToken stoppingToken)    {        _logger.LogInformation("写日志~~");        using (var scope = _scopeFactory.CreateScope())        {            var services = scope.ServiceProvider;            // 获取数据库上下文            var dbContext = Db.GetDbContext(services);            // 获取仓储            var respository = Db.GetRepository<Person>(services);            // 解析其他服务            var otherService = services.GetService<XXX>();        }        return Task.CompletedTask;    }}

18.9 多线程共享作用域

默认情况下,所有的 字符串实体 拓展都有自己独立维护的 ServiceProvider 作用域。

Web 请求中,默认是 HttpContext.RequestServices,但在 非 Web,如多线程操作,后台任务,事件总线等场景下会自动创建新的作用域,实际上这是非常不必要的内存开销。

这时,我们只需要通过 .SetXXXScoped(service) 共享当前服务提供器作用域即可,如:

Scoped.Create(async (fac, scope) => {   "写日志".SetLoggerScoped(scope.ServiceProvider).LogInformation();});

18.10 静态 Default 方式构建

StringLoggingPart.Default.SetMessage("这是一个日志").LogInformation();

18.11 规范日志模板

Furion v3.5.3+ 新增了 TP.Wrapper(...) 规范模板,使用如下:

// 生成模板字符串var template = TP.Wrapper("Furion 框架", "让 .NET 开发更简单,更通用,更流行。",    "##作者## 百小僧",    "##当前版本## v3.5.3",    "##文档地址## https://furion.icu",    "##Copyright## 百小僧, Baiqian Co.,Ltd.");Console.WriteLine(template);

日志打印模板如下:

┏━━━━━━━━━━━  Furion 框架 ━━━━━━━━━━━┣ 让 .NET 开发更简单,更通用,更流行。┣ 作者:        百小僧┣ 当前版本:     v3.5.3┣ 文档地址:     https://furion.icu┣ Copyright:   百小僧, Baiqian Co.,Ltd.┗━━━━━━━━━━━  Furion 框架 ━━━━━━━━━━━
关于属性生成

如果列表项以 ##属性名## 开头,自动生成 属性名: 作为行首且自动等宽对齐。

Furion 3.9.1 之前版本使用 [属性名] 开头。

18.12 日志上下文

版本说明

以下内容仅限 Furion 4.1.3 + 版本使用。

有时候我们希望为日志提供额外数据,这时候可通过 .ScopeContext() 配置,如:

// 写法一_logger.ScopeContext(ctx => ctx.Set("Name", "Furion").Set("UserId", 10))       .LogInformation("我是一个日志 {id}", 20);// 写法二_logger.ScopeContext(new Dictionary<object, object> {    { "Name", "Furion" },    { "UserId", 10 }}).LogInformation("我是一个日志 {id}", 20);// 写法三_logger.ScopeContext(new LogContext {    // ....}).LogInformation("我是一个日志 {id}", 20)

LogMessage 对象中使用:

var value = logMsg.Context.Get("Key");// 比如在过滤中使用services.AddFileLogging("infomation.log", options =>{    options.WriteFilter = (logMsg) =>    {        // 还可以设置给运行时使用:logMsg.Context.Set(...);        return logMsg.Context.Get("Name") == "Furion";    };});// 在  IDatabaseLoggingWriter 中使用public void Write(LogMessage logMsg, bool flush){    var name = logMsg.Context.Get("Name");}

还可以实现共享日志上下文,如:

private readonly ILogger<TestAppService> _logger;public TestAppService(ILogger<TestAppService> logger){    _logger = logger;     // 添加全局用户信息上下文数据    _logger.ScopeContext(ctx => ctx.Set("uid", "100").Set("uname", "百小僧"));}public string GetName(int id){    // 共享全局上下文数据    _logger.LogInformation("写入新的日志");    return "Furion";}public string GetTags(int id){    // 额外新增上下文数据    _logger.ScopeContext(ctx => ctx.Set("key", "value")).LogInformation("设置额外的上上下文日志");    return "百小僧";}

18.13 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 日志 知识可查阅 ASP.NET Core - 日志 章节 和 Serilog 文档。

演练场
- - +

18. 日志记录

18.1 关于日志

通常日志指的是系统日志程序日志

系统日志 是记录系统中硬件、软件和系统问题的信息,同时还可以监视系统中发生的事件。用户可以通过它来检查错误发生的原因,或者寻找受到攻击时攻击者留下的痕迹。系统日志包括系统日志、应用程序日志和安全日志。

程序日志 是程序运行中产生的日志,通常由框架运行时或开发者提供的日志。包括请求日志,异常日志、审计日志、行为日志等。

18.2 日志作用

在项目开发中,都不可避免的使用到日志。没有日志虽然不会影响项目的正确运行,但是没有日志的项目可以说是不完整的。日志在调试,错误或者异常定位,数据分析中的作用是不言而喻的。

  • 调试

在项目调试时,查看栈信息可以方便地知道当前程序的运行状态,输出的日志便于记录程序在之前的运行结果。

  • 错误定位

不要以为项目能正确跑起来就可以高枕无忧,项目在运行一段时候后,可能由于数据问题,网络问题,内存问题等出现异常。这时日志可以帮助开发或者运维人员快速定位错误位置,提出解决方案。

  • 数据分析

大数据的兴起,使得大量的日志分析成为可能,ELK 也让日志分析门槛降低了很多。日志中蕴含了大量的用户数据,包括点击行为,兴趣偏好等,用户画像对于公司下一步的战略方向有一定指引作用。

18.3 日志级别

日志级别可以有效的对日志信息进行归类,方便准确的查看特定日志内容。通常日志类别有以下级别:

级别方法描述
Trace(跟踪)0LogTrace包含最详细的消息。 这些消息可能包含敏感的应用数据。 这些消息默认情况下处于禁用状态,并且不应在生产中启用。
Debug(调试)1LogDebug用于调试和开发。 由于量大,请在生产中小心使用。
Information(信息)2LogInformation跟踪应用的常规流。 可能具有长期值。
Warning(警告)3LogWarning对于异常事件或意外事件。 通常包括不会导致应用失败的错误或情况。
Error(错误)4LogError表示无法处理的错误和异常。 这些消息表示当前操作或请求失败,而不是整个应用失败。
Critical(严重)5LogCritical需要立即关注的失败。 例如数据丢失、磁盘空间不足。

18.4 如何使用

.NET 5 框架中,微软已经为我们内置了 日志组件,正常情况下,无需我们引用第三方包进行日志记录。.NET 5 框架为我们提供了两种日志对象创建方式。

18.4.1 ILogger<T> 泛型方式

使用非常简单,可以通过 ILogger<T> 对象进行注入,如:

public class PrivacyModel : PageModel{    private readonly ILogger<PrivacyModel> _logger;    public PrivacyModel(ILogger<PrivacyModel> logger)    {        _logger = logger;    }    public void OnGet()    {        _logger.LogInformation("GET Pages.PrivacyModel called.");    }}
小知识

通过泛型 ILogger<T> 方式写入日志,那么默认将 T 类型完整类型名称作为 日志类别

18.4.2 ILoggerFactory 工厂方式

使用工厂方式,需手动传入 日志类别,如:

public class ContactModel : PageModel{    private readonly ILogger _logger;    public ContactModel(ILoggerFactory logger)    {        _logger = logger.CreateLogger("MyCategory");    }    public void OnGet()    {        _logger.LogInformation("GET Pages.ContactModel called.");    }}

18.4.3 Log 静态类方式

版本说明

以下内容仅限 Furion 4.2.1 + 版本使用。

// 创建日志对象var logger = Log.CreateLogger("日志名称");// 创建日志工厂using var loggerFactory = Log.CreateLoggerFactory(builder => {    // ....});// 日志记录Log.Information("Information");Log.Warning("Warning");Log.Error("Error");Log.Debug("Debug");Log.Trace("Trace");Log.Critical("Critical");

18.4.4 懒人模式 😁

Furion 框架中,提供了更懒的方式写入日志,也就是通过字符串拓展的方式写入,如:

"简单日志".LogInformation();"百小僧 新增了一条记录".LogInformation<HomeController>();"程序出现异常啦".LogError<HomeController>();"这是自定义类别日志".SetCategory("类别").LogInformation();

通过字符串拓展方式可以在任何时候方便记录日志,专门为懒人提供的。

18.5 配置日志输出介质

版本说明

以下小节仅在 Furion 3.9.0+ 版本提供。

ASP.NET Core 应用程序中,主机启动时默认注册了 ConsoleLoggerProvider 提供器,也就是控制台日志输出提供器,所以无需任何注册服务即可在控制台输出。

18.5.1 输出到控制台

info: Furion.EventBus.EventBusHostedService[0]      EventBus Hosted Service is running.info: Microsoft.Hosting.Lifetime[14]      Now listening on: https://localhost:5001info: Microsoft.Hosting.Lifetime[14]      Now listening on: http://localhost:5000info: Microsoft.Hosting.Lifetime[0]      Application started. Press Ctrl+C to shut down.info: Microsoft.Hosting.Lifetime[0]      Hosting environment: Developmentinfo: Microsoft.Hosting.Lifetime[0]      Content root path: C:\Workplaces\Furion\samples\Furion.Web.Entry\
  • 控制台输出过滤

.NET5 版本:

Host.CreateDefaultBuilder(args)    .ConfigureLogging(logging =>    {        logging.AddFilter((provider, category, logLevel) =>        {            // .....        });    })

.NET6+ 版本:

var builder = WebApplication.CreateBuilder(args);builder.Logging.AddFilter((provider, category, logLevel) =>{    // .....});

如需其他配置可在 appsettings.json 配置即可:

{  "Logging": {    "Console": {      "IncludeScopes": true,      "LogLevel": {        "Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",        "Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",        "Microsoft.AspNetCore.Mvc.Razor": "Error",        "Default": "Information"      }    }  }}

如需自定义控制台日志模板可查看微软官方文档 https://docs.microsoft.com/zh-cn/dotnet/core/extensions/console-log-formatter#implement-a-custom-formatter

这里也提供相关 Issue 参考:#I5JJJH

18.5.2 输出到文件

  • 基础使用
// 例子一:启动层根目录输出services.AddFileLogging("application.log");// 例子二:支持路径services.AddFileLogging("logs/application.log");// 例子三:支持日志追加还是覆盖,设置 true 为追加,false 为覆盖services.AddFileLogging("application.log", true);
  • 从配置文件读取配置
特别注意

只有不在 .AddFile 第一个参数配置文件名才会自动加载配置,也就是文件名应该配置在配置文件中。

文件日志配置说明:

{  "Logging": {    "LogLevel": {      "Default": "Information"      // .... appsettings 默认配置    },    "File": {      "FileName": "application.log", // 日志文件完整路径或文件名,推荐 .log 作为拓展名      "Append": true, // 追加到已存在日志文件或覆盖它们      "MinimumLevel": "Information", // 最低日志记录级别      "FileSizeLimitBytes": 0, // 控制每一个日志文件最大存储大小,默认无限制,如果指定了该值,那么日志文件大小超出了该配置就会创建新的日志文件,新创建的日志文件命名规则:文件名+[递增序号].log      "MaxRollingFiles": 0 // 控制最大创建的日志文件数量,默认无限制,配合 FileSizeLimitBytes 使用,如果指定了该值,那么超出该值将从最初日志文件中从头写入覆盖    }  },  // 自定义配置节点  "MyLogger": {    "FileName": "application.log",    "Append": true,    "MinimumLevel": "Information",    "FileSizeLimitBytes": 0,    "MaxRollingFiles": 0  }}
// 例子一:默认读取 Logging:File 节点services.AddFileLogging();// 例子二:默认读取 Logging:File 节点,支持更多配置services.AddFileLogging(options =>{    options.MinimumLevel = LogLevel.Warning;    // 其他配置...});// 例子三:自定义配置节点services.AddFileLogging(() => "MyLogger");// 例子四:自定义配置节点,支持更多配置services.AddFileLogging(() => "MyLogger", options =>{    options.MinimumLevel = LogLevel.Warning;    // 其他配置...});
  • 自定义日志文件名规则
// 例子一:支持系统环境变量,如%SystemDrive%,%SystemRoot%services.AddFileLogging("application%SystemDrive%-%SystemRoot%.log");// 例子二:每天创建一个日志文件services.AddFileLogging("application-{0:yyyy}-{0:MM}-{0:dd}.log", options =>{    options.FileNameRule = fileName =>    {        return string.Format(fileName, DateTime.UtcNow);    };});// 例子三,任何自己喜欢的命名规则services.AddFileLogging("application-{0:yyyy}-{0:MM}-{0:dd}.log", options =>{    options.FileNameRule = fileName =>    {        // your rule...    };});// 例子四,批量设置多个Array.ForEach(new[] { LogLevel.Information, LogLevel.Warning, LogLevel.Error }, logLevel =>{    services.AddFileLogging("application-{1}-{0:yyyy}-{0:MM}-{0:dd}.log", options =>    {        options.FileNameRule = fileName => string.Format(fileName, DateTime.UtcNow, logLevel.ToString());        options.WriteFilter = logMsg => logMsg.LogLevel == logLevel;    });});
  • 日志过滤器/筛选器

通过日志筛选器可以对日志进行归类写入

// 例子一:根据日志级别输出services.AddFileLogging("infomation.log", options =>{    options.WriteFilter = (logMsg) =>    {        return logMsg.LogLevel == LogLevel.Information;    };});services.AddFileLogging("error.log", options =>{    options.WriteFilter = (logMsg) =>    {        return logMsg.LogLevel == LogLevel.Error;    };});// 例子二,根据任何规则,比如特定的类名services.AddFileLogging("someclass.log", options =>{    options.WriteFilter = (logMsg) =>    {        return logMsg.LogName.Contains("SomeClassName");    };});
  • 自定义日志模板

默认情况下,Furion 提供了标准的日志输出模板,如:

2022-07-23T20:16:29.3459053+08:00   [INF]   [Furion.EventBus.EventBusHostedService] [0] EventBus Hosted Service is running.2022-07-23T20:16:29.5827366+08:00   [INF]   [Microsoft.Hosting.Lifetime]    [0] Application started. Press Ctrl+C to shut down.2022-07-23T20:16:29.5828798+08:00   [INF]   [Microsoft.Hosting.Lifetime]    [0] Hosting environment: Development2022-07-23T20:16:29.5829377+08:00   [INF]   [Microsoft.Hosting.Lifetime]    [0] Content root path: C:\Workplaces\Furion\samples\Furion.Web.Entry\

如需自定义:

// 例子一,自定义日志模板(常用)services.AddFileLogging("mytemplate.log", options =>{    options.MessageFormat = (logMsg) =>    {        var stringBuilder = new StringBuilder();        stringBuilder.Append(DateTime.Now.ToString("o"));        // 其他的。。。自己组装        return stringBuilder.ToString();    };});// 例子二,需要输出 json 格式,比如对接阿里云日志,kibana第三方日志使用这个services.AddFileLogging("mytemplate.log", options =>{    options.MessageFormat = (logMsg) =>    {        // 高性能写入        return logMsg.WriteArray(writer =>        {            writer.WriteStringValue(DateTime.Now.ToString("o"));            writer.WriteStringValue(logMsg.LogLevel.ToString());            writer.WriteStringValue(logMsg.LogName);            writer.WriteNumberValue(logMsg.EventId.Id);            writer.WriteStringValue(logMsg.Message);            writer.WriteStringValue(logMsg.Exception?.ToString());        });    };});// 例子二,需要输出 json (自定义)格式,比如对接阿里云日志,kibana第三方日志使用这个services.AddFileLogging("mytemplate.log", options =>{    options.MessageFormat = (logMsg) =>    {        // 高性能写入        return logMsg.Write(writer =>        {            // write 对象为 Utf8JsonWriter,可通过流写入,性能极高        });    };});
  • 日志写入失败处理

有时候可能因为日志文件被打开或者其他应用程序占用了,那么就会导致日志写入失败,这时候可以进行其他相关处理:

// 例子一:其他处理services.AddFileLogging("template-obj.log", options =>{    options.HandleWriteError = (writeError) =>    {        // ~~    };});// 例子二,启用备用日志文件功能,也就是如果文件被占用了,可以创建新的备用日志继续写入,推荐!!!services.AddFileLogging("template-obj.log", options =>{    options.HandleWriteError = (writeError) =>    {        writeError.UseRollbackFileName(Path.GetFileNameWithoutExtension(writeError.CurrentFileName) + "-oops" + Path.GetExtension(writeError.CurrentFileName));    };});

18.5.3 输出到数据库/其他存储介质

将日志输出到数据库中也是非常常见的需求,Furion 把该功能做到了非常简单,支持任何存储介质。

在写入数据库/其他存储介质之前需创建数据库日志写入器并实现 IDatabaseLoggingWriter 接口,支持多个,如:

using Furion.Logging;namespace Your.Core;public class DatabaseLoggingWriter : IDatabaseLoggingWriter{    // 支持构造函数注入任何实例,会自动释放任何服务,比如注入 IRepository,或者 SqlSugarClient    public DatabaseLoggingWriter()    {    }    public void Write(LogMessage logMsg, bool flush)    {        // 这里写你任何插入数据库的操作,无需 try catch    }}

你没看错,就这么简单!!

  • 基础使用
// 例子一,默认配置services.AddDatabaseLogging<DatabaseLoggingWriter>(options => {});// 例子二:自定义配置services.AddDatabaseLogging<DatabaseLoggingWriter>(options =>{    options.MinimumLevel = LogLevel.Warning;    // 其他配置...});
  • 从配置文件中读取
特别注意

只有不在 .AddDatabase 第一个参数为空才会自动加载配置。

数据库日志配置说明:

{  "Logging": {    "LogLevel": {      "Default": "Information"      // .... appsettings 默认配置    },    "Database": {      "MinimumLevel": "Information" // 最低日志记录级别    }  },  // 自定义配置节点  "MyLogger": {    "MinimumLevel": "Information"  }}
// 例子一:默认读取 Logging:Database 节点services.AddDatabaseLogging<DatabaseLoggingWriter>();// 例子二:默认读取 Logging:Database 节点,支持更多配置services.AddDatabaseLogging<DatabaseLoggingWriter>(default(string), options =>{    options.MinimumLevel = LogLevel.Warning;    // 其他配置...});// 例子三:自定义配置节点services.AddDatabaseLogging<DatabaseLoggingWriter>("MyLogger");// 或services.AddDatabaseLogging<DatabaseLoggingWriter>(() => "MyLogger");// 例子四:自定义配置节点,支持更多配置services.AddDatabaseLogging<DatabaseLoggingWriter>("MyLogger", options =>{    options.MinimumLevel = LogLevel.Warning;    // 其他配置...});// 或services.AddDatabaseLogging<DatabaseLoggingWriter>(() => "MyLogger", options =>{    options.MinimumLevel = LogLevel.Warning;    // 其他配置...});
  • 日志过滤器/筛选器

通过日志筛选器可以对日志进行归类写入

// 例子一:根据日志级别输出,可以分别定义 IDatabaseLoggingWriter,也可以用同一个底层进行判断services.AddDatabaseLogging<InfomationLoggingWriter>(options =>{    options.WriteFilter = (logMsg) =>    {        return logMsg.LogLevel == LogLevel.Information;    };});// 可以分别定义 IDatabaseLoggingWriter,也可以用同一个底层进行判断services.AddDatabaseLogging<ErrorLoggingWriter>(options =>{    options.WriteFilter = (logMsg) =>    {        return logMsg.LogLevel == LogLevel.Error;    };});// 例子二,根据任何规则,比如特定的类名services.AddDatabaseLogging<DatabaseLoggingWriter>(options =>{    options.WriteFilter = (logMsg) =>    {        return logMsg.LogName.Contains("SomeClassName");    };});
  • 日志写入失败处理

有时候可能因为数据库连接异常或其他原因连接池满,那么就会导致日志写入失败,这时候可以进行其他相关处理:

// 例子一:其他处理services.AddDatabaseLogging<DatabaseLoggingWriter>(options =>{    options.HandleWriteError = (writeError) =>    {        // ~~    };});

18.5.4 ILoggerFactory 方式

Furion 也提供了运行时动态创建日志提供器并写入:

public class ContactModel : PageModel{    private readonly ILogger _logger;    public ContactModel(ILoggerFactory logger)    {        // 支持所有 AddLoggingFile 和 AddDatabaseFile 配置        _logger = logger.AddFile(....).CreateLogger("MyCategory");    }    public void OnGet()    {        _logger.LogInformation("GET Pages.ContactModel called.");    }}

18.5.5 ILoggingBuilder 方式

Furion 也提供了原生 services.AddLogging(builder => {}) 方式配置,如

services.AddLogging(builder =>{    builder.AddFile("applicaion.log");    builder.AddDatabase<DatabaseLoggingWriter>();    //....});

18.5.6 记录请求日志

ASP.NET 6 中,框架默认提供了 app.UseHttpLogging() 记录 HTTP 请求日志功能,详细了解可查看官方文档 ASP.NET Core - HTTP 日志记录

当然也可以自定义中间件的方式写,只需要注入 ILogger<> 接口即可。

18.5.7 DebugTrace 默认不输出问题

默认情况下,微软在 appsettings.jsonappsettings.Development.json 中配置了 Default 日志级别,如需自定义:

{  "Logging": {    "LogLevel": {      "Default": "Information"    }  }}

这时候只需要修改 DefaultDebugTrace 即可,注意不同环境加载不同的配置文件。开发环境应修改 appsettings.Development.json 下的配置。

18.6 [LoggingMonitor] 监听日志

Furion 3.9.1 版本新增了 [LoggingMonitor] 特性,支持在控制器或操作中贴该特性,可以实现强大的请求日志监听,方便测试,如:

18.6.1 特性配置

using Furion.Logging;namespace Furion.Application;public class TestLoggerServices : IDynamicApiController{    [LoggingMonitor]    public PersonDto GetPerson(int id)    {        return new PersonDto        {            Id = id        };    }}
  • [LoggingMonitor] 支持以下配置:
    • Title:配置标题,string 类型,默认 Logging Monitor
    • WithReturnValue:是否包含返回值打印,bool 类型,默认 trueFurion 4.3.9+ 有效
    • ReturnValueThreshold:配置返回值字符串阈值,int 类型,默认 0 全量输出,Furion 4.3.9+ 有效

输出日志为:

┏━━━━━━━━━━━  Logging Monitor ━━━━━━━━━━━┣ Furion.Application.TestLoggerServices.GetPerson (Furion.Application)┣ 控制器名称:              TestLoggerServices┣ 操作名称:                GetPerson┣ 路由信息:                [area]: ; [controller]: test-logger; [action]: person┣ 请求方式:                POST┣ 请求地址:                https://localhost:44316/api/test-logger/person/11┣ 来源地址:                https://localhost:44316/api/index.html┣ 浏览器标识:              Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62┣ 客户端 IP 地址:          0.0.0.1┣ 服务端 IP 地址:          0.0.0.1┣ 服务端运行环境:          Development┣ 执行耗时:                31ms┣ ━━━━━━━━━━━━━━━  授权信息 ━━━━━━━━━━━━━━━┣ JWT Token:               Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjEsIkFjY291bnQiOiJhZG1pbiIsImlhdCI6MTY1ODcxNjc5NywibmJmIjoxNjU4NzE2Nzk3LCJleHAiOjE2NTg3MTc5OTcsImlzcyI6ImRvdG5ldGNoaW5hIiwiYXVkIjoicG93ZXJieSBGdXJpb24ifQ.VYZkwwqCwlUy3aJjuL-og62I0rkxNQ96kSjEm3VgXtg┣ UserId (integer)1┣ Account (string):        admin┣ iat (integer)1658716797┣ nbf (integer)1658716797┣ exp (integer)1658717997┣ iss (string):            dotnetchina┣ aud (string):            powerby Furion┣ ━━━━━━━━━━━━━━━  参数列表 ━━━━━━━━━━━━━━━┣ Content-Type:id (Int32)11┣ ━━━━━━━━━━━━━━━  返回信息 ━━━━━━━━━━━━━━━┣ 类型:                    Furion.Application.Persons.PersonDto┣ 返回值:                  {"Id":11,"Name":null,"Age":0,"Address":null,"PhoneNumber":null,"QQ":null,"CreatedTime":"0001-01-01T00:00:00+00:00","Childrens":null,"Posts":null}┗━━━━━━━━━━━  Logging Monitor ━━━━━━━━━━━

18.6.2 全局配置

如需全局启用 LoggingMonitor 功能,无需在每个控制器或者方法中贴,全局注册如下:

services.AddMvcFilter<LoggingMonitorAttribute>();
Furion 4.0.2 新推荐配置

Furion 4.0.2 版本中新增了非常灵活方便的 services.AddMonitorLogging() 服务配置,可在配置中随意控制哪个类哪个方法启用或不启用。

  • 注册服务
services.AddMonitorLogging();   // 默认读取 Logging:Monitor 下配置,支持传入参数自定义
  • 添加配置
{  "Logging": {    "Monitor": {      "GlobalEnabled": false, // 是否启用全局拦截,默认 `false`      "IncludeOfMethods": [], // 是否指定拦截特定方法,当 GlobalEnabled: false 有效      "ExcludeOfMethods": [], // 是否指定排除特定方法,当 GlobalEnabled: true 有效      "BahLogLevel": "Information", // 配置 Oops.Oh 和 Oops.Bah 业务日志输出级别,默认 Information      "WithReturnValue": true, // 配置是否包含返回值,默认 `true`,Furion 4.3.9+ 有效      "ReturnValueThreshold": 0, // 配置返回值字符串阈值,默认 0,全量输出,Furion 4.3.9+ 有效      "MethodsSettings": [        // 配置被监视方法更多信息,Furion 4.3.9+ 有效        {          "FullName": "Furion.Application.TestLoggerServices.MethodName", // 方法完全限定名          "WithReturnValue": true, // 配置是否包含返回值,默认 `true`,Furion 4.3.9+ 有效          "ReturnValueThreshold": 0 // 配置返回值字符串阈值,默认 0,全量输出,Furion 4.3.9+ 有效        }      ]    }  }}

IncludeOfMethodsExcludeOfMethods 方法签名格式为:类完全限定名.方法名,如:Furion.Application.TestNamedServices.GetNameFurion.Application.TestNamedServices 是类名,GetName 是方法名。

如果配置了全局请求监视日志,对个别不需要监视的接口方法只需要贴 [SuppressMonitor] 特性即可。

18.6.3 更多配置

版本说明

以下内容仅限 Furion 4.3.9 + 版本使用。

支持 LoggingMonitor 写入日志拦截,如添加额外数据:

services.AddMonitorLogging(options =>{    options.ConfigureLogger((logger, logContext, context) =>    {        var httpContext = context.HttpContext;        logContext.Set("extra", "其他数据");    });});

除此之外,还支持配置 json 路径:

services.AddMonitorLogging(jsonKey: "YourKey:Monitor");

18.7 打印日志到 Swagger

Furion 框架中默认集成了 MiniProfiler 组件并与 Swagger 进行了结合,如需打印日志或调试代码,只需调用以下方法即可:

App.PrintToMiniProfiler("分类", "状态", "要打印的消息");

18.8 在后台任务中使用

由于 DbContext 默认注册为 Scoped 生存周期,所以在后台任务中使用 IServiceScopeFactory 获取所有服务,如:

public class JobService : BackgroundService{    // 日志对象    private readonly ILogger<JobService> _logger;    // 服务工厂    private readonly IServiceScopeFactory _scopeFactory;    public JobService(ILogger<JobService> logger        , IServiceScopeFactory scopeFactory)    {        _logger = logger;        _scopeFactory = scopeFactory;    }    protected override Task ExecuteAsync(CancellationToken stoppingToken)    {        _logger.LogInformation("写日志~~");        using (var scope = _scopeFactory.CreateScope())        {            var services = scope.ServiceProvider;            // 获取数据库上下文            var dbContext = Db.GetDbContext(services);            // 获取仓储            var respository = Db.GetRepository<Person>(services);            // 解析其他服务            var otherService = services.GetService<XXX>();        }        return Task.CompletedTask;    }}

18.9 多线程共享作用域

默认情况下,所有的 字符串实体 拓展都有自己独立维护的 ServiceProvider 作用域。

Web 请求中,默认是 HttpContext.RequestServices,但在 非 Web,如多线程操作,后台任务,事件总线等场景下会自动创建新的作用域,实际上这是非常不必要的内存开销。

这时,我们只需要通过 .SetXXXScoped(service) 共享当前服务提供器作用域即可,如:

Scoped.Create(async (fac, scope) => {   "写日志".SetLoggerScoped(scope.ServiceProvider).LogInformation();});

18.10 静态 Default 方式构建

StringLoggingPart.Default.SetMessage("这是一个日志").LogInformation();

18.11 规范日志模板

Furion v3.5.3+ 新增了 TP.Wrapper(...) 规范模板,使用如下:

// 生成模板字符串var template = TP.Wrapper("Furion 框架", "让 .NET 开发更简单,更通用,更流行。",    "##作者## 百小僧",    "##当前版本## v3.5.3",    "##文档地址## https://furion.icu",    "##Copyright## 百小僧, Baiqian Co.,Ltd.");Console.WriteLine(template);

日志打印模板如下:

┏━━━━━━━━━━━  Furion 框架 ━━━━━━━━━━━┣ 让 .NET 开发更简单,更通用,更流行。┣ 作者:        百小僧┣ 当前版本:     v3.5.3┣ 文档地址:     https://furion.icu┣ Copyright:   百小僧, Baiqian Co.,Ltd.┗━━━━━━━━━━━  Furion 框架 ━━━━━━━━━━━
关于属性生成

如果列表项以 ##属性名## 开头,自动生成 属性名: 作为行首且自动等宽对齐。

Furion 3.9.1 之前版本使用 [属性名] 开头。

18.12 日志上下文

版本说明

以下内容仅限 Furion 4.1.3 + 版本使用。

有时候我们希望为日志提供额外数据,这时候可通过 .ScopeContext() 配置,如:

// 写法一_logger.ScopeContext(ctx => ctx.Set("Name", "Furion").Set("UserId", 10))       .LogInformation("我是一个日志 {id}", 20);// 写法二_logger.ScopeContext(new Dictionary<object, object> {    { "Name", "Furion" },    { "UserId", 10 }}).LogInformation("我是一个日志 {id}", 20);// 写法三_logger.ScopeContext(new LogContext {    // ....}).LogInformation("我是一个日志 {id}", 20)

LogMessage 对象中使用:

var value = logMsg.Context.Get("Key");// 比如在过滤中使用services.AddFileLogging("infomation.log", options =>{    options.WriteFilter = (logMsg) =>    {        // 还可以设置给运行时使用:logMsg.Context.Set(...);        return logMsg.Context.Get("Name") == "Furion";    };});// 在  IDatabaseLoggingWriter 中使用public void Write(LogMessage logMsg, bool flush){    var name = logMsg.Context.Get("Name");}

还可以实现共享日志上下文,如:

private readonly ILogger<TestAppService> _logger;public TestAppService(ILogger<TestAppService> logger){    _logger = logger;     // 添加全局用户信息上下文数据    _logger.ScopeContext(ctx => ctx.Set("uid", "100").Set("uname", "百小僧"));}public string GetName(int id){    // 共享全局上下文数据    _logger.LogInformation("写入新的日志");    return "Furion";}public string GetTags(int id){    // 额外新增上下文数据    _logger.ScopeContext(ctx => ctx.Set("key", "value")).LogInformation("设置额外的上上下文日志");    return "百小僧";}

18.13 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 日志 知识可查阅 ASP.NET Core - 日志 章节 和 Serilog 文档。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/middleware/index.html b/handbook/build/docs/middleware/index.html index e88b388c03..85e4126abd 100644 --- a/handbook/build/docs/middleware/index.html +++ b/handbook/build/docs/middleware/index.html @@ -2,22 +2,21 @@ - - - + +5.5 中间件 (Middleware) | Furion -5.5 中间件 (Middleware) | Furion - - + + +
-

5.5 中间件 (Middleware)

5.5.1 关于中间件

中间件是一种装配到应用管道以处理请求和响应的软件。 每个组件:

  • 选择是否将请求传递到管道中的下一个组件。
  • 可在管道中的下一个组件前后执行工作。
  • 请求委托用于生成请求管道。 请求委托处理每个 HTTP 请求。

一句话总结:中间件是比筛选器更底层,更上游的面向切面技术,其性能最高,可处理的应用范围远比过滤器广,如实现网关,URL 转发,限流等等。

中间件更多内容

本章节暂不考虑将中间件展开讲,想了解更多知识可阅读官方文档 【ASP.NET Core - 中间件

5.5.2 常见中间件

5.5.2.1 所有请求返回同一个结果

app.Run(async context =>{    await context.Response.WriteAsync("Hello world!");});

5.5.2.2 拦截所有请求(可多个)

app.Use(async (context, next) =>{    // 比如设置统一头    context.Response.Headers["framework"] = "Furion";    // 执行下一个中间件    await next.Invoke();});// 多个app.Use(...);

5.5.2.3 特定路由中间件(可多个)

app.Map("/hello", app => {    app.Run(async context =>    {        await context.Response.WriteAsync("Map Test 1");    });});app.Map("/hello/say", app => {    // ....});

5.5.2.4 嵌套路由中间件(可多个)

app.Map("/level1", level1App => {    level1App.Map("/level2a", level2AApp => {        // "/level1/level2a" processing    });    level1App.Map("/level2b", level2BApp => {        // "/level1/level2b" processing    });});

更多例子查看官方文档 https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-6.0

5.5.3 自定义中间件

自定义中间件有多种方式,最简单的是通过 app.Use 方式,另外还支持独立类定义方式。

5.5.3.1 app.Use 方式 (不推荐)

Starup.cs
app.Use(async (context, next) =>{    var cultureQuery = context.Request.Query["culture"];    if (!string.IsNullOrWhiteSpace(cultureQuery))    {        var culture = new CultureInfo(cultureQuery);        CultureInfo.CurrentCulture = culture;        CultureInfo.CurrentUICulture = culture;    }    // 调用下一个中间件    await next(context);});

5.5.3.2 独立类 方式(推荐)

独立类的方式是目前最为推荐的方式,拓展性强,维护性高,如:

  • 定义中间件,建议以 Middleware 结尾:
using System.Globalization;namespace Middleware.Example;public class RequestCultureMiddleware{    private readonly RequestDelegate _next;    public RequestCultureMiddleware(RequestDelegate next)    {        _next = next;    }    public async Task InvokeAsync(HttpContext context)    {        var cultureQuery = context.Request.Query["culture"];        if (!string.IsNullOrWhiteSpace(cultureQuery))        {            var culture = new CultureInfo(cultureQuery);            CultureInfo.CurrentCulture = culture;            CultureInfo.CurrentUICulture = culture;        }        // 调用下一个中间件        await _next(context);    }}
  • 添加中间件拓展类

定义了中间件之后,需要创建这个中间件的拓展类,中间件拓展方法建议以 Use 开头,如:

public static class RequestCultureMiddlewareExtensions{    public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder)    {        return builder.UseMiddleware<RequestCultureMiddleware>();    }}
  • Startup.cs 中使用
public void Configure(IApplicationBuilder app, IWebHostEnvironment env){    // ... 其他中间件    app.UseRequestCulture();    // ... 其他中间件}

5.5.3.3 配置更多参数

默认情况下,自定义独立类中间件构造函数只有一个 RequestDelegate 参数,除此之后,还可以注入服务接口/类(建议是单例服务),另外还支持传入任何其他类型。

  • 服务类型参数
using System.Globalization;namespace Middleware.Example;public class RequestCultureMiddleware{    private readonly RequestDelegate _next;    private readonly ILogger<RequestCultureMiddleware> _logger;    public RequestCultureMiddleware(RequestDelegate next        , ILogger<RequestCultureMiddleware> logger)    {        _next = next;        _logger = logger;    }    public async Task InvokeAsync(HttpContext context)    {        // 其他代码        _logger.LogInformation("...");        // 调用下一个中间件        await _next(context);    }}
  • 非服务类型参数

除此之外,还可以添加 非服务参数 参数,但必须是最后一个参数!!!

using System.Globalization;namespace Middleware.Example;public class RequestCultureMiddleware{    private readonly RequestDelegate _next;    private readonly ILogger<RequestCultureMiddleware> _logger;    public RequestCultureMiddleware(RequestDelegate next        , ILogger<RequestCultureMiddleware> logger        , int age        , string name)    {        _next = next;        _logger = logger;    }    public async Task InvokeAsync(HttpContext context)    {        // 其他代码        _logger.LogInformation("...");        // 调用下一个中间件        await _next(context);    }}

之后还需要修改中间件拓展类:

public static class RequestCultureMiddlewareExtensions{    public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder, int age, string name)    {        return builder.UseMiddleware<RequestCultureMiddleware>(new object[] {age, name });    }}

使用:

app.UseRequestCulture(30, "百小僧");

5.5.4 中间件顺序

中间件是有执行顺序的,而且是先注册的先执行,无法通过其他方式更改,参考下图:

5.5.5 依赖注入/解析服务

中间件有两种方式注入服务,一种是通过构造函数注入,一种是通过 httpContext.RequestServices 方式解析。

5.5.5.1 构造函数方式

using System.Globalization;namespace Middleware.Example;public class RequestCultureMiddleware{    private readonly RequestDelegate _next;    private readonly ILogger<RequestCultureMiddleware> _logger;    public RequestCultureMiddleware(RequestDelegate next        , ILogger<RequestCultureMiddleware> logger        , IHostEnvironment hostEnvironment)    {        _next = next;        _logger = logger;    }    public async Task InvokeAsync(HttpContext context)    {        // 其他代码        // 调用下一个中间件        await _next(context);    }}
特别说明

通过构造函数的方式建议注入 单例模式 的服务,否则可能存在服务不能释放问题,如需使用瞬时或作用域的服务,可使用下列 httpContext.RequestServices 方式

5.5.5.2 httpContext.RequestServices 方式

通过这种方式可以使用非单例服务解析:

using System.Globalization;namespace Middleware.Example;public class RequestCultureMiddleware{    private readonly RequestDelegate _next;    private readonly ILogger<RequestCultureMiddleware> _logger;    // 构造函数注册单例    public RequestCultureMiddleware(RequestDelegate next        , ILogger<RequestCultureMiddleware> logger        , IHostEnvironment hostEnvironment)    {        _next = next;        _logger = logger;    }    public async Task InvokeAsync(HttpContext context)    {        // 非单例模式        using var serviceProvider = context.RequestServices.CreateScope();        var repository = serviceProvider.ServiceProvider.GetService<IRepository>();        // 调用下一个中间件        await _next(context);    }}

5.5.6 常见问题

由于中间件是比较原始的切面方式,有时候我们需要获取终点路由的特性或者其他信息,则需要一点技巧:

// 获取终点路由特性var endpointFeature = context.Features.Get<IEndpointFeature>();// 获取是否定义了特性var attribute = endpointFeature?.Endpoint?.Metadata?.GetMetadata<YourAttribute>()

5.5.7 了解更多

想了解更多中间件知识可阅读官方文档 【ASP.NET Core - 中间件

5.5.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

5.5 中间件 (Middleware)

5.5.1 关于中间件

中间件是一种装配到应用管道以处理请求和响应的软件。 每个组件:

  • 选择是否将请求传递到管道中的下一个组件。
  • 可在管道中的下一个组件前后执行工作。
  • 请求委托用于生成请求管道。 请求委托处理每个 HTTP 请求。

一句话总结:中间件是比筛选器更底层,更上游的面向切面技术,其性能最高,可处理的应用范围远比过滤器广,如实现网关,URL 转发,限流等等。

中间件更多内容

本章节暂不考虑将中间件展开讲,想了解更多知识可阅读官方文档 【ASP.NET Core - 中间件

5.5.2 常见中间件

5.5.2.1 所有请求返回同一个结果

app.Run(async context =>{    await context.Response.WriteAsync("Hello world!");});

5.5.2.2 拦截所有请求(可多个)

app.Use(async (context, next) =>{    // 比如设置统一头    context.Response.Headers["framework"] = "Furion";    // 执行下一个中间件    await next.Invoke();});// 多个app.Use(...);

5.5.2.3 特定路由中间件(可多个)

app.Map("/hello", app => {    app.Run(async context =>    {        await context.Response.WriteAsync("Map Test 1");    });});app.Map("/hello/say", app => {    // ....});

5.5.2.4 嵌套路由中间件(可多个)

app.Map("/level1", level1App => {    level1App.Map("/level2a", level2AApp => {        // "/level1/level2a" processing    });    level1App.Map("/level2b", level2BApp => {        // "/level1/level2b" processing    });});

更多例子查看官方文档 https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-6.0

5.5.3 自定义中间件

自定义中间件有多种方式,最简单的是通过 app.Use 方式,另外还支持独立类定义方式。

5.5.3.1 app.Use 方式 (不推荐)

Starup.cs
app.Use(async (context, next) =>{    var cultureQuery = context.Request.Query["culture"];    if (!string.IsNullOrWhiteSpace(cultureQuery))    {        var culture = new CultureInfo(cultureQuery);        CultureInfo.CurrentCulture = culture;        CultureInfo.CurrentUICulture = culture;    }    // 调用下一个中间件    await next(context);});

5.5.3.2 独立类 方式(推荐)

独立类的方式是目前最为推荐的方式,拓展性强,维护性高,如:

  • 定义中间件,建议以 Middleware 结尾:
using System.Globalization;namespace Middleware.Example;public class RequestCultureMiddleware{    private readonly RequestDelegate _next;    public RequestCultureMiddleware(RequestDelegate next)    {        _next = next;    }    public async Task InvokeAsync(HttpContext context)    {        var cultureQuery = context.Request.Query["culture"];        if (!string.IsNullOrWhiteSpace(cultureQuery))        {            var culture = new CultureInfo(cultureQuery);            CultureInfo.CurrentCulture = culture;            CultureInfo.CurrentUICulture = culture;        }        // 调用下一个中间件        await _next(context);    }}
  • 添加中间件拓展类

定义了中间件之后,需要创建这个中间件的拓展类,中间件拓展方法建议以 Use 开头,如:

public static class RequestCultureMiddlewareExtensions{    public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder)    {        return builder.UseMiddleware<RequestCultureMiddleware>();    }}
  • Startup.cs 中使用
public void Configure(IApplicationBuilder app, IWebHostEnvironment env){    // ... 其他中间件    app.UseRequestCulture();    // ... 其他中间件}

5.5.3.3 配置更多参数

默认情况下,自定义独立类中间件构造函数只有一个 RequestDelegate 参数,除此之后,还可以注入服务接口/类(建议是单例服务),另外还支持传入任何其他类型。

  • 服务类型参数
using System.Globalization;namespace Middleware.Example;public class RequestCultureMiddleware{    private readonly RequestDelegate _next;    private readonly ILogger<RequestCultureMiddleware> _logger;    public RequestCultureMiddleware(RequestDelegate next        , ILogger<RequestCultureMiddleware> logger)    {        _next = next;        _logger = logger;    }    public async Task InvokeAsync(HttpContext context)    {        // 其他代码        _logger.LogInformation("...");        // 调用下一个中间件        await _next(context);    }}
  • 非服务类型参数

除此之外,还可以添加 非服务参数 参数,但必须是最后一个参数!!!

using System.Globalization;namespace Middleware.Example;public class RequestCultureMiddleware{    private readonly RequestDelegate _next;    private readonly ILogger<RequestCultureMiddleware> _logger;    public RequestCultureMiddleware(RequestDelegate next        , ILogger<RequestCultureMiddleware> logger        , int age        , string name)    {        _next = next;        _logger = logger;    }    public async Task InvokeAsync(HttpContext context)    {        // 其他代码        _logger.LogInformation("...");        // 调用下一个中间件        await _next(context);    }}

之后还需要修改中间件拓展类:

public static class RequestCultureMiddlewareExtensions{    public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder, int age, string name)    {        return builder.UseMiddleware<RequestCultureMiddleware>(new object[] {age, name });    }}

使用:

app.UseRequestCulture(30, "百小僧");

5.5.4 中间件顺序

中间件是有执行顺序的,而且是先注册的先执行,无法通过其他方式更改,参考下图:

5.5.5 依赖注入/解析服务

中间件有两种方式注入服务,一种是通过构造函数注入,一种是通过 httpContext.RequestServices 方式解析。

5.5.5.1 构造函数方式

using System.Globalization;namespace Middleware.Example;public class RequestCultureMiddleware{    private readonly RequestDelegate _next;    private readonly ILogger<RequestCultureMiddleware> _logger;    public RequestCultureMiddleware(RequestDelegate next        , ILogger<RequestCultureMiddleware> logger        , IHostEnvironment hostEnvironment)    {        _next = next;        _logger = logger;    }    public async Task InvokeAsync(HttpContext context)    {        // 其他代码        // 调用下一个中间件        await _next(context);    }}
特别说明

通过构造函数的方式建议注入 单例模式 的服务,否则可能存在服务不能释放问题,如需使用瞬时或作用域的服务,可使用下列 httpContext.RequestServices 方式

5.5.5.2 httpContext.RequestServices 方式

通过这种方式可以使用非单例服务解析:

using System.Globalization;namespace Middleware.Example;public class RequestCultureMiddleware{    private readonly RequestDelegate _next;    private readonly ILogger<RequestCultureMiddleware> _logger;    // 构造函数注册单例    public RequestCultureMiddleware(RequestDelegate next        , ILogger<RequestCultureMiddleware> logger        , IHostEnvironment hostEnvironment)    {        _next = next;        _logger = logger;    }    public async Task InvokeAsync(HttpContext context)    {        // 非单例模式        using var serviceProvider = context.RequestServices.CreateScope();        var repository = serviceProvider.ServiceProvider.GetService<IRepository>();        // 调用下一个中间件        await _next(context);    }}

5.5.6 常见问题

由于中间件是比较原始的切面方式,有时候我们需要获取终点路由的特性或者其他信息,则需要一点技巧:

// 获取终点路由特性var endpointFeature = context.Features.Get<IEndpointFeature>();// 获取是否定义了特性var attribute = endpointFeature?.Endpoint?.Metadata?.GetMetadata<YourAttribute>()

5.5.7 了解更多

想了解更多中间件知识可阅读官方文档 【ASP.NET Core - 中间件

5.5.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/module-dev/index.html b/handbook/build/docs/module-dev/index.html index 4e9e27579b..d734d56fac 100644 --- a/handbook/build/docs/module-dev/index.html +++ b/handbook/build/docs/module-dev/index.html @@ -2,22 +2,21 @@ - - - + +28. 模块化开发 | Furion -28. 模块化开发 | Furion - - + + +
-

28. 模块化开发

特别注意

以下的模块化配置必须在 appsettings.json 下配置才有效,原因是启动的时候 appsettings.json 已经加载,自定义配置文件还未加载。

28.1 关于模块化开发

模块化是代码的组成的一种方式,模块化系统就像乐高玩具一样,一块一块零散积木堆积起一个精彩的世界。每种积木的形状各不相同,功能各不相同,积木与积木直接互相依赖,互相支撑。

28.1.1 模块化开发好处

模块化开发能够将不同的功能组装在一起,实现功能的累加,诸多功能组装在一起,最终形成项目。

28.2 模块分类

  • 应用程序模块:通常这类模块是完整的应用程序,可以独立运行,有自己的实体、服务、API 及 UI 组件等。
  • 框架级模块:这类通常是解决某个业务功能进行开发的模块,比如上传文件、分布式缓存、数据验证等。

28.3 如何进行模块化开发

Furion 框架设计之初就考虑到模块化开发,所以从最初版本就具备此功能。启用 Furion 模块化支持非常简单。

28.3.1 启用模块化支持

{  "AppSettings": {    "EnabledReferenceAssemblyScan": true,    // 启用模块化程序集扫描    "SupportPackageNamePrefixs": ["Module1", "Module2",...] // 配置通过 Nuget 方式安装的模块化包,如果不是通过 Nuget 方式可不配置    // "ExternalAssemblies": ["plugins/Module1.dll", "plugins/Module2.dll", ...]   // 配置加载网站 plugins 目录下的模块程序集,可不配置  }}

28.3.2 各种添加模块配置方式

添加模块到现有的应用中有多种方式:

  1. 直接通过项目添加模块化引用或编辑 .csproj 添加模块

这种方式无需任何配置,Furion 框架可自动加载模块。

  1. 通过添加 .dll 方式引用模块

需要配置 EnabledReferenceAssemblyScan 节点,如:

{  "AppSettings": {    "EnabledReferenceAssemblyScan": true  }}
  1. 通过 Nuget 方式安装模块

如果通过 Nuget 方式安装模块,需要配置 SupportPackageNamePrefixs 节点,如:

{  "AppSettings": {    "SupportPackageNamePrefixs": ["Nuget包名称", "Nuget包名称",...]  }}
  1. 通过动态加载 .dll 方式安装模块

这种方式通常是在网站创建一个文件夹放入模块化 .dll 文件,如:plugins,无需添加引用可自动加载。

{  "AppSettings": {    "ExternalAssemblies": ["plugins/Module1.dll", "plugins/Module2.dll", ...]  }}
特别注意

如果非生产环境,那么 plugins 文件夹放在 bin\Debug\net n.0\bin\Release\net n.0 目录下。

如果是生产环境,则直接放在根目录即可。

28.4 模块化开发注意事项

  • 尽可能保证每个模块都有独立的路由地址格式:/模块化名称/路由地址,这样才能保证不会和现有的系统出现冲突。
  • 开发模块化是尽可能设计为完全独立的引用,如果需要包含 UI 元素如视图、html/cs/javascript 应采用嵌入式方式
  • 模块化开发如果需要添加第三方服务,应配置在 AppStartup 的派生类中。
  • 模块化的所在程序集的注释文件 .xml 需放在和 .dll 同级目录

28.5 关于热插拔机制

Furion v2.4.0 + 版本之后,框架移除了热加载和热卸载模块的功能,原因是目前微软提供的 AssemblyLoadContext + 文件夹监听 处理 .dll 运行时热拔插机制还未成熟,此功能将在 .NET6 版本得到改善。

也就是,自 v2.4.0+ 版本之后,Furion 框架只提供在启动时加载模块,不在运行时进行任何处理。

28.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

28. 模块化开发

特别注意

以下的模块化配置必须在 appsettings.json 下配置才有效,原因是启动的时候 appsettings.json 已经加载,自定义配置文件还未加载。

28.1 关于模块化开发

模块化是代码的组成的一种方式,模块化系统就像乐高玩具一样,一块一块零散积木堆积起一个精彩的世界。每种积木的形状各不相同,功能各不相同,积木与积木直接互相依赖,互相支撑。

28.1.1 模块化开发好处

模块化开发能够将不同的功能组装在一起,实现功能的累加,诸多功能组装在一起,最终形成项目。

28.2 模块分类

  • 应用程序模块:通常这类模块是完整的应用程序,可以独立运行,有自己的实体、服务、API 及 UI 组件等。
  • 框架级模块:这类通常是解决某个业务功能进行开发的模块,比如上传文件、分布式缓存、数据验证等。

28.3 如何进行模块化开发

Furion 框架设计之初就考虑到模块化开发,所以从最初版本就具备此功能。启用 Furion 模块化支持非常简单。

28.3.1 启用模块化支持

{  "AppSettings": {    "EnabledReferenceAssemblyScan": true,    // 启用模块化程序集扫描    "SupportPackageNamePrefixs": ["Module1", "Module2",...] // 配置通过 Nuget 方式安装的模块化包,如果不是通过 Nuget 方式可不配置    // "ExternalAssemblies": ["plugins/Module1.dll", "plugins/Module2.dll", ...]   // 配置加载网站 plugins 目录下的模块程序集,可不配置  }}

28.3.2 各种添加模块配置方式

添加模块到现有的应用中有多种方式:

  1. 直接通过项目添加模块化引用或编辑 .csproj 添加模块

这种方式无需任何配置,Furion 框架可自动加载模块。

  1. 通过添加 .dll 方式引用模块

需要配置 EnabledReferenceAssemblyScan 节点,如:

{  "AppSettings": {    "EnabledReferenceAssemblyScan": true  }}
  1. 通过 Nuget 方式安装模块

如果通过 Nuget 方式安装模块,需要配置 SupportPackageNamePrefixs 节点,如:

{  "AppSettings": {    "SupportPackageNamePrefixs": ["Nuget包名称", "Nuget包名称",...]  }}
  1. 通过动态加载 .dll 方式安装模块

这种方式通常是在网站创建一个文件夹放入模块化 .dll 文件,如:plugins,无需添加引用可自动加载。

{  "AppSettings": {    "ExternalAssemblies": ["plugins/Module1.dll", "plugins/Module2.dll", ...]  }}
特别注意

如果非生产环境,那么 plugins 文件夹放在 bin\Debug\net n.0\bin\Release\net n.0 目录下。

如果是生产环境,则直接放在根目录即可。

28.4 模块化开发注意事项

  • 尽可能保证每个模块都有独立的路由地址格式:/模块化名称/路由地址,这样才能保证不会和现有的系统出现冲突。
  • 开发模块化是尽可能设计为完全独立的引用,如果需要包含 UI 元素如视图、html/cs/javascript 应采用嵌入式方式
  • 模块化开发如果需要添加第三方服务,应配置在 AppStartup 的派生类中。
  • 模块化的所在程序集的注释文件 .xml 需放在和 .dll 同级目录

28.5 关于热插拔机制

Furion v2.4.0 + 版本之后,框架移除了热加载和热卸载模块的功能,原因是目前微软提供的 AssemblyLoadContext + 文件夹监听 处理 .dll 运行时热拔插机制还未成熟,此功能将在 .NET6 版本得到改善。

也就是,自 v2.4.0+ 版本之后,Furion 框架只提供在启动时加载模块,不在运行时进行任何处理。

28.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/mongodb/index.html b/handbook/build/docs/mongodb/index.html index 7650f2a95e..f1a923a1c0 100644 --- a/handbook/build/docs/mongodb/index.html +++ b/handbook/build/docs/mongodb/index.html @@ -2,22 +2,21 @@ - - - + +10.3 MongoDB 操作 | Furion -10.3 MongoDB 操作 | Furion - - + + +
-

10.3 MongoDB 操作

温馨提醒

Furion 包中默认集成了 EFCore如果不使用 EFCore,可安装纯净版 Furion.Pure 代替 Furion

10.3.1 关于 MongoDB

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。

MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

10.3.2 如何集成

Furion 框架中,已经推出 MongoDB 拓展包 Furion.Extras.DatabaseAccessor.MongoDB

10.3.2.1 注册 MongoDB 服务

使用非常简单,只需要在 Startup.cs 中添加 services.AddMongoDB(connectionString) 即可。如:

// 方式一services.AddMongoDB("mongodb://localhost:27017");// 方式二services.AddMongoDB(new MongoClientSettings {});// 方式三services.AddMongoDB(new MongoUrl {});

10.3.3 基本使用

在使用之前,我们可以通过构造函数注入 IMongoDBRepository 接口,如:

  • 非泛型版本
private readonly IMongoDBRepository _mongoRepository;public PersonService(IMongoDBRepository mongoRepository){    _mongoRepository = mongoRepository;}

10.3.3.1 常见例子

var database = _mongoRepository.Context.GetDatabase("foo");var collection = database.GetCollection<BsonDocument>("bar");await collection.InsertOneAsync(new BsonDocument("Name", "Jack"));var list = await collection.Find(new BsonDocument("Name", "Jack"))    .ToListAsync();foreach(var document in list){    Console.WriteLine(document["Name"]);}
public class Person{    public ObjectId Id { get; set; }    public string Name { get; set; }}var database = _mongoRepository.Context.GetDatabase("foo");var collection = database.GetCollection<Person>("bar");await collection.InsertOneAsync(new Person { Name = "Jack" });var list = await collection.Find(x => x.Name == "Jack")                           .ToListAsync();foreach(var person in list){    Console.WriteLine(person.Name);}

10.3.3.2 获取 MongoClient 对象

IMongoDBRepository 只封装了 MongoDB 基础功能,如需获取更多操作可通过 .Context 属性获取 MongoClient 对象,如:

var client = _mongoRepository.Context;

10.3.4 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 MongoDB 知识可查阅 MongoDB 仓库

演练场
- - +

10.3 MongoDB 操作

温馨提醒

Furion 包中默认集成了 EFCore如果不使用 EFCore,可安装纯净版 Furion.Pure 代替 Furion

10.3.1 关于 MongoDB

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。

MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

10.3.2 如何集成

Furion 框架中,已经推出 MongoDB 拓展包 Furion.Extras.DatabaseAccessor.MongoDB

10.3.2.1 注册 MongoDB 服务

使用非常简单,只需要在 Startup.cs 中添加 services.AddMongoDB(connectionString) 即可。如:

// 方式一services.AddMongoDB("mongodb://localhost:27017");// 方式二services.AddMongoDB(new MongoClientSettings {});// 方式三services.AddMongoDB(new MongoUrl {});

10.3.3 基本使用

在使用之前,我们可以通过构造函数注入 IMongoDBRepository 接口,如:

  • 非泛型版本
private readonly IMongoDBRepository _mongoRepository;public PersonService(IMongoDBRepository mongoRepository){    _mongoRepository = mongoRepository;}

10.3.3.1 常见例子

var database = _mongoRepository.Context.GetDatabase("foo");var collection = database.GetCollection<BsonDocument>("bar");await collection.InsertOneAsync(new BsonDocument("Name", "Jack"));var list = await collection.Find(new BsonDocument("Name", "Jack"))    .ToListAsync();foreach(var document in list){    Console.WriteLine(document["Name"]);}
public class Person{    public ObjectId Id { get; set; }    public string Name { get; set; }}var database = _mongoRepository.Context.GetDatabase("foo");var collection = database.GetCollection<Person>("bar");await collection.InsertOneAsync(new Person { Name = "Jack" });var list = await collection.Find(x => x.Name == "Jack")                           .ToListAsync();foreach(var person in list){    Console.WriteLine(person.Name);}

10.3.3.2 获取 MongoClient 对象

IMongoDBRepository 只封装了 MongoDB 基础功能,如需获取更多操作可通过 .Context 属性获取 MongoClient 对象,如:

var client = _mongoRepository.Context;

10.3.4 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 MongoDB 知识可查阅 MongoDB 仓库

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/net5-to-net6/index.html b/handbook/build/docs/net5-to-net6/index.html index 751b1435e6..82c506a3cd 100644 --- a/handbook/build/docs/net5-to-net6/index.html +++ b/handbook/build/docs/net5-to-net6/index.html @@ -2,23 +2,22 @@ - - - + +2.5 .NET5 升级 .NET6 | Furion -2.5 .NET5 升级 .NET6 | Furion - - + + +
-

2.5 .NET5 升级 .NET6

2.5.1 升级注意事项

目前使用 Furion v2.x 版本的用户均可以快速无缝升级至 Furion v4.x 版本,只需要做少量更改即可。

2.5.1.1 安装 .NET6 SDK

https://dotnet.microsoft.com/download/dotnet/6.0

2.5.1.2 编辑 .csproj 文件

编辑解决方案所有项目的 .csproj 文件,并替换 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>,如:

当然也可以使用 Ctrl + F 全局替换

2.5.1.3 升级 Nuget

Furion 所有包升级至 v4.3.9 版本,同时 Microsoft 所有包升级至 v6.0.8 版本,如:

2.5.1.4 删除 Startup.cs 文件

删除 Web 启动层Startup.cs 文件,如:

2.5.1.5 编辑 Web 启动层 .csproj

编辑 Web 启动层 .csproj 文件,并添加 <ImplicitUsings>enable</ImplicitUsings>,如:

2.5.1.6 替换 Program.cs 内容为:

var builder = WebApplication.CreateBuilder(args).Inject();var app = builder.Build();app.Run();
v3.6.4+ 版本

如果使用 Furion 3.6.4+ 版本,可直接使用 Serve.Run(RunOptions.Default); 替代上面即可。

小提醒

如果使用了 Serilog 日志组件,可添加 builder.UseSerilogDefault();

也可以使用 Serve.Run(RunOptions.Default.ConfigureBuilder(builder => builder.UseSerilogDefault()));

如果使用了 pgsql 数据库,你还可能需要添加 AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); -=> 相关说明:在 .NET6 中 Npgsql 6.0 对时间戳的映射方式进行了一些重要的更改。

2.5.1.7 重新编译整个解决方案

升级完成!!!

演练场
- - +

2.5 .NET5 升级 .NET6

2.5.1 升级注意事项

目前使用 Furion v2.x 版本的用户均可以快速无缝升级至 Furion v4.x 版本,只需要做少量更改即可。

2.5.1.1 安装 .NET6 SDK

https://dotnet.microsoft.com/download/dotnet/6.0

2.5.1.2 编辑 .csproj 文件

编辑解决方案所有项目的 .csproj 文件,并替换 <TargetFramework>net5.0</TargetFramework><TargetFramework>net6.0</TargetFramework>,如:

当然也可以使用 Ctrl + F 全局替换

2.5.1.3 升级 Nuget

Furion 所有包升级至 v4.4.0 版本,同时 Microsoft 所有包升级至 v6.0.8 版本,如:

2.5.1.4 删除 Startup.cs 文件

删除 Web 启动层Startup.cs 文件,如:

2.5.1.5 编辑 Web 启动层 .csproj

编辑 Web 启动层 .csproj 文件,并添加 <ImplicitUsings>enable</ImplicitUsings>,如:

2.5.1.6 替换 Program.cs 内容为:

var builder = WebApplication.CreateBuilder(args).Inject();var app = builder.Build();app.Run();
v3.6.4+ 版本

如果使用 Furion 3.6.4+ 版本,可直接使用 Serve.Run(RunOptions.Default); 替代上面即可。

小提醒

如果使用了 Serilog 日志组件,可添加 builder.UseSerilogDefault();

也可以使用 Serve.Run(RunOptions.Default.ConfigureBuilder(builder => builder.UseSerilogDefault()));

如果使用了 pgsql 数据库,你还可能需要添加 AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); +=> 相关说明:在 .NET6 中 Npgsql 6.0 对时间戳的映射方式进行了一些重要的更改。

2.5.1.7 重新编译整个解决方案

升级完成!!!

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/nuget-local/index.html b/handbook/build/docs/nuget-local/index.html index d290d90c66..a006c456e6 100644 --- a/handbook/build/docs/nuget-local/index.html +++ b/handbook/build/docs/nuget-local/index.html @@ -2,22 +2,21 @@ - - - + +2.9 Nuget 本地调试包 | Furion -2.9 Nuget 本地调试包 | Furion - - + + +
-

2.9 Nuget 本地调试包

2.9.1 关于本地测试包

正常情况下,我们都是通过 Nuget 在线平台(Visual Studio 内置的 Nuget 包管理器)安装拓展依赖,但有时候我们不希望发布到 Nuget 平台或者只想在本地使用又或者先在本地测试通过再发布。

这样做的好处是:

  • 可以有效保护公司核心代码
  • 方便开源项目测试

2.9.2 如何配置

2.9.2.1 测试包命名规则

默认情况下,Furion 会根据 Furion.版本号-beta.Issue编号 规则生成 .nupkg.snupkg 包,前者是不包含调试的无符号 Nuget 包,后者则是调试符号包(方便 IDE 调试用的),如:

D:\Furion_Nuget_Test_Packages
Furion.4.2.3-beta-I5MM3O.nupkg
Furion.4.2.3-beta-I5MM3O.snupkg

其中 I5MM3O 对应的正是 Issue 的编号:https://gitee.com/dotnetchina/Furion/issues/I5MM3O

2.9.2.2 配置本地包路径

有了这两个包之后,就可以在本地磁盘中创建文件夹并放进去,如 D:\Furion_Nuget_Test_Packages

2.9.2.3 在 Visual Studio 中配置路径

关于命令行操作

如果不使用可视化 IDE 配置,可通过下列命令行配置:

dotnet restore "YourProject.Web.Entry/YourProject.Web.Entry.csproj" -s "D:\Furion_Nuget_Test_Packages";
dotnet restore "YourProject.Web.Entry/YourProject.Web.Entry.csproj" -s "https://api.nuget.org/v3/index.json";

2.9.2.4 选择测试版安装或更新


测试通过后可以删除之前的配置即可,如:

2.9.3 Visual Studio 调试 Nuget

Furion 提供了 .snupkg 包,在安装 Furion 的时候自动下载到本地,如需启用源码调试,只需要启用以下配置即可:

启用之后重新编译解决方案就可以通过 F12 跳转到源代码区并调试源代码了。

2.9.4 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

2.9 Nuget 本地调试包

2.9.1 关于本地测试包

正常情况下,我们都是通过 Nuget 在线平台(Visual Studio 内置的 Nuget 包管理器)安装拓展依赖,但有时候我们不希望发布到 Nuget 平台或者只想在本地使用又或者先在本地测试通过再发布。

这样做的好处是:

  • 可以有效保护公司核心代码
  • 方便开源项目测试

2.9.2 如何配置

2.9.2.1 测试包命名规则

默认情况下,Furion 会根据 Furion.版本号-beta.Issue编号 规则生成 .nupkg.snupkg 包,前者是不包含调试的无符号 Nuget 包,后者则是调试符号包(方便 IDE 调试用的),如:

D:\Furion_Nuget_Test_Packages
Furion.4.2.3-beta-I5MM3O.nupkg
Furion.4.2.3-beta-I5MM3O.snupkg

其中 I5MM3O 对应的正是 Issue 的编号:https://gitee.com/dotnetchina/Furion/issues/I5MM3O

2.9.2.2 配置本地包路径

有了这两个包之后,就可以在本地磁盘中创建文件夹并放进去,如 D:\Furion_Nuget_Test_Packages

2.9.2.3 在 Visual Studio 中配置路径

关于命令行操作

如果不使用可视化 IDE 配置,可通过下列命令行配置:

dotnet restore "YourProject.Web.Entry/YourProject.Web.Entry.csproj" -s "D:\Furion_Nuget_Test_Packages";
dotnet restore "YourProject.Web.Entry/YourProject.Web.Entry.csproj" -s "https://api.nuget.org/v3/index.json";

2.9.2.4 选择测试版安装或更新


测试通过后可以删除之前的配置即可,如:

2.9.3 Visual Studio 调试 Nuget

Furion 提供了 .snupkg 包,在安装 Furion 的时候自动下载到本地,如需启用源码调试,只需要启用以下配置即可:

启用之后重新编译解决方案就可以通过 F12 跳转到源代码区并调试源代码了。

2.9.4 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/object-mapper/index.html b/handbook/build/docs/object-mapper/index.html index 6f80a80b55..e50d54093e 100644 --- a/handbook/build/docs/object-mapper/index.html +++ b/handbook/build/docs/object-mapper/index.html @@ -2,22 +2,21 @@ - - - + +13. 对象数据映射 | Furion -13. 对象数据映射 | Furion - - + + +
-

13. 对象数据映射

使用 Mapster 以外的拓展说明

Furion 框架提供了 Mapster 的拓展 Furion.Extras.ObjectMapper.Mapster,如需使用第三方如 AutoMapper 则无需安装此拓展。

13.1 对象映射

简单来说,就是将一个对象的数据根据特定规则批量映射到另一个对象中,减少手工操作和降低人为出错率。如将 DTO 对象映射到 Entity 实体中,反之亦然。

13.2 先看例子

在过去,我们需要将一个对象的值转换到另一个对象中,我们需要这样做,如:

var entity = repository.Find(1);var dto = new Dto();dto.Id = entity.Id;dto.Name = entity.Name;dto.Age = entity.Age;dto.Address = entity.Address;dto.FullName = entity.FirstName + entity.LastName;dto.IdCard = entity.IdCard.Replace("1234", "****");

上面的例子似乎没有任何问题,但是如果很多地方需要这样的赋值操作、或者相同的赋值操作在多个地方使用,又或者一个类中含有非常多的属性或自定义赋值操作。那么这样的操作效率极低,容易出错,且代码非常臃肿和冗余。

所以,实现自动映射赋值和支持特殊配置的需求就有了。目前 C# 平台有两个优秀的对象映射工具:MapsterAutoMapperFurion 框架中,推荐使用 MapsterMapster 是一款极易使用且超高性能的对象映射框架。

13.3 Mapster 使用

现在,我们可以通过 Mapster 提供的对象映射方法:Adapt 方法改造上面的例子:

安装拓展包

Furion.Core 层安装 Furion.Extras.ObjectMapper.Mapster 拓展包,无需手动调用,Furion 会自动加载并调用。

13.3.1 快速入门

var entity = repository.Find(1);var dto = entity.Adapt<Dto>();

仅仅一行代码就可以实现 entity -> dto 的转换,如果涉及到赋值的复制操作,如 dto.FullNamedto.IdCard,我们只需要自定义映射规则类即可。

13.3.2 自定义映射规则

using Mapster;using System;namespace Furion.Application{    public class Mapper : IRegister    {        public void Register(TypeAdapterConfig config)        {            config.ForType<Entity, Dto>()                .Map(dest => dest.FullName, src => src.FirstName + src.LastName)                .Map(dest => dest.IdCard, src => src.IdCard.Replace("1234", "****"));        }    }}
小知识

该映射文件 Mapper.cs 可以放在任何项目或文件夹中,Furion 会在程序启动的时候自动扫描并注入配置。

13.3.3 依赖注入方式

Mapster 除了提供 Adapt 拓展方法以外,同时还提供依赖注入的方式。

public  Person(IMapper mapper){  var dto =  _mapper.Map<Dto>(entity);}

13.3.4 和 EFCore 配合

Mapster 还提供了 ProjectToType Linq 拓展方法减少我们手动 Select 操作,如:

正常的操作:

var destinations = context.Sources        .Select(p => new Destination {            Id = p.Id,            Name = p.Name,            Surname = p.Surname,            ....        })        .ToList();

使用 Mapster 之后:

 var destinations = context.Sources.ProjectToType<Destination>().ToList();

13.4 全局默认配置

Furion 提供全局默认映射配置选项 TypeAdapterConfig.GlobalSettings.Default,可在 Startup 中配置即可,如:

TypeAdapterConfig.GlobalSettings.Default    .PreserveReference(true);

13.5 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 Mapster 知识可查阅 Mapster - Wiki 文档。

演练场
- - +

13. 对象数据映射

使用 Mapster 以外的拓展说明

Furion 框架提供了 Mapster 的拓展 Furion.Extras.ObjectMapper.Mapster,如需使用第三方如 AutoMapper 则无需安装此拓展。

13.1 对象映射

简单来说,就是将一个对象的数据根据特定规则批量映射到另一个对象中,减少手工操作和降低人为出错率。如将 DTO 对象映射到 Entity 实体中,反之亦然。

13.2 先看例子

在过去,我们需要将一个对象的值转换到另一个对象中,我们需要这样做,如:

var entity = repository.Find(1);var dto = new Dto();dto.Id = entity.Id;dto.Name = entity.Name;dto.Age = entity.Age;dto.Address = entity.Address;dto.FullName = entity.FirstName + entity.LastName;dto.IdCard = entity.IdCard.Replace("1234", "****");

上面的例子似乎没有任何问题,但是如果很多地方需要这样的赋值操作、或者相同的赋值操作在多个地方使用,又或者一个类中含有非常多的属性或自定义赋值操作。那么这样的操作效率极低,容易出错,且代码非常臃肿和冗余。

所以,实现自动映射赋值和支持特殊配置的需求就有了。目前 C# 平台有两个优秀的对象映射工具:MapsterAutoMapperFurion 框架中,推荐使用 MapsterMapster 是一款极易使用且超高性能的对象映射框架。

13.3 Mapster 使用

现在,我们可以通过 Mapster 提供的对象映射方法:Adapt 方法改造上面的例子:

安装拓展包

Furion.Core 层安装 Furion.Extras.ObjectMapper.Mapster 拓展包,无需手动调用,Furion 会自动加载并调用。

13.3.1 快速入门

var entity = repository.Find(1);var dto = entity.Adapt<Dto>();

仅仅一行代码就可以实现 entity -> dto 的转换,如果涉及到赋值的复制操作,如 dto.FullNamedto.IdCard,我们只需要自定义映射规则类即可。

13.3.2 自定义映射规则

using Mapster;using System;namespace Furion.Application{    public class Mapper : IRegister    {        public void Register(TypeAdapterConfig config)        {            config.ForType<Entity, Dto>()                .Map(dest => dest.FullName, src => src.FirstName + src.LastName)                .Map(dest => dest.IdCard, src => src.IdCard.Replace("1234", "****"));        }    }}
小知识

该映射文件 Mapper.cs 可以放在任何项目或文件夹中,Furion 会在程序启动的时候自动扫描并注入配置。

13.3.3 依赖注入方式

Mapster 除了提供 Adapt 拓展方法以外,同时还提供依赖注入的方式。

public  Person(IMapper mapper){  var dto =  _mapper.Map<Dto>(entity);}

13.3.4 和 EFCore 配合

Mapster 还提供了 ProjectToType Linq 拓展方法减少我们手动 Select 操作,如:

正常的操作:

var destinations = context.Sources        .Select(p => new Destination {            Id = p.Id,            Name = p.Name,            Surname = p.Surname,            ....        })        .ToList();

使用 Mapster 之后:

 var destinations = context.Sources.ProjectToType<Destination>().ToList();

13.4 全局默认配置

Furion 提供全局默认映射配置选项 TypeAdapterConfig.GlobalSettings.Default,可在 Startup 中配置即可,如:

TypeAdapterConfig.GlobalSettings.Default    .PreserveReference(true);

13.5 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 Mapster 知识可查阅 Mapster - Wiki 文档。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/options/index.html b/handbook/build/docs/options/index.html index 415ae3e999..8e343b8c23 100644 --- a/handbook/build/docs/options/index.html +++ b/handbook/build/docs/options/index.html @@ -2,22 +2,21 @@ - - - + +4.2 选项 | Furion -4.2 选项 | Furion - - + + +
-

4.2 选项

4.2.1 什么是选项

选项是 ASP.NET Core 推荐的动态读取配置的方式,这种方式将配置文件数据用一个强类型来托管,能够实现配置验证、默认值配置、实时读取等功能。

4.2.2 与配置的区别

选项实际上也是配置,但在后者的基础上添加了配置验证、默认值/后期配置设定及提供了多种接口读取配置信息,同时还支持供配置更改通知等强大灵活功能。

所以,除了一次性读取使用的配置以外,都应该选用 选项 替换 配置

知识导航

有关配置说明可查看《4.1 配置》 章节。

4.2.3 选项的使用

假设我们需要在系统运行时获取系统名称、版本号及版权信息,这些信息可能随时变化而且需要在多个地方使用。这时就需要将这些信息配置起来。具体步骤如下:

4.2.3.1 配置 appsettings.json 信息

{  "AppInfo": {    "Name": "Furion",    "Version": "1.0.0",    "Company": "Baiqian"  }}

4.2.3.2 创建 AppInfoOptions 强类型类

using Furion.ConfigurableOptions;namespace Furion.Application{    public class AppInfoOptions : IConfigurableOptions    {        public string Name { get; set; }        public string Version { get; set; }        public string Company { get; set; }    }}
温馨提示

建议所有选项类都应该以 Options 命名结尾。

另外,Furion 框架提供了非常灵活的注册选项服务的方法,只需要继承 IConfigurableOptions 接口即可,该接口位于 Furion.ConfigurableOptions 命名空间下。

4.2.3.3 注册 AppInfoOptions 服务

选项不同于配置,需在应用启动时注册

Furion.Web.Core\FurWebCoreStartup.cs
using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Core{    [AppStartup(800)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddConfigurableOptions<AppInfoOptions>();        }    }}

4.2.3.4 读取 AppInfoOptions 信息

Furion 框架中,提供了多种读取方式:

  • 通过 App.GetOptions<TOptions>(path) 读取(不推荐
  • 通过依赖注入以下实例读取:
    • IOptions<TOptions>
    • IOptionsSnapshot<TOptions>
    • IOptionsMonitor<TOptions>
  • 通过 App 静态类提供的静态方法获取:
    • App.GetOptions<TOptions>()
    • App.GetOptionsMonitor<TOptions>()
    • App.GetOptionsSnapshot<TOptions>()
using Furion.Application;using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    [Route("api/[controller]")]    public class DefaultController : ControllerBase    {        [HttpGet]        public string Get()        {            // 不推荐采用此方式读取,该方式仅在 ConfigureServices 启动时使用            var appInfo = App.GetConfig<AppInfoOptions>("AppInfo", true);            return $@"名称:{appInfo.Name}                      版本:{appInfo.Version}                      公司:{appInfo.Company}";        }    }}

4.2.3.5 如何选择读取方式

  • 如果选项需要在多个地方使用,则无论任何时候都不推荐使用 App.GetOptions<TOptions>(path)
  • 在可依赖注入类中,依赖注入 IOptions[Snapshot|Monitor]<TOptions> 读取
  • 在静态类/非依赖注入类中,选择 App.GetOptions[Snapshot|Monitor]<TOptions>() 读取

4.2.4 选项接口说明

ASP.NET Core 应用提供了多种读取选项的接口:

  • IOptions<TOptions>
    • 不支持:
      • 在应用启动后读取配置数据
      • 命名选项
    • 注册为单一实例且可以注入到任何服务生存期
  • IOptionsSnapshot<TOptions>
    • 在每次请求时应重新计算选项的方案中有用
    • 注册为范围内,因此无法注入到单一实例服务
    • 支持命名选项
  • IOptionsMonitor<TOptions>
    • 用于检索选项并管理 TOptions 实例的选项通知。
    • 注册为单一实例且可以注入到任何服务生存期。
    • 支持:
      • 更改通知
      • 命名选项
      • 可重载配置
      • 选择性选项失效 (IOptionsMonitorCache<TOptions>)
注意事项

在使用 IConfigurableOptionsListener 监听选项后,如要获取最新的配置信息,请使用 App.GetOptionsMonitor<TOptions>() 而不是 App.GetOptions<TOptions>()

了解更多

想了解更多 选项接口 知识可查阅 ASP.NET Core - 选项 - 选项接口 小节。

4.2.5 选项自定义配置

我们知道,选项实际上需要和配置文件特定键值挂钩,那 Furion 是如何准确的找到配置文件中的键值的呢?

4.2.5.1 选项查找键流程

  • 没有贴 [OptionsSettings] 特性
    • Options 结尾,则去除 Options 字符串
    • 否则返回 类名称
  • 贴了 [OptionsSettings] 特性
    • 如果配置了 Path 属性,则返回 Path 的值
    • 否则返回 类名称
  • Options 结尾,则键名为:AppInfo
public class AppInfoOptions : IConfigurableOptions{    public string Name { get; set; }    public string Version { get; set; }    public string Company { get; set; }}
  • 不以 Options 结尾,则键名为:AppInfoSettings
public class AppInfoSettings : IConfigurableOptions{    public string Name { get; set; }    public string Version { get; set; }    public string Company { get; set; }}

4.2.6 [OptionsSettings] 说明

选项类可以通过 [OptionsSettings] 来配置查找路径值。

4.2.7 选项验证

选项支持验证配置有效性,在 Furion 框架中,通过 services.AddConfigurableOptions<TOptions>() 注册选项默认启用了验证支持。

包括:

  • 特性方式 DataAnnotations
  • 自定义复杂验证 IValidateOptions<TOptions>
using Furion.ConfigurableOptions;using System.ComponentModel.DataAnnotations;namespace Furion.Application{    public class AppInfoOptions : IConfigurableOptions    {        [Required(ErrorMessage = "名称不能为空")]        public string Name { get; set; }        [Required, RegularExpression(@"^[0-9][0-9\.]+[0-9]$", ErrorMessage = "不是有效的版本号")]        public string Version { get; set; }        [Required, MaxLength(100)]        public string Company { get; set; }    }}
特别说明

IConfigurableOptions<TOptions, TOptionsValidation> 继承自 IConfigurableOptions<TOptions>,也就是自定义复杂验证默认具有 PostConfigure(TOptions options) 选项后期配置方法。关于《4.2.8 选项后期配置》将在下一小节说明。

4.2.8 选项后期配置

选项后期配置通俗一点来说,可以在运行时解析值或设定默认值/后期配置等。

Furion 框架中,配置选项后期配置很简单,只需要继承 IConfigurableOptions<TOptions> 接口并实现 PostConfigure(TOptions options) 方法。

using Furion.ConfigurableOptions;using Microsoft.Extensions.Configuration;using System.ComponentModel.DataAnnotations;namespace Furion.Application{    public class AppInfoOptions : IConfigurableOptions<AppInfoOptions>    {        [Required(ErrorMessage = "名称不能为空")]        public string Name { get; set; }        [Required]        public string Version { get; set; }        [Required, MaxLength(100)]        public string Company { get; set; }        public void PostConfigure(AppInfoOptions options, IConfiguration configuration)        {            options.Name ??= "Furion";            options.Version ??= "1.0.0";            options.Company ??= "Baiqian";        }    }}
特别说明

IConfigurableOptions<TOptions, TOptionsValidation> 继承自 IConfigurableOptions<TOptions>,也就是自定义复杂验证默认具有 PostConfigure(TOptions options, IConfiguration configuration) 选项后期配置方法。

4.2.9 选项更改通知(热更新

Furion 框架提供了非常简单且灵活的方式监听选项更改,也就是 appsettings.json 或 自定义配置文件发生任何更改都会触发处理方法

使用非常简单,只需要继承 IConfigurableOptionsListener<TOptions> 接口并实现 void OnListener(TOptions options, IConfiguration configuration) 方法即可。

using Furion.ConfigurableOptions;namespace Furion.Application{    public class AppInfoOptions : IConfigurableOptionsListener<AppInfoOptions>    {        public string Name { get; set; }        public string Version { get; set; }        public string Company { get; set; }        public void OnListener(AppInfoOptions options, IConfiguration configuration)        {            var name = options.Name;  // 实时的最新值            var version = options.Version;  // 实时的最新值        }        public void PostConfigure(AppInfoOptions options, IConfiguration configuration)        {        }    }}
特别说明

IConfigurableOptionsListener<TOptions> 继承自 IConfigurableOptions<TOptions>

4.2.10 选项的优缺点

  • 优点

    • 强类型配置
    • 提供多种读取方式
    • 支持热加载
    • 支持设置默认值/后期配置
    • 支持在运行环境中动态配置
    • 支持验证配置有效性
    • 支持更改通知
    • 支持命名选项
  • 缺点

    • 需要定义对应类型
    • 需要在启动时注册

4.2.11 自定义属性 Key 映射

版本说明

以下内容仅限 Furion v3.4.3+ 版本使用。

有时候我们在 appsettings.json 中配置的 Key 和选项定义的属性名不一样,这时候就需要用到 [MapSettings] 特性即可,如:

"AppInfo": {    "Name": "Furion",    "Version": "1.0.0",    "Company_Name": "Baiqian"}
public class AppInfoOptions : IConfigurableOptions{    public string Name { get; set; }    public string Version { get; set; }    [MapSettings("Company_Name")]    public string Company { get; set; }}
特别注意

[MapSettings] 配置的 Key 会自定应用选项的 Key 作为起始点,如实际上 Company 属性对应的 Key 为:AppInfo:Company_Name

4.2.12 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 选项 知识可查阅 ASP.NET Core - 选项 章节。

演练场
- - +

4.2 选项

4.2.1 什么是选项

选项是 ASP.NET Core 推荐的动态读取配置的方式,这种方式将配置文件数据用一个强类型来托管,能够实现配置验证、默认值配置、实时读取等功能。

4.2.2 与配置的区别

选项实际上也是配置,但在后者的基础上添加了配置验证、默认值/后期配置设定及提供了多种接口读取配置信息,同时还支持供配置更改通知等强大灵活功能。

所以,除了一次性读取使用的配置以外,都应该选用 选项 替换 配置

知识导航

有关配置说明可查看《4.1 配置》 章节。

4.2.3 选项的使用

假设我们需要在系统运行时获取系统名称、版本号及版权信息,这些信息可能随时变化而且需要在多个地方使用。这时就需要将这些信息配置起来。具体步骤如下:

4.2.3.1 配置 appsettings.json 信息

{  "AppInfo": {    "Name": "Furion",    "Version": "1.0.0",    "Company": "Baiqian"  }}

4.2.3.2 创建 AppInfoOptions 强类型类

using Furion.ConfigurableOptions;namespace Furion.Application{    public class AppInfoOptions : IConfigurableOptions    {        public string Name { get; set; }        public string Version { get; set; }        public string Company { get; set; }    }}
温馨提示

建议所有选项类都应该以 Options 命名结尾。

另外,Furion 框架提供了非常灵活的注册选项服务的方法,只需要继承 IConfigurableOptions 接口即可,该接口位于 Furion.ConfigurableOptions 命名空间下。

4.2.3.3 注册 AppInfoOptions 服务

选项不同于配置,需在应用启动时注册

Furion.Web.Core\FurWebCoreStartup.cs
using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;namespace Furion.Web.Core{    [AppStartup(800)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddConfigurableOptions<AppInfoOptions>();        }    }}

4.2.3.4 读取 AppInfoOptions 信息

Furion 框架中,提供了多种读取方式:

  • 通过 App.GetOptions<TOptions>(path) 读取(不推荐
  • 通过依赖注入以下实例读取:
    • IOptions<TOptions>
    • IOptionsSnapshot<TOptions>
    • IOptionsMonitor<TOptions>
  • 通过 App 静态类提供的静态方法获取:
    • App.GetOptions<TOptions>()
    • App.GetOptionsMonitor<TOptions>()
    • App.GetOptionsSnapshot<TOptions>()
using Furion.Application;using Microsoft.AspNetCore.Mvc;namespace Furion.Web.Entry.Controllers{    [Route("api/[controller]")]    public class DefaultController : ControllerBase    {        [HttpGet]        public string Get()        {            // 不推荐采用此方式读取,该方式仅在 ConfigureServices 启动时使用            var appInfo = App.GetConfig<AppInfoOptions>("AppInfo", true);            return $@"名称:{appInfo.Name}                      版本:{appInfo.Version}                      公司:{appInfo.Company}";        }    }}

4.2.3.5 如何选择读取方式

  • 如果选项需要在多个地方使用,则无论任何时候都不推荐使用 App.GetOptions<TOptions>(path)
  • 在可依赖注入类中,依赖注入 IOptions[Snapshot|Monitor]<TOptions> 读取
  • 在静态类/非依赖注入类中,选择 App.GetOptions[Snapshot|Monitor]<TOptions>() 读取

4.2.4 选项接口说明

ASP.NET Core 应用提供了多种读取选项的接口:

  • IOptions<TOptions>
    • 不支持:
      • 在应用启动后读取配置数据
      • 命名选项
    • 注册为单一实例且可以注入到任何服务生存期
  • IOptionsSnapshot<TOptions>
    • 在每次请求时应重新计算选项的方案中有用
    • 注册为范围内,因此无法注入到单一实例服务
    • 支持命名选项
  • IOptionsMonitor<TOptions>
    • 用于检索选项并管理 TOptions 实例的选项通知。
    • 注册为单一实例且可以注入到任何服务生存期。
    • 支持:
      • 更改通知
      • 命名选项
      • 可重载配置
      • 选择性选项失效 (IOptionsMonitorCache<TOptions>)
注意事项

在使用 IConfigurableOptionsListener 监听选项后,如要获取最新的配置信息,请使用 App.GetOptionsMonitor<TOptions>() 而不是 App.GetOptions<TOptions>()

了解更多

想了解更多 选项接口 知识可查阅 ASP.NET Core - 选项 - 选项接口 小节。

4.2.5 选项自定义配置

我们知道,选项实际上需要和配置文件特定键值挂钩,那 Furion 是如何准确的找到配置文件中的键值的呢?

4.2.5.1 选项查找键流程

  • 没有贴 [OptionsSettings] 特性
    • Options 结尾,则去除 Options 字符串
    • 否则返回 类名称
  • 贴了 [OptionsSettings] 特性
    • 如果配置了 Path 属性,则返回 Path 的值
    • 否则返回 类名称
  • Options 结尾,则键名为:AppInfo
public class AppInfoOptions : IConfigurableOptions{    public string Name { get; set; }    public string Version { get; set; }    public string Company { get; set; }}
  • 不以 Options 结尾,则键名为:AppInfoSettings
public class AppInfoSettings : IConfigurableOptions{    public string Name { get; set; }    public string Version { get; set; }    public string Company { get; set; }}

4.2.6 [OptionsSettings] 说明

选项类可以通过 [OptionsSettings] 来配置查找路径值。

4.2.7 选项验证

选项支持验证配置有效性,在 Furion 框架中,通过 services.AddConfigurableOptions<TOptions>() 注册选项默认启用了验证支持。

包括:

  • 特性方式 DataAnnotations
  • 自定义复杂验证 IValidateOptions<TOptions>
using Furion.ConfigurableOptions;using System.ComponentModel.DataAnnotations;namespace Furion.Application{    public class AppInfoOptions : IConfigurableOptions    {        [Required(ErrorMessage = "名称不能为空")]        public string Name { get; set; }        [Required, RegularExpression(@"^[0-9][0-9\.]+[0-9]$", ErrorMessage = "不是有效的版本号")]        public string Version { get; set; }        [Required, MaxLength(100)]        public string Company { get; set; }    }}
特别说明

IConfigurableOptions<TOptions, TOptionsValidation> 继承自 IConfigurableOptions<TOptions>,也就是自定义复杂验证默认具有 PostConfigure(TOptions options) 选项后期配置方法。关于《4.2.8 选项后期配置》将在下一小节说明。

4.2.8 选项后期配置

选项后期配置通俗一点来说,可以在运行时解析值或设定默认值/后期配置等。

Furion 框架中,配置选项后期配置很简单,只需要继承 IConfigurableOptions<TOptions> 接口并实现 PostConfigure(TOptions options) 方法。

using Furion.ConfigurableOptions;using Microsoft.Extensions.Configuration;using System.ComponentModel.DataAnnotations;namespace Furion.Application{    public class AppInfoOptions : IConfigurableOptions<AppInfoOptions>    {        [Required(ErrorMessage = "名称不能为空")]        public string Name { get; set; }        [Required]        public string Version { get; set; }        [Required, MaxLength(100)]        public string Company { get; set; }        public void PostConfigure(AppInfoOptions options, IConfiguration configuration)        {            options.Name ??= "Furion";            options.Version ??= "1.0.0";            options.Company ??= "Baiqian";        }    }}
特别说明

IConfigurableOptions<TOptions, TOptionsValidation> 继承自 IConfigurableOptions<TOptions>,也就是自定义复杂验证默认具有 PostConfigure(TOptions options, IConfiguration configuration) 选项后期配置方法。

4.2.9 选项更改通知(热更新

Furion 框架提供了非常简单且灵活的方式监听选项更改,也就是 appsettings.json 或 自定义配置文件发生任何更改都会触发处理方法

使用非常简单,只需要继承 IConfigurableOptionsListener<TOptions> 接口并实现 void OnListener(TOptions options, IConfiguration configuration) 方法即可。

using Furion.ConfigurableOptions;namespace Furion.Application{    public class AppInfoOptions : IConfigurableOptionsListener<AppInfoOptions>    {        public string Name { get; set; }        public string Version { get; set; }        public string Company { get; set; }        public void OnListener(AppInfoOptions options, IConfiguration configuration)        {            var name = options.Name;  // 实时的最新值            var version = options.Version;  // 实时的最新值        }        public void PostConfigure(AppInfoOptions options, IConfiguration configuration)        {        }    }}
特别说明

IConfigurableOptionsListener<TOptions> 继承自 IConfigurableOptions<TOptions>

4.2.10 选项的优缺点

  • 优点

    • 强类型配置
    • 提供多种读取方式
    • 支持热加载
    • 支持设置默认值/后期配置
    • 支持在运行环境中动态配置
    • 支持验证配置有效性
    • 支持更改通知
    • 支持命名选项
  • 缺点

    • 需要定义对应类型
    • 需要在启动时注册

4.2.11 自定义属性 Key 映射

版本说明

以下内容仅限 Furion v3.4.3+ 版本使用。

有时候我们在 appsettings.json 中配置的 Key 和选项定义的属性名不一样,这时候就需要用到 [MapSettings] 特性即可,如:

"AppInfo": {    "Name": "Furion",    "Version": "1.0.0",    "Company_Name": "Baiqian"}
public class AppInfoOptions : IConfigurableOptions{    public string Name { get; set; }    public string Version { get; set; }    [MapSettings("Company_Name")]    public string Company { get; set; }}
特别注意

[MapSettings] 配置的 Key 会自定应用选项的 Key 作为起始点,如实际上 Company 属性对应的 Key 为:AppInfo:Company_Name

4.2.12 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 选项 知识可查阅 ASP.NET Core - 选项 章节。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/performance/index.html b/handbook/build/docs/performance/index.html index 23a67085b0..709e98d0e6 100644 --- a/handbook/build/docs/performance/index.html +++ b/handbook/build/docs/performance/index.html @@ -2,22 +2,21 @@ - - - + +36.2 负载压测 | Furion -36.2 负载压测 | Furion - - + + + - - +
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/pillar-of-humiliation/index.html b/handbook/build/docs/pillar-of-humiliation/index.html index 6a871bbd46..d541b43ff4 100644 --- a/handbook/build/docs/pillar-of-humiliation/index.html +++ b/handbook/build/docs/pillar-of-humiliation/index.html @@ -2,22 +2,21 @@ - - - + +1.8 耻辱柱 | Furion -1.8 耻辱柱 | Furion - - + + +
-

1.8 耻辱柱

谨言慎行

Furion 诞生之初,受到诸多标题党、造谣喷子党无脑黑,故设立耻辱柱,将这些情节极其严重的人钉在 Furion 耻辱柱上,以示世人。

网络不是不法之地,望大家谨言慎行。

特别补充

张善友 .NET 颇有影响力的人,Furion 作为唯一一个 .NET 项目成功加入木兰开源社区时,张善友在腾讯 TVP 公开群说 Furion 只是个营销框架,短短一句话引起各大知名项目大佬纷纷议论,有超过 7 位大佬截图并微信私发我,对此也不过多说什么,简单记录。

演练场
- - +

1.8 耻辱柱

谨言慎行

Furion 诞生之初,受到诸多标题党、造谣喷子党无脑黑,故设立耻辱柱,将这些情节极其严重的人钉在 Furion 耻辱柱上,以示世人。

网络不是不法之地,望大家谨言慎行。

特别补充

张善友 .NET 颇有影响力的人,Furion 作为唯一一个 .NET 项目成功加入木兰开源社区时,张善友在腾讯 TVP 公开群说 Furion 只是个营销框架,短短一句话引起各大知名项目大佬纷纷议论,有超过 7 位大佬截图并微信私发我,对此也不过多说什么,简单记录。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/pm2/index.html b/handbook/build/docs/pm2/index.html index 500e644e3b..a68d65324b 100644 --- a/handbook/build/docs/pm2/index.html +++ b/handbook/build/docs/pm2/index.html @@ -2,23 +2,22 @@ - - - + +34.6 pm2 部署 | Furion -34.6 pm2 部署 | Furion - - + + +
-

34.6 pm2 部署

34.6.1 关于 pm2

pm2NodeJS 平台高级生产流程管理器,也是一个守护进程管理器,它能够管理和保持应用程序 7*24 小时在线。

pm2 优点:

- - + + \ No newline at end of file diff --git a/handbook/build/docs/process-service/index.html b/handbook/build/docs/process-service/index.html index 8e4eeaee74..fbca72dfaf 100644 --- a/handbook/build/docs/process-service/index.html +++ b/handbook/build/docs/process-service/index.html @@ -2,24 +2,23 @@ - - - + +25. 辅助角色服务 | Furion -25. 辅助角色服务 | Furion - - + + +
-

25. 辅助角色服务

25.1 关于辅助角色服务

.NET Core 3.0 新增了 Worker Service 的新项目模板,可以编写长时间运行的后台服务,并且能轻松的部署成 Windows服务Linux 守护程序

目前微软提供了两种方式创建长时间运行的后台服务:

  • 共宿主方式:中小型项目推荐,无需单独部署 Windows/Linux 服务
  • 独立 Worker Service 方式:需独立部署 Windows/Linux 服务

25.2 共宿主方式

共宿主方式指的是在现有的 Web 或其他应用程中创建类文件并派生自 BackgroundService 类即可。这种方式的典型特点就是和应用共生存周期,应用启动时启动,应用结束停止运行。

推荐等级

推荐中小型项目使用这种方式。

using Microsoft.Extensions.Hosting;using System;using System.Threading;using System.Threading.Tasks;namespace YourPoject.Web.Core;public class Worker : BackgroundService{    protected override async Task ExecuteAsync(CancellationToken stoppingToken)    {        while (!stoppingToken.IsCancellationRequested)        {            Console.WriteLine(DateTime.Now);            // 延迟 1 秒            await Task.Delay(1000, stoppingToken);        }    }}

之后在 Startup.cs 中注册即可:

services.AddHostedService<Worker>();

25.2.1 最佳实践

最好的实践方式是创建独立的类库项目:YourProject.BackgroundServices,之后添加 YourPoject.ApplicationYourPoject.Core 层引用,将所有的 Worker 放在该层,同时创建 Startup.cs 类进行 Worker 统一注册,如:

using Microsoft.Extensions.DependencyInjection;namespace YourProject.BackgroundServices;public sealed class Startup : AppStartup{    public void ConfigureServices(IServiceCollection services)    {        services.AddHostedService<Worker>();        services.AddHostedService<Worker2>();    }}

25.3 独立 Worker Service 方式

独立 Worker Service 方式的主要特点就是它是一个独立的项目,和现有的项目没有直接关联关系,需要分开独立部署

推荐等级

推荐中大型项目使用这种方式,也就是独立部署成 Windows Service 或者 Linux 守护进程,具有独立生存周期,即使应用故障了也不会影响它的运行。

25.3.1 如何创建 Worker Service

通过 Visual Studio 2019 提供的 Worker Service 可直接创建。如图:

25.3.2 创建 Worker

当我们创建好 Worker Service 项目时,已经自带了一个 Worker 类并继承自 BackgroundService 基类。

Worker 正是我们辅助角色的主要工作类,在这里我们编写我们所有的业务逻辑。通常 Worker 默认格式为:

using Microsoft.Extensions.Hosting;using Microsoft.Extensions.Logging;using System;using System.Threading;using System.Threading.Tasks;namespace FurionWorkers{    public class Worker : BackgroundService    {        private readonly ILogger<Worker> _logger;        public Worker(ILogger<Worker> logger)        {            _logger = logger;        }        protected override async Task ExecuteAsync(CancellationToken stoppingToken)        {            while (!stoppingToken.IsCancellationRequested)            {                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);                await Task.Delay(1000, stoppingToken);            }        }    }}

当我们创建了 Worker 类之后,需要在 Program.cs 中进行注册,如:

using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace FurionWorkers{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args) =>            Host.CreateDefaultBuilder(args)                .ConfigureServices((hostContext, services) =>                {                    services.AddHostedService<Worker>();                });    }}
小知识

如果使用了 Furion 包后可实现自动注册。

25.3.3 多个 Worker

Worker Service 是支持定义多个 Worker 进行协调工作的,每个 Worker 是完全独立的工作环境,但可共享同一主进程信息。

25.3.4 生命周期

Worker ServiceWorker 提供了三个执行方法,分别代表三个生命周期:

  • StartAsync:负责启动 Worker Service,如果调用 StartAsync 方法的线程被一直阻塞了,那么 Worker Service 的启动就一直完成不了
  • ExecuteAsyncWorker Service 真正实现业务逻辑的地方,这里不能调用阻塞代码!!!
  • StopAsync:负责结束 Worker Service,如果调用 StopAsync 方法的线程被一直阻塞了,那么 Worker Service 的结束就一直完成不了
using Microsoft.Extensions.Hosting;using Microsoft.Extensions.Logging;using System;using System.Threading;using System.Threading.Tasks;namespace FurionWorkers{    public class Worker : BackgroundService    {        private readonly ILogger<Worker> _logger;        public Worker(ILogger<Worker> logger)        {            _logger = logger;        }        // 启动        public override Task StartAsync(CancellationToken cancellationToken)        {            return base.StartAsync(cancellationToken);        }        // 执行逻辑        protected override async Task ExecuteAsync(CancellationToken stoppingToken)        {            while (!stoppingToken.IsCancellationRequested)            {                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);                await Task.Delay(1000, stoppingToken);            }        }        // 停止        public override Task StopAsync(CancellationToken cancellationToken)        {            return base.StopAsync(cancellationToken);        }    }}

25.3.5 集成 Furion

Worker Service 集成 Furion 非常方便,只需要安装 Furion 的包即可,并在 Program.cs 中调用 .Inject() 方法,如:

using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace FurionWorkers{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args) =>            Host.CreateDefaultBuilder(args)                .Inject()                .ConfigureServices((hostContext, services) =>                {                    // 以下代码可不用编写,Furion 已实现自动注册 Worker;                    // services.AddHostedService<Worker>();                });    }}

默认情况下,Inject() 方法注册了 日志、缓存、依赖注入、加载配置、自定义 Startup 功能。

小知识

集成 Furion 后会自动扫描 Worker 类并实现自动注册。

25.3.6 注册服务

Worker Service 注册服务和 Web 略有不同,Web 主要在 Starup.cs 类中注册,Worker ServiceProgram.cs 启动类的 ConfigureServices 方法中注册,如:

using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace FurionWorkers{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args) =>            Host.CreateDefaultBuilder(args)                .Inject()                .ConfigureServices((hostContext, services) =>                {                    // 注册数据库服务                    services.AddDatabaseAccessor(options =>                    {                        options.AddDb<DefaultDbContext>();                    });                    // 注册远程请求                    services.AddRemoteRequest();                    // 等等其他服务注册                });    }}

25.4 实现定时任务

Furion 框架为 BackgroundService 提供了定时任务的支持。

26.4.1 间隔执行方式

namespace WorkerService;public class Worker : BackgroundService{    private readonly ILogger<Worker> _logger;    private const int delay = 1000;    public Worker(ILogger<Worker> logger)    {        _logger = logger;    }    protected override async Task ExecuteAsync(CancellationToken stoppingToken)    {        while (!stoppingToken.IsCancellationRequested)        {            var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);            await taskFactory.StartNew(async () =>            {                // 你的业务代码写到这里面                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);                await Task.CompletedTask;            }, stoppingToken);            await Task.Delay(delay, stoppingToken);        }    }}

26.4.2 Cron 表达式执行方式

using Furion.TimeCrontab;namespace WorkerService;public class Worker : BackgroundService{    private readonly ILogger<Worker> _logger;    private readonly Crontab _crontab;    public Worker(ILogger<Worker> logger)    {        _logger = logger;        _crontab = Crontab.Parse("* * * * * *", CronStringFormat.WithSeconds);    }    protected override async Task ExecuteAsync(CancellationToken stoppingToken)    {        while (!stoppingToken.IsCancellationRequested)        {            var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);            await taskFactory.StartNew(async () =>            {                // 你的业务代码写到这里面                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);                await Task.CompletedTask;            }, stoppingToken);            await Task.Delay(_crontab.GetSleepMilliseconds(DateTime.UtcNow), stoppingToken);        }    }}

25.5 依赖注入使用

Worker Service 只为 Worker 提供了单例作用域的服务注入,如果需要注入瞬时或作用域对象,需手动创建作用域,如:

public class Worker : BackgroundService{    // 日志对象    private readonly ILogger<JobService> _logger;    // 服务工厂    private readonly IServiceScopeFactory _scopeFactory;    public Worker(ILogger<Worker> logger        , IServiceScopeFactory scopeFactory)    {        _logger = logger;        _scopeFactory = scopeFactory;    }    protected override Task ExecuteAsync(CancellationToken stoppingToken)    {        while (!stoppingToken.IsCancellationRequested)        {            using (var scope = _scopeFactory.CreateScope())            {                var services = scope.ServiceProvider;                // 获取数据库上下文                var dbContext = Db.GetDbContext(services);                // 获取仓储                var respository = Db.GetRepository<Person>(services);                // 解析其他服务                var otherService = services.GetService<XXX>();            }        }        return Task.CompletedTask;    }}

25.6 如何部署

25.6.1 共宿主方式

共宿主方式方式部署非常简单,只需要部署所在的 Web 或其他应用程序项目即可,会自动随着项目启动自动启动。

特别说明

如果部署到 IIS 中,可能存在 Worker Service 被回收的情况,毕竟是和网站同一个宿主。

25.6.2 独立 Worker Service 方式

Worker Service 支持部署到 Windows Service 中 或 Linux 守护进程中


部署到 Windows Service

  • 第一步:安装 Microsoft.Extensions.Hosting.WindowsServices 拓展包

  • 第二步:在 Program.cs 中添加 .UseWindowsService()

using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace FurionWorkers{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args) =>            Host.CreateDefaultBuilder(args)                .UseWindowsService()                .Inject()                .ConfigureServices((hostContext, services) =>                {                    // 以下代码可不用编写,Furion 已实现自动注册 Worker;                    // services.AddHostedService<Worker>();                });    }}
  • 第三步:发布 Worker Service,可通过 dotnet publish -c Release -o C:\FurionWorker 命令发布或通过 Visual Studio 2019 发布。

独立发布不依赖 SDK 方式 dotnet publish -c release -r win10-x64 --framework net6.0

  • 第四步:通过 sc.exe 工具来管理并创建 Windows 服务,通过 管理员模式 并打开控制台,输入:
sc.exe create FurionWorkerServices binPath= C:\FurionWorker\FurionWorker.exe

注意=后面要有一个空格
+

25. 辅助角色服务

25.1 关于辅助角色服务

.NET Core 3.0 新增了 Worker Service 的新项目模板,可以编写长时间运行的后台服务,并且能轻松的部署成 Windows服务Linux 守护程序

目前微软提供了两种方式创建长时间运行的后台服务:

  • 共宿主方式:中小型项目推荐,无需单独部署 Windows/Linux 服务
  • 独立 Worker Service 方式:需独立部署 Windows/Linux 服务

25.2 共宿主方式

共宿主方式指的是在现有的 Web 或其他应用程中创建类文件并派生自 BackgroundService 类即可。这种方式的典型特点就是和应用共生存周期,应用启动时启动,应用结束停止运行。

推荐等级

推荐中小型项目使用这种方式。

using Microsoft.Extensions.Hosting;using System;using System.Threading;using System.Threading.Tasks;namespace YourPoject.Web.Core;public class Worker : BackgroundService{    protected override async Task ExecuteAsync(CancellationToken stoppingToken)    {        while (!stoppingToken.IsCancellationRequested)        {            Console.WriteLine(DateTime.Now);            // 延迟 1 秒            await Task.Delay(1000, stoppingToken);        }    }}

之后在 Startup.cs 中注册即可:

services.AddHostedService<Worker>();

25.2.1 最佳实践

最好的实践方式是创建独立的类库项目:YourProject.BackgroundServices,之后添加 YourPoject.ApplicationYourPoject.Core 层引用,将所有的 Worker 放在该层,同时创建 Startup.cs 类进行 Worker 统一注册,如:

using Microsoft.Extensions.DependencyInjection;namespace YourProject.BackgroundServices;public sealed class Startup : AppStartup{    public void ConfigureServices(IServiceCollection services)    {        services.AddHostedService<Worker>();        services.AddHostedService<Worker2>();    }}

25.3 独立 Worker Service 方式

独立 Worker Service 方式的主要特点就是它是一个独立的项目,和现有的项目没有直接关联关系,需要分开独立部署

推荐等级

推荐中大型项目使用这种方式,也就是独立部署成 Windows Service 或者 Linux 守护进程,具有独立生存周期,即使应用故障了也不会影响它的运行。

25.3.1 如何创建 Worker Service

通过 Visual Studio 2019 提供的 Worker Service 可直接创建。如图:

25.3.2 创建 Worker

当我们创建好 Worker Service 项目时,已经自带了一个 Worker 类并继承自 BackgroundService 基类。

Worker 正是我们辅助角色的主要工作类,在这里我们编写我们所有的业务逻辑。通常 Worker 默认格式为:

using Microsoft.Extensions.Hosting;using Microsoft.Extensions.Logging;using System;using System.Threading;using System.Threading.Tasks;namespace FurionWorkers{    public class Worker : BackgroundService    {        private readonly ILogger<Worker> _logger;        public Worker(ILogger<Worker> logger)        {            _logger = logger;        }        protected override async Task ExecuteAsync(CancellationToken stoppingToken)        {            while (!stoppingToken.IsCancellationRequested)            {                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);                await Task.Delay(1000, stoppingToken);            }        }    }}

当我们创建了 Worker 类之后,需要在 Program.cs 中进行注册,如:

using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace FurionWorkers{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args) =>            Host.CreateDefaultBuilder(args)                .ConfigureServices((hostContext, services) =>                {                    services.AddHostedService<Worker>();                });    }}
小知识

如果使用了 Furion 包后可实现自动注册。

25.3.3 多个 Worker

Worker Service 是支持定义多个 Worker 进行协调工作的,每个 Worker 是完全独立的工作环境,但可共享同一主进程信息。

25.3.4 生命周期

Worker ServiceWorker 提供了三个执行方法,分别代表三个生命周期:

  • StartAsync:负责启动 Worker Service,如果调用 StartAsync 方法的线程被一直阻塞了,那么 Worker Service 的启动就一直完成不了
  • ExecuteAsyncWorker Service 真正实现业务逻辑的地方,这里不能调用阻塞代码!!!
  • StopAsync:负责结束 Worker Service,如果调用 StopAsync 方法的线程被一直阻塞了,那么 Worker Service 的结束就一直完成不了
using Microsoft.Extensions.Hosting;using Microsoft.Extensions.Logging;using System;using System.Threading;using System.Threading.Tasks;namespace FurionWorkers{    public class Worker : BackgroundService    {        private readonly ILogger<Worker> _logger;        public Worker(ILogger<Worker> logger)        {            _logger = logger;        }        // 启动        public override Task StartAsync(CancellationToken cancellationToken)        {            return base.StartAsync(cancellationToken);        }        // 执行逻辑        protected override async Task ExecuteAsync(CancellationToken stoppingToken)        {            while (!stoppingToken.IsCancellationRequested)            {                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);                await Task.Delay(1000, stoppingToken);            }        }        // 停止        public override Task StopAsync(CancellationToken cancellationToken)        {            return base.StopAsync(cancellationToken);        }    }}

25.3.5 集成 Furion

Worker Service 集成 Furion 非常方便,只需要安装 Furion 的包即可,并在 Program.cs 中调用 .Inject() 方法,如:

using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace FurionWorkers{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args) =>            Host.CreateDefaultBuilder(args)                .Inject()                .ConfigureServices((hostContext, services) =>                {                    // 以下代码可不用编写,Furion 已实现自动注册 Worker;                    // services.AddHostedService<Worker>();                });    }}

默认情况下,Inject() 方法注册了 日志、缓存、依赖注入、加载配置、自定义 Startup 功能。

小知识

集成 Furion 后会自动扫描 Worker 类并实现自动注册。

25.3.6 注册服务

Worker Service 注册服务和 Web 略有不同,Web 主要在 Starup.cs 类中注册,Worker ServiceProgram.cs 启动类的 ConfigureServices 方法中注册,如:

using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace FurionWorkers{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args) =>            Host.CreateDefaultBuilder(args)                .Inject()                .ConfigureServices((hostContext, services) =>                {                    // 注册数据库服务                    services.AddDatabaseAccessor(options =>                    {                        options.AddDb<DefaultDbContext>();                    });                    // 注册远程请求                    services.AddRemoteRequest();                    // 等等其他服务注册                });    }}

25.4 实现定时任务

Furion 框架为 BackgroundService 提供了定时任务的支持。

26.4.1 间隔执行方式

namespace WorkerService;public class Worker : BackgroundService{    private readonly ILogger<Worker> _logger;    private const int delay = 1000;    public Worker(ILogger<Worker> logger)    {        _logger = logger;    }    protected override async Task ExecuteAsync(CancellationToken stoppingToken)    {        while (!stoppingToken.IsCancellationRequested)        {            var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);            await taskFactory.StartNew(async () =>            {                // 你的业务代码写到这里面                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);                await Task.CompletedTask;            }, stoppingToken);            await Task.Delay(delay, stoppingToken);        }    }}

26.4.2 Cron 表达式执行方式

using Furion.TimeCrontab;namespace WorkerService;public class Worker : BackgroundService{    private readonly ILogger<Worker> _logger;    private readonly Crontab _crontab;    public Worker(ILogger<Worker> logger)    {        _logger = logger;        _crontab = Crontab.Parse("* * * * * *", CronStringFormat.WithSeconds);    }    protected override async Task ExecuteAsync(CancellationToken stoppingToken)    {        while (!stoppingToken.IsCancellationRequested)        {            var taskFactory = new TaskFactory(System.Threading.Tasks.TaskScheduler.Current);            await taskFactory.StartNew(async () =>            {                // 你的业务代码写到这里面                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);                await Task.CompletedTask;            }, stoppingToken);            await Task.Delay(_crontab.GetSleepMilliseconds(DateTime.UtcNow), stoppingToken);        }    }}

25.5 依赖注入使用

Worker Service 只为 Worker 提供了单例作用域的服务注入,如果需要注入瞬时或作用域对象,需手动创建作用域,如:

public class Worker : BackgroundService{    // 日志对象    private readonly ILogger<JobService> _logger;    // 服务工厂    private readonly IServiceScopeFactory _scopeFactory;    public Worker(ILogger<Worker> logger        , IServiceScopeFactory scopeFactory)    {        _logger = logger;        _scopeFactory = scopeFactory;    }    protected override Task ExecuteAsync(CancellationToken stoppingToken)    {        while (!stoppingToken.IsCancellationRequested)        {            using (var scope = _scopeFactory.CreateScope())            {                var services = scope.ServiceProvider;                // 获取数据库上下文                var dbContext = Db.GetDbContext(services);                // 获取仓储                var respository = Db.GetRepository<Person>(services);                // 解析其他服务                var otherService = services.GetService<XXX>();            }        }        return Task.CompletedTask;    }}

25.6 如何部署

25.6.1 共宿主方式

共宿主方式方式部署非常简单,只需要部署所在的 Web 或其他应用程序项目即可,会自动随着项目启动自动启动。

特别说明

如果部署到 IIS 中,可能存在 Worker Service 被回收的情况,毕竟是和网站同一个宿主。

25.6.2 独立 Worker Service 方式

Worker Service 支持部署到 Windows Service 中 或 Linux 守护进程中


部署到 Windows Service

  • 第一步:安装 Microsoft.Extensions.Hosting.WindowsServices 拓展包

  • 第二步:在 Program.cs 中添加 .UseWindowsService()

using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace FurionWorkers{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args) =>            Host.CreateDefaultBuilder(args)                .UseWindowsService()                .Inject()                .ConfigureServices((hostContext, services) =>                {                    // 以下代码可不用编写,Furion 已实现自动注册 Worker;                    // services.AddHostedService<Worker>();                });    }}
  • 第三步:发布 Worker Service,可通过 dotnet publish -c Release -o C:\FurionWorker 命令发布或通过 Visual Studio 2019 发布。

独立发布不依赖 SDK 方式 dotnet publish -c release -r win10-x64 --framework net6.0

  • 第四步:通过 sc.exe 工具来管理并创建 Windows 服务,通过 管理员模式 并打开控制台,输入:
sc.exe create FurionWorkerServices binPath= C:\FurionWorker\FurionWorker.exe

注意=后面要有一个空格
创建成功后可通过 sc.exe query FurionWorkerServices 查看服务状态。

  • 第五步

启动服务:sc.exe start FurionWorkerServices,启动之后就可以在 Windows 服务工具中查看了。

停止服务:sc.exe stop NETCoreDemoWorkerService

删除服务:sc.exe delete NETCoreDemoWorkerService

特别提醒

以上所有 sc.exe 命令必须在 管理员 模式下进行。 sc.exe delete NETCoreDemoWorkerService, 执行删除时候, 把Windows 服务工具关闭, 否则, 电脑重启后才会显示删除;


部署到 Linux 守护程序

  • 第一步:安装 Microsoft.Extensions.Hosting.Systemd 拓展包

  • 第二步:在 Program.cs 中添加 .UseSystemd()

using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace FurionWorkers{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args) =>            Host.CreateDefaultBuilder(args)                .UseSystemd()                .Inject()                .ConfigureServices((hostContext, services) =>                {                    // 以下代码可不用编写,Furion 已实现自动注册 Worker;                    // services.AddHostedService<Worker>();                });    }}

部署到 Linux 守护进程 就是这么简单。

25.7 关于 Windows 部署日志问题

默认情况下,使用 Windows Services 部署后,日志文件可能会在系统盘的 System32 下。

25.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - + + \ No newline at end of file diff --git a/handbook/build/docs/reference/index.html b/handbook/build/docs/reference/index.html index b19d9250c1..296d94c784 100644 --- a/handbook/build/docs/reference/index.html +++ b/handbook/build/docs/reference/index.html @@ -2,22 +2,21 @@ - - - + +2.3 手动搭建分层 | Furion -2.3 手动搭建分层 | Furion - - + + +
-

2.3 手动搭建分层

推荐使用脚手架

Furion 官方提供了非常灵活方便的脚手架,可以快速的创建多层架构项目。

推荐使用 《2.2 官方脚手架》代替本章节功能。

2.3.1 推荐分层设计

Furion 推荐采用多层项目设计架构,每一个项目层的依赖分别是:

  • YourName.Application:添加 YourName.Core 引用
  • YourName.Core:添加 Furion 引用SqlSugar 版本添加 Furion.Pure 🎗
  • YourName.Database.Migrations:添加 YourName.EntityFramework.Core 引用
  • YourName.EntityFramework.Core:添加 YourName.Core 引用
  • YourName.Web.Core:添加 YourName.ApplicationYourName.Database.Migrations 引用
  • YourName.Web.Entry:添加 YourName.Web.Core 引用 和 Microsoft.EntityFrameworkCore.Tools
特别说明

如果采用 EFCore 以外的 ORM 框架,如 SqlSugar,那么无需创建 YourName.Database.MigrationsYourName.EntityFramework.Core 层。

另外 YourName.Web.Entry 无需引用 Microsoft.EntityFrameworkCore.Tools 包。

2.3.2 集成 Furion 功能

项目搭建好之后,集成 Furion 框架只需要在 Program.cs 中 添加 Inject() 方法即可:

  • .NET5 版本:
using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.Hosting;namespace YourName.Web.Entry{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args)        {            return Host.CreateDefaultBuilder(args)                .ConfigureWebHostDefaults(webBuilder =>                {                    webBuilder.Inject()                              .UseStartup<Startup>();                });        }    }}
  • .NET6 版本
var builder = WebApplication.CreateBuilder(args).Inject();builder.Services.AddControllers().AddInject();var app = builder.Build();app.UseHttpsRedirection();app.UseAuthorization();app.UseInject();app.MapControllers();app.Run();

2.3.3 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

2.3 手动搭建分层

推荐使用脚手架

Furion 官方提供了非常灵活方便的脚手架,可以快速的创建多层架构项目。

推荐使用 《2.2 官方脚手架》代替本章节功能。

2.3.1 推荐分层设计

Furion 推荐采用多层项目设计架构,每一个项目层的依赖分别是:

  • YourName.Application:添加 YourName.Core 引用
  • YourName.Core:添加 Furion 引用SqlSugar 版本添加 Furion.Pure 🎗
  • YourName.Database.Migrations:添加 YourName.EntityFramework.Core 引用
  • YourName.EntityFramework.Core:添加 YourName.Core 引用
  • YourName.Web.Core:添加 YourName.ApplicationYourName.Database.Migrations 引用
  • YourName.Web.Entry:添加 YourName.Web.Core 引用 和 Microsoft.EntityFrameworkCore.Tools
特别说明

如果采用 EFCore 以外的 ORM 框架,如 SqlSugar,那么无需创建 YourName.Database.MigrationsYourName.EntityFramework.Core 层。

另外 YourName.Web.Entry 无需引用 Microsoft.EntityFrameworkCore.Tools 包。

2.3.2 集成 Furion 功能

项目搭建好之后,集成 Furion 框架只需要在 Program.cs 中 添加 Inject() 方法即可:

  • .NET5 版本:
using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.Hosting;namespace YourName.Web.Entry{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }        public static IHostBuilder CreateHostBuilder(string[] args)        {            return Host.CreateDefaultBuilder(args)                .ConfigureWebHostDefaults(webBuilder =>                {                    webBuilder.Inject()                              .UseStartup<Startup>();                });        }    }}
  • .NET6 版本
var builder = WebApplication.CreateBuilder(args).Inject();builder.Services.AddControllers().AddInject();var app = builder.Build();app.UseHttpsRedirection();app.UseAuthorization();app.UseInject();app.MapControllers();app.Run();

2.3.3 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/saas/index.html b/handbook/build/docs/saas/index.html index 9b19a8a12e..37d2b1c6d7 100644 --- a/handbook/build/docs/saas/index.html +++ b/handbook/build/docs/saas/index.html @@ -2,28 +2,27 @@ - - - + +11. SaaS 多租户 | Furion -11. SaaS 多租户 | Furion - - + + +
-

11. SaaS 多租户

11.1 什么是 SaaS

SaaS 是 Software-as-a-Service(软件即服务)的简称,随着互联网技术的发展和应用软件的成熟, 在 21 世纪开始兴起的一种完全创新的软件应用模式。它与“on-demand software”,the application service provider(ASP,应用服务提供商),hosted software(托管软件)所具有相似的含义。

它是一种通过 Internet 提供软件的模式,厂商将应用软件统一部署在自己的服务器上,客户可以根据自己实际需求,通过互联网向厂商定购所需的应用软件服务,按定购的服务多少和时间长短向厂商支付费用,并通过互联网获得厂商提供的服务。用户不用再购买软件,而改用向提供商租用基于 Web 的软件,来管理企业经营活动,且无需对软件进行维护,服务提供商会全权管理和维护软件,软件厂商在向客户提供互联网应用的同时,也提供软件的离线操作和本地数据存储,让用户随时随地都可以使用其定购的软件和服务。

对于许多小型企业来说,SaaS 是采用先进技术的最好途径,它消除了企业购买、构建和维护基础设施和应用程序的需要。

11.2 什么是多租户

多租户技术或称多重租赁技术,简称 SaaS,是一种软件架构技术,是实现如何在多用户环境下(此处的多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离性。

简单讲:在一台服务器上运行单个应用实例,它为多个租户(客户)提供服务。从定义中我们可以理解:多租户是一种架构,目的是为了让多用户环境下使用同一套程序,且保证用户间数据隔离。那么重点就很浅显易懂了,多租户的重点就是同一套程序下实现多用户数据的隔离。

11.3 实现多租户方案

11.3.1 独立数据库(基于 Database 的方式)

这是第一种方案,即一个租户一个数据库,这种方案的用户数据隔离级别最高,安全性最好,但成本较高。

  • 优点: +

    11. SaaS 多租户

    11.1 什么是 SaaS

    SaaS 是 Software-as-a-Service(软件即服务)的简称,随着互联网技术的发展和应用软件的成熟, 在 21 世纪开始兴起的一种完全创新的软件应用模式。它与“on-demand software”,the application service provider(ASP,应用服务提供商),hosted software(托管软件)所具有相似的含义。

    它是一种通过 Internet 提供软件的模式,厂商将应用软件统一部署在自己的服务器上,客户可以根据自己实际需求,通过互联网向厂商定购所需的应用软件服务,按定购的服务多少和时间长短向厂商支付费用,并通过互联网获得厂商提供的服务。用户不用再购买软件,而改用向提供商租用基于 Web 的软件,来管理企业经营活动,且无需对软件进行维护,服务提供商会全权管理和维护软件,软件厂商在向客户提供互联网应用的同时,也提供软件的离线操作和本地数据存储,让用户随时随地都可以使用其定购的软件和服务。

    对于许多小型企业来说,SaaS 是采用先进技术的最好途径,它消除了企业购买、构建和维护基础设施和应用程序的需要。

    11.2 什么是多租户

    多租户技术或称多重租赁技术,简称 SaaS,是一种软件架构技术,是实现如何在多用户环境下(此处的多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离性。

    简单讲:在一台服务器上运行单个应用实例,它为多个租户(客户)提供服务。从定义中我们可以理解:多租户是一种架构,目的是为了让多用户环境下使用同一套程序,且保证用户间数据隔离。那么重点就很浅显易懂了,多租户的重点就是同一套程序下实现多用户数据的隔离。

    11.3 实现多租户方案

    11.3.1 独立数据库(基于 Database 的方式)

    这是第一种方案,即一个租户一个数据库,这种方案的用户数据隔离级别最高,安全性最好,但成本较高。

    • 优点: 为不同的租户提供独立的数据库,有助于简化数据模型的扩展设计,满足不同租户的独特需求;如果出现故障,恢复数据比较简单。

    • 缺点: 增多了数据库的安装数量,随之带来维护成本和购置成本的增加。 这种方案与传统的一个客户、一套数据、一套部署类似,差别只在于软件统一部署在运营商那里。如果面对的是银行、医院等需要非常高数据隔离级别的租户,可以选择这种模式,提高租用的定价。如果定价较低,产品走低价路线,这种方案一般对运营商来说是无法承受的。

    11.3.2 共享数据库,独立 Schema (基于 Schema 的方式)

    这是第二种方案,即多个或所有租户共享 Database,但是每个租户一个 Schema(也可叫做一个 user)。底层库比如是:SqlServerOracle 等,一个数据库下可以有多个 Schema

    • 优点: 为安全性要求较高的租户提供了一定程度的逻辑数据隔离,并不是完全隔离;每个数据库可支持更多的租户数量。

    • 缺点: 如果出现故障,数据恢复比较困难,因为恢复数据库将牵涉到其他租户的数据; 如果需要跨租户统计数据,存在一定困难。

    11.3.3 共享数据库,共享 Schema (基于 TenantId 的方式)

    共享数据表 这是第三种方案,即租户共享同一个 Database、同一个 Schema,但在表中增加 TenantId 多租户的数据字段。这是共享程度最高、隔离级别最低的模式。 即每插入一条数据时都需要有一个客户的标识。这样才能在同一张表中区分出不同客户的数据。

    • 优点: 三种方案比较,第三种方案的维护和购置成本最低,允许每个数据库支持的租户数量最多。

    • 缺点: 隔离级别最低,安全性最低,需要在设计开发时加大对安全的开发量; 数据备份和恢复最困难,需要逐表逐条备份和还原。

    11.4 多租户使用方案

    Furion 框架支持以上三种多租户实现方案,使用简单且容易维护。下面分别使用三种不同方式演示多租户方案用法。

    特别说明

    一旦 数据库上下文 类继承了租户任意接口,则自动开始多租户功能支持。

    11.5 基于 TenantId 的方式

    此方式在中小型企业系统中最为常用,维护成本低,购置成本低。

    11.5.1 创建租户数据库上下文

    Furion.EntityFramework.Core\DbContexts\MultiTenantDbContext.cs
    using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class MultiTenantDbContext : AppDbContext<MultiTenantDbContext, MultiTenantDbContextLocator>    {        public MultiTenantDbContext(DbContextOptions<MultiTenantDbContext> options) : base(options)        {        }    }}
    特别注意

    多租户操作建议单独一个数据库上下文,而且需指定 MultiTenantDbContextLocator 数据库上下文定位器。

    11.5.2 注册多租户数据库上下文

    using Furion.DatabaseAccessor;using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(600)]    public sealed class FurEntityFrameworkCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddDatabaseAccessor(options =>            {                options.AddDbPool<FurionDbContext>();                options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>();            });        }    }}

    11.5.3 添加 Tenant 种子数据

    Furion.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using System;using System.Collections.Generic;namespace Furion.EntityFramework.Core{    public class TenantSeedData : IEntitySeedData<Tenant, MultiTenantDbContextLocator>    {        public IEnumerable<Tenant> HasData(DbContext dbContext, Type dbContextLocator)        {            return new List<Tenant>            {                new Tenant                {                    TenantId = Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),                    Name = "默认租户",                    Host = "localhost:44313",                    CreatedTime = DateTime.Parse("2020-10-06 20:19:07")                },                new Tenant                {                    TenantId = Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),                    Name = "其他租户",                    Host = "localhost:5000",                    CreatedTime = DateTime.Parse("2020-10-06 20:20:32")                }            };        }    }}
    特别说明

    该步骤只在 Code First 方式执行,Database First 无需配置种子数据。

    11.5.4 根据模型创建 Tenant

    Add-Migration add_tenant_table -Context MultiTenantDbContext
    Update-Database -Context MultiTenantDbContext

    11.5.5 实现 IMultiTenantOnTable 接口

    在需要多租户的数据库上下文中实现 IMultiTenantOnTable 接口,如:

    using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using System;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class FurionDbContext : AppDbContext<FurionDbContext>, IMultiTenantOnTable, IModelBuilderFilter    {        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }        public object GetTenantId()        {           return base.Tenant?.TenantId ?? Guid.Empty;        }    }}

    GetTenantId() 方法中,首先获取请求的 主机地址,然后根据主机地址查询对应的租户 TenantId,避免多次查询数据库,这里使用了 IMemoryCache 内存缓存。

    特别说明

    base.Tenant 只是 Furion 框架提供的默认租户实现方法,如果不能满足业务需求,只需要在 GetTenantId 里面写你的业务代码即可,也就是无需调用 base.Tenant。如:

    public object GetTenantId(){   // 这里是你获取 TenantId 的逻辑   return 你的 TenantId;}

    11.5.6 实现 IModelBuilderFilter 接口

    IModelBuilderFilter 接口是全局查询过滤器实现接口,所以我们需要配置实体 TenantId 过滤器

    using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class FurionDbContext : AppDbContext<FurionDbContext>, IMultiTenantOnTable, IModelBuilderFilter    {        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }        public object GetTenantId()        {            return base.Tenant?.TenantId ?? Guid.Empty;        }        public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)        {            entityBuilder.HasQueryFilter(BuildTenantQueryFilter(entityBuilder, dbContext));        }    }}

    11.5.7 重写 SavingChangesEvent 事件方法

    通过上面的步骤,我们已经解决了 查询 租户过滤功能,但是 新增更新 还未处理。

    • 新增 数据的时候自动设置 TenantId 的值
    • 更新 数据的时候排除 TenantId 属性更新

    实现上面的步骤很简单,只需要重写 SavingChangesEvent 事件方法即可。

    using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Metadata.Builders;using System;using System.Linq;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class FurionDbContext : AppDbContext<FurionDbContext>, IMultiTenantOnTable, IModelBuilderFilter    {        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }        public object GetTenantId()        {            return base.Tenant?.TenantId ?? Guid.Empty;        }        public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)        {            entityBuilder.HasQueryFilter(BuildTenantQueryFilter(entityBuilder, dbContext));        }        protected override void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result)        {            // 获取当前事件对应上下文            var dbContext = eventData.Context;            // 获取所有新增、更新、删除的实体            var entities = dbContext.ChangeTracker.Entries().Where(u => u.State == EntityState.Added || u.State == EntityState.Modified || u.State == EntityState.Deleted);            foreach (var entity in entities)            {                                switch (entity.State)                {                    // 自动设置租户Id                    case EntityState.Added:                        entity.Property(nameof(Entity.TenantId)).CurrentValue = GetTenantId();                        break;                    // 排除租户Id                    case EntityState.Modified:                        entity.Property(nameof(Entity.TenantId)).IsModified = false;                        break;                    // 删除处理                    case EntityState.Deleted:                        break;                }            }        }    }}

    11.6 基于 Database 的方式

    此方式在中大型企业系统中最为常用,一个租户(客户)一个独立的数据库。

    11.6.1 创建租户数据库上下文

    Furion.EntityFramework.Core\DbContexts\MultiTenantDbContext.cs
    using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class MultiTenantDbContext : AppDbContext<MultiTenantDbContext, MultiTenantDbContextLocator>    {        public MultiTenantDbContext(DbContextOptions<MultiTenantDbContext> options) : base(options)        {        }    }}
    特别注意

    多租户操作建议单独一个数据库上下文,而且需指定 MultiTenantDbContextLocator 数据库上下文定位器。

    11.6.2 注册多租户数据库上下文

    using Furion.DatabaseAccessor;using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(600)]    public sealed class FurEntityFrameworkCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddDatabaseAccessor(options =>            {                options.AddDb<FurionDbContext>();                options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>();            });        }    }}
    特别注意

    需要 Database 多租户方案的数据库上下文需要采用 AddDb 注册,而不是 AddDbPool。原因是 AddDbPool 方式注册后续不支持 OnConfiguring 重写!!!

    11.6.3 添加 Tenant 种子数据

    Furion.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using System;using System.Collections.Generic;namespace Furion.EntityFramework.Core{    public class TenantSeedData : IEntitySeedData<Tenant, MultiTenantDbContextLocator>    {        public IEnumerable<Tenant> HasData(DbContext dbContext, Type dbContextLocator)        {            return new List<Tenant>            {                new Tenant                {                    TenantId = Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),                    Name = "默认租户",                    Host = "localhost:44313",                    CreatedTime = DateTime.Parse("2020-10-06 20:19:07"),                    ConnectionString = "Data Source=./Furion.db" // 配置连接字符串                },                new Tenant                {                    TenantId = Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),                    Name = "其他租户",                    Host = "localhost:5000",                    CreatedTime = DateTime.Parse("2020-10-06 20:20:32"),                    ConnectionString = "Data Source=./Fur2.db" // 配置连接字符串                }            };        }    }}
    特别说明

    该步骤只在 Code First 方式执行,Database First 无需配置种子数据。

    11.6.4 根据模型创建 Tenant

    Add-Migration add_tenant_table -Context MultiTenantDbContext
    Update-Database -Context MultiTenantDbContext

    11.6.5 实现 IMultiTenantOnDatabase 接口

    在需要多租户的数据库上下文中实现 IMultiTenantOnDatabase 接口,如:

    using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    // 这里可不配置    public class FurionDbContext : AppDbContext<FurionDbContext>, IMultiTenantOnDatabase    {        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }        public string GetDatabaseConnectionString()        {            return base.Tenant?.ConnectionString??"默认链接字符串";        }    }}
    特别说明

    base.Tenant 只是 Furion 框架提供的默认租户实现方法,如果不能满足业务需求,只需要在 GetDatabaseConnectionString 里面写你的业务代码即可,也就是无需调用 base.Tenant。如:

    public string GetDatabaseConnectionString(){   // 这里是你获取 DatabaseConnecionString 的逻辑   return 你的 连接字符串;}

    11.6.6 重写 OnConfiguring 方法

    在需要多租户的数据库上下文中重写 OnConfiguring 方法并配置连接字符串:

    using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    public class FurionDbContext : AppDbContext<FurionDbContext>, IMultiTenantOnDatabase    {        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)        {            optionsBuilder.UseSqlite(GetDatabaseConnectionString());            base.OnConfiguring(optionsBuilder);        }        public string GetDatabaseConnectionString()        {            return base.Tenant?.ConnectionString??"默认链接字符串";        }    }}
    特别注意

    基于 Database 方式做 Code First 的时候,需要手动指定迁移程序名称,如:

    optionsBuilder.UseSqlite(GetDatabaseConnectionString(), options=>{    options.MigrationsAssembly("My.Migrations");});

    11.7 基于 Schema 的方式

    此方式在中小型企业系统中也不少见,一个租户(客户)共享数据库且不同 Schema

    11.7.1 创建租户数据库上下文

    Furion.EntityFramework.Core\DbContexts\MultiTenantDbContext.cs
    using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class MultiTenantDbContext : AppDbContext<MultiTenantDbContext, MultiTenantDbContextLocator>    {        public MultiTenantDbContext(DbContextOptions<MultiTenantDbContext> options) : base(options)        {        }    }}
    特别注意

    多租户操作建议单独一个数据库上下文,而且需指定 MultiTenantDbContextLocator 数据库上下文定位器。

    11.7.2 注册多租户数据库上下文

    using Furion.DatabaseAccessor;using Microsoft.Extensions.DependencyInjection;namespace Furion.EntityFramework.Core{    [AppStartup(600)]    public sealed class FurEntityFrameworkCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddDatabaseAccessor(options =>            {                options.AddDbPool<FurionDbContext>();                options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>();            });        }    }}

    11.7.3 添加 Tenant 种子数据

    Furion.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;using System;using System.Collections.Generic;namespace Furion.EntityFramework.Core{    public class TenantSeedData : IEntitySeedData<Tenant, MultiTenantDbContextLocator>    {        public IEnumerable<Tenant> HasData(DbContext dbContext, Type dbContextLocator)        {            return new List<Tenant>            {                new Tenant                {                    TenantId = Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),                    Name = "默认租户",                    Host = "localhost:44313",                    CreatedTime = DateTime.Parse("2020-10-06 20:19:07"),                    Schema = "dbo" // Schema                },                new Tenant                {                    TenantId = Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),                    Name = "其他租户",                    Host = "localhost:5000",                    CreatedTime = DateTime.Parse("2020-10-06 20:20:32"),                    Schema = "furion" // Schema                }            };        }    }}
    特别说明

    该步骤只在 Code First 方式执行,Database First 无需配置种子数据。

    11.7.4 根据模型创建 Tenant

    Add-Migration add_tenant_table -Context MultiTenantDbContext
    Update-Database -Context MultiTenantDbContext

    11.7.5 实现 IMultiTenantOnSchema 接口

    在需要多租户的数据库上下文中实现 IMultiTenantOnSchema 接口,如:

    using Furion.DatabaseAccessor;using Microsoft.EntityFrameworkCore;namespace Furion.EntityFramework.Core{    [AppDbContext("Sqlite3ConnectionString", DbProvider.Sqlite)]    public class FurionDbContext : AppDbContext<FurionDbContext>, IMultiTenantOnSchema    {        public FurionDbContext(DbContextOptions<FurionDbContext> options) : base(options)        {        }        public string GetSchemaName()        {            return base.Tenant?.Schema??"dbo";        }    }}
    特别说明

    base.Tenant 只是 Furion 框架提供的默认租户实现方法,如果不能满足业务需求,只需要在 GetSchemaName 里面写你的业务代码即可,也就是无需调用 base.Tenant。如:

    public string GetSchemaName(){   // 这里是你获取 Schema 的逻辑   return 你的 Schema;}

    11.7.6 关于 Code First 数据迁移

    基于 Schema 方式比较特别,生成数据迁移的时候没办法获取租户信息,所以建议分开多次迁移,如:

    public string GetSchemaName(){    return base.Tenant?.Schema?? "租户一Schema";}
    public string GetSchemaName(){    return base.Tenant?.Schema?? "租户二Schema";}

    这样就可以在迁移的时候生成多次迁移了。

    11.8 自定义 Tenant 类型

    默认情况下,Furion 框架提供了内置的 Tenant 类型,方便大家快速实现 SaaS 多租户功能,如果需要自定义多租户 Tenant 类型,只需要启用以下配置即可:

    11.8.1 启动自定义多租户类型配置

    services.AddDatabaseAccessor(options =>{    options.CustomizeMultiTenants();    // 启用自定义多租户类型,有一个默认参数,配置多租户表字段名    options.AddDbPool<FurionDbContext>();});

    11.8.2 自定义租户类

    using System;using System.ComponentModel.DataAnnotations.Schema;namespace Furion.Core{    public class MyTenant : IEntity<MultiTenantDbContextLocator>    {        [Key]        public Guid TenantId { get; set; }        public string Name { get; set; }        public string Host { get; set; }    }}

    如果需要查询该租户信息,可通过以下代码获取,如:

    var tenantDbContext = Db.GetDbContext<MultiTenantDbContextLocator>();var myTenant = tenantDbContext.Set<MyTenant>();

    11.9 刷新租户缓存

    Furion 框架会在租户上下文第一次查询时候将租户表缓存起来,避免频发查询数据库,如果更新了租户表,则需要手动刷新租户信息,如:

    using Furion.DatabaseAccessor.Extensions;// 在更新租户信息后调用_repository.Context.RefreshTenantCache();

    11.10 反馈与建议

    与我们交流

    给 Furion 提 Issue

    演练场
- - + + \ No newline at end of file diff --git a/handbook/build/docs/sensitive-detection/index.html b/handbook/build/docs/sensitive-detection/index.html index 95bf75222e..3486d795ff 100644 --- a/handbook/build/docs/sensitive-detection/index.html +++ b/handbook/build/docs/sensitive-detection/index.html @@ -2,22 +2,21 @@ - - - + +30. 脱敏处理 | Furion -30. 脱敏处理 | Furion - - + + +
-

30. 脱敏处理

版本说明

以下内容仅限 Furion 2.4.4 + 版本使用。

30.1 关于脱敏

引用百度百科:

数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。在涉及客户安全数据或者一些商业性敏感数据的情况下,在不违反系统规则条件下,对真实数据进行改造并提供测试使用,如身份证号、手机号、卡号、客户号等个人信息都需要进行数据脱敏。数据安全技术之一,数据库安全技术主要包括:数据库漏扫、数据库加密、数据库防火墙、数据脱敏、数据库安全审计系统。

Furion 系统中,脱敏处理 指的是对不符合系统合法词汇检测验证。

30.2 如何使用

Furion 框架内置了一套默认的脱敏词汇脱敏处理机制,并且提供自定义操作。

30.2.1 注册 脱敏词汇检测 服务

public void ConfigureServices(IServiceCollection services){    services.AddSensitiveDetection();}

30.2.2 创建 sensitive-words.txt 文件

Web 启动层项目中创建 sensitive-words.txt 文件,确保采用 UTF-8 编码格式且不能带 BOM 签名 且设置为嵌入式资源!🎃

sensitive-words.txt 内容格式为每一行标识一个脱敏词汇:

坏人
无语
滚开
八嘎
3.8.9+ 版本

Furion 3.8.9+ 版本支持 | 分隔符进行分割,也同时支持 换行| 混用,如:

坏人|无语|滚开
八嘎

推荐使用 | 方式,可以节省词库占用存储空间。

接下来设置为嵌入式资源:

30.2.3 使用脱敏检测

  • 实现数据验证脱敏检测 [SensitiveDetection]

Furion 框架提供了 [SensitiveDetection] 验证特性,可以对参数、属性进行脱敏验证,用法和 [DataValidation] 一致,如:

// 在属性中使用public class Content{    [SensitiveDetection]    public string Text { get; set; }}// 在 动态API/Controller 中使用public void Test([SensitiveDetection] string text){}
  • 通过 ISensitiveDetectionProvider 服务使用

Furion 框架也提供了 ISensitiveDetectionProvider 服务进行手动脱敏验证处理,如:

public class FurionService{    private readonly ISensitiveDetectionProvider _sensitiveDetectionProvider;    public FurionService(ISensitiveDetectionProvider sensitiveDetectionProvider)    {        _sensitiveDetectionProvider = sensitiveDetectionProvider;    }    /// <summary>    /// 获取所有脱敏词汇    /// </summary>    /// <returns></returns>    public async Task<IEnumerable<string>> GetWordsAsync()    {        return await _sensitiveDetectionProvider.GetWordsAsync();    }    /// <summary>    /// 判断是否是正常的词汇    /// </summary>    /// <param name="text"></param>    /// <returns></returns>    public async Task<bool> VaildedAsync(string text)    {        return await _sensitiveDetectionProvider.VaildedAsync(text);    }    /// <summary>    /// 替换非正常词汇    /// </summary>    /// <param name="text"></param>    /// <returns></returns>    public async Task<string> ReplaceAsync(string text)    {        return await _sensitiveDetectionProvider.ReplaceAsync(text, '*');    }}

30.2.3 脱敏词汇替换

Furion 框架也提供了替换脱敏词汇的特性支持,如:

// 在属性中使用public class Content{    [SensitiveDetection('*')]    public string Text { get; set; }}
特别注意

Furion 3.8.8+ 版本后支持方法特性直接替换

public void Test([SensitiveDetection('*')] string text){}

30.3 自定义脱敏词汇处理

Furion 框架除了内置了一套默认的 脱敏处理 程序,也支持自定义脱敏处理程序。

30.3.1 自定义 ISensitiveDetectionProvider 程序,如:

/// <summary>/// 自定义脱敏词汇检测器/// </summary>public class YourSensitiveDetectionProvider : ISensitiveDetectionProvider{    // 支持构造函数注入    public YourSensitiveDetectionProvider()    {    }    /// <summary>    /// 返回所有脱敏词汇    /// </summary>    /// <returns></returns>    public async Task<IEnumerable<string>> GetWordsAsync()    {        // 这里写你脱敏词汇数据的来源(如从数据库读取),建议做好缓存操作    }    /// <summary>    /// 判断脱敏词汇是否有效    /// </summary>    /// <param name="text"></param>    /// <returns></returns>    public async Task<bool> VaildedAsync(string text)    {        // 这里写你如何判断是正常的字符,返回 true 正常,返回 false 表示是个脱敏词汇    }    /// <summary>    /// 替换脱敏词汇    /// </summary>    /// <param name="text"></param>    /// <param name="transfer"></param>    /// <returns></returns>    public async Task<string> ReplaceAsync(string text, char transfer = '*')    {        // 这里写你替换非正常字符为指定字符    }}

30.3.2 注册自定义脱敏提供器

public void ConfigureServices(IServiceCollection services){    services.AddSensitiveDetection<YourSensitiveDetectionProvider>();}

之后系统将自动采用自定义的方式进行脱敏处理。

30.4 反馈与建议

与我们交流

给 Furion 提 Issue


演练场
- - +

30. 脱敏处理

版本说明

以下内容仅限 Furion 2.4.4 + 版本使用。

30.1 关于脱敏

引用百度百科:

数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。在涉及客户安全数据或者一些商业性敏感数据的情况下,在不违反系统规则条件下,对真实数据进行改造并提供测试使用,如身份证号、手机号、卡号、客户号等个人信息都需要进行数据脱敏。数据安全技术之一,数据库安全技术主要包括:数据库漏扫、数据库加密、数据库防火墙、数据脱敏、数据库安全审计系统。

Furion 系统中,脱敏处理 指的是对不符合系统合法词汇检测验证。

30.2 如何使用

Furion 框架内置了一套默认的脱敏词汇脱敏处理机制,并且提供自定义操作。

30.2.1 注册 脱敏词汇检测 服务

public void ConfigureServices(IServiceCollection services){    services.AddSensitiveDetection();}

30.2.2 创建 sensitive-words.txt 文件

Web 启动层项目中创建 sensitive-words.txt 文件,确保采用 UTF-8 编码格式且不能带 BOM 签名 且设置为嵌入式资源!🎃

sensitive-words.txt 内容格式为每一行标识一个脱敏词汇:

坏人
无语
滚开
八嘎
3.8.9+ 版本

Furion 3.8.9+ 版本支持 | 分隔符进行分割,也同时支持 换行| 混用,如:

坏人|无语|滚开
八嘎

推荐使用 | 方式,可以节省词库占用存储空间。

接下来设置为嵌入式资源:

30.2.3 使用脱敏检测

  • 实现数据验证脱敏检测 [SensitiveDetection]

Furion 框架提供了 [SensitiveDetection] 验证特性,可以对参数、属性进行脱敏验证,用法和 [DataValidation] 一致,如:

// 在属性中使用public class Content{    [SensitiveDetection]    public string Text { get; set; }}// 在 动态API/Controller 中使用public void Test([SensitiveDetection] string text){}
  • 通过 ISensitiveDetectionProvider 服务使用

Furion 框架也提供了 ISensitiveDetectionProvider 服务进行手动脱敏验证处理,如:

public class FurionService{    private readonly ISensitiveDetectionProvider _sensitiveDetectionProvider;    public FurionService(ISensitiveDetectionProvider sensitiveDetectionProvider)    {        _sensitiveDetectionProvider = sensitiveDetectionProvider;    }    /// <summary>    /// 获取所有脱敏词汇    /// </summary>    /// <returns></returns>    public async Task<IEnumerable<string>> GetWordsAsync()    {        return await _sensitiveDetectionProvider.GetWordsAsync();    }    /// <summary>    /// 判断是否是正常的词汇    /// </summary>    /// <param name="text"></param>    /// <returns></returns>    public async Task<bool> VaildedAsync(string text)    {        return await _sensitiveDetectionProvider.VaildedAsync(text);    }    /// <summary>    /// 替换非正常词汇    /// </summary>    /// <param name="text"></param>    /// <returns></returns>    public async Task<string> ReplaceAsync(string text)    {        return await _sensitiveDetectionProvider.ReplaceAsync(text, '*');    }}

30.2.3 脱敏词汇替换

Furion 框架也提供了替换脱敏词汇的特性支持,如:

// 在属性中使用public class Content{    [SensitiveDetection('*')]    public string Text { get; set; }}
特别注意

Furion 3.8.8+ 版本后支持方法特性直接替换

public void Test([SensitiveDetection('*')] string text){}

30.3 自定义脱敏词汇处理

Furion 框架除了内置了一套默认的 脱敏处理 程序,也支持自定义脱敏处理程序。

30.3.1 自定义 ISensitiveDetectionProvider 程序,如:

/// <summary>/// 自定义脱敏词汇检测器/// </summary>public class YourSensitiveDetectionProvider : ISensitiveDetectionProvider{    // 支持构造函数注入    public YourSensitiveDetectionProvider()    {    }    /// <summary>    /// 返回所有脱敏词汇    /// </summary>    /// <returns></returns>    public async Task<IEnumerable<string>> GetWordsAsync()    {        // 这里写你脱敏词汇数据的来源(如从数据库读取),建议做好缓存操作    }    /// <summary>    /// 判断脱敏词汇是否有效    /// </summary>    /// <param name="text"></param>    /// <returns></returns>    public async Task<bool> VaildedAsync(string text)    {        // 这里写你如何判断是正常的字符,返回 true 正常,返回 false 表示是个脱敏词汇    }    /// <summary>    /// 替换脱敏词汇    /// </summary>    /// <param name="text"></param>    /// <param name="transfer"></param>    /// <returns></returns>    public async Task<string> ReplaceAsync(string text, char transfer = '*')    {        // 这里写你替换非正常字符为指定字符    }}

30.3.2 注册自定义脱敏提供器

public void ConfigureServices(IServiceCollection services){    services.AddSensitiveDetection<YourSensitiveDetectionProvider>();}

之后系统将自动采用自定义的方式进行脱敏处理。

30.4 反馈与建议

与我们交流

给 Furion 提 Issue


演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/serverun/index.html b/handbook/build/docs/serverun/index.html index 68438ae654..cd5b01244e 100644 --- a/handbook/build/docs/serverun/index.html +++ b/handbook/build/docs/serverun/index.html @@ -2,22 +2,21 @@ - - - + +2.0 入门指南 | Furion -2.0 入门指南 | Furion - - + + +
-

2.0 入门指南

版本说明

以下内容仅限 Furion 3.6.3 + 版本使用。

推荐使用脚手架

Furion 官方提供了非常灵活方便的脚手架,可以快速的创建多层架构项目。

推荐使用 《2.2 官方脚手架》代替本章节功能。

2.0.1 历史背景

相信从 ASP.NET 5 升级至 ASP.NET 6 的开发者都经历过这样变更:

  • ASP.NET 5 中,我们这样创建 Web 主机
Program.cs
Host.CreateDefaultBuilder(args)    .ConfigureWebHostDefaults(webBuilder =>    {        webBuilder.UseStartup<Startup>();    });
  • ASP.NET 6 中, 我们这样创建 Web 主机
Program.cs
var builder = WebApplication.CreateBuilder(args);var app = builder.Build();

试问,ASP.NET 7ASP.NET 8 ... ASP.NET N 呢?会不会每一个版本都有不同的创建方式,那后续项目如何无缝升级?

所以,为了保证一致的代码体验和后续无缝升级,创造出了 Serve.Run(),即使未来创建方式变了,也不用担心,交给框架即可。

2.0.2 创建 控制台 项目

  • 打开 Visual Studio 2022 并创建 控制台 项目
  • 配置项目名称
  • 选择 .NET6
使用命令行方式
// 创建控制台项目dotnet new console -n HelloFurion

2.0.3 添加 Furion 依赖包

使用命令行方式
// 进入创建的目录cd HelloFurion// 添加包dotnet add package Furion

2.0.4 一句话搞定

修改 Program.cs 代码为:

Program.cs
Serve.Run();

对,你没看错,Furion 已经配置好了!

功能说明

Serve.Run() 已经包含了基本的 WebAPI 功能,包含动态 WebAPI跨域 等等,如需完全自定义配置可使用 Serve.Run(RunOptions.Default),之后 AppStartup 派生类自行配置。

2.0.5 启动浏览器

启动浏览器查看效果

是不是超级超级简单!!!

2.0.6 编写第一个 API

Program.cs
Serve.Run();[DynamicApiController]public class HelloService{    public string Say()    {        return "Hello, Furion";    }}

启动浏览器查看效果

2.0.7 Serve.Run() 更多配置

2.0.7.1 配置默认端口

默认情况下,创建的 Web 主机端口为 5000/5001 端口,如需自定义配置,可通过第一个参数配置:

Serve.Run("https://localhost:8080");

同时也支持 dotnet rundotnet watch run 指定:

dotnet run --urls https://localhost:8080# watch 方式dotnet watch run --urls https://localhost:8080

也可以通过 ConfigureBuilder 方式配置:

Serve.Run(RunOptions.Default.ConfigureBuilder(builder =>{    builder.WebHost.UseUrls("https://localhost:8080");  // 也可以通过 builder.Configuration 读取 urls 配置}));
关于 localhost 和多端口

建议使用 * 代替 localhost,这样可以自适应主机地址,多个端口使用 ; 分割,结尾无需 ;

通过 json 方式配置

如需通过配置文件配置端口,需两个该步骤:

  1. 编辑控制台启动项目 .csproj 文件,修改 Project 节点为:
<Project Sdk="Microsoft.NET.Sdk.Web">

也就是在原来的 Sdk 中添加 .Web 即可。

  1. 在控制台启动项目中添加 Properties 文件夹并在此文件夹中创建 launchSettings.json 文件,同时写入以下内容:
launchSettings.json
{  "$schema": "http://json.schemastore.org/launchsettings.json",  "profiles": {    "启动项目名称": {      "commandName": "Project",      "launchBrowser": true,      "launchUrl": "",      "applicationUrl": "https://localhost:8080;http://localhost:8081",      "environmentVariables": {        "ASPNETCORE_ENVIRONMENT": "Development"      }    }  }}

除了 launchsettings.json 的方式,还可以在 appsettings.json 简单配置


appsettings.json
{  "Urls": "http://localhost:8081"}

2.0.7.2 自定义配置

传入 RunOptions 对象相当于自由定义和控制,也就是除了默认集成了 Furion 以外,没有注册任何功能。

  • 仅集成 Furion 的默认配置
Serve.Run(RunOptions.Default);
  • 配置更多服务/中间件
Serve.Run(RunOptions.Default    .ConfigureBuilder(builder =>    {        builder.Services.AddControllers()                        .AddInject();    })    .Configure(app =>    {        app.UseRouting();        app.UseInject(string.Empty);        app.UseEndpoints(endpoints =>        {            endpoints.MapControllers();        });    }));
  • WebComponent 方式
版本说明

以下内容仅限 Furion 4.3.5 + 版本使用。

Serve.Run(RunOptions.Default     .AddWebComponent<XXXWebComponent>());public class XXXWebComponent : IWebComponent{    public void Load(WebApplicationBuilder builder, ComponentContext componentContext)    {        // ....    }}

2.0.7.3 Serve.RunStartup 最佳组合

默认情况下 Serve.Run() 内置了 跨域控制器路由规范化结果静态文件 服务/中间件。适合快速开始项目和编写测试代码。

但不能对这些已注册服务/中间件进行自定义配置,这时只需要配置 RunOptions 属性/方法即可,如:

Program.cs
Serve.Run(RunOptions.Default    .ConfigureBuilder(...)    .Configure(..));

但把所有服务/中间件都放在 Program.cs 中好吗?答案是不好的,因为会导致后续迁移代码维护代码造成了一些困扰。

所以 Furion 推荐下面更加灵活且易维护的方式,Program.cs 只需一句话即可:

推荐使用组件启动

Furion 3.7.3+ 官方提供了非常灵活方便的组件化启动配置服务。

推荐使用 《3.1 组件化启动》代替 AppStartup 方式功能。

Program.cs
Serve.Run(RunOptions.Default);

然后添加自定义 Startup.cs 文件,代码如下:

Startup.cs
using Furion;using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;namespace HelloFurion;public class Startup : AppStartup{    public void ConfigureServices(IServiceCollection services)    {        // ....    }    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    {        // ....    }}
小提示

正常情况下,自定义 Startup.cs 文件应该放在独立的 YourProject.Web.Core 层或其他层。

2.0.7.4 更多配置

如配置 WebHost...

Serve.Run(RunOptions.Default    .ConfigureBuilder(builder => {        builder.WebHost.....    }));

2.0.8 支持 Furion 所有功能

Serve.Run() 看似非常简单,实则非常灵活,而且支持 Furion.NET 所有功能。

2.0.8.1 添加 appsettings.json

创建 appsettings.json 文件,并设置 属性如果较新则复制内容(生成操作)

{  "Logging": {    "LogLevel": {      "Default": "Information",      "Microsoft": "Warning",      "Microsoft.Hosting.Lifetime": "Information",      "Microsoft.EntityFrameworkCore": "Information"    }  },  "AllowedHosts": "*"}

在代码中读取配置:

using Furion;Serve.Run();[DynamicApiController]public class HelloService{    public string Say()    {        return "Hello, Furion " + App.Configuration["Logging:LogLevel:Default"];    }}

2.0.8.2 添加自定义 Startup

Furion 中可以派生自 AppStartup 可以实现更多配置,如:

Program.cs
Serve.Run();
特别注意

如果您想自己配置 Web 项目服务,可通过 Serve.Run(RunOptions.Default); 方式,因为 Serve.Run() 已经包含了常用的 Web 可能会提示重复注册错误。

MyStartup.cs
using Furion;using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;namespace HelloFurion;public class MyStartup : AppStartup{    public void ConfigureServices(IServiceCollection services)    {        Console.WriteLine("调用服务注册啦~~");    }    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    {        Console.WriteLine("调用中间件注册啦");    }}

2.0.8.3 将控制台项目变成 Web 项目

只需要编辑 .csproj 文件,将第一行 Project 节点的 Sdk

<Project Sdk="Microsoft.NET.Sdk">

修改为:

<Project Sdk="Microsoft.NET.Sdk.Web">

即可完成转换,实际上只是追加了 .Web

2.0.8.4 添加 args 启动参数

版本说明

以下内容仅限 Furion 4.2.4 + 版本使用。

Serve.Run(args: args);Serve.Run(RunOptions.Default.WithArgs(args));Serve.Run(RunOptions.Main(args));

2.0.8.5 还没看够?

是不是非常强大啊,Serve.Run() 虽然简单,但是 100% 支持 Furion.NET 所有功能。尽情去体验吧!

2.0.9 RunOptionsLegacyRunOptionsGenericRunOptions

Serve.Run 提供了 RunOptionsLegacyRunOptionsGenericRunOptions 重载参数类型,他们的主要区别:

  • RunOptions:使用的是 WebApplication 方式,创建 Web 主机优先推荐方式
  • LegacyRunOptions:使用的是 Host 方式,但默认配置了 Web 主机
  • GenericRunOptions:使用的是 Host 方式,通用类型主机,可用于 WorkerService

LegacyRunOptions 配置例子:

using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;Serve.Run(LegacyRunOptions.Default    // 配置 Web 主机    .ConfigureWebDefaults(builder => builder.ConfigureServices(services =>        {            // ...        })        .Configure(app =>        {            // ...        });    })    // 配置 Host 主机    .ConfigureBuilder(builder => builder....));

GenericRunOptions 配置例子:

Serve.Run(GenericRunOptions.Default    // 配置 Host 主机    .ConfigureBuilder(hostBuilder => hostBuilder....);

更多发布命令说明可查阅微软官方文档 https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish

2.0.10 在 Winform/WPF 桌面中使用

WinformWPF 中使用,请确保 Serve.Run() 在桌面应用程序之前初始化:

  • Winform
namespace WinFormsApp2{    internal static class Program    {        [STAThread]        static void Main()        {            Serve.Run(silence: true);   // 静默启动            ApplicationConfiguration.Initialize();            Application.Run(new Form1());        }    }}
  • WPF
using System;using System.Windows;namespace WpfApp1{    public partial class App : Application    {        public App()        {            Serve.Run(silence: true);   // 静默启动        }    }}

2.0.11 静默启动

默认情况下,Serve.Run() 使用阻塞线程方式启动,但有些时候我们不希望阻塞现有的代码,可使用静默启动的方式:

Serve.Run(silence: true);Console.WriteLine("Hello, World!");Console.ReadKey();

也可以通过 RunOptionsLegacyRunOptionsGenericRunOptions 方式,如:

// RunOptions 方式Serve.Run(RunOptions.DefaultSilence);// LegacyRunOptions 方式Serve.Run(LegacyRunOptions.DefaultSilence);// GenericRunOptions 方式Serve.Run(GenericRunOptions.DefaultSilence);

2.0.12 .NET5 模式找不到 Views 视图路径

由于 .NET5 必须在使用 .UseStartup<> 配置启动项,所以 Serve.Run() 模式会提示找不到 Views 视图路径,这时候只需要在启动目录创建 Startup.cs 文件并通过泛型方式指定即可,如:

Startup.cs
using Microsoft.AspNetCore.Builder;using Microsoft.Extensions.DependencyInjection;namespace YourProject.Web.Entity{    public class Startup    {        public void ConfigureServices(IServiceCollection _)        {        }        public void Configure(IApplicationBuilder _)        {        }    }}

Startup 类通过 Serve.Run 泛型指定:

Serve.Run<Startup>(LegacyRunOptions.Default);

2.0.13 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

2.0 入门指南

版本说明

以下内容仅限 Furion 3.6.3 + 版本使用。

推荐使用脚手架

Furion 官方提供了非常灵活方便的脚手架,可以快速的创建多层架构项目。

推荐使用 《2.2 官方脚手架》代替本章节功能。

2.0.1 历史背景

相信从 ASP.NET 5 升级至 ASP.NET 6 的开发者都经历过这样变更:

  • ASP.NET 5 中,我们这样创建 Web 主机
Program.cs
Host.CreateDefaultBuilder(args)    .ConfigureWebHostDefaults(webBuilder =>    {        webBuilder.UseStartup<Startup>();    });
  • ASP.NET 6 中, 我们这样创建 Web 主机
Program.cs
var builder = WebApplication.CreateBuilder(args);var app = builder.Build();

试问,ASP.NET 7ASP.NET 8 ... ASP.NET N 呢?会不会每一个版本都有不同的创建方式,那后续项目如何无缝升级?

所以,为了保证一致的代码体验和后续无缝升级,创造出了 Serve.Run(),即使未来创建方式变了,也不用担心,交给框架即可。

2.0.2 创建 控制台 项目

  • 打开 Visual Studio 2022 并创建 控制台 项目
  • 配置项目名称
  • 选择 .NET6
使用命令行方式
// 创建控制台项目dotnet new console -n HelloFurion

2.0.3 添加 Furion 依赖包

使用命令行方式
// 进入创建的目录cd HelloFurion// 添加包dotnet add package Furion

2.0.4 一句话搞定

修改 Program.cs 代码为:

Program.cs
Serve.Run();

对,你没看错,Furion 已经配置好了!

功能说明

Serve.Run() 已经包含了基本的 WebAPI 功能,包含动态 WebAPI跨域 等等,如需完全自定义配置可使用 Serve.Run(RunOptions.Default),之后 AppStartup 派生类自行配置。

2.0.5 启动浏览器

启动浏览器查看效果

是不是超级超级简单!!!

2.0.6 编写第一个 API

Program.cs
Serve.Run();[DynamicApiController]public class HelloService{    public string Say()    {        return "Hello, Furion";    }}

启动浏览器查看效果

2.0.7 Serve.Run() 更多配置

2.0.7.1 配置默认端口

默认情况下,创建的 Web 主机端口为 5000/5001 端口,如需自定义配置,可通过第一个参数配置:

Serve.Run("https://localhost:8080");

同时也支持 dotnet rundotnet watch run 指定:

dotnet run --urls https://localhost:8080# watch 方式dotnet watch run --urls https://localhost:8080

也可以通过 ConfigureBuilder 方式配置:

Serve.Run(RunOptions.Default.ConfigureBuilder(builder =>{    builder.WebHost.UseUrls("https://localhost:8080");  // 也可以通过 builder.Configuration 读取 urls 配置}));
关于 localhost 和多端口

建议使用 * 代替 localhost,这样可以自适应主机地址,多个端口使用 ; 分割,结尾无需 ;

通过 json 方式配置

如需通过配置文件配置端口,需两个该步骤:

  1. 编辑控制台启动项目 .csproj 文件,修改 Project 节点为:
<Project Sdk="Microsoft.NET.Sdk.Web">

也就是在原来的 Sdk 中添加 .Web 即可。

  1. 在控制台启动项目中添加 Properties 文件夹并在此文件夹中创建 launchSettings.json 文件,同时写入以下内容:
launchSettings.json
{  "$schema": "http://json.schemastore.org/launchsettings.json",  "profiles": {    "启动项目名称": {      "commandName": "Project",      "launchBrowser": true,      "launchUrl": "",      "applicationUrl": "https://localhost:8080;http://localhost:8081",      "environmentVariables": {        "ASPNETCORE_ENVIRONMENT": "Development"      }    }  }}

除了 launchsettings.json 的方式,还可以在 appsettings.json 简单配置


appsettings.json
{  "Urls": "http://localhost:8081"}

2.0.7.2 自定义配置

传入 RunOptions 对象相当于自由定义和控制,也就是除了默认集成了 Furion 以外,没有注册任何功能。

  • 仅集成 Furion 的默认配置
Serve.Run(RunOptions.Default);
  • 配置更多服务/中间件
Serve.Run(RunOptions.Default    .ConfigureBuilder(builder =>    {        builder.Services.AddControllers()                        .AddInject();    })    .Configure(app =>    {        app.UseRouting();        app.UseInject(string.Empty);        app.UseEndpoints(endpoints =>        {            endpoints.MapControllers();        });    }));
  • WebComponent 方式
版本说明

以下内容仅限 Furion 4.3.5 + 版本使用。

Serve.Run(RunOptions.Default     .AddWebComponent<XXXWebComponent>());public class XXXWebComponent : IWebComponent{    public void Load(WebApplicationBuilder builder, ComponentContext componentContext)    {        // ....    }}

2.0.7.3 Serve.RunStartup 最佳组合

默认情况下 Serve.Run() 内置了 跨域控制器路由规范化结果静态文件 服务/中间件。适合快速开始项目和编写测试代码。

但不能对这些已注册服务/中间件进行自定义配置,这时只需要配置 RunOptions 属性/方法即可,如:

Program.cs
Serve.Run(RunOptions.Default    .ConfigureBuilder(...)    .Configure(..));

但把所有服务/中间件都放在 Program.cs 中好吗?答案是不好的,因为会导致后续迁移代码维护代码造成了一些困扰。

所以 Furion 推荐下面更加灵活且易维护的方式,Program.cs 只需一句话即可:

推荐使用组件启动

Furion 3.7.3+ 官方提供了非常灵活方便的组件化启动配置服务。

推荐使用 《3.1 组件化启动》代替 AppStartup 方式功能。

Program.cs
Serve.Run(RunOptions.Default);

然后添加自定义 Startup.cs 文件,代码如下:

Startup.cs
using Furion;using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;namespace HelloFurion;public class Startup : AppStartup{    public void ConfigureServices(IServiceCollection services)    {        // ....    }    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    {        // ....    }}
小提示

正常情况下,自定义 Startup.cs 文件应该放在独立的 YourProject.Web.Core 层或其他层。

2.0.7.4 更多配置

如配置 WebHost...

Serve.Run(RunOptions.Default    .ConfigureBuilder(builder => {        builder.WebHost.....    }));

2.0.8 支持 Furion 所有功能

Serve.Run() 看似非常简单,实则非常灵活,而且支持 Furion.NET 所有功能。

2.0.8.1 添加 appsettings.json

创建 appsettings.json 文件,并设置 属性如果较新则复制内容(生成操作)

{  "Logging": {    "LogLevel": {      "Default": "Information",      "Microsoft": "Warning",      "Microsoft.Hosting.Lifetime": "Information",      "Microsoft.EntityFrameworkCore": "Information"    }  },  "AllowedHosts": "*"}

在代码中读取配置:

using Furion;Serve.Run();[DynamicApiController]public class HelloService{    public string Say()    {        return "Hello, Furion " + App.Configuration["Logging:LogLevel:Default"];    }}

2.0.8.2 添加自定义 Startup

Furion 中可以派生自 AppStartup 可以实现更多配置,如:

Program.cs
Serve.Run();
特别注意

如果您想自己配置 Web 项目服务,可通过 Serve.Run(RunOptions.Default); 方式,因为 Serve.Run() 已经包含了常用的 Web 可能会提示重复注册错误。

MyStartup.cs
using Furion;using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;namespace HelloFurion;public class MyStartup : AppStartup{    public void ConfigureServices(IServiceCollection services)    {        Console.WriteLine("调用服务注册啦~~");    }    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    {        Console.WriteLine("调用中间件注册啦");    }}

2.0.8.3 将控制台项目变成 Web 项目

只需要编辑 .csproj 文件,将第一行 Project 节点的 Sdk

<Project Sdk="Microsoft.NET.Sdk">

修改为:

<Project Sdk="Microsoft.NET.Sdk.Web">

即可完成转换,实际上只是追加了 .Web

2.0.8.4 添加 args 启动参数

版本说明

以下内容仅限 Furion 4.2.4 + 版本使用。

Serve.Run(args: args);Serve.Run(RunOptions.Default.WithArgs(args));Serve.Run(RunOptions.Main(args));

2.0.8.5 还没看够?

是不是非常强大啊,Serve.Run() 虽然简单,但是 100% 支持 Furion.NET 所有功能。尽情去体验吧!

2.0.9 RunOptionsLegacyRunOptionsGenericRunOptions

Serve.Run 提供了 RunOptionsLegacyRunOptionsGenericRunOptions 重载参数类型,他们的主要区别:

  • RunOptions:使用的是 WebApplication 方式,创建 Web 主机优先推荐方式
  • LegacyRunOptions:使用的是 Host 方式,但默认配置了 Web 主机
  • GenericRunOptions:使用的是 Host 方式,通用类型主机,可用于 WorkerService

LegacyRunOptions 配置例子:

using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;Serve.Run(LegacyRunOptions.Default    // 配置 Web 主机    .ConfigureWebDefaults(builder => builder.ConfigureServices(services =>        {            // ...        })        .Configure(app =>        {            // ...        });    })    // 配置 Host 主机    .ConfigureBuilder(builder => builder....));

GenericRunOptions 配置例子:

Serve.Run(GenericRunOptions.Default    // 配置 Host 主机    .ConfigureBuilder(hostBuilder => hostBuilder....);

更多发布命令说明可查阅微软官方文档 https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish

2.0.10 在 Winform/WPF 桌面中使用

WinformWPF 中使用,请确保 Serve.Run() 在桌面应用程序之前初始化:

  • Winform
namespace WinFormsApp2{    internal static class Program    {        [STAThread]        static void Main()        {            Serve.Run(silence: true);   // 静默启动            ApplicationConfiguration.Initialize();            Application.Run(new Form1());        }    }}
  • WPF
using System;using System.Windows;namespace WpfApp1{    public partial class App : Application    {        public App()        {            Serve.Run(silence: true);   // 静默启动        }    }}

2.0.11 静默启动

默认情况下,Serve.Run() 使用阻塞线程方式启动,但有些时候我们不希望阻塞现有的代码,可使用静默启动的方式:

Serve.Run(silence: true);Console.WriteLine("Hello, World!");Console.ReadKey();

也可以通过 RunOptionsLegacyRunOptionsGenericRunOptions 方式,如:

// RunOptions 方式Serve.Run(RunOptions.DefaultSilence);// LegacyRunOptions 方式Serve.Run(LegacyRunOptions.DefaultSilence);// GenericRunOptions 方式Serve.Run(GenericRunOptions.DefaultSilence);

2.0.12 .NET5 模式找不到 Views 视图路径

由于 .NET5 必须在使用 .UseStartup<> 配置启动项,所以 Serve.Run() 模式会提示找不到 Views 视图路径,这时候只需要在启动目录创建 Startup.cs 文件并通过泛型方式指定即可,如:

Startup.cs
using Microsoft.AspNetCore.Builder;using Microsoft.Extensions.DependencyInjection;namespace YourProject.Web.Entity{    public class Startup    {        public void ConfigureServices(IServiceCollection _)        {        }        public void Configure(IApplicationBuilder _)        {        }    }}

Startup 类通过 Serve.Run 泛型指定:

Serve.Run<Startup>(LegacyRunOptions.Default);

2.0.13 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/sesssion-state/index.html b/handbook/build/docs/sesssion-state/index.html index 9ecfe5690f..94631875eb 100644 --- a/handbook/build/docs/sesssion-state/index.html +++ b/handbook/build/docs/sesssion-state/index.html @@ -2,22 +2,21 @@ - - - + +32. 会话和状态管理 | Furion -32. 会话和状态管理 | Furion - - + + +
-

32. 会话和状态管理

32.1 关于会话和状态管理

HTTP 是无状态的协议。 默认情况下,HTTP 请求是不保留用户值的独立消息。但是我们可以通过以下几种方式保留请求用户数据:

  • Cookie:通常存储在客户端的数据,请求时带回服务端
  • Session:存储在服务端的数据(可以在存储在内存、进程等介质中)
  • Query Strings:通过 Http 请求地址参数共享
  • HttpContext.Items:存储在服务端,只在请求声明周期内使用,请求结束自动销毁
  • Cache:服务端缓存,包括内存缓存、分布式内存缓存、IO 缓存、序列化缓存以及数据库缓存
  • AsyncLocal<T>:通过异步控制流实现本地数据共享,跨线程

32.2 如何使用

使用 Cookie 非常简单,如:

// 读取 Cookiesvar value = httpContext.Request.Cookies["key"];// 设置 Cookiesvar option = new CookieOptions();option.Expires = DateTime.Now.AddMilliseconds(10);httpContext.Response.Cookies.Append(key, value, option);// 删除 CookieshttpContext.Response.Cookies.Delete(key);
特别说明

httpContext 可以通过 IHttpContextAccessor 获取,也可以通过 App.HttpContext 获取。

我们还可以通过 Cookie 实现授权功能及单点登录(SSO):网站共享 Cookie

32.2.2 Session 使用

在使用 Session 之前,必须注册 Session 服务:(如果

public class Startup{    public void ConfigureServices(IServiceCollection services)    {        // services.AddDistributedMemoryCache(); 框架内部已经默认注册        services.AddSession(options =>        {            options.IdleTimeout = TimeSpan.FromSeconds(10);            options.Cookie.HttpOnly = true;            options.Cookie.IsEssential = true;        }); // 注意在控制器之前注册!!!!        services.AddControllersWithViews();    }    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    {        if (env.IsDevelopment())        {            app.UseDeveloperExceptionPage();        }        else        {            app.UseExceptionHandler("/Home/Error");            app.UseHsts();        }        app.UseHttpsRedirection();        app.UseStaticFiles();        app.UseRouting();        app.UseAuthentication();        app.UseAuthorization();        app.UseSession();        app.UseEndpoints(endpoints =>        {            endpoints.MapDefaultControllerRoute();            endpoints.MapRazorPages();        });    }}
中间件注册顺序

app.UseSession() 必须在 app.UseRouting()app.UseEndpoints() 之间注册!

  • 常见例子:
// 读取 Sessionvar byteArr = httpContext.Session.Get("key"); // 返回 byte[]var str = httpContext.Session.GetString("key");   // 返回 string[]var num = httpContext.Session.GetInt32("key");    // 返回 int// 设置 SessionhttpContext.Session.SetString("key", "value");  // 设置字符串httpContext.Session.SetInt32("key", 1); // 设置 int 类型
  • 自定义设置任意类型拓展:
public static class SessionExtensions{    public static void Set<T>(this ISession session, string key, T value)    {        session.SetString(key, JsonSerializer.Serialize(value));    }    public static T Get<T>(this ISession session, string key)    {        var value = session.GetString(key);        return value == null ? default : JsonSerializer.Deserialize<T>(value);    }}
  • 防止 Session ID 改变或 Session 失效

Startup.csConfigureServices 配置即可:

services.Configure<CookiePolicyOptions>(options =>{   options.CheckConsentNeeded = context => false; // 默认为true,改为false   options.MinimumSameSitePolicy = SameSiteMode.None;});

32.2.3 Query Strings 使用

该方式使用非常简单,只需 httpContext.Request.Query["key"] 即可。

32.2.4 HttpContext.Items 使用

HttpContext 对象提供了 Items 集合属性,可以让我们在单次请求间共享数据,请求结束立即销毁,可以存储任何数据。使用也非常简单,如:

// 读取var value = httpContext.Items["key"];// 添加httpContext.Items["key"] = "任何值包括对象";// 删除httpContext.Items.Remove("key");

32.2.5 Cache 方式

参见 分布式缓存 文档

32.2.6 AsyncLocal<T> 方式

AsyncLocal<T> 可以说是进程内共享数据的大利器,可以通过该类实现跨线程、异步控制流中共享数据,如:

using System;using System.Threading;using System.Threading.Tasks;class Example{    static AsyncLocal<string> _asyncLocalString = new AsyncLocal<string>();    static ThreadLocal<string> _threadLocalString = new ThreadLocal<string>();    static async Task AsyncMethodA()    {        // Start multiple async method calls, with different AsyncLocal values.        // We also set ThreadLocal values, to demonstrate how the two mechanisms differ.        _asyncLocalString.Value = "Value 1";        _threadLocalString.Value = "Value 1";        var t1 = AsyncMethodB("Value 1");        _asyncLocalString.Value = "Value 2";        _threadLocalString.Value = "Value 2";        var t2 = AsyncMethodB("Value 2");        // Await both calls        await t1;        await t2;     }    static async Task AsyncMethodB(string expectedValue)    {        Console.WriteLine("Entering AsyncMethodB.");        Console.WriteLine("   Expected '{0}', AsyncLocal value is '{1}', ThreadLocal value is '{2}'",                          expectedValue, _asyncLocalString.Value, _threadLocalString.Value);        await Task.Delay(100);        Console.WriteLine("Exiting AsyncMethodB.");        Console.WriteLine("   Expected '{0}', got '{1}', ThreadLocal value is '{2}'",                          expectedValue, _asyncLocalString.Value, _threadLocalString.Value);    }    static async Task Main(string[] args)    {        await AsyncMethodA();    }}// The example displays the following output://   Entering AsyncMethodB.//      Expected 'Value 1', AsyncLocal value is 'Value 1', ThreadLocal value is 'Value 1'//   Entering AsyncMethodB.//      Expected 'Value 2', AsyncLocal value is 'Value 2', ThreadLocal value is 'Value 2'//   Exiting AsyncMethodB.//      Expected 'Value 2', got 'Value 2', ThreadLocal value is ''//   Exiting AsyncMethodB.//      Expected 'Value 1', got 'Value 1', ThreadLocal value is ''

为了简化操作,Furion v2.18+ 版本实现了轻量级的 CallContext 静态类,内部使用 AsyncLocal<T> 实现,使用如下:

CallContext.SetLocalValue("name", "Furion");CallContext.GetLocalValue("name");CallContext<int>.SetLocalValue("count", 1);CallContext<int>.GetLocalValue("count");

了解更多 AsyncLocal<T> 知识:https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.asynclocal-1?redirectedfrom=MSDN&view=net-5.0

32.3 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

32. 会话和状态管理

32.1 关于会话和状态管理

HTTP 是无状态的协议。 默认情况下,HTTP 请求是不保留用户值的独立消息。但是我们可以通过以下几种方式保留请求用户数据:

  • Cookie:通常存储在客户端的数据,请求时带回服务端
  • Session:存储在服务端的数据(可以在存储在内存、进程等介质中)
  • Query Strings:通过 Http 请求地址参数共享
  • HttpContext.Items:存储在服务端,只在请求声明周期内使用,请求结束自动销毁
  • Cache:服务端缓存,包括内存缓存、分布式内存缓存、IO 缓存、序列化缓存以及数据库缓存
  • AsyncLocal<T>:通过异步控制流实现本地数据共享,跨线程

32.2 如何使用

使用 Cookie 非常简单,如:

// 读取 Cookiesvar value = httpContext.Request.Cookies["key"];// 设置 Cookiesvar option = new CookieOptions();option.Expires = DateTime.Now.AddMilliseconds(10);httpContext.Response.Cookies.Append(key, value, option);// 删除 CookieshttpContext.Response.Cookies.Delete(key);
特别说明

httpContext 可以通过 IHttpContextAccessor 获取,也可以通过 App.HttpContext 获取。

我们还可以通过 Cookie 实现授权功能及单点登录(SSO):网站共享 Cookie

32.2.2 Session 使用

在使用 Session 之前,必须注册 Session 服务:(如果

public class Startup{    public void ConfigureServices(IServiceCollection services)    {        // services.AddDistributedMemoryCache(); 框架内部已经默认注册        services.AddSession(options =>        {            options.IdleTimeout = TimeSpan.FromSeconds(10);            options.Cookie.HttpOnly = true;            options.Cookie.IsEssential = true;        }); // 注意在控制器之前注册!!!!        services.AddControllersWithViews();    }    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    {        if (env.IsDevelopment())        {            app.UseDeveloperExceptionPage();        }        else        {            app.UseExceptionHandler("/Home/Error");            app.UseHsts();        }        app.UseHttpsRedirection();        app.UseStaticFiles();        app.UseRouting();        app.UseAuthentication();        app.UseAuthorization();        app.UseSession();        app.UseEndpoints(endpoints =>        {            endpoints.MapDefaultControllerRoute();            endpoints.MapRazorPages();        });    }}
中间件注册顺序

app.UseSession() 必须在 app.UseRouting()app.UseEndpoints() 之间注册!

  • 常见例子:
// 读取 Sessionvar byteArr = httpContext.Session.Get("key"); // 返回 byte[]var str = httpContext.Session.GetString("key");   // 返回 string[]var num = httpContext.Session.GetInt32("key");    // 返回 int// 设置 SessionhttpContext.Session.SetString("key", "value");  // 设置字符串httpContext.Session.SetInt32("key", 1); // 设置 int 类型
  • 自定义设置任意类型拓展:
public static class SessionExtensions{    public static void Set<T>(this ISession session, string key, T value)    {        session.SetString(key, JsonSerializer.Serialize(value));    }    public static T Get<T>(this ISession session, string key)    {        var value = session.GetString(key);        return value == null ? default : JsonSerializer.Deserialize<T>(value);    }}
  • 防止 Session ID 改变或 Session 失效

Startup.csConfigureServices 配置即可:

services.Configure<CookiePolicyOptions>(options =>{   options.CheckConsentNeeded = context => false; // 默认为true,改为false   options.MinimumSameSitePolicy = SameSiteMode.None;});

32.2.3 Query Strings 使用

该方式使用非常简单,只需 httpContext.Request.Query["key"] 即可。

32.2.4 HttpContext.Items 使用

HttpContext 对象提供了 Items 集合属性,可以让我们在单次请求间共享数据,请求结束立即销毁,可以存储任何数据。使用也非常简单,如:

// 读取var value = httpContext.Items["key"];// 添加httpContext.Items["key"] = "任何值包括对象";// 删除httpContext.Items.Remove("key");

32.2.5 Cache 方式

参见 分布式缓存 文档

32.2.6 AsyncLocal<T> 方式

AsyncLocal<T> 可以说是进程内共享数据的大利器,可以通过该类实现跨线程、异步控制流中共享数据,如:

using System;using System.Threading;using System.Threading.Tasks;class Example{    static AsyncLocal<string> _asyncLocalString = new AsyncLocal<string>();    static ThreadLocal<string> _threadLocalString = new ThreadLocal<string>();    static async Task AsyncMethodA()    {        // Start multiple async method calls, with different AsyncLocal values.        // We also set ThreadLocal values, to demonstrate how the two mechanisms differ.        _asyncLocalString.Value = "Value 1";        _threadLocalString.Value = "Value 1";        var t1 = AsyncMethodB("Value 1");        _asyncLocalString.Value = "Value 2";        _threadLocalString.Value = "Value 2";        var t2 = AsyncMethodB("Value 2");        // Await both calls        await t1;        await t2;     }    static async Task AsyncMethodB(string expectedValue)    {        Console.WriteLine("Entering AsyncMethodB.");        Console.WriteLine("   Expected '{0}', AsyncLocal value is '{1}', ThreadLocal value is '{2}'",                          expectedValue, _asyncLocalString.Value, _threadLocalString.Value);        await Task.Delay(100);        Console.WriteLine("Exiting AsyncMethodB.");        Console.WriteLine("   Expected '{0}', got '{1}', ThreadLocal value is '{2}'",                          expectedValue, _asyncLocalString.Value, _threadLocalString.Value);    }    static async Task Main(string[] args)    {        await AsyncMethodA();    }}// The example displays the following output://   Entering AsyncMethodB.//      Expected 'Value 1', AsyncLocal value is 'Value 1', ThreadLocal value is 'Value 1'//   Entering AsyncMethodB.//      Expected 'Value 2', AsyncLocal value is 'Value 2', ThreadLocal value is 'Value 2'//   Exiting AsyncMethodB.//      Expected 'Value 2', got 'Value 2', ThreadLocal value is ''//   Exiting AsyncMethodB.//      Expected 'Value 1', got 'Value 1', ThreadLocal value is ''

为了简化操作,Furion v2.18+ 版本实现了轻量级的 CallContext 静态类,内部使用 AsyncLocal<T> 实现,使用如下:

CallContext.SetLocalValue("name", "Furion");CallContext.GetLocalValue("name");CallContext<int>.SetLocalValue("count", 1);CallContext<int>.GetLocalValue("count");

了解更多 AsyncLocal<T> 知识:https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.asynclocal-1?redirectedfrom=MSDN&view=net-5.0

32.3 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/settings/appsettings/index.html b/handbook/build/docs/settings/appsettings/index.html index 955da6ccfa..751118fb08 100644 --- a/handbook/build/docs/settings/appsettings/index.html +++ b/handbook/build/docs/settings/appsettings/index.html @@ -2,22 +2,21 @@ - - - + +1. 应用配置 | Furion -1. 应用配置 | Furion - - + + +
-

1. 应用配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

1.1 关于配置

应用配置指的是 Furion 框架全局配置选项。

1.2 配置信息

  • AppSettings:配置根节点
    • InjectMiniProfiler:是否注入 MiniProfilerbool 类型,默认 true关闭 Swagger 左上角监听
    • InjectSpecificationDocument:是否启用 Swagger 文档,bool 类型,默认 true生产环境可关闭
    • EnabledReferenceAssemblyScan:是否启用通过 dll 方式添加的引用程序集扫描,bool 类型,默认 false
    • ExternalAssemblies:配置外部程序集完整路径,支持动态加载,string[] 类型,默认 []
    • ExcludeAssemblies:排除扫描的程序集名称,string[] 类型,默认 []
    • PrintDbConnectionInfo:是否打印数据库连接信息到 MiniProfiler 中,bool 类型,默认 true
    • SupportPackageNamePrefixs:配置支持的包前缀名,string[] 类型,默认 []
    • OutputOriginalSqlExecuteLog:是否输出原始 Sql 执行日志(ADO.NET),默认 true
    • VirtualPath:配置虚拟目录,必须以 / 开头

1.3 配置示例

{  "AppSettings": {    "InjectMiniProfiler": false  }}

1.4 特别注意

默认情况下,Furion 框架会自动扫描根目录下的 *.json*.config.xml 文件载入配置中,如需忽略个别文件,需在 appsettings.json 配置文件根节点下配置 IgnoreConfigurationFiles 节点即可,string[] 类型,如:

{  "IgnoreConfigurationFiles": ["runtime.json"]}

如果需要自定义扫描目录(非根目录),需在 appsettings.json 中添加下面配置:

支持版本

v2.16.7+ 版本有效

{  "ConfigurationScanDirectories": ["目录1名称", "目录1名称/子目录名称"]}

必须在 appsettings.json 文件中配置才有效

演练场
- - +

1. 应用配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

1.1 关于配置

应用配置指的是 Furion 框架全局配置选项。

1.2 配置信息

  • AppSettings:配置根节点
    • InjectMiniProfiler:是否注入 MiniProfilerbool 类型,默认 true关闭 Swagger 左上角监听
    • InjectSpecificationDocument:是否启用 Swagger 文档,bool 类型,默认 true生产环境可关闭
    • EnabledReferenceAssemblyScan:是否启用通过 dll 方式添加的引用程序集扫描,bool 类型,默认 false
    • ExternalAssemblies:配置外部程序集完整路径,支持动态加载,string[] 类型,默认 []
    • ExcludeAssemblies:排除扫描的程序集名称,string[] 类型,默认 []
    • PrintDbConnectionInfo:是否打印数据库连接信息到 MiniProfiler 中,bool 类型,默认 true
    • SupportPackageNamePrefixs:配置支持的包前缀名,string[] 类型,默认 []
    • OutputOriginalSqlExecuteLog:是否输出原始 Sql 执行日志(ADO.NET),默认 true
    • VirtualPath:配置虚拟目录,必须以 / 开头

1.3 配置示例

{  "AppSettings": {    "InjectMiniProfiler": false  }}

1.4 特别注意

默认情况下,Furion 框架会自动扫描根目录下的 *.json*.config.xml 文件载入配置中,如需忽略个别文件,需在 appsettings.json 配置文件根节点下配置 IgnoreConfigurationFiles 节点即可,string[] 类型,如:

{  "IgnoreConfigurationFiles": ["runtime.json"]}

如果需要自定义扫描目录(非根目录),需在 appsettings.json 中添加下面配置:

支持版本

v2.16.7+ 版本有效

{  "ConfigurationScanDirectories": ["目录1名称", "目录1名称/子目录名称"]}

必须在 appsettings.json 文件中配置才有效

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/settings/corsaccessorsettings/index.html b/handbook/build/docs/settings/corsaccessorsettings/index.html index 3a17fbf257..1b0f48fe99 100644 --- a/handbook/build/docs/settings/corsaccessorsettings/index.html +++ b/handbook/build/docs/settings/corsaccessorsettings/index.html @@ -2,22 +2,21 @@ - - - + +2. 跨域配置 | Furion -2. 跨域配置 | Furion - - + + +
-

2. 跨域配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

2.1 关于配置

跨域配置指的是 Furion 框架客户端跨域配置选项。

2.2 配置信息

  • CorsAccessorSettings:配置根节点
    • PolicyName:跨域策略名,string 类型,必填,默认 App.Cors.Policy
    • WithOrigins:允许跨域的域名列表,string[] 类型,默认 *
    • WithHeaders:请求表头,没有配置则允许所有表头,string[] 类型
    • WithExposedHeaders:设置客户端可获取的响应标头,string[] 类型,默认 ["access-token", "x-access-token"]
    • WithMethods:设置跨域允许请求谓词,没有配置则允许所有,string[] 类型
    • AllowCredentials:是否允许跨域请求中的凭据,bool 类型,默认值 true
    • SetPreflightMaxAge:设置预检过期时间,int 类型,默认值 24小时
    • FixedClientToken:是否默认配置 WithExposedHeadersbool 类型,默认 true
    • SignalRSupport:是否启用 SignalR 跨域支持,bool 类型,默认 false

2.3 配置示例

{  "CorsAccessorSettings": {    "PolicyName": "MyPolicy",    "WithOrigins": ["http://localhost:4200", "https://furion.icu"]  }}

2.4 使用 axios 前端注意事项

由于 axios 对跨域有特定的需要,需要响应报文中添加特定 Header 才能放行,如:Access-Control-Expose-Headers: xxxxx,所以,如果前端使用了 axios 请求,需要添加以下配置:

{  "CorsAccessorSettings": {    "WithExposedHeaders": ["X-Pagination","access-token","x-access-token"]  }}
演练场
- - +

2. 跨域配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

2.1 关于配置

跨域配置指的是 Furion 框架客户端跨域配置选项。

2.2 配置信息

  • CorsAccessorSettings:配置根节点
    • PolicyName:跨域策略名,string 类型,必填,默认 App.Cors.Policy
    • WithOrigins:允许跨域的域名列表,string[] 类型,默认 *
    • WithHeaders:请求表头,没有配置则允许所有表头,string[] 类型
    • WithExposedHeaders:设置客户端可获取的响应标头,string[] 类型,默认 ["access-token", "x-access-token"]
    • WithMethods:设置跨域允许请求谓词,没有配置则允许所有,string[] 类型
    • AllowCredentials:是否允许跨域请求中的凭据,bool 类型,默认值 true
    • SetPreflightMaxAge:设置预检过期时间,int 类型,默认值 24小时
    • FixedClientToken:是否默认配置 WithExposedHeadersbool 类型,默认 true
    • SignalRSupport:是否启用 SignalR 跨域支持,bool 类型,默认 false

2.3 配置示例

{  "CorsAccessorSettings": {    "PolicyName": "MyPolicy",    "WithOrigins": ["http://localhost:4200", "https://furion.icu"]  }}

2.4 使用 axios 前端注意事项

由于 axios 对跨域有特定的需要,需要响应报文中添加特定 Header 才能放行,如:Access-Control-Expose-Headers: xxxxx,所以,如果前端使用了 axios 请求,需要添加以下配置:

{  "CorsAccessorSettings": {    "WithExposedHeaders": ["X-Pagination","access-token","x-access-token"]  }}
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/settings/dependencyinjectionsettings/index.html b/handbook/build/docs/settings/dependencyinjectionsettings/index.html index 9f90bb5fbc..a1f45ad8bc 100644 --- a/handbook/build/docs/settings/dependencyinjectionsettings/index.html +++ b/handbook/build/docs/settings/dependencyinjectionsettings/index.html @@ -2,22 +2,21 @@ - - - + +4. 依赖注入配置 | Furion -4. 依赖注入配置 | Furion - - + + +
-

4. 依赖注入配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

4.1 关于配置

依赖注入配置指的是 Furion 框架依赖注入配置选项。

4.2 配置信息

  • DependencyInjectionSettings:依赖注入配置根节点
    • Definitions:动态依赖注入配置节点,ExternalService 数组类型
      • ExternalService:配置单个依赖注入信息
        • Interface:配置依赖接口信息,格式:程序集名称;接口完整名称,如:Furion.Application;Furion.Application.ITestService
        • Service:配置接口实现信息,格式同上
        • RegisterType:配置依赖注入的对象生存期,取值:TransientScopedSingleton
        • Action:注册行为,可选值:AddTryAdd,参见 依赖注入-特性配置
        • Pattern:注册选项,参见 依赖注入-特性配置置
        • Named:注册别名,参见 依赖注入-特性配置
        • Order:注册排序,参见 依赖注入-特性配置
        • Proxy:配置代理拦截,格式:程序集名称;代理类完整名称,参见 依赖注入-特性配置

4.3 配置示例

{  "DependencyInjectionSettings": {    "Definitions": [      {        "Interface": "Furion.Application;Furion.Application.ITestService",        "Service": "Furion.Application;Furion.Application.TestService",        "RegisterType": "Transient",        "Action": "Add",        "Pattern": "SelfWithFirstInterface",        "Named": "TestService",        "Order": 1,        "Proxy": "Furion.Application;Furion.Application.LogDispathProxy"      }    ]  }}
演练场
- - +

4. 依赖注入配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

4.1 关于配置

依赖注入配置指的是 Furion 框架依赖注入配置选项。

4.2 配置信息

  • DependencyInjectionSettings:依赖注入配置根节点
    • Definitions:动态依赖注入配置节点,ExternalService 数组类型
      • ExternalService:配置单个依赖注入信息
        • Interface:配置依赖接口信息,格式:程序集名称;接口完整名称,如:Furion.Application;Furion.Application.ITestService
        • Service:配置接口实现信息,格式同上
        • RegisterType:配置依赖注入的对象生存期,取值:TransientScopedSingleton
        • Action:注册行为,可选值:AddTryAdd,参见 依赖注入-特性配置
        • Pattern:注册选项,参见 依赖注入-特性配置置
        • Named:注册别名,参见 依赖注入-特性配置
        • Order:注册排序,参见 依赖注入-特性配置
        • Proxy:配置代理拦截,格式:程序集名称;代理类完整名称,参见 依赖注入-特性配置

4.3 配置示例

{  "DependencyInjectionSettings": {    "Definitions": [      {        "Interface": "Furion.Application;Furion.Application.ITestService",        "Service": "Furion.Application;Furion.Application.TestService",        "RegisterType": "Transient",        "Action": "Add",        "Pattern": "SelfWithFirstInterface",        "Named": "TestService",        "Order": 1,        "Proxy": "Furion.Application;Furion.Application.LogDispathProxy"      }    ]  }}
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/settings/dynamicapicontrollersettings/index.html b/handbook/build/docs/settings/dynamicapicontrollersettings/index.html index 04327a6468..0b6f44545f 100644 --- a/handbook/build/docs/settings/dynamicapicontrollersettings/index.html +++ b/handbook/build/docs/settings/dynamicapicontrollersettings/index.html @@ -2,22 +2,21 @@ - - - + +5. 动态API配置 | Furion -5. 动态API配置 | Furion - - + + +
-

5. 动态API配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

5.1 关于配置

动态 API 配置指的是 Furion 框架动态 API 配置选项。

5.2 配置信息

  • DynamicApiControllerSettings:配置根节点
    • DefaultRoutePrefix:默认路由前缀,string,默认 api
    • DefaultHttpMethod:默认请求谓词,string,默认:POST
    • DefaultModule:默认模块名称(区域),可用作接口版本,string,默认:v1
    • LowercaseRoute:小写路由格式,bool,默认:true
    • AsLowerCamelCase:启用小驼峰命名(首字母小写),默认 false
    • KeepVerb:是否保留动作谓词,bool,默认:false
    • KeepName:是否保留默认名称,bool,默认:fasle
    • CamelCaseSeparator:骆驼(驼峰)命名分隔符,string,默认:-
    • VersionSeparator:版本分隔符,string,默认:@
    • ModelToQueryGET/HEAD 请求将 类类型参数转查询参数bool,默认 false
    • SupportedMvcController:是否支持 Mvc Controller 动态配置,bool,默认 false
    • UrlParameterization:路由参数采用 [FromQuery] 化,默认 false[FromRoute] 方式)
    • DefaultArea:配置默认区域,默认 null
    • ForceWithRoutePrefix:配置是否强制添加 DefaultRoutePrefix,当控制器自定义了 [Route] 有效,仅限 v3.4.1+版本有效
    • AbandonControllerAffixes:默认去除控制器名称前后缀列表名,string[],默认:
      • AppServices
      • AppService
      • ApiController
      • Controller
      • Services
      • Service
    • AbandonActionAffixes:默认去除动作方法名称前后缀列表名,string[],默认:
      • Async
    • VerbToHttpMethods:复写默认方法名转 [HttpMethod] 规则,string[][] 二维数组类型,内置匹配规则为:
      ["post"] = "POST",["add"] = "POST",["create"] = "POST",["insert"] = "POST",["submit"] = "POST",["get"] = "GET",["find"] = "GET",["fetch"] = "GET",["query"] = "GET",["getlist"] = "GET",["getall"] = "GET",["put"] = "PUT",["update"] = "PUT",["delete"] = "DELETE",["remove"] = "DELETE",["clear"] = "DELETE",["patch"] = "PATCH"
      • 复写示例
      "DynamicApiControllerSettings": {    "VerbToHttpMethods": [      [ "getall", "HEAD" ],  // => getall 会被复写为 `[HttpHead]`      [ "other", "PUT" ]  // => 新增一条新规则,比如,一 `[other]` 开头会转换为 `[HttpPut]` 请求    ]  }

5.3 配置示例

{  "DynamicApiControllerSettings": {    "SupportedMvcController": true  }}
演练场
- - +

5. 动态API配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

5.1 关于配置

动态 API 配置指的是 Furion 框架动态 API 配置选项。

5.2 配置信息

  • DynamicApiControllerSettings:配置根节点
    • DefaultRoutePrefix:默认路由前缀,string,默认 api
    • DefaultHttpMethod:默认请求谓词,string,默认:POST
    • DefaultModule:默认模块名称(区域),可用作接口版本,string,默认:v1
    • LowercaseRoute:小写路由格式,bool,默认:true
    • AsLowerCamelCase:启用小驼峰命名(首字母小写),默认 false
    • KeepVerb:是否保留动作谓词,bool,默认:false
    • KeepName:是否保留默认名称,bool,默认:fasle
    • CamelCaseSeparator:骆驼(驼峰)命名分隔符,string,默认:-
    • VersionSeparator:版本分隔符,string,默认:@
    • ModelToQueryGET/HEAD 请求将 类类型参数转查询参数bool,默认 false
    • SupportedMvcController:是否支持 Mvc Controller 动态配置,bool,默认 false
    • UrlParameterization:路由参数采用 [FromQuery] 化,默认 false[FromRoute] 方式)
    • DefaultArea:配置默认区域,默认 null
    • ForceWithRoutePrefix:配置是否强制添加 DefaultRoutePrefix,当控制器自定义了 [Route] 有效,仅限 v3.4.1+版本有效
    • AbandonControllerAffixes:默认去除控制器名称前后缀列表名,string[],默认:
      • AppServices
      • AppService
      • ApiController
      • Controller
      • Services
      • Service
    • AbandonActionAffixes:默认去除动作方法名称前后缀列表名,string[],默认:
      • Async
    • VerbToHttpMethods:复写默认方法名转 [HttpMethod] 规则,string[][] 二维数组类型,内置匹配规则为:
      ["post"] = "POST",["add"] = "POST",["create"] = "POST",["insert"] = "POST",["submit"] = "POST",["get"] = "GET",["find"] = "GET",["fetch"] = "GET",["query"] = "GET",["getlist"] = "GET",["getall"] = "GET",["put"] = "PUT",["update"] = "PUT",["delete"] = "DELETE",["remove"] = "DELETE",["clear"] = "DELETE",["patch"] = "PATCH"
      • 复写示例
      "DynamicApiControllerSettings": {    "VerbToHttpMethods": [      [ "getall", "HEAD" ],  // => getall 会被复写为 `[HttpHead]`      [ "other", "PUT" ]  // => 新增一条新规则,比如,一 `[other]` 开头会转换为 `[HttpPut]` 请求    ]  }

5.3 配置示例

{  "DynamicApiControllerSettings": {    "SupportedMvcController": true  }}
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/settings/friendlyexceptionsettings/index.html b/handbook/build/docs/settings/friendlyexceptionsettings/index.html index ee8d209129..99da45b80d 100644 --- a/handbook/build/docs/settings/friendlyexceptionsettings/index.html +++ b/handbook/build/docs/settings/friendlyexceptionsettings/index.html @@ -2,22 +2,21 @@ - - - + +6. 友好异常配置 | Furion -6. 友好异常配置 | Furion - - + + +
-

6. 友好异常配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

6.1 关于配置

友好异常配置指的是 Furion 框架友好异常配置选项。

6.2 配置信息

  • FriendlyExceptionSettings:配置根节点
    • HideErrorCode:隐藏错误码,bool 类型,默认 false
    • DefaultErrorCode:默认错误码,string 类型
    • DefaultErrorMessage:默认错误消息,string 类型
    • ThrowBah:是否将 Oops.Oh 默认抛出为业务异常,bool 类型,默认 false,设置 true 之后 Oops.Oh 默认进入 OnValidateFailed 处理,而不是 OnException

6.3 配置示例

{  "FriendlyExceptionSettings": {    "DefaultErrorMessage": "系统异常,请联系管理员"  }}

6.4 异常消息配置

Furion 框架还为友好异常消息提供外部配置

6.4.1 配置信息

  • ErrorCodeMessageSettings:配置根节点
    • Definitions:配置异常错误码消息类型,[错误状态码,错误消息][] 类型,如:["5000", "{0} 不能小于 {1}"]

6.4.2 配置示例

{  "ErrorCodeMessageSettings": {    "Definitions": [      ["5000", "{0} 不能小于 {1}"],      ["5001", "我叫 {0} 名字", "百小僧"],      ["5002", "Oops! 出错了"]    ]  }}
演练场
- - +

6. 友好异常配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

6.1 关于配置

友好异常配置指的是 Furion 框架友好异常配置选项。

6.2 配置信息

  • FriendlyExceptionSettings:配置根节点
    • HideErrorCode:隐藏错误码,bool 类型,默认 false
    • DefaultErrorCode:默认错误码,string 类型
    • DefaultErrorMessage:默认错误消息,string 类型
    • ThrowBah:是否将 Oops.Oh 默认抛出为业务异常,bool 类型,默认 false,设置 true 之后 Oops.Oh 默认进入 OnValidateFailed 处理,而不是 OnException
    • LogError:是否输出异常日志,bool 类型,默认 true

6.3 配置示例

{  "FriendlyExceptionSettings": {    "DefaultErrorMessage": "系统异常,请联系管理员"  }}

6.4 异常消息配置

Furion 框架还为友好异常消息提供外部配置

6.4.1 配置信息

  • ErrorCodeMessageSettings:配置根节点
    • Definitions:配置异常错误码消息类型,[错误状态码,错误消息][] 类型,如:["5000", "{0} 不能小于 {1}"]

6.4.2 配置示例

{  "ErrorCodeMessageSettings": {    "Definitions": [      ["5000", "{0} 不能小于 {1}"],      ["5001", "我叫 {0} 名字", "百小僧"],      ["5002", "Oops! 出错了"]    ]  }}
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/settings/jwtsettings/index.html b/handbook/build/docs/settings/jwtsettings/index.html index 8b1bda96b8..fea72aebdf 100644 --- a/handbook/build/docs/settings/jwtsettings/index.html +++ b/handbook/build/docs/settings/jwtsettings/index.html @@ -2,22 +2,21 @@ - - - + +9. JWT 配置 | Furion -9. JWT 配置 | Furion - - + + +
-

9. JWT 配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

9.1 关于配置

JWT 配置指的是生成 JWT token 配置。

9.2 配置信息

  • JWTSettings:根节点
    • ValidateIssuerSigningKey:是否验证密钥,bool 类型,默认 true
    • IssuerSigningKey:密钥,string 类型,必须是复杂密钥,长度大于 16
    • ValidateIssuer:是否验证签发方,bool 类型,默认 true
    • ValidIssuer:签发方,string 类型
    • ValidateAudience:是否验证签收方,bool 类型,默认 true
    • ValidAudience:签收方,string 类型
    • ValidateLifetim:是否验证过期时间,bool 类型,默认 true,建议 true
    • ExpiredTime:过期时间,long 类型,单位分钟,默认 20 分钟
    • ClockSkew:过期时间容错值,long 类型,单位秒,默认 5
    • Algorithm:加密算法,string 类型,默认 HS256,可选算法有:
      • HS256
      • HS384
      • HS512
      • PS256
      • PS384
      • PS512
      • RS256
      • RS384
      • RS512
      • ES256
      • ES256K
      • ES384
      • ES512
      • EdDSA

9.3 配置示例

{  "JWTSettings": {    "ValidateIssuerSigningKey": true, // 是否验证密钥,bool 类型,默认true    "IssuerSigningKey": "你的密钥", // 密钥,string 类型,必须是复杂密钥,长度大于16    "ValidateIssuer": true, // 是否验证签发方,bool 类型,默认true    "ValidIssuer": "签发方", // 签发方,string 类型    "ValidateAudience": true, // 是否验证签收方,bool 类型,默认true    "ValidAudience": "签收方", // 签收方,string 类型    "ValidateLifetime": true, // 是否验证过期时间,bool 类型,默认true,建议true    "ExpiredTime": 20, // 过期时间,long 类型,单位分钟,默认20分钟    "ClockSkew": 5, // 过期时间容错值,long 类型,单位秒,默认 5秒    "Algorithm": "HS256" // 加密算法,string 类型,默认 HS256  }}
演练场
- - +

9. JWT 配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

9.1 关于配置

JWT 配置指的是生成 JWT token 配置。

9.2 配置信息

  • JWTSettings:根节点
    • ValidateIssuerSigningKey:是否验证密钥,bool 类型,默认 true
    • IssuerSigningKey:密钥,string 类型,必须是复杂密钥,长度大于 16
    • ValidateIssuer:是否验证签发方,bool 类型,默认 true
    • ValidIssuer:签发方,string 类型
    • ValidateAudience:是否验证签收方,bool 类型,默认 true
    • ValidAudience:签收方,string 类型
    • ValidateLifetim:是否验证过期时间,bool 类型,默认 true,建议 true
    • ExpiredTime:过期时间,long 类型,单位分钟,默认 20 分钟
    • ClockSkew:过期时间容错值,long 类型,单位秒,默认 5
    • Algorithm:加密算法,string 类型,默认 HS256,可选算法有:
      • HS256
      • HS384
      • HS512
      • PS256
      • PS384
      • PS512
      • RS256
      • RS384
      • RS512
      • ES256
      • ES256K
      • ES384
      • ES512
      • EdDSA

9.3 配置示例

{  "JWTSettings": {    "ValidateIssuerSigningKey": true, // 是否验证密钥,bool 类型,默认true    "IssuerSigningKey": "你的密钥", // 密钥,string 类型,必须是复杂密钥,长度大于16    "ValidateIssuer": true, // 是否验证签发方,bool 类型,默认true    "ValidIssuer": "签发方", // 签发方,string 类型    "ValidateAudience": true, // 是否验证签收方,bool 类型,默认true    "ValidAudience": "签收方", // 签收方,string 类型    "ValidateLifetime": true, // 是否验证过期时间,bool 类型,默认true,建议true    "ExpiredTime": 20, // 过期时间,long 类型,单位分钟,默认20分钟    "ClockSkew": 5, // 过期时间容错值,long 类型,单位秒,默认 5秒    "Algorithm": "HS256" // 加密算法,string 类型,默认 HS256  }}
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/settings/localizationsettings/index.html b/handbook/build/docs/settings/localizationsettings/index.html index c989121300..9bc905755b 100644 --- a/handbook/build/docs/settings/localizationsettings/index.html +++ b/handbook/build/docs/settings/localizationsettings/index.html @@ -2,22 +2,21 @@ - - - + +8. 多语言配置 | Furion -8. 多语言配置 | Furion - - + + +
-

8. 多语言配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

8.1 关于配置

多语言配置指的是 Furion 框架全球化和本地化选项。

8.2 配置信息

  • LocalizationSettings 多语言配置根节点
    • ResourcesPath:资源目录,string 类型,默认 Resources
    • SupportedCultures:支持的语言区域码类别,string[] 类型
    • DefaultCulture:默认语言区域码,如果为空,则取 SupportedCultures 第一项
    • LanguageFilePrefix:配置资源文件前缀,string 类型,默认 Lang
    • AssemblyName:配置资源文件存放程序集名,string 类型,默认 启动层 名称

8.3 配置示例

{  "LocalizationSettings": {    "SupportedCultures": ["zh-CN", "en-US"], // 配置支持的语言列表    "DefaultCulture": "zh-CN" // 配置默认语言,如果不配置,取 SupportedCultures 的第一项  }}
演练场
- - +

8. 多语言配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

8.1 关于配置

多语言配置指的是 Furion 框架全球化和本地化选项。

8.2 配置信息

  • LocalizationSettings 多语言配置根节点
    • ResourcesPath:资源目录,string 类型,默认 Resources
    • SupportedCultures:支持的语言区域码类别,string[] 类型
    • DefaultCulture:默认语言区域码,如果为空,则取 SupportedCultures 第一项
    • LanguageFilePrefix:配置资源文件前缀,string 类型,默认 Lang
    • AssemblyName:配置资源文件存放程序集名,string 类型,默认 启动层 名称

8.3 配置示例

{  "LocalizationSettings": {    "SupportedCultures": ["zh-CN", "en-US"], // 配置支持的语言列表    "DefaultCulture": "zh-CN" // 配置默认语言,如果不配置,取 SupportedCultures 的第一项  }}
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/settings/specificationdocumentsettings/index.html b/handbook/build/docs/settings/specificationdocumentsettings/index.html index b317ea8840..e8f03ec9a8 100644 --- a/handbook/build/docs/settings/specificationdocumentsettings/index.html +++ b/handbook/build/docs/settings/specificationdocumentsettings/index.html @@ -2,22 +2,21 @@ - - - + +7. 规范化文档配置 | Furion -7. 规范化文档配置 | Furion - - + + +
-

7. 规范化文档配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

7.1 关于配置

规范化文档配置指的是 Furion 框架 Swagger 文档配置选项。

7.2 配置信息

  • SpecificationDocumentSettings:配置根节点
    • DocumentTitle:文档标题,string,默认 Specification Api Document
    • DefaultGroupName:默认分组名,string,默认 Default
    • EnableAuthorized:是否启用权限控制,bool,默认 true
    • FormatAsV2:采用 Swagger 2.0 版本,bool,默认 false 已弃用
    • RoutePrefix:规范化文档地址,string,默认 api如果希望在首页,改为空字符串即可
    • DocExpansionState:文档显示方式,DocExpansion,默认 List,取值:
      • List:列表式(展开子类),默认值
      • Full:完全展开
      • None:列表式(不展开子类)
    • XmlComments:程序集注释描述文件名(可带 .xmlstring,默认 Furion.Application, Furion.Web.Entry, Furion.Web.Core
    • GroupOpenApiInfos:分组信息配置,SpecificationOpenApiInfo[],默认 { 'Group': 'Default'}
    • SecurityDefinitions:安全策略定义配置,SpecificationOpenApiSecurityScheme[],默认 []
    • Servers:配置 Server 下拉列表,OpenApiServer[] 类型,默认 [],如:{Servers:[ { Url:"地址", Description:"描述"} ]}
    • HideServers:是否隐藏 Server 下拉列表,bool 类型,默认 true
    • RouteTemplate:配置文档 swagger.json 路由模板,默认模板:swagger/{documentName}/swagger.json, {documentName} 代表分组名,必须保留原样
    • PackagesGroups:配置模块化内置分组名称,string[] 类型,默认 []
    • EnableEnumSchemaFilter:启用枚举 Schema 筛选器,bool 类型,默认 true
    • EnableTagsOrderDocumentFilter:启用标签排序筛选器,bool 类型,默认 true
    • ServerDir:配置 IIS 添加 Application 部署名,string 类型,默认空,仅在 Furion v3.2.0+` 有效
    • LoginInfo:配置 Swagger 是否需要登录才能访问,SpecificationLoginInfo 类型,默认 null仅在 Furion v3.3.3+` 有效
      • Enabled:是否启用登录授权,默认 false
      • CheckUrl:检查登录状态的 Url 地址,该地址必须是 POST 请求
    • SubmitUrl:提交登录的 Url 地址,该地址必须是 POST 请求且只有一个 SpecificationAuth 类型参数,成功登录返回 200,否则返回 401,支持相对地址,以 / 开头
    • EnableAllGroups:启用 Swagger 总分组功能,自动将所有分组的接口合并到 All Groups 中,bool 类型,默认 false仅在 Furion v3.3.4+` 有效

另外 SpecificationOpenApiInfo 内置配置如下:

  • Group:分组唯一标识,string 类型,必填
  • Order:分组排序,int 类型,数字越大排前面,默认 0
  • Visible:配置分组是否可见,bool 类型,默认 true
  • Title:配置分组标题,string 类型
  • Description:配置分组描述,string 类型
  • Version:配置分组版本,默认 1.0
  • TermsOfService:配置相关链接地址,Uri 类型
  • Contact:配置联系方式,OpenApiContact 类型
  • License:配置协议,OpenApiLicense 类型

7.3 配置示例

{  "SpecificationDocumentSettings": {    "GroupOpenApiInfos": [      {        "Group": "Group1",        "Title": "分组标题",        "Description": "这里是分组描述",        "Version": "版本号",        "TermsOfService": "https://furion.icu",        "Contact": {          "Name": "百小僧",          "Url": "https://gitee.com/monksoul",          "Email": "monksoul@outlook.com"        },        "License": {          "Name": "MIT",          "Url": "https://gitee.com/dotnetchina/Furion/blob/alpha/LICENSE"        }      }    ]  }}
演练场
- - +

7. 规范化文档配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

7.1 关于配置

规范化文档配置指的是 Furion 框架 Swagger 文档配置选项。

7.2 配置信息

  • SpecificationDocumentSettings:配置根节点
    • DocumentTitle:文档标题,string,默认 Specification Api Document
    • DefaultGroupName:默认分组名,string,默认 Default
    • EnableAuthorized:是否启用权限控制,bool,默认 true
    • FormatAsV2:采用 Swagger 2.0 版本,bool,默认 false 已弃用
    • RoutePrefix:规范化文档地址,string,默认 api如果希望在首页,改为空字符串即可
    • DocExpansionState:文档显示方式,DocExpansion,默认 List,取值:
      • List:列表式(展开子类),默认值
      • Full:完全展开
      • None:列表式(不展开子类)
    • XmlComments:程序集注释描述文件名(可带 .xmlstring,默认 Furion.Application, Furion.Web.Entry, Furion.Web.Core
    • GroupOpenApiInfos:分组信息配置,SpecificationOpenApiInfo[],默认 { 'Group': 'Default'}
    • SecurityDefinitions:安全策略定义配置,SpecificationOpenApiSecurityScheme[],默认 []
    • Servers:配置 Server 下拉列表,OpenApiServer[] 类型,默认 [],如:{Servers:[ { Url:"地址", Description:"描述"} ]}
    • HideServers:是否隐藏 Server 下拉列表,bool 类型,默认 true
    • RouteTemplate:配置文档 swagger.json 路由模板,默认模板:swagger/{documentName}/swagger.json, {documentName} 代表分组名,必须保留原样
    • PackagesGroups:配置模块化内置分组名称,string[] 类型,默认 []
    • EnableEnumSchemaFilter:启用枚举 Schema 筛选器,bool 类型,默认 true
    • EnableTagsOrderDocumentFilter:启用标签排序筛选器,bool 类型,默认 true
    • ServerDir:配置 IIS 添加 Application 部署名,string 类型,默认空,仅在 Furion v3.2.0+` 有效
    • LoginInfo:配置 Swagger 是否需要登录才能访问,SpecificationLoginInfo 类型,默认 null仅在 Furion v3.3.3+` 有效
      • Enabled:是否启用登录授权,默认 false
      • CheckUrl:检查登录状态的 Url 地址,该地址必须是 POST 请求
    • SubmitUrl:提交登录的 Url 地址,该地址必须是 POST 请求且只有一个 SpecificationAuth 类型参数,成功登录返回 200,否则返回 401,支持相对地址,以 / 开头
    • EnableAllGroups:启用 Swagger 总分组功能,自动将所有分组的接口合并到 All Groups 中,bool 类型,默认 false仅在 Furion v3.3.4+` 有效

另外 SpecificationOpenApiInfo 内置配置如下:

  • Group:分组唯一标识,string 类型,必填
  • Order:分组排序,int 类型,数字越大排前面,默认 0
  • Visible:配置分组是否可见,bool 类型,默认 true
  • Title:配置分组标题,string 类型
  • Description:配置分组描述,string 类型
  • Version:配置分组版本,默认 1.0
  • TermsOfService:配置相关链接地址,Uri 类型
  • Contact:配置联系方式,OpenApiContact 类型
  • License:配置协议,OpenApiLicense 类型

7.3 配置示例

{  "SpecificationDocumentSettings": {    "GroupOpenApiInfos": [      {        "Group": "Group1",        "Title": "分组标题",        "Description": "这里是分组描述",        "Version": "版本号",        "TermsOfService": "https://furion.icu",        "Contact": {          "Name": "百小僧",          "Url": "https://gitee.com/monksoul",          "Email": "monksoul@outlook.com"        },        "License": {          "Name": "MIT",          "Url": "https://gitee.com/dotnetchina/Furion/blob/alpha/LICENSE"        }      }    ]  }}
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/settings/unifyresultsettings/index.html b/handbook/build/docs/settings/unifyresultsettings/index.html index ffa0cb619b..4b073c5388 100644 --- a/handbook/build/docs/settings/unifyresultsettings/index.html +++ b/handbook/build/docs/settings/unifyresultsettings/index.html @@ -2,22 +2,21 @@ - - - + +10. 规范化结果配置 | Furion -10. 规范化结果配置 | Furion - - + + +
-

10. 规范化结果配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

10.1 关于配置

规范化配置指的是配置响应结果,响应状态码等配置

10.2 配置信息

  • UnifyResultSettings 规范化配置根节点
    • Return200StatusCodes:配置返回 200 状态码的请求,int[] 类型,只支持 400+(404除外) 状态码篡改
    • AdaptStatusCodes:配置篡改状态码规则,int[][] 类型,只支持 400+(404除外) 状态码篡改
    • SupportMvcController:是否支持 MVC 控制台规范化处理,bool 类型,默认 false

10.3 配置示例

{  "UnifyResultSettings": {    "Return200StatusCodes": [401, 403],    "AdaptStatusCodes": [      [401, 200],      [403, 401]    ],    "SupportMvcController": true  }}
演练场
- - +

10. 规范化结果配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

10.1 关于配置

规范化配置指的是配置响应结果,响应状态码等配置

10.2 配置信息

  • UnifyResultSettings 规范化配置根节点
    • Return200StatusCodes:配置返回 200 状态码的请求,int[] 类型,只支持 400+(404除外) 状态码篡改
    • AdaptStatusCodes:配置篡改状态码规则,int[][] 类型,只支持 400+(404除外) 状态码篡改
    • SupportMvcController:是否支持 MVC 控制台规范化处理,bool 类型,默认 false

10.3 配置示例

{  "UnifyResultSettings": {    "Return200StatusCodes": [401, 403],    "AdaptStatusCodes": [      [401, 200],      [403, 401]    ],    "SupportMvcController": true  }}
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/settings/validationTypemessagesettings/index.html b/handbook/build/docs/settings/validationTypemessagesettings/index.html index 988ba2f49f..043866b699 100644 --- a/handbook/build/docs/settings/validationTypemessagesettings/index.html +++ b/handbook/build/docs/settings/validationTypemessagesettings/index.html @@ -2,22 +2,21 @@ - - - + +3. 验证消息配置 | Furion -3. 验证消息配置 | Furion - - + + +
-

3. 验证消息配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

3.1 关于配置

验证消息配置指的是 Furion 框架数据校验中验证类型默认消息配置选项。

3.2 配置信息

  • ValidationTypeMessageSettings:配置根节点
    • Definitions:配置验证类型对应的消息类型,[类型名称,类型消息][] 类型,如:["Required", "值不能为空或Null"]

3.3 配置示例

{  "ValidationTypeMessageSettings": {    "Definitions": [      ["Required", "值不能为空或Null"],      ["Numeric", "必须是数值类型"],      ["StrongPassword", "密码太简单了!!!"]    ]  }}
演练场
- - +

3. 验证消息配置

配置智能提示和校验

如需编写配置的时候提供智能提示和校验,可查看 【2.7 JSON Schema 使用

只需要在 .json 文件头部添加下列配置即可:

{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json"}

3.1 关于配置

验证消息配置指的是 Furion 框架数据校验中验证类型默认消息配置选项。

3.2 配置信息

  • ValidationTypeMessageSettings:配置根节点
    • Definitions:配置验证类型对应的消息类型,[类型名称,类型消息][] 类型,如:["Required", "值不能为空或Null"]

3.3 配置示例

{  "ValidationTypeMessageSettings": {    "Definitions": [      ["Required", "值不能为空或Null"],      ["Numeric", "必须是数值类型"],      ["StrongPassword", "密码太简单了!!!"]    ]  }}
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/signalr/index.html b/handbook/build/docs/signalr/index.html index ac45d2e1ad..06449d496d 100644 --- a/handbook/build/docs/signalr/index.html +++ b/handbook/build/docs/signalr/index.html @@ -2,22 +2,21 @@ - - - + +24. 即时通讯 | Furion -24. 即时通讯 | Furion - - + + +
-

24. 即时通讯

24.1 什么是即时通讯

即时通讯(Instant messaging,简称 IM)通常是指互联网上用以进行实时通讯的系统,允许两人或多人使用网络即时的传递文字信息、文档、语音与视频交流。

即时通讯不同于 e-mail 在于它的交谈是实时的。大部分的即时通讯服务提供了状态信息的特性 ── 显示联络人名单,联络人是否在线上与能否与联络人交谈。

在互联网上目前使用较广的即时通讯服务包括 Windows Live Messenger、AOL Instant Messenger、skype、Yahoo! Messenger、NET Messenger Service、Jabber、ICQ 与 QQ 等。

24.2 即时通讯应用场景

即时通讯应用场景非常广泛,需要实时交互消息的都需要。如:

  • 聊天工具:QQ、WeChat、在线客服等
  • 手游网游:王者荣耀、魔兽等
  • 网络直播:腾讯课堂、抖音直播等
  • 订单推送:美团、餐饮下单系统等
  • 协同办公:公司内部文件分享、工作安排、在线会议等。

以上只是列举了比较常用的应用场景,但即时通讯的作用远不止于此。

文档紧急编写中,可以先看官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction?view=aspnetcore-5.0

24.3 关于 SignalR

即时通讯技术实现是复杂且过于底层化,所以微软为了简化即时通讯应用程序,开发出了一个强大且简易使用的通信库:SignalR,通过该库我们可以轻松实现类似 QQ、微信这类 IM 聊天工具,也能快速实现消息推送、订单推送这样的系统。

24.3.1 微软官方介绍

ASP.NET Core SignalR 是一种开放源代码库,可简化将实时 web 功能添加到应用程序的功能。 实时 web 功能使服务器端代码可以立即将内容推送到客户端。

适用于 SignalR :

  • 需要从服务器进行高频率更新的应用。 示例包括游戏、社交网络、投票、拍卖、地图和 GPS 应用。
  • 仪表板和监视应用。 示例包括公司仪表板、即时销售更新或旅行警报。
  • 协作应用。 协作应用的示例包括白板应用和团队会议软件。
  • 需要通知的应用。 社交网络、电子邮件、聊天、游戏、旅行警报和很多其他应用都需使用通知。

目前 SignalR 已经内置在 .NET 5 SDK 中。同时 SignalR 支持 Web、App、Console、Desktop 等多个应用平台。

24.4 注册 SignalR 服务

Furion 框架中,任何服务功能都需要先注册后再使用,SignalR 也不例外。只需要在 Startup.cs 中添加注册即可:

using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace Furion.Web.Core{    public sealed class Startup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            // 其他代码...            // 添加即时通讯            services.AddSignalR();        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            // 其他代码...            app.UseEndpoints(endpoints =>            {                // 注册集线器                endpoints.MapHubs();                endpoints.MapControllerRoute(                    name: "default",                    pattern: "{controller=Home}/{action=Index}/{id?}");            });        }    }}

24.5 SignalR 长连接和集线器

SignalR 包含两种用于在客户端和服务器之间进行通信的模型:持久性连接集线器 中心。

25.5.1 持久性连接

连接表示用于发送单接收方、分组或广播消息的简单终结点。 持久性连接 (在 .NET 代码中由 PersistentConnection 类表示,在 ASP.NET Core SignalR 中 ,PersistentConnection 类已被删除。) 使开发人员能够直接访问 SignalR 公开的低级别通信协议。 使用基于连接的 Api (如 Windows Communication Foundation)的开发人员将对使用连接通信模型非常熟悉。

24.5.2 集线器

集线器是一种基于连接 API 构建的更高级别管道,它允许客户端和服务器直接调用方法SignalR 就像魔术一样处理跨机器边界的调度,使客户端能够像本地方法一样轻松地调用服务器上的方法,反之亦然。 如果开发人员已使用远程调用 (如 .NET 远程处理),则将对使用中心通信模型非常熟悉。 使用集线器还可以将强类型参数传递给方法,从而启用模型绑定。

小知识

想了解更多关于 持久性连接集线器中心 可查阅 SignalR 官方文档

24.6 集线器 Hub 定义

在本章节中主要推荐使用集线器通信模型方式。这里主要说明 Hub 定义,如果无法理解该通信模型的作用也没关系,接下来的例子会带大家慢慢熟悉并使用。

24.6.1 两种定义方式

定义集线器只需要继承 HubHub<TStrongType> 泛型基类即可,如:

  • Hub 方式
using Furion.InstantMessaging;using Microsoft.AspNetCore.SignalR;namespace Furion.Core{    /// <summary>    /// 聊天集线器    /// </summary>    public class ChatHub : Hub    {        // 定义一个方法供客户端调用        public Task SendMessage(string user, string message)        {            // 触发客户端定义监听的方法            return Clients.All.SendAsync("ReceiveMessage", user, message);        }    }}
  • Hub<TStrongType> 类型方式
public interface IChatClient{    Task ReceiveMessage(string user, string message);}
public class StronglyTypedChatHub : Hub<IChatClient>{    // 定义一个方法供客户端调用    public async Task SendMessage(string user, string message)    {        // 触发客户端定义监听的方法        await Clients.All.ReceiveMessage(user, message);    }}

通过使用 Hub<IChatClient> 可以对客户端方法进行编译时检查。 这可以防止由于使用神奇字符串而导致的问题,因为 Hub<T> 只能提供对在接口中定义的方法的访问。

24.6.2 [MapHub] 配置连接地址

SignalR 库中要求每一个公开的集线器都需要配置客户端连接地址,所以,Furion 框架提供了更加 [MapHub] 配置,如:

using Furion.InstantMessaging;using Microsoft.AspNetCore.SignalR;using System;using System.Threading.Tasks;namespace Furion.Core{    /// <summary>    /// 聊天集线器    /// </summary>    [MapHub("/hubs/chathub")]    public class ChatHub : Hub    {        // ...    }}
SignalR 原生配置方式

Furion 中推荐使用 [MapHub] 方式配置集线器客户端连接地址,当然也可以使用 SignalR 提供的方式,如在 Startup.cs 配置:

public sealed class Startup : AppStartup{   // 其他代码    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    {        // 其他代码...        app.UseEndpoints(endpoints =>        {            // 注册集线器            endpoints.MapHub<ChatHub>("/hubs/chathub");        });    }}

24.6.3 Hub 注册更多配置

有些时候,我们需要注册 Hub 时配置更多参数,比如权限、跨域等,这时只需要在 Hub 派生类中编写以下静态方法即可:

using Furion.InstantMessaging;using Microsoft.AspNetCore.SignalR;using System;using System.Threading.Tasks;namespace Furion.Core{    [MapHub("/hubs/chathub")]    public class ChatHub : Hub    {        // 其他代码        public static void HttpConnectionDispatcherOptionsSettings(HttpConnectionDispatcherOptions options)        {            // 配置        }        public static void HubEndpointConventionBuilderSettings(HubEndpointConventionBuilder Builder)        {            // 配置        }    }}

以上配置等价于 SignalRStartup.cs 中的配置:

app.UseEndpoints(endpoints =>{    var builder = endpoints.MapHub<ChatHub>("/hubs/chathub", options =>       {           // 配置       });});

24.7 服务端和客户端双工通信

24.7.1 触发所有客户端代码

Clients.All.客户端方法(参数);

24.7.2 触发调用者客户端

Clients.Caller.客户端方法(参数);

24.7.3 触发除了调用者以外的客户端

Clients.Others.客户端方法(参数);

24.7.4 触发特定用户客户端

Clients.User("用户").客户端方法(参数);

24.7.5 触发多个用户客户端

Clients.Users("用户","用户2",...).客户端方法(参数);

24.7.6 触发分组内客户端

Clients.Group("分组").客户端方法(参数);

24.7.7 触发多个分组客户端

Clients.Groups("分组","分组2",...).客户端方法(参数);

24.7.8 触发分组外的客户端

Clients.GroupExcept("分组").客户端方法(参数);

24.8 自定义用户唯一标识

默认情况下 SignalR 会为每一个链接创建 ConnectionId,但是这个 ConnectionId 并没有和我们系统的用户绑关联起来,所以需要采用自定义 ConnectionId,如:

public class YourUserIdProvider : IUserIdProvider{    public virtual string GetUserId(HubConnectionContext connection)    {        // 你如何获取 UserId,可以通过 connection.User 获取 JWT 授权的用户    }}

然后在 Startup.cs 中注册即可:

builder.Services.AddSingleton<IUserIdProvider, YourUserIdProvider>();

之后就可以通过自定义 UserId 发送消息:

Clients.User(userId).客户端方法(参数);

查看更多文档 https://docs.microsoft.com/zh-cn/aspnet/core/signalr/authn-and-authz?view=aspnetcore-6.0#use-claims-to-customize-identity-handling

24.9 分组管理

24.10 各个客户端连接 API

24.10.1 Javascript 客户端

24.10.2 Typescript 客户端

vue3.2+ 中使用

  1. 安装微软的 signalr typescript 客户端包,主要用于调用服务端方法,如( Hub 中的 SendMessage 方法):
npm i @microsoft/signalr @types/node
  1. 示例代码
import { HubConnectionBuilder } from "@microsoft/signalr";<script setup lang="ts">    import { HubConnectionBuilder } from "@microsoft/signalr";    import { ref } from "vue";    const messages = ref('');    const reciveMessage = (msg: string) => {        console.log("msg", msg);    }    //初始化signalr HubConnection对象    const connection = new HubConnectionBuilder()        .withUrl("<你的signalr连接地址>")//https://localhost:7260/chatHub        .build();    //启动连接并发送消息测试    connection.start()              .then(() => connection.send("SendMessage", "Hello"));    //注册web端方法以供后端调用    connection.on("ReciveMessage", reciveMessage);    const sendMsg = async () => {        console.log(messages.value);        await connection.send("SendMessage", messages.value).catch(function (err) {            console.log(err);        });    }</script>

参考文档

24.10.3 .NET 客户端

24.10.4 Java 客户端

24.11 常见例子

24.11.1 实现消息广播、推送

整理中...

24.11.2 实现聊天功能

整理中...

24.11.3 实现 你画我来猜

整理中...

24.12 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 SignalR 知识可查阅 SignalR 官方文档ASP.NET Core SignalR 章节。

演练场
- - +

24. 即时通讯

24.1 什么是即时通讯

即时通讯(Instant messaging,简称 IM)通常是指互联网上用以进行实时通讯的系统,允许两人或多人使用网络即时的传递文字信息、文档、语音与视频交流。

即时通讯不同于 e-mail 在于它的交谈是实时的。大部分的即时通讯服务提供了状态信息的特性 ── 显示联络人名单,联络人是否在线上与能否与联络人交谈。

在互联网上目前使用较广的即时通讯服务包括 Windows Live Messenger、AOL Instant Messenger、skype、Yahoo! Messenger、NET Messenger Service、Jabber、ICQ 与 QQ 等。

24.2 即时通讯应用场景

即时通讯应用场景非常广泛,需要实时交互消息的都需要。如:

  • 聊天工具:QQ、WeChat、在线客服等
  • 手游网游:王者荣耀、魔兽等
  • 网络直播:腾讯课堂、抖音直播等
  • 订单推送:美团、餐饮下单系统等
  • 协同办公:公司内部文件分享、工作安排、在线会议等。

以上只是列举了比较常用的应用场景,但即时通讯的作用远不止于此。

文档紧急编写中,可以先看官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction?view=aspnetcore-5.0

24.3 关于 SignalR

即时通讯技术实现是复杂且过于底层化,所以微软为了简化即时通讯应用程序,开发出了一个强大且简易使用的通信库:SignalR,通过该库我们可以轻松实现类似 QQ、微信这类 IM 聊天工具,也能快速实现消息推送、订单推送这样的系统。

24.3.1 微软官方介绍

ASP.NET Core SignalR 是一种开放源代码库,可简化将实时 web 功能添加到应用程序的功能。 实时 web 功能使服务器端代码可以立即将内容推送到客户端。

适用于 SignalR :

  • 需要从服务器进行高频率更新的应用。 示例包括游戏、社交网络、投票、拍卖、地图和 GPS 应用。
  • 仪表板和监视应用。 示例包括公司仪表板、即时销售更新或旅行警报。
  • 协作应用。 协作应用的示例包括白板应用和团队会议软件。
  • 需要通知的应用。 社交网络、电子邮件、聊天、游戏、旅行警报和很多其他应用都需使用通知。

目前 SignalR 已经内置在 .NET 5 SDK 中。同时 SignalR 支持 Web、App、Console、Desktop 等多个应用平台。

24.4 注册 SignalR 服务

Furion 框架中,任何服务功能都需要先注册后再使用,SignalR 也不例外。只需要在 Startup.cs 中添加注册即可:

using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace Furion.Web.Core{    public sealed class Startup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            // 其他代码...            // 添加即时通讯            services.AddSignalR();        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            // 其他代码...            app.UseEndpoints(endpoints =>            {                // 注册集线器                endpoints.MapHubs();                endpoints.MapControllerRoute(                    name: "default",                    pattern: "{controller=Home}/{action=Index}/{id?}");            });        }    }}

24.5 SignalR 长连接和集线器

SignalR 包含两种用于在客户端和服务器之间进行通信的模型:持久性连接集线器 中心。

25.5.1 持久性连接

连接表示用于发送单接收方、分组或广播消息的简单终结点。 持久性连接 (在 .NET 代码中由 PersistentConnection 类表示,在 ASP.NET Core SignalR 中 ,PersistentConnection 类已被删除。) 使开发人员能够直接访问 SignalR 公开的低级别通信协议。 使用基于连接的 Api (如 Windows Communication Foundation)的开发人员将对使用连接通信模型非常熟悉。

24.5.2 集线器

集线器是一种基于连接 API 构建的更高级别管道,它允许客户端和服务器直接调用方法SignalR 就像魔术一样处理跨机器边界的调度,使客户端能够像本地方法一样轻松地调用服务器上的方法,反之亦然。 如果开发人员已使用远程调用 (如 .NET 远程处理),则将对使用中心通信模型非常熟悉。 使用集线器还可以将强类型参数传递给方法,从而启用模型绑定。

小知识

想了解更多关于 持久性连接集线器中心 可查阅 SignalR 官方文档

24.6 集线器 Hub 定义

在本章节中主要推荐使用集线器通信模型方式。这里主要说明 Hub 定义,如果无法理解该通信模型的作用也没关系,接下来的例子会带大家慢慢熟悉并使用。

24.6.1 两种定义方式

定义集线器只需要继承 HubHub<TStrongType> 泛型基类即可,如:

  • Hub 方式
using Furion.InstantMessaging;using Microsoft.AspNetCore.SignalR;namespace Furion.Core{    /// <summary>    /// 聊天集线器    /// </summary>    public class ChatHub : Hub    {        // 定义一个方法供客户端调用        public Task SendMessage(string user, string message)        {            // 触发客户端定义监听的方法            return Clients.All.SendAsync("ReceiveMessage", user, message);        }    }}
  • Hub<TStrongType> 类型方式
public interface IChatClient{    Task ReceiveMessage(string user, string message);}
public class StronglyTypedChatHub : Hub<IChatClient>{    // 定义一个方法供客户端调用    public async Task SendMessage(string user, string message)    {        // 触发客户端定义监听的方法        await Clients.All.ReceiveMessage(user, message);    }}

通过使用 Hub<IChatClient> 可以对客户端方法进行编译时检查。 这可以防止由于使用神奇字符串而导致的问题,因为 Hub<T> 只能提供对在接口中定义的方法的访问。

24.6.2 [MapHub] 配置连接地址

SignalR 库中要求每一个公开的集线器都需要配置客户端连接地址,所以,Furion 框架提供了更加 [MapHub] 配置,如:

using Furion.InstantMessaging;using Microsoft.AspNetCore.SignalR;using System;using System.Threading.Tasks;namespace Furion.Core{    /// <summary>    /// 聊天集线器    /// </summary>    [MapHub("/hubs/chathub")]    public class ChatHub : Hub    {        // ...    }}
SignalR 原生配置方式

Furion 中推荐使用 [MapHub] 方式配置集线器客户端连接地址,当然也可以使用 SignalR 提供的方式,如在 Startup.cs 配置:

public sealed class Startup : AppStartup{   // 其他代码    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    {        // 其他代码...        app.UseEndpoints(endpoints =>        {            // 注册集线器            endpoints.MapHub<ChatHub>("/hubs/chathub");        });    }}

24.6.3 Hub 注册更多配置

有些时候,我们需要注册 Hub 时配置更多参数,比如权限、跨域等,这时只需要在 Hub 派生类中编写以下静态方法即可:

using Furion.InstantMessaging;using Microsoft.AspNetCore.SignalR;using System;using System.Threading.Tasks;namespace Furion.Core{    [MapHub("/hubs/chathub")]    public class ChatHub : Hub    {        // 其他代码        public static void HttpConnectionDispatcherOptionsSettings(HttpConnectionDispatcherOptions options)        {            // 配置        }        public static void HubEndpointConventionBuilderSettings(HubEndpointConventionBuilder Builder)        {            // 配置        }    }}

以上配置等价于 SignalRStartup.cs 中的配置:

app.UseEndpoints(endpoints =>{    var builder = endpoints.MapHub<ChatHub>("/hubs/chathub", options =>       {           // 配置       });});

24.7 服务端和客户端双工通信

24.7.1 触发所有客户端代码

Clients.All.客户端方法(参数);

24.7.2 触发调用者客户端

Clients.Caller.客户端方法(参数);

24.7.3 触发除了调用者以外的客户端

Clients.Others.客户端方法(参数);

24.7.4 触发特定用户客户端

Clients.User("用户").客户端方法(参数);

24.7.5 触发多个用户客户端

Clients.Users("用户","用户2",...).客户端方法(参数);

24.7.6 触发分组内客户端

Clients.Group("分组").客户端方法(参数);

24.7.7 触发多个分组客户端

Clients.Groups("分组","分组2",...).客户端方法(参数);

24.7.8 触发分组外的客户端

Clients.GroupExcept("分组").客户端方法(参数);

24.8 自定义用户唯一标识

默认情况下 SignalR 会为每一个链接创建 ConnectionId,但是这个 ConnectionId 并没有和我们系统的用户绑关联起来,所以需要采用自定义 ConnectionId,如:

public class YourUserIdProvider : IUserIdProvider{    public virtual string GetUserId(HubConnectionContext connection)    {        // 你如何获取 UserId,可以通过 connection.User 获取 JWT 授权的用户    }}

然后在 Startup.cs 中注册即可:

builder.Services.AddSingleton<IUserIdProvider, YourUserIdProvider>();

之后就可以通过自定义 UserId 发送消息:

Clients.User(userId).客户端方法(参数);

查看更多文档 https://docs.microsoft.com/zh-cn/aspnet/core/signalr/authn-and-authz?view=aspnetcore-6.0#use-claims-to-customize-identity-handling

24.9 分组管理

24.10 各个客户端连接 API

24.10.1 Javascript 客户端

24.10.2 Typescript 客户端

vue3.2+ 中使用

  1. 安装微软的 signalr typescript 客户端包,主要用于调用服务端方法,如( Hub 中的 SendMessage 方法):
npm i @microsoft/signalr @types/node
  1. 示例代码
import { HubConnectionBuilder } from "@microsoft/signalr";<script setup lang="ts">    import { HubConnectionBuilder } from "@microsoft/signalr";    import { ref } from "vue";    const messages = ref('');    const reciveMessage = (msg: string) => {        console.log("msg", msg);    }    //初始化signalr HubConnection对象    const connection = new HubConnectionBuilder()        .withUrl("<你的signalr连接地址>")//https://localhost:7260/chatHub        .build();    //启动连接并发送消息测试    connection.start()              .then(() => connection.send("SendMessage", "Hello"));    //注册web端方法以供后端调用    connection.on("ReciveMessage", reciveMessage);    const sendMsg = async () => {        console.log(messages.value);        await connection.send("SendMessage", messages.value).catch(function (err) {            console.log(err);        });    }</script>

参考文档

24.10.3 .NET 客户端

24.10.4 Java 客户端

24.11 常见例子

24.11.1 实现消息广播、推送

整理中...

24.11.2 实现聊天功能

整理中...

24.11.3 实现 你画我来猜

整理中...

24.12 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 SignalR 知识可查阅 SignalR 官方文档ASP.NET Core SignalR 章节。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/singlefile/index.html b/handbook/build/docs/singlefile/index.html index 8b8e3fe9e8..0e4a0be402 100644 --- a/handbook/build/docs/singlefile/index.html +++ b/handbook/build/docs/singlefile/index.html @@ -2,22 +2,21 @@ - - - + +34.5. 单文件发布 | Furion -34.5. 单文件发布 | Furion - - + + +
-

34.5. 单文件发布

版本说明

以下内容仅限 Furion 3.5.2 + 版本使用。

34.5.1 历史背景

.NET Core 3 起,微软就提供了单文件发布的技术支持,但实际上并不是 .NET 所有 CLR 都支持单文件发布,如 Microsoft.Extensions.DependencyModel 包本身不支持单文件发布,原因是内部使用了 Assembley.CodeBase

好巧不巧Furion 中招了,在过去两年中,Furion 依赖该包的 DependencyContext.Default 特性进行程序集扫描,所以单文件发布也就成了 Furion 不愿提起的痛!!!

终于,在 Furion v3.5.2+ 版本想出了新的解决方案,自此彻底解决了单文件发布的问题。

34.5.2 必要配置

Furion v3.5.2+ 版本之后,新增了 ISingleFilePublish 接口。

  • 编辑启动层 .csproj 文件,添加下列代码到 <PropertyGroup> 节点中
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
关于 ReadyToRun

如果发布时未打勾 ReadyToRun 选项,则无需配置上述代码。

  • Web 启动层 创建类型并实现该接口,如:
using System.Reflection;namespace YourProject.Web.Entry;/// <summary>/// 解决单文件发布问题/// </summary>public class SingleFilePublish : ISingleFilePublish{    /// <summary>    /// 解决单文件不能扫描的程序集    /// </summary>    /// <remarks>和 <see cref="IncludeAssemblyNames"/> 可同时配置</remarks>    /// <returns></returns>    public Assembly[] IncludeAssemblies()    {        // 需要 Furion 框架扫描哪些程序集就写上去即可        return Array.Empty<Assembly>();    }    /// <summary>    /// 解决单文件不能扫描的程序集名称    /// </summary>    /// <remarks>和 <see cref="IncludeAssemblies"/> 可同时配置</remarks>    /// <returns></returns>    public string[] IncludeAssemblyNames()    {        // 需要 Furion 框架扫描哪些程序集就写上去即可        return new[]        {            "YourProject.Application",            "YourProject.Core",            "YourProject.EntityFramework.Core",            "YourProject.Web.Core",            "Furion.Extras.ObjectMapper.Mapster"    // 解决 Mapster 单文件失效问题,v3.5.3+版本后无需配置        };    }}
配置说明

IncludeAssembliesIncludeAssemblyNames 的区别是前者是开发者直接返回 Assembley 集合,后者是直接返回名称,Furion 会自动加载程序集,可同时配置,也可以配置其中一个。

如果只配置启用一个,则另外一个返回 Array.Empty<Assembley>()Array.Empty<string>() 即可。

如果发布后出现 Mapster 不能映射问题,可将 Furion.Extras.ObjectMapper.Mapster 添加到 IncludeAssemblyNames 集合中即可。v3.5.3+ 版本后无需配置。

34.5.3 发布

小知识

如无需生成 .pdb 调试包可在生成中禁用即可。

34.5.4 自定义启动端口

默认单文件发布监听的是 https://localhost:5001,如果需要修改,可在 program.cs 中配置:

var builder = WebApplication.CreateBuilder(args).Inject();builder.WebHost.UseUrls("https://*:8089");var app = builder.Build();app.Run();

这样就可以通过 https://localhost:8089 访问。

34.5.5 pm2 守护进程部署

34.5.5.1 运行弊端

正常情况下,将应用程序发布成单文件后,需点击 XXXXX.exe 进行启动,这时候程序自动打开终端(控制台),之后根据提示在浏览器上打开对应的地址即可。

但是这种方式有以下问题:

  • 必须保证终端/控制台一直运行
  • 终端/控制台有时候会出现假死的情况,导致应用程序无法访问
  • 无法实时监听应用程序资源使用情况(如 CPU,内存,日志等)
  • 无法映射端口启动
  • 集群变得复杂

34.5.5.2 pm2 守护进程部署

为了解决上述问题,推荐 NodeJS 一个非常强大的工具 pm2 https://pm2.keymetrics.io/,通过该工具可以解决上述的所有问题。

必要条件

  1. 系统必须安装 NodeJS 环境 https://nodejs.org/en/

相信大部分人电脑都已经安装。

  1. 通过 npmyarn 全局安装 pm2 工具

npm:

npm install pm2@latest -g

yarn:

yarn global add pm2
  1. 启动应用程序

使用 pm2 非常简单就可以启动守护进程应用程序。

pm2 start --name pms PMS.Web.Entry.exe
指定端口

如需指定端口,可使用下列命令:

pm2 start --name pms PMS.Web.Entry.exe -- --urls=https://localhost:8089

注意 -- 后面可以写完整的 dotnet 命令。

命令说明

pms.exe 为项目发布后的启动层名称,如果名称包含 空格,则使用双引号包裹,如 "p ms.exe"

--name 配置应用程序在 pm2 中的唯一标识。

start 后面跟着是 .exe 文件,在 linux/macos 下无需指定后缀名。

启动成功后即可通过浏览器访问指定端口,通常是 http://localhost:5000

PS C:\Users\bqrjsoft\Desktop\pms> pm2 start --name pms PMS.Web.Entry.exe[PM2] Starting C:\Users\bqrjsoft\Desktop\pms\PMS.Web.Entry.exe in fork_mode (1 instance)[PM2] Done.┌─────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐id  │ name   │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │├─────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤0   │ pms    │ default     │ N/A     │ fork    │ 41764    │ 0s     │ 0    │ online    │ 0%       │ 85.0mb   │ bqrjsoft │ disabled │└─────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘PS C:\Users\bqrjsoft\Desktop\pms>

34.5.5.3 pm2 常见操作

  • 实时监听运行状态
pm2 monit
  • 显示运行日志
pm2 logs
  • 查看应用信息
pm2 info pms

注意,pms 为您配置的 --name 名称。

  • 随机启动
pm2 startuppm2 save
Windows 下随即启动

可查阅 pm2-windows-startup

npm install pm2-windows-startup -gpm2-startup installpm2 save
  • 其他操作
// 重启应用pm2 restart app_name// 重载应用pm2 reload app_name// 停止应用pm2 stop app_name// 删除应用pm2 delete app_name

更多 pm2 文档可查阅 https://pm2.keymetrics.io/docs/usage/quick-start/

34.5.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

34.5. 单文件发布

版本说明

以下内容仅限 Furion 3.5.2 + 版本使用。

34.5.1 历史背景

.NET Core 3 起,微软就提供了单文件发布的技术支持,但实际上并不是 .NET 所有 CLR 都支持单文件发布,如 Microsoft.Extensions.DependencyModel 包本身不支持单文件发布,原因是内部使用了 Assembley.CodeBase

好巧不巧Furion 中招了,在过去两年中,Furion 依赖该包的 DependencyContext.Default 特性进行程序集扫描,所以单文件发布也就成了 Furion 不愿提起的痛!!!

终于,在 Furion v3.5.2+ 版本想出了新的解决方案,自此彻底解决了单文件发布的问题。

34.5.2 必要配置

Furion v3.5.2+ 版本之后,新增了 ISingleFilePublish 接口。

  • 编辑启动层 .csproj 文件,添加下列代码到 <PropertyGroup> 节点中
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
关于 ReadyToRun

如果发布时未打勾 ReadyToRun 选项,则无需配置上述代码。

  • Web 启动层 创建类型并实现该接口,如:
using System.Reflection;namespace YourProject.Web.Entry;/// <summary>/// 解决单文件发布问题/// </summary>public class SingleFilePublish : ISingleFilePublish{    /// <summary>    /// 解决单文件不能扫描的程序集    /// </summary>    /// <remarks>和 <see cref="IncludeAssemblyNames"/> 可同时配置</remarks>    /// <returns></returns>    public Assembly[] IncludeAssemblies()    {        // 需要 Furion 框架扫描哪些程序集就写上去即可        return Array.Empty<Assembly>();    }    /// <summary>    /// 解决单文件不能扫描的程序集名称    /// </summary>    /// <remarks>和 <see cref="IncludeAssemblies"/> 可同时配置</remarks>    /// <returns></returns>    public string[] IncludeAssemblyNames()    {        // 需要 Furion 框架扫描哪些程序集就写上去即可        return new[]        {            "YourProject.Application",            "YourProject.Core",            "YourProject.EntityFramework.Core",            "YourProject.Web.Core",            "Furion.Extras.ObjectMapper.Mapster"    // 解决 Mapster 单文件失效问题,v3.5.3+版本后无需配置        };    }}
配置说明

IncludeAssembliesIncludeAssemblyNames 的区别是前者是开发者直接返回 Assembley 集合,后者是直接返回名称,Furion 会自动加载程序集,可同时配置,也可以配置其中一个。

如果只配置启用一个,则另外一个返回 Array.Empty<Assembley>()Array.Empty<string>() 即可。

如果发布后出现 Mapster 不能映射问题,可将 Furion.Extras.ObjectMapper.Mapster 添加到 IncludeAssemblyNames 集合中即可。v3.5.3+ 版本后无需配置。

34.5.3 发布

小知识

如无需生成 .pdb 调试包可在生成中禁用即可。

34.5.4 自定义启动端口

默认单文件发布监听的是 https://localhost:5001,如果需要修改,可在 program.cs 中配置:

var builder = WebApplication.CreateBuilder(args).Inject();builder.WebHost.UseUrls("https://*:8089");var app = builder.Build();app.Run();

这样就可以通过 https://localhost:8089 访问。

34.5.5 pm2 守护进程部署

34.5.5.1 运行弊端

正常情况下,将应用程序发布成单文件后,需点击 XXXXX.exe 进行启动,这时候程序自动打开终端(控制台),之后根据提示在浏览器上打开对应的地址即可。

但是这种方式有以下问题:

  • 必须保证终端/控制台一直运行
  • 终端/控制台有时候会出现假死的情况,导致应用程序无法访问
  • 无法实时监听应用程序资源使用情况(如 CPU,内存,日志等)
  • 无法映射端口启动
  • 集群变得复杂

34.5.5.2 pm2 守护进程部署

为了解决上述问题,推荐 NodeJS 一个非常强大的工具 pm2 https://pm2.keymetrics.io/,通过该工具可以解决上述的所有问题。

必要条件

  1. 系统必须安装 NodeJS 环境 https://nodejs.org/en/

相信大部分人电脑都已经安装。

  1. 通过 npmyarn 全局安装 pm2 工具

npm:

npm install pm2@latest -g

yarn:

yarn global add pm2
  1. 启动应用程序

使用 pm2 非常简单就可以启动守护进程应用程序。

pm2 start --name pms PMS.Web.Entry.exe
指定端口

如需指定端口,可使用下列命令:

pm2 start --name pms PMS.Web.Entry.exe -- --urls=https://localhost:8089

注意 -- 后面可以写完整的 dotnet 命令。

命令说明

pms.exe 为项目发布后的启动层名称,如果名称包含 空格,则使用双引号包裹,如 "p ms.exe"

--name 配置应用程序在 pm2 中的唯一标识。

start 后面跟着是 .exe 文件,在 linux/macos 下无需指定后缀名。

启动成功后即可通过浏览器访问指定端口,通常是 http://localhost:5000

PS C:\Users\bqrjsoft\Desktop\pms> pm2 start --name pms PMS.Web.Entry.exe[PM2] Starting C:\Users\bqrjsoft\Desktop\pms\PMS.Web.Entry.exe in fork_mode (1 instance)[PM2] Done.┌─────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐id  │ name   │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │├─────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤0   │ pms    │ default     │ N/A     │ fork    │ 41764    │ 0s     │ 0    │ online    │ 0%       │ 85.0mb   │ bqrjsoft │ disabled │└─────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘PS C:\Users\bqrjsoft\Desktop\pms>

34.5.5.3 pm2 常见操作

  • 实时监听运行状态
pm2 monit
  • 显示运行日志
pm2 logs
  • 查看应用信息
pm2 info pms

注意,pms 为您配置的 --name 名称。

  • 随机启动
pm2 startuppm2 save
Windows 下随即启动

可查阅 pm2-windows-startup

npm install pm2-windows-startup -gpm2-startup installpm2 save
  • 其他操作
// 重启应用pm2 restart app_name// 重载应用pm2 reload app_name// 停止应用pm2 stop app_name// 删除应用pm2 delete app_name

更多 pm2 文档可查阅 https://pm2.keymetrics.io/docs/usage/quick-start/

34.5.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/source/index.html b/handbook/build/docs/source/index.html index 3e23436b97..ac77d8c705 100644 --- a/handbook/build/docs/source/index.html +++ b/handbook/build/docs/source/index.html @@ -2,22 +2,21 @@ - - - + +1.3 示例架构说明 | Furion -1.3 示例架构说明 | Furion - - + + +
-

1.3 示例架构说明

1.3.1 示例架构

源码仓库中的 samples 示例采用多层分层设计,主要设计是 自动抽象工厂DDD 领域驱动设计 相结合。

Furion 示例项目结构如下:

  • Furion:框架核心层
  • Furion.Application:业务应用层(业务代码主要编写层)
  • Furion.Core:核心层(实体,仓储,其他核心代码)
  • Furion.Database.Migrations:EFCore 架构迁移文件层
  • Furion.EntityFramework.Core:EF Core 配置层
  • Furion.Web.Core:Web 核心层(存放 Web 公共代码,如 过滤器、中间件、Web Helpers 等)
  • Furion.Web.Entry:Web 入口层/启动层

示例地址:https://gitee.com/dotnetchina/Furion/tree/net6/samples

1.3.2 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

1.3 示例架构说明

1.3.1 示例架构

源码仓库中的 samples 示例采用多层分层设计,主要设计是 自动抽象工厂DDD 领域驱动设计 相结合。

Furion 示例项目结构如下:

  • Furion:框架核心层
  • Furion.Application:业务应用层(业务代码主要编写层)
  • Furion.Core:核心层(实体,仓储,其他核心代码)
  • Furion.Database.Migrations:EFCore 架构迁移文件层
  • Furion.EntityFramework.Core:EF Core 配置层
  • Furion.Web.Core:Web 核心层(存放 Web 公共代码,如 过滤器、中间件、Web Helpers 等)
  • Furion.Web.Entry:Web 入口层/启动层

示例地址:https://gitee.com/dotnetchina/Furion/tree/net6/samples

1.3.2 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/specification-document/index.html b/handbook/build/docs/specification-document/index.html index fb519f8f36..f2106ccd53 100644 --- a/handbook/build/docs/specification-document/index.html +++ b/handbook/build/docs/specification-document/index.html @@ -2,22 +2,21 @@ - - - + +6. 规范化接口文档 | Furion -6. 规范化接口文档 | Furion - - + + +
-

6. 规范化接口文档

6.1 什么是接口文档

在现在移动为王、多端互辅、前端百花齐放的开放时代,不再是一人包揽式开发,大家各司其职,后端工程师负责接口开发,前端负责接口联调,也就是互联网现在流行的前后端分离架构。

所以就需要由前后端工程师共同定义接口,编写接口文档,之后大家按照这个接口文档进行开发、维护及开放给第三方。

6.2 为什么要写接口文档

  • 能够让前端开发与后台开发人员更好的配合,提高工作效率
  • 项目迭代或者项目人员更迭时,方便后期人员查看和维护
  • 方便测试人员进行接口测试

6.3 为什么需要规范化文档

由于每个公司后端人员技术参差不齐,技术文档能力也不例外,导致接口定义及文档五花八门,不同项目或不同公司对接极其困难,而且体验糟糕。所以,无规矩不成方圆,为了开发人员间更好的配合,迫切需要整理出一套规范。

通常接口规范分为六个部分:

6.3.1 协议规范

为了确保不同系统/模块间的数据交互,需要事先约定好通讯协议,如:TCP、HTTP、HTTPS 协议。为了确保数据交互安全,建议使用 HTTPS 协议

6.3.2 接口路径规范

作为接口路径,为了方便清晰的区分来自不同的系统,可以采用不同系统/模块名作为接口路径前缀,如:支付模块:/pay/xxx,订单模块:/order/xxx

6.3.3 版本控制规范

为了便于后期接口的升级和维护,建议在接口路径中加入版本号,便于管理,实现接口多版本的可维护性。如:接口路径中添加类似"v1"、"v2"等版本号

6.3.4 接口命名规范

和 C# 命名规范一样,好的、统一的接口命名规范,不仅可以增强其可读性,而且还会减少很多不必要的口头/书面上的解释。可使用"驼峰命名法"按照实现接口的业务类型、业务场景等命名,有必要时可采取多级目录命名,但目录不宜过长,两级目录较为适宜

  • 常见命名方式:
    • 接口名称动词前/后缀化: 接口名称以接口数据操作的动词为前/后缀,常见动词有:Add、Delete、Update、Query、Get、Send、Save、Detail、List等,如:新建用户 AddUser、查询订单详情 QueryOrderDetail
    • 接口名称动词 + 请求方式:接口路径中包含具体接口名称的名词,接口数据操作动作以 HTTP 请求方式来区分。常用的 HTTP 请求方式有:
      • GET:从服务器取出资源(一项或多项)
      • POST:在服务器新建一个资源
      • PUT:在服务器更新资源(客户端提供改变后的完整资源)
      • PATCH:在服务器更新资源(客户端提供改变的属性)
      • DELETE:从服务器删除资源

6.3.5 请求参数规范

  • 请求方式:按照 GET、POST、PUT 等含义定义,避免出现不一致现象,对人造成误解、歧义
    • 请求头:请求头根据项目需求添加配置参数。如:请求数据格式,accept=application/json 等。如有需要,请求头可根据项目需求要求传入用户 token、唯一验签码等加密数据
    • 请求参数/请求体: 请求参数字段,尽可能与数据库表字段、对象属性名等保持一致,因为保持一致是最省事,最舒服的一件事

6.3.6 返回数据规范

统一规范返回数据的格式,对己对彼都有好处,此处以 json 格式为例。返回数据应包含:返回状态码、返回状态信息、具体数据返回数据中的状态码、状态信息,常指具体的业务状态,不建议和 HTTP 状态码混在一起。HTTP 状态,是用来体现 HTTP 链路状态情况,如:404-Not Found。HTTP 状态码和 json 结果中的状态码,并存尚可,用于体现不同维度的状态。

6.4 什么是 Swagger

相信无论是前端还是后端开发,都或多或少地被接口文档折磨过。前端经常抱怨后端给的接口文档与实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新。

其实无论是前端调用后端,还是后端调用后端,都期望有一个好的接口文档。但是这个接口文档对于程序员来说,就跟注释一样,经常会抱怨别人写的代码没有写注释,然而自己写起代码起来,最讨厌的,也是写注释。所以仅仅只通过强制来规范大家是不够的,随着时间推移,版本迭代,接口文档往往很容易就跟不上代码了。

发现了痛点就要去找解决方案。解决方案用的人多了,就成了标准的规范,这就是 Swagger 的由来

通过这套规范,你只需要按照它的规范去定义接口及接口相关的信息。再通过 Swagger 衍生出来的一系列项目和工具,就可以做到生成各种格式的接口文档,生成多种语言的客户端和服务端的代码,以及在线接口调试页面等等。

这样,如果按照新的开发模式,在开发新版本或者迭代版本的时候,只需要更新 Swagger 描述文件,就可以自动生成接口文档和客户端服务端代码,做到调用端代码、服务端代码以及接口文档的一致性。

所以,Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful 风格的 Web 服务。

总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法、参数和模型紧密集成到服务器端的代码,允许 API 来始终保持同步。Swagger 让部署管理和使用功能强大的 API 从未如此简单。

6.5 Swagger 使用

Furion 框架提供了非常方便且灵活的 Swagger 配置,无需增加额外学习成本。

6.5.1 注册服务

备注

.UseInject() 已经包含了 .UseSpecificationDocuments() 注册,无需再次注册。

Furion.Web.Core\FurWebCoreStartup.cs
using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace Furion.Web.Core{    [AppStartup(800)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddSpecificationDocuments();            services.AddControllers();        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            // Other Codes            app.UseSpecificationDocuments();            app.UseEndpoints(endpoints =>            {                endpoints.MapControllers();            });        }    }}
小知识

services.AddSpecificationDocuments() 通常和 .AddDynamicApiControllers() 成对出现。

6.5.2 默认地址

Furion 框架中,默认 规范化文档 地址为 /api 目录,支持自定义配置

如下图所示:

可以通过两种方式配置:

  • app.UseInject("路由") 方式,如
app.UseInject("testapi"); // 那么  /testapi 就是规范化地址
  • 配置文件配置
{  "SpecificationDocumentSettings": {    "RoutePrefix": "testapi"  }}

配置文件优先级大于 UseInject() 方式

6.5.3 默认分组

Furion 框架中默认分组名为 Default支持自定义配置

{  "SpecificationDocumentSettings": {    "DefaultGroupName": "MyGroup"  }}

6.5.4 文档注释

规范化文档默认扫描 Furion.ApplicationFurion.Web.CoreFurion.Web.Entry 三个程序集.xml 注释文件,支持自定义配置

只支持 /// 标识的注释语法,如:类、方法、属性、参数、返回值、验证特性

using Furion.DynamicApiController;namespace Furion.Application{    /// <summary>    /// 类注释    /// </summary>    public class FurionAppService : IDynamicApiController    {        /// <summary>        /// 方法注释        /// </summary>        /// <returns></returns>        public string Get()        {            return nameof(Furion);        }        /// <summary>        /// 带 ID 参数的方法注释        /// </summary>        /// <param name="id"></param>        /// <returns></returns>        public int Get(int id)        {            return id;        }    }}

如下图所示:

小提示

如果文档注释没有显示,请检查项目 属性->生成->输出 中 XML 文档是否配置输出路径。注意:只有不带路径的 【项目名称.xml】 才会自动加载。

特别说明

Debug 模式下和 Release 模式下的注释文件是不通用的,所以导致很多开发者发布到服务器上发现没有显示注释。我们只需要在 Visual Studio 中切换 Debug 模式为 Release,然后重新配置一次即可。

这样不管是 Debug 还是 Release 模式都会显示注释了。

6.5.5 多分组支持

多分组是一个系统中必备功能,我们可以将系统划分为多个模块,每个模块都独立的 api 配置。在 Furion 框架中,实现多分组非常简单。如:

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings("Group1")]    public class FurionAppService : IDynamicApiController    {        /// <summary>        /// 随父类 Group1 分组        /// </summary>        /// <returns></returns>        public string Post()        {            return nameof(Furion);        }        /// <summary>        /// 在 Group1、Group3 都有我        /// </summary>        /// <returns></returns>        [ApiDescriptionSettings("Group1", "Group3")]        public string Get()        {            return nameof(Furion);        }        /// <summary>        /// 我只在 Group2 出现        /// </summary>        /// <param name="id"></param>        /// <returns></returns>        [ApiDescriptionSettings("Group2")]        public int Get(int id)        {            return id;        }    }}

如下图所示:

6.5.6 多分组排序

通过分组名称添加 @整数 进行排序

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings("Group1@1")]    public class FurionAppService : IDynamicApiController    {        public string Post()        {            return nameof(Furion);        }        [ApiDescriptionSettings("Group1", "Group3")]        public string Get()        {            return nameof(Furion);        }        [ApiDescriptionSettings("Group@2")]        public int Get(int id)        {            return id;        }    }}

可以通过在分组名后面添加 @整数 进行排序,整数 越大排前面。如果分组名称多次指定且多次指定了 @整数 ,则自动取该分组最大的整数进行排序。

如下图所示:

排序说明

分组默认排序 Order0。如果同时配置了 @整数appsettings.json 配置文件,那么优先采用 appsettings.json 中的 Order

6.5.7 多分组信息配置

Furion 框架提供了可通过 appsetting.json 配置分组信息:

Furion.Web.Entry/appsettings.json
{  "SpecificationDocumentSettings": {    "GroupOpenApiInfos": [      {        "Group": "Group1",        "Title": "分组标题",        "Description": "这里是分组描述",        "Version": "版本号",        "TermsOfService": "https://furion.icu",        "Contact": {          "Name": "百小僧",          "Url": "https://gitee.com/monksoul",          "Email": "monksoul@outlook.com"        },        "License": {          "Name": "MIT",          "Url": "https://gitee.com/dotnetchina/Furion/blob/alpha/LICENSE"        }      }    ]  }}

如下图所示:

6.5.8 组中组(标签)

Tag 配置主要用于配置 Swagger 标签分组信息及合并标签。也就是 组中组:

未贴标签之前

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }    public class TestAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }}

贴标签之后

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings(Tag = "分组一")]    public class FurionAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }    [ApiDescriptionSettings(Tag = "分组二")]    public class TestAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }}

如下图所示:

小知识

如果 Tag 名字一样,则会自动合并,否则只是命名。

6.5.9 默认展开所有文档

Furion.Web.Entry/appsettings.json
{  "SpecificationDocumentSettings": {    "DocExpansionState": "Full"  }}

如下图所示:

DocExpansionState 配置说明:

  • List:列表式(展开子类),默认值
  • Full:完全展开
  • None:列表式(不展开子类)

6.5.10 配置文档标题

Furion.Web.Entry/appsettings.json
{  "SpecificationDocumentSettings": {    "DocumentTitle": "我是自定义标题"  }}

如下图所示:

6.5.11 授权控制

新版本 Furion 已经默认启用了 Bearer Token 授权配置,无需手动配置,如需手动配置,可手动添加以下类似配置:

Furion.Web.Entry/appsettings.json
{  "SpecificationDocumentSettings": {    "EnableAuthorized": true,    "SecurityDefinitions": [      {        "Id": "Bearer",        "Type": "Http",        "Name": "Authorization",        "Description": "JWT Authorization header using the Bearer scheme.",        "BearerFormat": "JWT",        "Scheme": "bearer",        "In": "Header",        "Requirement": {          "Scheme": {            "Reference": {              "Id": "Bearer",              "Type": "SecurityScheme"            },            "Accesses": []          }        }      }    ]  }}

6.5.12 在线测试

如下图所示:

6.5.13 性能监视 MiniProfiler

规范化文档默认集成了 MiniProfiler 第三方性能组件,通过该组件可以方便查看请求性能、异常堆栈、数据库操作等信息。默认在 Swagger 首页左上角显示。

如下图所示:

小提示

也可以通过 appsetting.jsonAppSettings:InjectMiniProfiler 设为 false 关闭。

6.5.14 定义接口输出类型

using Furion.DynamicApiController;using Microsoft.AspNetCore.Mvc;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [ProducesResponseType(201, Type = typeof(TestDto))]        [ProducesResponseType(400)]        public string Get()        {            return nameof(Furion);        }    }}

如下图所示:

6.5.15 隐藏特定分组

Furion 新版本提供了隐藏分组的 Visible 配置,设置为 false 之后该分组将不显示在规范化文档中,如:

appsetting.json
{  "SpecificationDocumentSettings": {    "GroupOpenApiInfos": [      {        "Group": "Group1",        "Visible": false      }    ]  }}

6.5.16 中文乱码问题

默认情况下,.json 文件并未采用 utf-8 编码,所以如果配置中文分组信息就会出现乱码情况,这时候,只需要修改 .json 文件编码为 utf-8 即可。

6.5.17 生产环境中关闭 Swagger

如果不需要线上环境开启 Swagger 功能,只需要在 appsetting.json 配置即可:

{  "AppSettings": {    "InjectSpecificationDocument": false  }}

6.5.18 设置 Example Value 默认值

Swagger 会自动根据对象类型输入参数添加 Example Value 默认值,但是该默认值通常是对象属性的类型字符串或缺省值,如果我们需要自定义这些默认值,只需要添加 /// <example>默认值</example> 注释即可。

如:

/// <summary>/// 年龄/// </summary>/// <example>13</example>[Required, Range(10, 110)]public int Age { get; set; }

如下图所示:

更多类型默认值设置示例:

  • bool 类型:/// <example>true</example>
  • string 类型:/// <example>foobar</example>
  • number 类型:/// <example>123</example>
  • null 类型: /// <example>null</example>
  • array 类型:/// <example>[ 1, 2, 3 ]</example>
关于 object 类型输入参数

默认情况下,Example Value 不会显示 object 类型的对象属性,因为 Swagger 认为这是不合理的定义。如果需要强制显示,只需要添加 /// <example>"object"</example> 注释即可。

6.5.19 自定义 Swagger 配置

Furion 框架除了内置了不少配置以外,还提供了直接配置 Swagger Api 的参数,如:

public void ConfigureServices(IServiceCollection services){    services.AddInject(options =>    {        options.SpecificationDocument = spt =>        {            spt.SwaggerGen = gen =>            {                // 配置 Swagger Gen            };        };    });}
 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {      app.UseInject(configure: options =>      {          options.SpecificationDocument = spt =>          {              spt.Swagger = swg =>              {                  // 配置 Swagger Options              };              spt.SwaggerUI = ui =>              {                  // 配置 Swagger UI              };          };      });}

6.5.20 配置 SwaggerSchemes

Furion 框架默认只显示名称,如果需要自定义显示规则,只需要添加配置即可。

services.AddControllersWithViews()        .AddInject(options =>        {            options.SpecificationDocument = spt =>            {                spt.SwaggerGen = gen =>                {                    gen.CustomSchemaIds(x => x.FullName);                };            };        });

6.5.21 自定义 swagger.json 路由模板

默认情况下,Furion 框架会生成统一的分组模板,如:swagger/{documentName}/swagger.json{documentName} 会在运行时替换为分组名,如需自定义,配置 RouteTemplate 即可:

appsetting.json
{  "SpecificationDocumentSettings": {    "RouteTemplate": "myapp/{documentName}/xxxx.json"  }}

6.5.22 关于 application/x-www-form-urlencoded 请求

默认情况下,Swagger 并未添加 application/x-www-form-urlencoded 支持,如需启用该配置,只需在方法顶部贴 [Consumes] 特性即可,如:

[Consumes("application/x-www-form-urlencoded")]public async Task<IActionResult> Test([FromForm] TestRequest testRequest){  // ....}public class TestRequest{   public string TestValue { get; set; }}
特别注意

参数必须贴 [FromForm] 特性。另外请求时将参数按 URL 地址拼接并放在 Body 中请求。

6.5.23 Swagger 出现 CORS 问题解决

如果 Swagger 出现以下错误,如图:

则需要添加以下配置:

{  "SpecificationDocumentSettings": {    "HideServers": true  }}

6.5.24 Swagger 出现默认 xml 参数问题解决

产生此原因有两个必要条件:

  1. 使用了 Microsoft.AspNetCore.Mvc.NewtonsoftJson 包并添加了 AddNewtonsoftJson() 注册。
  2. .AddNewtonsoftJson() 写在了 .AddInjectWithUnifyResult() 后面。

所以解决方法是,先注册 .AddNewtonsoftJson() 再注册规范化结果,如:

services.AddControllers()        .AddNewtonsoftJson()        .AddInjectWithUnifyResult();

6.5.25 Swagger 多语言支持

Furion 2.9.0 + 版本已经支持了 Swagger 文档地址 ?culture=en-US 参数多语言转发功能了,也就是 Swagger 地址带 ?culture= 参数将自动添加到每一个请求的 api 地址中。

6.5.26 自定义逻辑控制 Swagger 每一个 api 可见性

有时候我们需要自定义 Swagger 接口可见性,比如根据权限,不同用户类型,各种逻辑控制,如:

// 也可以用 .AddInjectWithUnifyResultservices.AddInject(options =>{    options.SpecificationDocument = spt =>    {        spt.SwaggerGen = gen =>        {            gen.DocInclusionPredicate((currentGroup, apiDescription) =>            {                // Furion 内部检查,必须放第一行                var isShow = SpecificationDocumentBuilder.CheckApiDescriptionInCurrentGroup(currentGroup, apiDescription);                // 获取当前方法                _ = apiDescription.TryGetMethodInfo(out var method);                // 有了方法,这里做你想做的事情,isShow 设置 true 可见,设置 false 不可见                return isShow;            });        };    };});

6.5.27 配置 MVC 控制器支持规范化处理

{  "UnifyResultSettings": {    "SupportMvcController": true  }}

6.5.28 Swagger 刷新记住授权状态

默认情况下,Swagger 刷新浏览器后,授权状态将被重置,也就是需要重新登录,通过下面代码在 用户登录成功后 调用即可:

// ....验证用户名/密码...._httpContextAccessor.HttpContext.SigninToSwagger("传入 token");

6.5.29 带登录的 Swagger 文档

版本说明

以下内容仅限 Furion v3.3.3+ 版本使用。

默认情况下,Swagger 是任何人都可以访问的,这样也暴露出一些安全问题,所以在该版本之后添加了登录功能,只需要配置 SpecificationDocumentSettingsLoginInfo 即可:

{  "SpecificationDocumentSettings": {    "LoginInfo": {      "Enabled": true,      "CheckUrl": "/Home/CheckUrl",      "SubmitUrl": "/Home/SubmitUrl",      "UserName": "admin",      "Password": "admin"    }  }}

配置说明

  • LoginInfo:配置 Swagger 是否需要登录才能访问,SpecificationLoginInfo 类型,默认 null仅在 Furion v3.3.3+` 有效
    • Enabled:是否启用登录授权,默认 false
    • CheckUrl:检查登录状态的 Url 地址,该地址必须是 POST 请求,已授权返回 200,否则返回 401,支持相对地址,以 / 开头
    • SubmitUrl:提交登录的 Url 地址,该地址必须是 POST 请求且只有一个 SpecificationAuth 类型参数,成功登录返回 200,否则返回 401,支持相对地址,以 / 开头

配置示例

using Furion.SpecificationDocument;using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Mvc;using System.ComponentModel.DataAnnotations;namespace Furion.Web.Entry.Controllers;public class HomeController : Controller{    [HttpPost, AllowAnonymous, NonUnify]    public int CheckUrl()    {        return 401;    }    [HttpPost, AllowAnonymous, NonUnify]    public int SubmitUrl([FromForm] SpecificationAuth auth)    {        // 读取配置信息        var userName = App.Configuration["SpecificationDocumentSettings:LoginInfo:UserName"];        var password = App.Configuration["SpecificationDocumentSettings:LoginInfo:Password"];        if (auth.UserName == userName && auth.Password == password)        {            return 200;        }        else        {            return 401;        }    }}

6.5.30 inheritdoc 实现注释继承

版本说明

以下内容仅限 Furion v3.3.3+ 版本使用。

在过去我们在接口定义的时候编写了完整的成员注释,然后在派生成员中又要重复写一次,实际上做了很大无用功,现在 Furion 支持了注释继承了,同时 Swagger 中也能正确显示。

using Furion.DynamicApiController;namespace Furion.Application{    /// <inheritdoc cref="ITestInheritdoc" />    public class TestInheritdoc : ITestInheritdoc, IDynamicApiController    {        /// <inheritdoc cref="ITestInheritdoc.GetName"/>        public string GetName()        {            return "Furion";        }        /// <inheritdoc />        public string GetVersion()        {            return "3.3.3";        }    }    /// <summary>    /// 测试注释继承    /// </summary>    public interface ITestInheritdoc    {        /// <summary>        /// 获取名称        /// </summary>        /// <returns></returns>        string GetName();        /// <summary>        /// 获取版本        /// </summary>        /// <returns></returns>        string GetVersion();    }}

显示效果:

注意事项

<inheritdoc /> 不指定 cref 仅限成员可用且所在的类型必须指定 <inheritdoc cref="" />,这样才能自动识别。

6.5.31 启用 All Groups 分组功能

版本说明

以下内容仅限 Furion v3.3.4+ 版本使用。

有时候我们为了更好的对接口进行归类,配置了 Swagger 多个分组的功能,但这样也对生成客户端请求代码造成了困扰,所以添加了新的配置:

{  "SpecificationDocumentSettings": {    "EnableAllGroups": true  }}

6.5.32 接口过时控制

版本说明

以下内容仅限 Furion v3.3.5+ 版本使用。

有时候我们某个接口已经过时,提示尽早调用最新接口,只需要在方法上面贴 [Obsolete] 即可,如:

[Obsolete("GetName() 已经过时,请调用 GetFrameworkName() 替代")]public string GetName(){  return nameof(Furion);}[Obsolete]public string Other(){  // ...}

6.5.33 单一接口更多描述

版本说明

以下内容仅限 Furion v3.3.5+ 版本使用。

在该版本新增了 [ApiDescriptionSettings]Description 属性,支持定义更多描述,如:

[ApiDescriptionSettings(Description = "我是一段描述,显示更多内容 <button>我是按钮</button>")]public string add(){  //....}

6.5.34 Swagger 异常/不能显示/错误处理

有时候可能因为错误的配置导致 Swagger 不能显示,这时候只需要复制提示的错误 .json 链接地址到浏览器中访问即可,如:

https://localhost:你的端口/swagger/Default/swagger.json

后面的 /swagger/Default/swagger.json 就是 Swagger 错误提示的 .json 链接地址。

这样就可以看到详细的错误了。

6.5.35 自定义 SwaggerSchemaId

版本说明

以下内容仅限 Furion v3.6.4+ 版本使用。

有时候,不同程序集会定义相同的类型名称 Name,这样就会导致生成 SwaggerSchemaId 出现冲突,这时只需要在类型上贴 [SchemaId] 特性即可,如:

using Furion.SpecificationDocument;[SchemaId("Other_")]public class PersonDto{  // ...}
  • SchemaIdAttribute 配置选项:
    • SchemaId:自定义 SchemaId,字符串类型,只能是 字母,数字,下划线 组合
    • Replace:是否完全替换,bool 类型,默认 false,默认是作为前缀拼接,如上面的 PersonDto 会生成 Other_PersonDto,如果设置为 true,则直接使用 Test_

6.5.36 自定义 SwaggerOperationId

版本说明

以下内容仅限 Furion 4.1.7+ 版本使用。

通过我们根据 swagger.json 生成前端代码时,Swagger 会自动根据路由地址生成调用的 api 名称,但这样的名称往往不易读,这时候可自定义 [OperationId] 来配置生成的前端名称。

using Furion.SpecificationDocument;public class PersonDto{  [OperationId("MyClientMethodName")]  public string TestMethod()  {    // ...  }}

6.5.37 Swagger 接口文档支持完整的 Markdown

Furion 最新版中,支持了完整的 Markdown 注册,如:

/// <summary>/// 测试 Markdown/// </summary>/// <remarks>/// # 先知 / Furion ([探索版](https://gitee.com/dotnetchina/Furion/tree/experimental/))//////     一个应用程序框架,您可以将它集成到任何.NET/C# 应用程序中。////// An application framework that you can integrate into any.NET/C# application.////// ## 安装 / Installation////// - [Package Manager] (https://www.nuget.org/packages/Furion)////// ```powershell/// Install-Package Furion/// ```////// - [.NET CLI] (https://www.nuget.org/packages/Furion)////// ```powershell/// dotnet add package Furion/// ```////// ## 例子 / Examples////// 我们在[主页](https://dotnetchina.gitee.io/furion)上有不少例子,这是让您入门的第一个:////// We have several examples [on the website] (https://dotnetchina.gitee.io/furion). Here is the first one to get you started:////// ```cs/// Serve.Run();//////     [DynamicApiController]///     public class HelloService///     {///         public string Say()///         {///             return "Hello, Furion";///         }///     }/// ```////// 打开浏览器访问 `https://localhost:5001`。////// Open browser access `https://localhost:5001`.////// ## 文档 / Documentation////// 您可以在[主页] (https://dotnetchina.gitee.io/furion)或[备份主页](https://furion.icu)找到 Furion 文档。////// You can find the Furion documentation[on the website](https://dotnetchina.gitee.io/furion) or [on the backup website](https://furion.icu).////// ## 贡献 / Contributing////// 该存储库的主要目的是继续发展 Furion 核心,使其更快、更易于使用。 Furion 的开发在[Gitee](https://gitee.com/dotnetchina/Furion) 上公开进行,我们感谢社区贡献错误修复和改进。////// 阅读[贡献指南] (https://dotnetchina.gitee.io/furion/docs/contribute)内容,了解如何参与改进 Furion。////// The main purpose of this repository is to continue evolving Furion core, making it faster and easier to use.Development of Furion happens in the open on[Gitee] (https://gitee.com/dotnetchina/Furion), and we are grateful to the community for contributing bugfixes and improvements.////// Read[contribution documents] (https://dotnetchina.gitee.io/furion/docs/contribute) to learn how you can take part in improving Furion.////// ## 许可证 / License////// Furion 采用[MIT](https://gitee.com/dotnetchina/Furion/blob/net6/LICENSE) 开源许可证。////// Furion uses the[MIT] (https://gitee.com/dotnetchina/Furion/blob/net6/LICENSE) open source license.////// ```/// Copyright(c) 2020-2022 百小僧, Baiqian Co., Ltd./// Furion is licensed under Mulan PSL v2./// You can use this software according to the terms andconditions of the Mulan PSL v2./// You may obtain a copy of Mulan PSL v2 at:///             https://gitee.com/dotnetchina/Furion/blob/net6/LICENSE/// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUTWARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE./// See the Mulan PSL v2 for more details./// ```////// </remarks>/// <returns></returns>public string Hello(){    return "Furion";}

6.6 SpecificationDocumentSettings 配置

除了上述例子外,Furion 提供了一些配置选项,如:

  • DocumentTitle:文档标题,string,默认 Specification Api Document
  • DefaultGroupName:默认分组名,string,默认 Default
  • EnableAuthorized:是否启用权限控制,bool,默认 true
  • FormatAsV2:采用 Swagger 2.0 版本,bool,默认 false 已弃用
  • RoutePrefix:规范化文档地址,string,默认 api如果希望在首页,改为空字符串即可
  • DocExpansionState:文档显示方式,DocExpansion,默认 List,取值:
    • List:列表式(展开子类),默认值
    • Full:完全展开
    • None:列表式(不展开子类)
  • XmlComments:程序集注释描述文件名(可带 .xmlstring,默认 Furion.Application, Furion.Web.Entry, Furion.Web.Core
  • GroupOpenApiInfos:分组信息配置,SpecificationOpenApiInfo[],默认 { 'Group': 'Default'}
  • SecurityDefinitions:安全策略定义配置,SpecificationOpenApiSecurityScheme[],默认 []
  • Servers:配置 Server 下拉列表,OpenApiServer[] 类型,默认 [],如:{Servers:[ { Url:"地址", Description:"描述"} ]}
  • HideServers:是否隐藏 Server 下拉列表,bool 类型,默认 true
  • RouteTemplate:配置文档 swagger.json 路由模板,默认模板:swagger/{documentName}/swagger.json, {documentName} 代表分组名,必须保留原样
  • PackagesGroups:配置模块化内置分组名称,string[] 类型,默认 []
  • EnableEnumSchemaFilter:启用枚举 Schema 筛选器,bool 类型,默认 true
  • EnableTagsOrderDocumentFilter:启用标签排序筛选器,bool 类型,默认 true
  • ServerDir:配置 IIS 添加 Application 部署名,string 类型,默认空,仅在 Furion v3.2.0+` 有效
  • LoginInfo:配置 Swagger 是否需要登录才能访问,SpecificationLoginInfo 类型,默认 null仅在 Furion v3.3.3+` 有效
    • Enabled:是否启用登录授权,默认 false
    • CheckUrl:检查登录状态的 Url 地址,该地址必须是 POST 请求,已授权返回 200,否则返回 401
    • SubmitUrl:提交登录的 Url 地址,该地址必须是 POST 请求且只有一个 SpecificationAuth 类型参数,成功登录返回 200,否则返回 401,支持相对地址,以 / 开头
  • EnableAllGroups:启用 Swagger 总分组功能,自动将所有分组的接口合并到 All Groups 中,bool 类型,默认 false仅在 Furion v3.3.4+` 有效

另外 SpecificationOpenApiInfo 内置配置如下:

  • Group:分组唯一标识,string 类型,必填
  • Order:分组排序,int 类型,数字越大排前面,默认 0
  • Visible:配置分组是否可见,bool 类型,默认 true
  • Title:配置分组标题,string 类型
  • Description:配置分组描述,string 类型
  • Version:配置分组版本,默认 1.0
  • TermsOfService:配置相关链接地址,Uri 类型
  • Contact:配置联系方式,OpenApiContact 类型
  • License:配置协议,OpenApiLicense 类型

配置示例:

{  "SpecificationDocumentSettings": {    "GroupOpenApiInfos": [      {        "Group": "Group1",        "Title": "分组标题",        "Description": "这里是分组描述",        "Version": "版本号",        "TermsOfService": "https://furion.icu",        "Contact": {          "Name": "百小僧",          "Url": "https://gitee.com/monksoul",          "Email": "monksoul@outlook.com"        },        "License": {          "Name": "MIT",          "Url": "https://gitee.com/dotnetchina/Furion/blob/alpha/LICENSE"        }      }    ]  }}

6.7 统一返回值模型/规范化结果/API 返回值

Furion 框架提供 规范化结果 功能,可以通过实现 IUnifyResultProvider 提供器实现统一规范化返回值定制,如:

  • 定义结果包装类型
// 必须是泛型类型public class YourRESTfulResult<T>{    /// <summary>    /// 状态码    /// </summary>    public int? StatusCode { get; set; }    /// <summary>    /// 数据    /// </summary>    public T Data { get; set; }    /// <summary>    /// 执行成功    /// </summary>    public bool Succeeded { get; set; }    /// <summary>    /// 错误信息    /// </summary>    public object Errors { get; set; }    /// <summary>    /// 附加数据    /// </summary>    public object Extras { get; set; }    /// <summary>    /// 时间戳    /// </summary>    public long Timestamp { get; set; }}
  • 定义 IUnifyResultProvider 实现类,并贴特性 [UnifyModel(typeof(YourRESTfulResult<>))]
using Furion.DataValidation;using Furion.DependencyInjection;using Furion.UnifyResult.Internal;using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.Filters;using System;using System.Threading.Tasks;namespace YourProject.UnifyResult{    /// <summary>    /// RESTful 风格返回值    /// </summary>    [UnifyModel(typeof(YourRESTfulResult<>))]    public class YourRESTfulResultProvider  : IUnifyResultProvider    {        /// <summary>        /// 异常返回值        /// </summary>        /// <param name="context"></param>        /// <param name="metadata"></param>        /// <returns></returns>        public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata)        {            return new JsonResult(YourRESTfulResult(metadata.StatusCode, errors: metadata.Errors));        }        /// <summary>        /// 成功返回值        /// </summary>        /// <param name="context"></param>        /// <param name="data"></param>        /// <returns></returns>        public IActionResult OnSucceeded(ActionExecutedContext context, object data)        {            return new JsonResult(YourRESTfulResult(StatusCodes.Status200OK, true, data));        }        /// <summary>        /// 验证失败返回值        /// </summary>        /// <param name="context"></param>        /// <param name="metadata"></param>        /// <returns></returns>        public IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata)        {            return new JsonResult(YourRESTfulResult(metadata.StatusCode ?? StatusCodes.Status400BadRequest, errors: metadata.ValidationResult));        }        /// <summary>        /// 特定状态码返回值        /// </summary>        /// <param name="context"></param>        /// <param name="statusCode"></param>        /// <param name="unifyResultSettings"></param>        /// <returns></returns>        public async Task OnResponseStatusCodes(HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings)        {            // 设置响应状态码            UnifyContext.SetResponseStatusCodes(context, statusCode, unifyResultSettings);            switch (statusCode)            {                // 处理 401 状态码                case StatusCodes.Status401Unauthorized:                    await context.Response.WriteAsJsonAsync(YourRESTfulResult(statusCode, errors: "401 Unauthorized")                        , App.GetOptions<JsonOptions>()?.JsonSerializerOptions);                    break;                // 处理 403 状态码                case StatusCodes.Status403Forbidden:                    await context.Response.WriteAsJsonAsync(YourRESTfulResult(statusCode, errors: "403 Forbidden")                        , App.GetOptions<JsonOptions>()?.JsonSerializerOptions);                    break;                default: break;            }        }        /// <summary>        /// 返回 RESTful 风格结果集        /// </summary>        /// <param name="statusCode"></param>        /// <param name="succeeded"></param>        /// <param name="data"></param>        /// <param name="errors"></param>        /// <returns></returns>        private static YourRESTfulResult<object> YourRESTfulResult(int statusCode, bool succeeded = default, object data = default, object errors = default)        {            return new YourRESTfulResult<object>            {                StatusCode = statusCode,                Succeeded = succeeded,                Data = data,                Errors = errors,                Extras = UnifyContext.Take(),                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()            };        }    }}

之后在 Startup.cs 中注册即可:

services.AddControllers()        .AddInjectWithUnifyResult<YourRESTfulResultProvider>();
特别注意

默认情况下,规范化结果不会对 401403404 状态码进行规范化处理,如需启动该状态码处理,只需在 Startup.cs 中的 Configure 中启用接口:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env){    if (env.IsDevelopment())    {        app.UseDeveloperExceptionPage();    }    // 添加规范化结果状态码,需要在这里注册    app.UseUnifyResultStatusCodes();    // 其他注册...}

6.7.1 排除规范化处理

有些时候,我们某些接口不需要进行规范化处理,这时,我们只需要帖 [NonUnify] 特性即可。

6.7.2 规范化结果添加额外数据

默认的规范化结果中包含 extras 属性,可以配置额外数据返回到客户端:

UnifyContext.Fill(new { Message = "操作成功" });

6.7.3 自定义特别接口规范化结果

有些时候,我们特定接口需返回特定的接口类型,无需规范化处理,这时候我们只需要贴 [UnifyResult(typeof(结果类))][ProducesResponseType(typeof(结果类),200)],如:

[UnifyResult(typeof(Person))]public Person GetPerson(int id){  // ...}

6.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

6. 规范化接口文档

6.1 什么是接口文档

在现在移动为王、多端互辅、前端百花齐放的开放时代,不再是一人包揽式开发,大家各司其职,后端工程师负责接口开发,前端负责接口联调,也就是互联网现在流行的前后端分离架构。

所以就需要由前后端工程师共同定义接口,编写接口文档,之后大家按照这个接口文档进行开发、维护及开放给第三方。

6.2 为什么要写接口文档

  • 能够让前端开发与后台开发人员更好的配合,提高工作效率
  • 项目迭代或者项目人员更迭时,方便后期人员查看和维护
  • 方便测试人员进行接口测试

6.3 为什么需要规范化文档

由于每个公司后端人员技术参差不齐,技术文档能力也不例外,导致接口定义及文档五花八门,不同项目或不同公司对接极其困难,而且体验糟糕。所以,无规矩不成方圆,为了开发人员间更好的配合,迫切需要整理出一套规范。

通常接口规范分为六个部分:

6.3.1 协议规范

为了确保不同系统/模块间的数据交互,需要事先约定好通讯协议,如:TCP、HTTP、HTTPS 协议。为了确保数据交互安全,建议使用 HTTPS 协议

6.3.2 接口路径规范

作为接口路径,为了方便清晰的区分来自不同的系统,可以采用不同系统/模块名作为接口路径前缀,如:支付模块:/pay/xxx,订单模块:/order/xxx

6.3.3 版本控制规范

为了便于后期接口的升级和维护,建议在接口路径中加入版本号,便于管理,实现接口多版本的可维护性。如:接口路径中添加类似"v1"、"v2"等版本号

6.3.4 接口命名规范

和 C# 命名规范一样,好的、统一的接口命名规范,不仅可以增强其可读性,而且还会减少很多不必要的口头/书面上的解释。可使用"驼峰命名法"按照实现接口的业务类型、业务场景等命名,有必要时可采取多级目录命名,但目录不宜过长,两级目录较为适宜

  • 常见命名方式:
    • 接口名称动词前/后缀化: 接口名称以接口数据操作的动词为前/后缀,常见动词有:Add、Delete、Update、Query、Get、Send、Save、Detail、List等,如:新建用户 AddUser、查询订单详情 QueryOrderDetail
    • 接口名称动词 + 请求方式:接口路径中包含具体接口名称的名词,接口数据操作动作以 HTTP 请求方式来区分。常用的 HTTP 请求方式有:
      • GET:从服务器取出资源(一项或多项)
      • POST:在服务器新建一个资源
      • PUT:在服务器更新资源(客户端提供改变后的完整资源)
      • PATCH:在服务器更新资源(客户端提供改变的属性)
      • DELETE:从服务器删除资源

6.3.5 请求参数规范

  • 请求方式:按照 GET、POST、PUT 等含义定义,避免出现不一致现象,对人造成误解、歧义
    • 请求头:请求头根据项目需求添加配置参数。如:请求数据格式,accept=application/json 等。如有需要,请求头可根据项目需求要求传入用户 token、唯一验签码等加密数据
    • 请求参数/请求体: 请求参数字段,尽可能与数据库表字段、对象属性名等保持一致,因为保持一致是最省事,最舒服的一件事

6.3.6 返回数据规范

统一规范返回数据的格式,对己对彼都有好处,此处以 json 格式为例。返回数据应包含:返回状态码、返回状态信息、具体数据返回数据中的状态码、状态信息,常指具体的业务状态,不建议和 HTTP 状态码混在一起。HTTP 状态,是用来体现 HTTP 链路状态情况,如:404-Not Found。HTTP 状态码和 json 结果中的状态码,并存尚可,用于体现不同维度的状态。

6.4 什么是 Swagger

相信无论是前端还是后端开发,都或多或少地被接口文档折磨过。前端经常抱怨后端给的接口文档与实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新。

其实无论是前端调用后端,还是后端调用后端,都期望有一个好的接口文档。但是这个接口文档对于程序员来说,就跟注释一样,经常会抱怨别人写的代码没有写注释,然而自己写起代码起来,最讨厌的,也是写注释。所以仅仅只通过强制来规范大家是不够的,随着时间推移,版本迭代,接口文档往往很容易就跟不上代码了。

发现了痛点就要去找解决方案。解决方案用的人多了,就成了标准的规范,这就是 Swagger 的由来

通过这套规范,你只需要按照它的规范去定义接口及接口相关的信息。再通过 Swagger 衍生出来的一系列项目和工具,就可以做到生成各种格式的接口文档,生成多种语言的客户端和服务端的代码,以及在线接口调试页面等等。

这样,如果按照新的开发模式,在开发新版本或者迭代版本的时候,只需要更新 Swagger 描述文件,就可以自动生成接口文档和客户端服务端代码,做到调用端代码、服务端代码以及接口文档的一致性。

所以,Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful 风格的 Web 服务。

总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法、参数和模型紧密集成到服务器端的代码,允许 API 来始终保持同步。Swagger 让部署管理和使用功能强大的 API 从未如此简单。

6.5 Swagger 使用

Furion 框架提供了非常方便且灵活的 Swagger 配置,无需增加额外学习成本。

6.5.1 注册服务

备注

.UseInject() 已经包含了 .UseSpecificationDocuments() 注册,无需再次注册。

Furion.Web.Core\FurWebCoreStartup.cs
using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;namespace Furion.Web.Core{    [AppStartup(800)]    public sealed class FurWebCoreStartup : AppStartup    {        public void ConfigureServices(IServiceCollection services)        {            services.AddSpecificationDocuments();            services.AddControllers();        }        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            // Other Codes            app.UseSpecificationDocuments();            app.UseEndpoints(endpoints =>            {                endpoints.MapControllers();            });        }    }}
小知识

services.AddSpecificationDocuments() 通常和 .AddDynamicApiControllers() 成对出现。

6.5.2 默认地址

Furion 框架中,默认 规范化文档 地址为 /api 目录,支持自定义配置

如下图所示:

可以通过两种方式配置:

  • app.UseInject("路由") 方式,如
app.UseInject("testapi"); // 那么  /testapi 就是规范化地址
  • 配置文件配置
{  "SpecificationDocumentSettings": {    "RoutePrefix": "testapi"  }}

配置文件优先级大于 UseInject() 方式

6.5.3 默认分组

Furion 框架中默认分组名为 Default支持自定义配置

{  "SpecificationDocumentSettings": {    "DefaultGroupName": "MyGroup"  }}

6.5.4 文档注释

规范化文档默认扫描 Furion.ApplicationFurion.Web.CoreFurion.Web.Entry 三个程序集.xml 注释文件,支持自定义配置

只支持 /// 标识的注释语法,如:类、方法、属性、参数、返回值、验证特性

using Furion.DynamicApiController;namespace Furion.Application{    /// <summary>    /// 类注释    /// </summary>    public class FurionAppService : IDynamicApiController    {        /// <summary>        /// 方法注释        /// </summary>        /// <returns></returns>        public string Get()        {            return nameof(Furion);        }        /// <summary>        /// 带 ID 参数的方法注释        /// </summary>        /// <param name="id"></param>        /// <returns></returns>        public int Get(int id)        {            return id;        }    }}

如下图所示:

小提示

如果文档注释没有显示,请检查项目 属性->生成->输出 中 XML 文档是否配置输出路径。注意:只有不带路径的 【项目名称.xml】 才会自动加载。

特别说明

Debug 模式下和 Release 模式下的注释文件是不通用的,所以导致很多开发者发布到服务器上发现没有显示注释。我们只需要在 Visual Studio 中切换 Debug 模式为 Release,然后重新配置一次即可。

这样不管是 Debug 还是 Release 模式都会显示注释了。

6.5.5 多分组支持

多分组是一个系统中必备功能,我们可以将系统划分为多个模块,每个模块都独立的 api 配置。在 Furion 框架中,实现多分组非常简单。如:

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings("Group1")]    public class FurionAppService : IDynamicApiController    {        /// <summary>        /// 随父类 Group1 分组        /// </summary>        /// <returns></returns>        public string Post()        {            return nameof(Furion);        }        /// <summary>        /// 在 Group1、Group3 都有我        /// </summary>        /// <returns></returns>        [ApiDescriptionSettings("Group1", "Group3")]        public string Get()        {            return nameof(Furion);        }        /// <summary>        /// 我只在 Group2 出现        /// </summary>        /// <param name="id"></param>        /// <returns></returns>        [ApiDescriptionSettings("Group2")]        public int Get(int id)        {            return id;        }    }}

如下图所示:

6.5.6 多分组排序

通过分组名称添加 @整数 进行排序

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings("Group1@1")]    public class FurionAppService : IDynamicApiController    {        public string Post()        {            return nameof(Furion);        }        [ApiDescriptionSettings("Group1", "Group3")]        public string Get()        {            return nameof(Furion);        }        [ApiDescriptionSettings("Group@2")]        public int Get(int id)        {            return id;        }    }}

可以通过在分组名后面添加 @整数 进行排序,整数 越大排前面。如果分组名称多次指定且多次指定了 @整数 ,则自动取该分组最大的整数进行排序。

如下图所示:

排序说明

分组默认排序 Order0。如果同时配置了 @整数appsettings.json 配置文件,那么优先采用 appsettings.json 中的 Order

6.5.7 多分组信息配置

Furion 框架提供了可通过 appsetting.json 配置分组信息:

Furion.Web.Entry/appsettings.json
{  "SpecificationDocumentSettings": {    "GroupOpenApiInfos": [      {        "Group": "Group1",        "Title": "分组标题",        "Description": "这里是分组描述",        "Version": "版本号",        "TermsOfService": "https://furion.icu",        "Contact": {          "Name": "百小僧",          "Url": "https://gitee.com/monksoul",          "Email": "monksoul@outlook.com"        },        "License": {          "Name": "MIT",          "Url": "https://gitee.com/dotnetchina/Furion/blob/alpha/LICENSE"        }      }    ]  }}

如下图所示:

6.5.8 组中组(标签)

Tag 配置主要用于配置 Swagger 标签分组信息及合并标签。也就是 组中组:

未贴标签之前

using Furion.DynamicApiController;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }    public class TestAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }}

贴标签之后

using Furion.DynamicApiController;namespace Furion.Application{    [ApiDescriptionSettings(Tag = "分组一")]    public class FurionAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }    [ApiDescriptionSettings(Tag = "分组二")]    public class TestAppService : IDynamicApiController    {        public string Get()        {            return nameof(Furion);        }        public int Get(int id)        {            return id;        }    }}

如下图所示:

小知识

如果 Tag 名字一样,则会自动合并,否则只是命名。

6.5.9 默认展开所有文档

Furion.Web.Entry/appsettings.json
{  "SpecificationDocumentSettings": {    "DocExpansionState": "Full"  }}

如下图所示:

DocExpansionState 配置说明:

  • List:列表式(展开子类),默认值
  • Full:完全展开
  • None:列表式(不展开子类)

6.5.10 配置文档标题

Furion.Web.Entry/appsettings.json
{  "SpecificationDocumentSettings": {    "DocumentTitle": "我是自定义标题"  }}

如下图所示:

6.5.11 授权控制

新版本 Furion 已经默认启用了 Bearer Token 授权配置,无需手动配置,如需手动配置,可手动添加以下类似配置:

Furion.Web.Entry/appsettings.json
{  "SpecificationDocumentSettings": {    "EnableAuthorized": true,    "SecurityDefinitions": [      {        "Id": "Bearer",        "Type": "Http",        "Name": "Authorization",        "Description": "JWT Authorization header using the Bearer scheme.",        "BearerFormat": "JWT",        "Scheme": "bearer",        "In": "Header",        "Requirement": {          "Scheme": {            "Reference": {              "Id": "Bearer",              "Type": "SecurityScheme"            },            "Accesses": []          }        }      }    ]  }}

6.5.12 在线测试

如下图所示:

6.5.13 性能监视 MiniProfiler

规范化文档默认集成了 MiniProfiler 第三方性能组件,通过该组件可以方便查看请求性能、异常堆栈、数据库操作等信息。默认在 Swagger 首页左上角显示。

如下图所示:

小提示

也可以通过 appsetting.jsonAppSettings:InjectMiniProfiler 设为 false 关闭。

6.5.14 定义接口输出类型

using Furion.DynamicApiController;using Microsoft.AspNetCore.Mvc;namespace Furion.Application{    public class FurionAppService : IDynamicApiController    {        [ProducesResponseType(201, Type = typeof(TestDto))]        [ProducesResponseType(400)]        public string Get()        {            return nameof(Furion);        }    }}

如下图所示:

6.5.15 隐藏特定分组

Furion 新版本提供了隐藏分组的 Visible 配置,设置为 false 之后该分组将不显示在规范化文档中,如:

appsetting.json
{  "SpecificationDocumentSettings": {    "GroupOpenApiInfos": [      {        "Group": "Group1",        "Visible": false      }    ]  }}

6.5.16 中文乱码问题

默认情况下,.json 文件并未采用 utf-8 编码,所以如果配置中文分组信息就会出现乱码情况,这时候,只需要修改 .json 文件编码为 utf-8 即可。

6.5.17 生产环境中关闭 Swagger

如果不需要线上环境开启 Swagger 功能,只需要在 appsetting.json 配置即可:

{  "AppSettings": {    "InjectSpecificationDocument": false  }}

6.5.18 设置 Example Value 默认值

Swagger 会自动根据对象类型输入参数添加 Example Value 默认值,但是该默认值通常是对象属性的类型字符串或缺省值,如果我们需要自定义这些默认值,只需要添加 /// <example>默认值</example> 注释即可。

如:

/// <summary>/// 年龄/// </summary>/// <example>13</example>[Required, Range(10, 110)]public int Age { get; set; }

如下图所示:

更多类型默认值设置示例:

  • bool 类型:/// <example>true</example>
  • string 类型:/// <example>foobar</example>
  • number 类型:/// <example>123</example>
  • null 类型: /// <example>null</example>
  • array 类型:/// <example>[ 1, 2, 3 ]</example>
关于 object 类型输入参数

默认情况下,Example Value 不会显示 object 类型的对象属性,因为 Swagger 认为这是不合理的定义。如果需要强制显示,只需要添加 /// <example>"object"</example> 注释即可。

6.5.19 自定义 Swagger 配置

Furion 框架除了内置了不少配置以外,还提供了直接配置 Swagger Api 的参数,如:

public void ConfigureServices(IServiceCollection services){    services.AddInject(options =>    {        options.SpecificationDocument = spt =>        {            spt.SwaggerGen = gen =>            {                // 配置 Swagger Gen            };        };    });}
 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {      app.UseInject(configure: options =>      {          options.SpecificationDocument = spt =>          {              spt.Swagger = swg =>              {                  // 配置 Swagger Options              };              spt.SwaggerUI = ui =>              {                  // 配置 Swagger UI              };          };      });}

6.5.20 配置 SwaggerSchemes

Furion 框架默认只显示名称,如果需要自定义显示规则,只需要添加配置即可。

services.AddControllersWithViews()        .AddInject(options =>        {            options.SpecificationDocument = spt =>            {                spt.SwaggerGen = gen =>                {                    gen.CustomSchemaIds(x => x.FullName);                };            };        });

6.5.21 自定义 swagger.json 路由模板

默认情况下,Furion 框架会生成统一的分组模板,如:swagger/{documentName}/swagger.json{documentName} 会在运行时替换为分组名,如需自定义,配置 RouteTemplate 即可:

appsetting.json
{  "SpecificationDocumentSettings": {    "RouteTemplate": "myapp/{documentName}/xxxx.json"  }}

6.5.22 关于 application/x-www-form-urlencoded 请求

默认情况下,Swagger 并未添加 application/x-www-form-urlencoded 支持,如需启用该配置,只需在方法顶部贴 [Consumes] 特性即可,如:

[Consumes("application/x-www-form-urlencoded")]public async Task<IActionResult> Test([FromForm] TestRequest testRequest){  // ....}public class TestRequest{   public string TestValue { get; set; }}
特别注意

参数必须贴 [FromForm] 特性。另外请求时将参数按 URL 地址拼接并放在 Body 中请求。

6.5.23 Swagger 出现 CORS 问题解决

如果 Swagger 出现以下错误,如图:

则需要添加以下配置:

{  "SpecificationDocumentSettings": {    "HideServers": true  }}

6.5.24 Swagger 出现默认 xml 参数问题解决

产生此原因有两个必要条件:

  1. 使用了 Microsoft.AspNetCore.Mvc.NewtonsoftJson 包并添加了 AddNewtonsoftJson() 注册。
  2. .AddNewtonsoftJson() 写在了 .AddInjectWithUnifyResult() 后面。

所以解决方法是,先注册 .AddNewtonsoftJson() 再注册规范化结果,如:

services.AddControllers()        .AddNewtonsoftJson()        .AddInjectWithUnifyResult();

6.5.25 Swagger 多语言支持

Furion 2.9.0 + 版本已经支持了 Swagger 文档地址 ?culture=en-US 参数多语言转发功能了,也就是 Swagger 地址带 ?culture= 参数将自动添加到每一个请求的 api 地址中。

6.5.26 自定义逻辑控制 Swagger 每一个 api 可见性

有时候我们需要自定义 Swagger 接口可见性,比如根据权限,不同用户类型,各种逻辑控制,如:

// 也可以用 .AddInjectWithUnifyResultservices.AddInject(options =>{    options.SpecificationDocument = spt =>    {        spt.SwaggerGen = gen =>        {            gen.DocInclusionPredicate((currentGroup, apiDescription) =>            {                // Furion 内部检查,必须放第一行                var isShow = SpecificationDocumentBuilder.CheckApiDescriptionInCurrentGroup(currentGroup, apiDescription);                // 获取当前方法                _ = apiDescription.TryGetMethodInfo(out var method);                // 有了方法,这里做你想做的事情,isShow 设置 true 可见,设置 false 不可见                return isShow;            });        };    };});

6.5.27 配置 MVC 控制器支持规范化处理

{  "UnifyResultSettings": {    "SupportMvcController": true  }}

6.5.28 Swagger 刷新记住授权状态

默认情况下,Swagger 刷新浏览器后,授权状态将被重置,也就是需要重新登录,通过下面代码在 用户登录成功后 调用即可:

// ....验证用户名/密码...._httpContextAccessor.HttpContext.SigninToSwagger("传入 token");

6.5.29 带登录的 Swagger 文档

版本说明

以下内容仅限 Furion v3.3.3+ 版本使用。

默认情况下,Swagger 是任何人都可以访问的,这样也暴露出一些安全问题,所以在该版本之后添加了登录功能,只需要配置 SpecificationDocumentSettingsLoginInfo 即可:

{  "SpecificationDocumentSettings": {    "LoginInfo": {      "Enabled": true,      "CheckUrl": "/Home/CheckUrl",      "SubmitUrl": "/Home/SubmitUrl",      "UserName": "admin",      "Password": "admin"    }  }}

配置说明

  • LoginInfo:配置 Swagger 是否需要登录才能访问,SpecificationLoginInfo 类型,默认 null仅在 Furion v3.3.3+` 有效
    • Enabled:是否启用登录授权,默认 false
    • CheckUrl:检查登录状态的 Url 地址,该地址必须是 POST 请求,已授权返回 200,否则返回 401,支持相对地址,以 / 开头
    • SubmitUrl:提交登录的 Url 地址,该地址必须是 POST 请求且只有一个 SpecificationAuth 类型参数,成功登录返回 200,否则返回 401,支持相对地址,以 / 开头

配置示例

using Furion.SpecificationDocument;using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Mvc;using System.ComponentModel.DataAnnotations;namespace Furion.Web.Entry.Controllers;public class HomeController : Controller{    [HttpPost, AllowAnonymous, NonUnify]    public int CheckUrl()    {        return 401;    }    [HttpPost, AllowAnonymous, NonUnify]    public int SubmitUrl([FromForm] SpecificationAuth auth)    {        // 读取配置信息        var userName = App.Configuration["SpecificationDocumentSettings:LoginInfo:UserName"];        var password = App.Configuration["SpecificationDocumentSettings:LoginInfo:Password"];        if (auth.UserName == userName && auth.Password == password)        {            return 200;        }        else        {            return 401;        }    }}

6.5.30 inheritdoc 实现注释继承

版本说明

以下内容仅限 Furion v3.3.3+ 版本使用。

在过去我们在接口定义的时候编写了完整的成员注释,然后在派生成员中又要重复写一次,实际上做了很大无用功,现在 Furion 支持了注释继承了,同时 Swagger 中也能正确显示。

using Furion.DynamicApiController;namespace Furion.Application{    /// <inheritdoc cref="ITestInheritdoc" />    public class TestInheritdoc : ITestInheritdoc, IDynamicApiController    {        /// <inheritdoc cref="ITestInheritdoc.GetName"/>        public string GetName()        {            return "Furion";        }        /// <inheritdoc />        public string GetVersion()        {            return "3.3.3";        }    }    /// <summary>    /// 测试注释继承    /// </summary>    public interface ITestInheritdoc    {        /// <summary>        /// 获取名称        /// </summary>        /// <returns></returns>        string GetName();        /// <summary>        /// 获取版本        /// </summary>        /// <returns></returns>        string GetVersion();    }}

显示效果:

注意事项

<inheritdoc /> 不指定 cref 仅限成员可用且所在的类型必须指定 <inheritdoc cref="" />,这样才能自动识别。

6.5.31 启用 All Groups 分组功能

版本说明

以下内容仅限 Furion v3.3.4+ 版本使用。

有时候我们为了更好的对接口进行归类,配置了 Swagger 多个分组的功能,但这样也对生成客户端请求代码造成了困扰,所以添加了新的配置:

{  "SpecificationDocumentSettings": {    "EnableAllGroups": true  }}

6.5.32 接口过时控制

版本说明

以下内容仅限 Furion v3.3.5+ 版本使用。

有时候我们某个接口已经过时,提示尽早调用最新接口,只需要在方法上面贴 [Obsolete] 即可,如:

[Obsolete("GetName() 已经过时,请调用 GetFrameworkName() 替代")]public string GetName(){  return nameof(Furion);}[Obsolete]public string Other(){  // ...}

6.5.33 单一接口更多描述

版本说明

以下内容仅限 Furion v3.3.5+ 版本使用。

在该版本新增了 [ApiDescriptionSettings]Description 属性,支持定义更多描述,如:

[ApiDescriptionSettings(Description = "我是一段描述,显示更多内容 <button>我是按钮</button>")]public string add(){  //....}

6.5.34 Swagger 异常/不能显示/错误处理

有时候可能因为错误的配置导致 Swagger 不能显示,这时候只需要复制提示的错误 .json 链接地址到浏览器中访问即可,如:

https://localhost:你的端口/swagger/Default/swagger.json

后面的 /swagger/Default/swagger.json 就是 Swagger 错误提示的 .json 链接地址。

这样就可以看到详细的错误了。

6.5.35 自定义 SwaggerSchemaId

版本说明

以下内容仅限 Furion v3.6.4+ 版本使用。

有时候,不同程序集会定义相同的类型名称 Name,这样就会导致生成 SwaggerSchemaId 出现冲突,这时只需要在类型上贴 [SchemaId] 特性即可,如:

using Furion.SpecificationDocument;[SchemaId("Other_")]public class PersonDto{  // ...}
  • SchemaIdAttribute 配置选项:
    • SchemaId:自定义 SchemaId,字符串类型,只能是 字母,数字,下划线 组合
    • Replace:是否完全替换,bool 类型,默认 false,默认是作为前缀拼接,如上面的 PersonDto 会生成 Other_PersonDto,如果设置为 true,则直接使用 Test_

6.5.36 自定义 SwaggerOperationId

版本说明

以下内容仅限 Furion 4.1.7+ 版本使用。

通过我们根据 swagger.json 生成前端代码时,Swagger 会自动根据路由地址生成调用的 api 名称,但这样的名称往往不易读,这时候可自定义 [OperationId] 来配置生成的前端名称。

using Furion.SpecificationDocument;public class PersonDto{  [OperationId("MyClientMethodName")]  public string TestMethod()  {    // ...  }}

6.5.37 Swagger 接口文档支持完整的 Markdown

Furion 最新版中,支持了完整的 Markdown 注册,如:

/// <summary>/// 测试 Markdown/// </summary>/// <remarks>/// # 先知 / Furion ([探索版](https://gitee.com/dotnetchina/Furion/tree/experimental/))//////     一个应用程序框架,您可以将它集成到任何.NET/C# 应用程序中。////// An application framework that you can integrate into any.NET/C# application.////// ## 安装 / Installation////// - [Package Manager] (https://www.nuget.org/packages/Furion)////// ```powershell/// Install-Package Furion/// ```////// - [.NET CLI] (https://www.nuget.org/packages/Furion)////// ```powershell/// dotnet add package Furion/// ```////// ## 例子 / Examples////// 我们在[主页](https://dotnetchina.gitee.io/furion)上有不少例子,这是让您入门的第一个:////// We have several examples [on the website] (https://dotnetchina.gitee.io/furion). Here is the first one to get you started:////// ```cs/// Serve.Run();//////     [DynamicApiController]///     public class HelloService///     {///         public string Say()///         {///             return "Hello, Furion";///         }///     }/// ```////// 打开浏览器访问 `https://localhost:5001`。////// Open browser access `https://localhost:5001`.////// ## 文档 / Documentation////// 您可以在[主页] (https://dotnetchina.gitee.io/furion)或[备份主页](https://furion.icu)找到 Furion 文档。////// You can find the Furion documentation[on the website](https://dotnetchina.gitee.io/furion) or [on the backup website](https://furion.icu).////// ## 贡献 / Contributing////// 该存储库的主要目的是继续发展 Furion 核心,使其更快、更易于使用。 Furion 的开发在[Gitee](https://gitee.com/dotnetchina/Furion) 上公开进行,我们感谢社区贡献错误修复和改进。////// 阅读[贡献指南] (https://dotnetchina.gitee.io/furion/docs/contribute)内容,了解如何参与改进 Furion。////// The main purpose of this repository is to continue evolving Furion core, making it faster and easier to use.Development of Furion happens in the open on[Gitee] (https://gitee.com/dotnetchina/Furion), and we are grateful to the community for contributing bugfixes and improvements.////// Read[contribution documents] (https://dotnetchina.gitee.io/furion/docs/contribute) to learn how you can take part in improving Furion.////// ## 许可证 / License////// Furion 采用[MIT](https://gitee.com/dotnetchina/Furion/blob/net6/LICENSE) 开源许可证。////// Furion uses the[MIT] (https://gitee.com/dotnetchina/Furion/blob/net6/LICENSE) open source license.////// ```/// Copyright(c) 2020-2022 百小僧, Baiqian Co., Ltd./// Furion is licensed under Mulan PSL v2./// You can use this software according to the terms andconditions of the Mulan PSL v2./// You may obtain a copy of Mulan PSL v2 at:///             https://gitee.com/dotnetchina/Furion/blob/net6/LICENSE/// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUTWARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE./// See the Mulan PSL v2 for more details./// ```////// </remarks>/// <returns></returns>public string Hello(){    return "Furion";}

6.6 SpecificationDocumentSettings 配置

除了上述例子外,Furion 提供了一些配置选项,如:

  • DocumentTitle:文档标题,string,默认 Specification Api Document
  • DefaultGroupName:默认分组名,string,默认 Default
  • EnableAuthorized:是否启用权限控制,bool,默认 true
  • FormatAsV2:采用 Swagger 2.0 版本,bool,默认 false 已弃用
  • RoutePrefix:规范化文档地址,string,默认 api如果希望在首页,改为空字符串即可
  • DocExpansionState:文档显示方式,DocExpansion,默认 List,取值:
    • List:列表式(展开子类),默认值
    • Full:完全展开
    • None:列表式(不展开子类)
  • XmlComments:程序集注释描述文件名(可带 .xmlstring,默认 Furion.Application, Furion.Web.Entry, Furion.Web.Core
  • GroupOpenApiInfos:分组信息配置,SpecificationOpenApiInfo[],默认 { 'Group': 'Default'}
  • SecurityDefinitions:安全策略定义配置,SpecificationOpenApiSecurityScheme[],默认 []
  • Servers:配置 Server 下拉列表,OpenApiServer[] 类型,默认 [],如:{Servers:[ { Url:"地址", Description:"描述"} ]}
  • HideServers:是否隐藏 Server 下拉列表,bool 类型,默认 true
  • RouteTemplate:配置文档 swagger.json 路由模板,默认模板:swagger/{documentName}/swagger.json, {documentName} 代表分组名,必须保留原样
  • PackagesGroups:配置模块化内置分组名称,string[] 类型,默认 []
  • EnableEnumSchemaFilter:启用枚举 Schema 筛选器,bool 类型,默认 true
  • EnableTagsOrderDocumentFilter:启用标签排序筛选器,bool 类型,默认 true
  • ServerDir:配置 IIS 添加 Application 部署名,string 类型,默认空,仅在 Furion v3.2.0+` 有效
  • LoginInfo:配置 Swagger 是否需要登录才能访问,SpecificationLoginInfo 类型,默认 null仅在 Furion v3.3.3+` 有效
    • Enabled:是否启用登录授权,默认 false
    • CheckUrl:检查登录状态的 Url 地址,该地址必须是 POST 请求,已授权返回 200,否则返回 401
    • SubmitUrl:提交登录的 Url 地址,该地址必须是 POST 请求且只有一个 SpecificationAuth 类型参数,成功登录返回 200,否则返回 401,支持相对地址,以 / 开头
  • EnableAllGroups:启用 Swagger 总分组功能,自动将所有分组的接口合并到 All Groups 中,bool 类型,默认 false仅在 Furion v3.3.4+` 有效

另外 SpecificationOpenApiInfo 内置配置如下:

  • Group:分组唯一标识,string 类型,必填
  • Order:分组排序,int 类型,数字越大排前面,默认 0
  • Visible:配置分组是否可见,bool 类型,默认 true
  • Title:配置分组标题,string 类型
  • Description:配置分组描述,string 类型
  • Version:配置分组版本,默认 1.0
  • TermsOfService:配置相关链接地址,Uri 类型
  • Contact:配置联系方式,OpenApiContact 类型
  • License:配置协议,OpenApiLicense 类型

配置示例:

{  "SpecificationDocumentSettings": {    "GroupOpenApiInfos": [      {        "Group": "Group1",        "Title": "分组标题",        "Description": "这里是分组描述",        "Version": "版本号",        "TermsOfService": "https://furion.icu",        "Contact": {          "Name": "百小僧",          "Url": "https://gitee.com/monksoul",          "Email": "monksoul@outlook.com"        },        "License": {          "Name": "MIT",          "Url": "https://gitee.com/dotnetchina/Furion/blob/alpha/LICENSE"        }      }    ]  }}

6.7 统一返回值模型/规范化结果/API 返回值

Furion 框架提供 规范化结果 功能,可以通过实现 IUnifyResultProvider 提供器实现统一规范化返回值定制,如:

  • 定义结果包装类型
// 必须是泛型类型public class YourRESTfulResult<T>{    /// <summary>    /// 状态码    /// </summary>    public int? StatusCode { get; set; }    /// <summary>    /// 数据    /// </summary>    public T Data { get; set; }    /// <summary>    /// 执行成功    /// </summary>    public bool Succeeded { get; set; }    /// <summary>    /// 错误信息    /// </summary>    public object Errors { get; set; }    /// <summary>    /// 附加数据    /// </summary>    public object Extras { get; set; }    /// <summary>    /// 时间戳    /// </summary>    public long Timestamp { get; set; }}
  • 定义 IUnifyResultProvider 实现类,并贴特性 [UnifyModel(typeof(YourRESTfulResult<>))]
using Furion.DataValidation;using Furion.DependencyInjection;using Furion.UnifyResult.Internal;using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.Filters;using System;using System.Threading.Tasks;namespace YourProject.UnifyResult{    /// <summary>    /// RESTful 风格返回值    /// </summary>    [UnifyModel(typeof(YourRESTfulResult<>))]    public class YourRESTfulResultProvider  : IUnifyResultProvider    {        /// <summary>        /// 异常返回值        /// </summary>        /// <param name="context"></param>        /// <param name="metadata"></param>        /// <returns></returns>        public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata)        {            return new JsonResult(YourRESTfulResult(metadata.StatusCode, errors: metadata.Errors));        }        /// <summary>        /// 成功返回值        /// </summary>        /// <param name="context"></param>        /// <param name="data"></param>        /// <returns></returns>        public IActionResult OnSucceeded(ActionExecutedContext context, object data)        {            return new JsonResult(YourRESTfulResult(StatusCodes.Status200OK, true, data));        }        /// <summary>        /// 验证失败返回值        /// </summary>        /// <param name="context"></param>        /// <param name="metadata"></param>        /// <returns></returns>        public IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata)        {            return new JsonResult(YourRESTfulResult(metadata.StatusCode ?? StatusCodes.Status400BadRequest, errors: metadata.ValidationResult));        }        /// <summary>        /// 特定状态码返回值        /// </summary>        /// <param name="context"></param>        /// <param name="statusCode"></param>        /// <param name="unifyResultSettings"></param>        /// <returns></returns>        public async Task OnResponseStatusCodes(HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings)        {            // 设置响应状态码            UnifyContext.SetResponseStatusCodes(context, statusCode, unifyResultSettings);            switch (statusCode)            {                // 处理 401 状态码                case StatusCodes.Status401Unauthorized:                    await context.Response.WriteAsJsonAsync(YourRESTfulResult(statusCode, errors: "401 Unauthorized")                        , App.GetOptions<JsonOptions>()?.JsonSerializerOptions);                    break;                // 处理 403 状态码                case StatusCodes.Status403Forbidden:                    await context.Response.WriteAsJsonAsync(YourRESTfulResult(statusCode, errors: "403 Forbidden")                        , App.GetOptions<JsonOptions>()?.JsonSerializerOptions);                    break;                default: break;            }        }        /// <summary>        /// 返回 RESTful 风格结果集        /// </summary>        /// <param name="statusCode"></param>        /// <param name="succeeded"></param>        /// <param name="data"></param>        /// <param name="errors"></param>        /// <returns></returns>        private static YourRESTfulResult<object> YourRESTfulResult(int statusCode, bool succeeded = default, object data = default, object errors = default)        {            return new YourRESTfulResult<object>            {                StatusCode = statusCode,                Succeeded = succeeded,                Data = data,                Errors = errors,                Extras = UnifyContext.Take(),                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()            };        }    }}

之后在 Startup.cs 中注册即可:

services.AddControllers()        .AddInjectWithUnifyResult<YourRESTfulResultProvider>();
特别注意

默认情况下,规范化结果不会对 401403404 状态码进行规范化处理,如需启动该状态码处理,只需在 Startup.cs 中的 Configure 中启用接口:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env){    if (env.IsDevelopment())    {        app.UseDeveloperExceptionPage();    }    // 添加规范化结果状态码,需要在这里注册    app.UseUnifyResultStatusCodes();    // 其他注册...}

6.7.1 排除规范化处理

有些时候,我们某些接口不需要进行规范化处理,这时,我们只需要帖 [NonUnify] 特性即可。

6.7.2 规范化结果添加额外数据

默认的规范化结果中包含 extras 属性,可以配置额外数据返回到客户端:

UnifyContext.Fill(new { Message = "操作成功" });

6.7.3 自定义特别接口规范化结果

有些时候,我们特定接口需返回特定的接口类型,无需规范化处理,这时候我们只需要贴 [UnifyResult(typeof(结果类))][ProducesResponseType(typeof(结果类),200)],如:

[UnifyResult(typeof(Person))]public Person GetPerson(int id){  // ...}

6.8 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/split-db/index.html b/handbook/build/docs/split-db/index.html index e353db8876..07d2077858 100644 --- a/handbook/build/docs/split-db/index.html +++ b/handbook/build/docs/split-db/index.html @@ -2,24 +2,23 @@ - - - + +9.28 分表分库 | Furion -9.28 分表分库 | Furion - - + + +
-

9.28 分表分库

特此声明

本章 9.28.29.28.5 小节挪用博主:雨点的名字分库分表 - 理论 博客内容。特此声明。

9.28.1 应用场景

数据库中的数据量不一定是可控的,在未进行分库分表的情况下,随着时间和业务的发展,库中的表会越来越多,表中的数据量也会越来越大,相应地,数据操作增删改查的开销也会越来越大。

另外,由于无法进行分布式部署,而一台服务器的资源(CPU、磁盘、内存、IO 等)是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈。

这个时候就需要对数据库或数据表进行拆分。

数据切分可以分为:垂直切分水平切分

9.28.2 垂直切分

垂直切分又可以分为: 垂直分库和垂直分表。

9.28.2.1 垂直分库

根据业务耦合性,将关联度低的不同表存储在不同的数据库。做法与大系统拆分为多个小系统类似,按业务分类进行独立划分。与"微服务治理"的做法相似,每个微服务使用单独的一个数据库。

说明

一开始我们是单体服务,所以只有一个数据库,所有的表都在这个库里。

后来因为业务需求,单体服务变成微服务治理。所以将之前的一个商品库,拆分成多个数据库。每个微服务对于一个数据库。

9.28.2.2 垂直分表

把一个表的多个字段分别拆成多个表,一般按字段的冷热拆分,热字段一个表,冷字段一个表。从而提升了数据库性能。

说明

一开始商品表中包含商品的所有字段,但是我们发现:

1.商品详情和商品属性字段较长。2.商品列表的时候我们是不需要显示商品详情和商品属性信息,只有在点进商品商品的时候才会展示商品详情信息。

所以可以考虑把商品详情和商品属性单独切分一张表,提高查询效率。

9.28.2.3 优缺点

  • 优点

    • 解决业务系统层面的耦合,业务清晰
    • 与微服务的治理类似,也能对不同业务的数据进行分级管理、维护、监控、扩展等
    • 高并发场景下,垂直切分一定程度的提升 IO、数据库连接数、单机硬件资源的瓶颈
  • 缺点

    • 分库后无法 Join,只能通过接口聚合方式解决,提升了开发的复杂度
    • 分库后分布式事务处理复杂
    • 依然存在单表数据量过大的问题(需要水平切分)

9.28.3 水平切分

当一个应用难以再细粒度的垂直切分或切分后数据量行数巨大,存在单库读写、存储性能瓶颈,这时候就需要进行水平切分了。

水平切分也可以分为:水平分库和水平分表。

9.28.3.1 水平分库

上面虽然已经把商品库分成 3 个库,但是随着业务的增加一个订单库也出现 QPS 过高,数据库响应速度来不及,一般 mysql 单机也就 1000 左右的 QPS,如果超过 1000 就要考虑分库。

9.28.3.2 水平分表

一般我们一张表的数据不要超过 1 千万,如果表数据超过 1 千万,并且还在不断增加数据,那就可以考虑分表。

9.28.3.3 优缺点

  • 优点

    • 不存在单库数据量过大、高并发的性能瓶颈,提升系统稳定性和负载能力
    • 应用端改造较小,不需要拆分业务模块
  • 缺点

    • 跨分片的事务一致性难以保证
    • 跨库的 Join 关联查询性能较差
    • 数据多次扩展难度和维护量极大

9.28.4 数据分片规则

我们考虑去水平切分表,将一张表水平切分成多张表,这就涉及到数据分片的规则,比较常见的有:Hash 取模分表、数值 Range 分表、一致性 Hash 算法分表。

9.28.4.1 Hash 取模分表

一般采用 Hash 取模的切分方式,例如:假设按 goods_id 分 4 张表。(goods_id%4 取整确定表)

优缺点

- - + + \ No newline at end of file diff --git a/handbook/build/docs/sqlsugar-old/index.html b/handbook/build/docs/sqlsugar-old/index.html index 3946e98d18..d4b0ae9fe5 100644 --- a/handbook/build/docs/sqlsugar-old/index.html +++ b/handbook/build/docs/sqlsugar-old/index.html @@ -2,23 +2,22 @@ - - - + +10.1. SqlSugar 集成 | Furion -10.1. SqlSugar 集成 | Furion - - + + +
-

10.1. SqlSugar 集成

温馨提醒

Furion 包中默认集成了 EFCore如果不使用 EFCore,可安装纯净版 Furion.Pure 代替 Furion,这样可以忽略本章节直接按照 SqlSugar 官方文档使用

10.1.1 关于 SqlSugar

SqlSugar 是 .NET/C# 平台非常优秀的 ORM 框架,目前 Nuget 总下载突破 700K,Github 关注量也高达 3.2K,是目前当之无愧的国产优秀 ORM 框架之一。

SqlSugar 官方地址:http://www.donet5.com/

SqlSugar 与 EF 优势: 性能比 EF 更快、语法上手更容易

SqlSugar 与 Dapper 优势: SqlSugar 功能更加丰富,性能丝毫不逊色于 Dapper,并且批量操作性能更好

10.1.2 如何集成

Furion 框架中,已经推出 SqlSugar 拓展包 Furion.Extras.DatabaseAccessor.SqlSugar

10.1.2.1 注册 SqlSugar 服务

使用非常简单,只需要在 Startup.cs 中添加 services.AddSqlSugar(config) 即可。如:

// =====配置单库=====services.AddSqlSugar(new ConnectionConfig{    ConnectionString = "Server=.xxxxx",//连接符字串    DbType = DbType.SqlServer,    IsAutoCloseConnection = true,    InitKeyType = InitKeyType.Attribute//从特性读取主键自增信息});// =====配置多库=====List<ConnectionConfig> connectConfigList = new List<ConnectionConfig>();//数据库1connectConfigList.Add(new ConnectionConfig{    ConnectionString = "链接字符串1",    DbType = DbType.MySql,    IsAutoCloseConnection = true,    InitKeyType = InitKeyType.Attribute,    ConfigId = "0",    AopEvents = new AopEvents    {        //多库状态下每个库必须单独绑定打印事件,否则只会打印第一个库的sql日志        OnLogExecuting = (sql, pars) =>        {            Console.WriteLine(SqlProfiler.ParameterFormat(sql, pars));            Console.WriteLine();        }    }});//数据库2connectConfigList.Add(new ConnectionConfig{    ConnectionString = "链接字符串2",    DbType = DbType.MySql,    IsAutoCloseConnection = true,    InitKeyType = InitKeyType.Attribute,    ConfigId = "1",    AopEvents = new AopEvents    {        //多库状态下每个库必须单独绑定打印事件,否则只会打印第一个库的sql日志        OnLogExecuting = (sql, pars) =>        {            Console.WriteLine(SqlProfiler.ParameterFormat(sql, pars));            Console.WriteLine();        }    }});services.AddSqlSugar(connectConfigList.ToArray());

同时也可以添加更多配置,如: +

10.1. SqlSugar 集成

温馨提醒

Furion 包中默认集成了 EFCore如果不使用 EFCore,可安装纯净版 Furion.Pure 代替 Furion,这样可以忽略本章节直接按照 SqlSugar 官方文档使用

10.1.1 关于 SqlSugar

SqlSugar 是 .NET/C# 平台非常优秀的 ORM 框架,目前 Nuget 总下载突破 700K,Github 关注量也高达 3.2K,是目前当之无愧的国产优秀 ORM 框架之一。

SqlSugar 官方地址:http://www.donet5.com/

SqlSugar 与 EF 优势: 性能比 EF 更快、语法上手更容易

SqlSugar 与 Dapper 优势: SqlSugar 功能更加丰富,性能丝毫不逊色于 Dapper,并且批量操作性能更好

10.1.2 如何集成

Furion 框架中,已经推出 SqlSugar 拓展包 Furion.Extras.DatabaseAccessor.SqlSugar

10.1.2.1 注册 SqlSugar 服务

使用非常简单,只需要在 Startup.cs 中添加 services.AddSqlSugar(config) 即可。如:

// =====配置单库=====services.AddSqlSugar(new ConnectionConfig{    ConnectionString = "Server=.xxxxx",//连接符字串    DbType = DbType.SqlServer,    IsAutoCloseConnection = true,    InitKeyType = InitKeyType.Attribute//从特性读取主键自增信息});// =====配置多库=====List<ConnectionConfig> connectConfigList = new List<ConnectionConfig>();//数据库1connectConfigList.Add(new ConnectionConfig{    ConnectionString = "链接字符串1",    DbType = DbType.MySql,    IsAutoCloseConnection = true,    InitKeyType = InitKeyType.Attribute,    ConfigId = "0",    AopEvents = new AopEvents    {        //多库状态下每个库必须单独绑定打印事件,否则只会打印第一个库的sql日志        OnLogExecuting = (sql, pars) =>        {            Console.WriteLine(SqlProfiler.ParameterFormat(sql, pars));            Console.WriteLine();        }    }});//数据库2connectConfigList.Add(new ConnectionConfig{    ConnectionString = "链接字符串2",    DbType = DbType.MySql,    IsAutoCloseConnection = true,    InitKeyType = InitKeyType.Attribute,    ConfigId = "1",    AopEvents = new AopEvents    {        //多库状态下每个库必须单独绑定打印事件,否则只会打印第一个库的sql日志        OnLogExecuting = (sql, pars) =>        {            Console.WriteLine(SqlProfiler.ParameterFormat(sql, pars));            Console.WriteLine();        }    }});services.AddSqlSugar(connectConfigList.ToArray());

同时也可以添加更多配置,如: ps:多库状态下每个库必须单独绑定打印事件,否则只会打印第一个库的sql日志(参考上面的多库配置)

services.AddSqlSugar(connectConfigList.ToArray(),db =>{    //处理日志事务    db.Aop.OnLogExecuting = (sql, pars) =>    {        Console.WriteLine(sql);        Console.WriteLine(string.Join(",", pars?.Select(it => it.ParameterName + ":" + it.Value)));        Console.WriteLine();        App.PrintToMiniProfiler("SqlSugar", "Info", sql + "\r\n" + db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));    };});
安装拓展包位置

Furion 框架中,推荐将拓展包 Furion.Extras.DatabaseAccessor.SqlSugar 安装到 Furion.Core 层中。

10.1.3 基本使用

在使用之前,我们可以通过构造函数注入 ISqlSugarRepository 接口,如:

private readonly ISqlSugarRepository repository; // 仓储对象:封装简单的CRUDprivate readonly SqlSugarClient db; // 核心对象:拥有完整的SqlSugar全部功能public PersonService(ISqlSugarRepository sqlSugarRepository){    repository = sqlSugarRepository;    db = repository.Context;    // 推荐操作}

10.1.4 数据库操作示例

// ================== SqlSugarClient ================//查询功能var data1 =db.Queryable<Student>().First(it=>it.Id==1); //db.GetById(1);var data2 = db.Queryable<Student>().ToList();// db.GetList();// ================== 简单仓储 ================//插入db.Insert(insertObj);var id = db.InsertReturnIdentity(insertObj);db.AsInsertable(insertObj).ExecuteCommand();//删除db.Delete(insertObj);db.Delete(it => it.Id == 1);//更新db.Update(insertObj);db.Update(it => new Order() { Name = "a", }, it => it.Id == 1);//异步方法用法db.Insert(insertObj);//同步db.InsertAsync(insertObj);//异步//切换仓储var orderRespository=db.GetSimpleClient<Order>();orderRespository.Insert(Order);

10.1.5 SqlSugarClient 操作示例

10.1.5.1 基础查询

//查询所有var getAll = db.Queryable<Student>().ToList();//查询前10var top10= db.Queryable<Student>().Take(10).ToList();//查询单条var getFirst = db.Queryable<Student>().First(it=>it.Id==1);//with nolockvar getAllNoLock = db.Queryable<Student>().With(SqlWith.NoLock).ToList();//根据主键查询var getByPrimaryKey = db.Queryable<Student>().InSingle(2);//查询总和var sum = db.Queryable<Student>().Sum(it=>it.Id);//是否存在var isAny = db.Queryable<Student>().Where(it=>it.Id==-1).Any();//模糊查var list2 = db.Queryable<Order>().Where(it =>it.Name.Contains("jack")).ToList();

10.1.5.2 联表查询

var list = db.Queryable<Student, School>((st, sc) => new JoinQueryInfos(        JoinType.Left,st.SchoolId==sc.Id))      .Select((st,sc)=>new{Id=st.Id,Name=st.Name,SchoolName=sc.Name}).ToList();生成的Sql如下:SELECT  [st].[ID] AS [id] ,          [st].[Name] AS [name] ,          [sc].[Name] AS [schoolName]  FROM [STudent] st          Left JOIN School sc ON ( [st].[SchoolId] =[sc].[Id])

10.1.5.3 分页查询

 int pageIndex = 1; int pageSize = 20; int totalCount=0; var page = db.Queryable<Student>().ToPageList(pageIndex, pageSize, ref totalCount);

更多查询用法 : http://www.donet5.com/Home/Doc?typeId=1185

10.1.5.4 插入

//可以是 类 或者 List<类>db.Insertable(insertObj).ExecuteCommand();//插入返回自增列db.Insertable(insertObj).ExecuteReturnIdentity();//可以是 Dictionary 或者 List<Dictionary >var dc= new Dictionary<string, object>();            dt.Add("name", "1");            dt.Add("CreateTime", null);db.Insertable(dc).AS("student").ExecuteCommand();//DataTable插入Dictionary<string,object> dc= db.Utilities.DataTableToDictionary(dataTable);//转成字典就可以按上面的字典更新了db.Insertable(dc).AS("student").ExecuteReturnIdentity();//实体可以配置主键和自增列public class Student{    [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]    public int Id { get; set; }    public int? SchoolId { get; set; }    public string Name { get; set; }}

更多插入用法: http://www.donet5.com/Home/Doc?typeId=1193

10.1.5.5 更新

实体配置参考插入,只需要配置主键即可

//根据主键更新单条 参数 Classvar result= db.Updateable(updateObj).ExecuteCommand();//不更新 Name 和TestIdvar result=db.Updateable(updateObj).IgnoreColumns(it => new { it.CreateTime,it.TestId }).ExecuteCommand()//只更新 Name 和 CreateTimevar result=db.Updateable(updateObj).UpdateColumns(it => new { it.Name,it.CreateTime }).ExecuteCommand();//根据表达式更新var result71 = db.Updateable<Order>()              .SetColumns(it => it.Name == "a")              .SetColumnsIF(p!=null ,it => it.CreateTime == p.Value)//当p不等于null更新createtime列            .Where(it => it.Id == 11).ExecuteCommand();

更多更新用法: http://www.donet5.com/Home/Doc?typeId=1191

10.1.5.6 删除

实体配置参考插入,只需要配置主键即可

//根据实体删除db.Deleteable<Student>().Where(new Student() { Id = 1 }).ExecuteCommand();//根据主键删除db.Deleteable<Student>().In(1).ExecuteCommand();//根据表达式删除db.Deleteable<Student>().Where(it => it.Id == 1).ExecuteCommand();

更多删除用法: http://www.donet5.com/Home/Doc?typeId=1195

10.1.6 Sql 查询

//sql分页var list = db.SqlQueryable<Student>("select * from student").ToPageList(1, 2,ref total);//原生Sql用法var dt=db.Ado.GetDataTable("select * from table where id=@id and name=@name",new List<SugarParameter>(){  new SugarParameter("@id",1),  new SugarParameter("@name",2)});//参数2var dt=db.Ado.GetDataTable("select * from table where id=@id and name=@name",new{id=1,name=2});//存储过程用法var nameP= new SugarParameter("@name", "张三");var ageP= new SugarParameter("@age", null, true);//设置为outputvar dt = db.Ado.UseStoredProcedure().GetDataTable("sp_school",nameP,ageP);
方法名描述返回值
SqlQuery< T >查询所有返回实体集合List
SqlQuery<T,T2>可以返回 2 个结果集Tuple<List, List>
SqlQuerySingle查询第一条记录T
GetDataTable查询所有DataTable
GetDataReader读取 DR 需要手动释放 DRDataReader
GetDataSetAll获取多个结果集DataSet
ExecuteCommand返回受影响行数,一般用于增删改int
GetScalar获取首行首列object
GetString获取首行首列string
GetInt获取首行首列int
GetLong获取首行首列long
GetDouble获取首行首列Double
GetDecimal获取首行首列Decimal
GetDateTime获取首行首列DateTime

想了解更多 SqlSugar 知识可查阅 SqlSugar 官网

10.1.7 打印 sqlSwagger

services.AddSqlSugar(new ConnectionConfig{    ConnectionString = "Server=.xxxxx",//连接符字串    DbType = DbType.SqlServer,    IsAutoCloseConnection = true,    InitKeyType = InitKeyType.Attribute//从特性读取主键自增信息},db =>{    db.Aop.OnLogExecuting = (sql, pars) =>    {        //方法一        App.PrintToMiniProfiler("SqlSugar", "Info", sql + "\r\n" +string.Join(",", pars?.Select(it => it.ParameterName + ":" + it.Value)));        //方法二:Furion对上述用法进行二次封装 建议方式 Sql参数会直接写入到生成Sql中        App.PrintToMiniProfiler("SqlSugar","Info",SqlProfiler.ParameterFormat(sql,pars));    };});

10.1.8 Oracle注意事项

注意 .NET5 用户需要在 API 或者项目解决方案 .csproj 文件加以下一行代码:

<PropertyGroup>   <TargetFramework>net5.0</TargetFramework>   <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization></PropertyGroup>

10.1.9 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - + + \ No newline at end of file diff --git a/handbook/build/docs/sqlsugar/index.html b/handbook/build/docs/sqlsugar/index.html index c9ec818ddc..48bd9a4c13 100644 --- a/handbook/build/docs/sqlsugar/index.html +++ b/handbook/build/docs/sqlsugar/index.html @@ -2,22 +2,21 @@ - - - + +10.1 SqlSugar 集成 | Furion -10.1 SqlSugar 集成 | Furion - - + + +
-

10.1 SqlSugar 集成

关于拓展包

由于 SqlSugar 高速发展,新版本带来了诸多特性,而 Furion.Extras.DatabaseAccessor.SqlSugar 拓展包更新不及时导致不能第一时间体验新特性。

所以,和 SqlSugar 作者商量后,决定全面推荐使用 SqlSugar 原生拓展包即可。以下文档已更新查看旧文档

温馨提醒

Furion 包中默认集成了 EFCore如果不使用 EFCore,可安装纯净版 Furion.Pure 代替 Furion

10.1.1 SqlSugar ORM

SqlSugar.NET/C# 平台非常优秀的 ORM 框架,目前 Nuget 总下载突破 1000KGithub 关注量也高达 3.7K,是目前当之无愧的国产优秀 ORM 框架之一。

SqlSugar 高性能,具有百万级插入、更新大数据分表等特色功能。

10.1.2 功能介绍

  • 支持 SqlServer、MySql、PgSql、Oracle 百万级插入和更新
  • 支持全自动分表
  • 支持多库事务
  • 支持 CodeFirst
  • 支持联表查询、嵌套查询、导航查询、子查询和动态 JSON 查询等查询操作
  • 支持配置查询
  • 支持工具生成实体和代码生成实体
  • 支持数据库 MySql、SqlServer、Sqlite、Oracle、postgresql、达梦、人大金仓、神通数据库

10.1.3 官网文档

点击以下链接可以跳转到 SqlSugar 官网查看详细 API

入门查询插入更新删 除
安装简单查询
入门联表

10.1.4 Furion 集成

  1. 创建一个拓展类:
public static class SqlsugarSetup{    public static void AddSqlsugarSetup(this IServiceCollection services, IConfiguration configuration, string dbName = "db_master")    {        //如果多个数数据库传 List<ConnectionConfig>        var configConnection=new ConnectionConfig()        {            DbType = SqlSugar.DbType.MySql,            ConnectionString = configuration.GetConnectionString(dbName),            IsAutoCloseConnection = true,        };                SqlSugarScope sqlSugar = new SqlSugarScope(configConnection,            db =>            {                //单例参数配置,所有上下文生效                db.Aop.OnLogExecuting = (sql, pars) =>                {                    //Console.WriteLine(sql);//输出sql                };            });        services.AddSingleton<ISqlSugarClient>(sqlSugar);//这边是SqlSugarScope用AddSingleton    }}

使用注入

//1.构造函数注入SqlSugar.ISqlSugarClient db;public WeatherForecastController(ISqlSugarClient db) {    this.db = db;}//2.手动获取App.GetService<ISqlSugarClient>();
  1. Startup.cs 中注册:
services.AddSqlsugarSetup(App.Configuration);
小知识

如果需要多库配置,可查看 https://www.donet5.com/home/Doc?typeId=2246

10.1.5 特色功能

10.1.5.1 联表查询

  • Linq/Lambda
var query5 = db.Queryable<Order>()            .LeftJoin<Custom>    ((o, cus) => o.CustomId == cus.Id)            .LeftJoin<OrderItem> ((o, cus, oritem ) => o.Id == oritem.OrderId)            .Where(o => o.Id == 1)              .Select((o, cus) => new ViewOrder { Id = o.Id, CustomName = cus.Name })            .ToList();   
  • 生成 SQL
SELECT  [o].[Id] AS [Id],  [cus].[Name] AS [CustomName]FROM  [Order] o  Left JOIN [Custom] cus ON ([o].[CustomId] = [cus].[Id])  Left JOIN [OrderDetail] oritem ON ([o].[Id] = [oritem].[OrderId])WHERE  ([o].[Id] = @Id0)

10.1.5.2 分页查询

int pageIndex = 1; int pageSize = 20;int totalCount=0;var page = db.Queryable<Student>().ToPageList(pageIndex, pageSize, ref totalCount);

10.1.5.3 动态表达式

  • Linq/Lambda
var names= new string [] { "a","b"};Expressionable<Order> exp = new Expressionable<Order>();foreach (var item in names){    exp.Or(it => it.Name.Contains(item.ToString()));}var list= db.Queryable<Order>().Where(exp.ToExpression()).ToList();
  • 生成 SQL
SELECT [Id],[Name],[Price],[CreateTime],[CustomId]        FROM [Order]  WHERE (                      ([Name] like '%'+ CAST(@MethodConst0 AS NVARCHAR(MAX))+'%') OR                       ([Name] like '%'+ CAST(@MethodConst1 AS NVARCHAR(MAX))+'%')                     )

10.1.5.4 仓储方法

新建一个仓储类,如果想扩展方法写到仓储类中

public class Repository<T> : SimpleClient<T> where T : class, new(){    public Repository(ISqlSugarClient context = null) : base(context)//默认值等于null不能少    {        base.Context = App.GetService<ISqlSugarClient>();//用手动获取方式支持切换仓储    }}

继承仓储类就可以使用仓储API了

//查询var data1 = base.GetById(1);//根据id查询var data4 = base.GetSingle(it => it.Id == 1);//查询单条记录,结果集不能超过1,不然会提示错误var data = base.GetFirst(it => it.Id == 1);//查询第一条记录var data2 = base.GetList();//查询所有var data3 = base.GetList(it => it.Id == 1); //根据条件查询var p = new PageModel() { PageIndex = 1, PageSize = 2 };var data5 = base.GetPageList(it => it.Name == "xx", p);Console.Write(p.PageCount);var data6 = base.GetPageList(it => it.Name == "xx", p, it => it.Name, OrderByType.Asc);Console.Write(p.PageCount);List<IConditionalModel> conModels = new List<IConditionalModel>();conModels.Add(new ConditionalModel(){FieldName="id",ConditionalType=ConditionalType.Equal,FieldValue="1"});//id=1var data7 = base.GetPageList(conModels, p, it => it.Name, OrderByType.Asc);base.AsQueryable().Where(x => x.Id == 1).ToList(); //插入base.Insert(insertObj);base.InsertRange(InsertObjs);var id = base.InsertReturnIdentity(insertObj);base.AsInsertable(insertObj).ExecuteCommand(); //删除base.Delete(insertObj);base.DeleteById(1);base.DeleteByIds(new object [] { 1, 2 }); //数组带是 ids方法 ,封装传 object [] 类型base.Delete(it => it.Id == 1);base.AsDeleteable().Where(it => it.Id == 1).ExecuteCommand(); //更新base.Update(insertObj); base.UpdateRange(InsertObjs); base.Update(it => new Order() { Name = "a", }, it => it.Id == 1);base.AsUpdateable(insertObj).UpdateColumns(it=>new { it.Name }).ExecuteCommand(); //高级操作base.AsSugarClient // 获取完整的db对象base.AsTenant  // 获取多库相关操作 //切换仓储base.ChangeRepository<Repository<OrderItem>>() //支持多租户和扩展方法,使用SqlSugarScope单例(或者SqlSugarClient Scope注入)base.Change<OrderItem>()//只支持自带方法和单库

10.1.5.5 多库事务

SqlSugarClient db = new SqlSugarClient(new List<ConnectionConfig>(){    new ConnectionConfig(){ ConfigId="0", DbType=DbType.SqlServer,  ConnectionString=Config.ConnectionString, IsAutoCloseConnection=true },    new ConnectionConfig(){ ConfigId="1", DbType=DbType.MySql, ConnectionString=Config.ConnectionString4 ,IsAutoCloseConnection=true}});var mysqldb = db.GetConnection("1"); // mysql dbvar sqlServerdb = db.GetConnection("0"); // sqlserver db db.BeginTran();mysqldb.Insertable(new Order(){    CreateTime = DateTime.Now,    CustomId = 1,    Name = "a",    Price = 1}).ExecuteCommand();mysqldb.Queryable<Order>().ToList();sqlServerdb.Queryable<Order>().ToList();db.CommitTran();

10.1.5.6 单例模式

public static SqlSugarScope Db = new SqlSugarScope(new ConnectionConfig()    {        DbType = SqlSugar.DbType.SqlServer,        ConnectionString = Config.ConnectionString,        IsAutoCloseConnection = true     },    db=> {            db.Aop.OnLogExecuting = (s, p) =>            {                Console.WriteLine(s);            };    }); using (var tran = Db.UseTran()){    new Test2().Insert(XX);    new Test1().Insert(XX);    .....                     tran.CommitTran(); }

10.1.5.7 全局过滤器

db.QueryFilter.Add(new TableFilterItem<Order>(it => it.Name.Contains("a")));     db.Queryable<Order>().ToList();// SELECT [Id],[Name],[Price],[CreateTime],[CustomId] FROM [Order]  WHERE  ([Name] like '%'+@MethodConst0+'%')  db.Queryable<OrderItem, Order>((i, o) => i.OrderId == o.Id)        .Where(i => i.OrderId != 0)        .Select("i.*").ToList();// SELECT i.* FROM [OrderDetail] i  ,[Order]  o  WHERE ( [i].[OrderId] = [o].[Id] )  AND // ( [i].[OrderId] <> @OrderId0 )  AND  ([o].[Name] like '%'+@MethodConst1+'%')

10.1.5.8 添加或者更新

var x = Db.Storageable(list2).ToStorage();  x.AsInsertable.ExecuteCommand();  x.AsUpdateable.ExecuteCommand();  
var x = Db.Storageable(list).SplitInsert(it => !it.Any()).ToStorage()x.AsInsertable.ExecuteCommand(); 

10.1.5.9 自动分表

[SplitTable(SplitType.Year)] // Table by year (the table supports year, quarter, month, week and day)[SugarTable("SplitTestTable_{year}{month}{day}")] public class SplitTestTable{    [SugarColumn(IsPrimaryKey =true)]    public long Id { get; set; }    public string Name { get; set; }        //When the sub-table field is inserted, which table will be inserted according to this field.     //When it is updated and deleted, it can also be convenient to use this field to          //find out the related table     [SplitField]     public DateTime CreateTime { get; set; }}
var lis2t = db.Queryable<OrderSpliteTest>().SplitTable(DateTime.Now.Date.AddYears(-1), DateTime.Now).ToPageList(1,2); 

10.1.5.10 大数据插入,更新,插入或者更新

//Insert A million only takes a few secondsdb.Fastest<RealmAuctionDatum>().BulkCopy(GetList()); //update A million only takes a few secondsdb.Fastest<RealmAuctionDatum>().BulkUpdate(GetList());//A million only takes a few seconds完db.Fastest<RealmAuctionDatum>().BulkUpdate(GetList(),new string[]{"id"},new string[]{"name","time"})//no primary key //if exists update, else  insert var x= db.Storageable<Order>(data).ToStorage();     x.BulkCopy();     x.BulkUpdate();      //set table namedb.Fastest<RealmAuctionDatum>().AS("tableName").BulkCopy(GetList()) //set page db.Fastest<Order>().PageSize(300000).BulkCopy(insertObjs);

10.1.5.11 更多功能

可查阅 SqlSugar 官网

10.1.6 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 SqlSugar 知识可查阅 SqlSugar 官网

演练场
- - +

10.1 SqlSugar 集成

关于拓展包

由于 SqlSugar 高速发展,新版本带来了诸多特性,而 Furion.Extras.DatabaseAccessor.SqlSugar 拓展包更新不及时导致不能第一时间体验新特性。

所以,和 SqlSugar 作者商量后,决定全面推荐使用 SqlSugar 原生拓展包即可。以下文档已更新查看旧文档

温馨提醒

Furion 包中默认集成了 EFCore如果不使用 EFCore,可安装纯净版 Furion.Pure 代替 Furion

10.1.1 SqlSugar ORM

SqlSugar.NET/C# 平台非常优秀的 ORM 框架,目前 Nuget 总下载突破 1000KGithub 关注量也高达 3.7K,是目前当之无愧的国产优秀 ORM 框架之一。

SqlSugar 高性能,具有百万级插入、更新大数据分表等特色功能。

10.1.2 功能介绍

  • 支持 SqlServer、MySql、PgSql、Oracle 百万级插入和更新
  • 支持全自动分表
  • 支持多库事务
  • 支持 CodeFirst
  • 支持联表查询、嵌套查询、导航查询、子查询和动态 JSON 查询等查询操作
  • 支持配置查询
  • 支持工具生成实体和代码生成实体
  • 支持数据库 MySql、SqlServer、Sqlite、Oracle、postgresql、达梦、人大金仓、神通数据库

10.1.3 官网文档

点击以下链接可以跳转到 SqlSugar 官网查看详细 API

入门查询插入更新删 除
安装简单查询
入门联表

10.1.4 Furion 集成

  1. 创建一个拓展类:
public static class SqlsugarSetup{    public static void AddSqlsugarSetup(this IServiceCollection services, IConfiguration configuration, string dbName = "db_master")    {        //如果多个数数据库传 List<ConnectionConfig>        var configConnection=new ConnectionConfig()        {            DbType = SqlSugar.DbType.MySql,            ConnectionString = configuration.GetConnectionString(dbName),            IsAutoCloseConnection = true,        };                SqlSugarScope sqlSugar = new SqlSugarScope(configConnection,            db =>            {                //单例参数配置,所有上下文生效                db.Aop.OnLogExecuting = (sql, pars) =>                {                    //Console.WriteLine(sql);//输出sql                };            });        services.AddSingleton<ISqlSugarClient>(sqlSugar);//这边是SqlSugarScope用AddSingleton    }}

使用注入

//1.构造函数注入SqlSugar.ISqlSugarClient db;public WeatherForecastController(ISqlSugarClient db) {    this.db = db;}//2.手动获取App.GetService<ISqlSugarClient>();
  1. Startup.cs 中注册:
services.AddSqlsugarSetup(App.Configuration);
小知识

如果需要多库配置,可查看 https://www.donet5.com/home/Doc?typeId=2246

10.1.5 特色功能

10.1.5.1 联表查询

  • Linq/Lambda
var query5 = db.Queryable<Order>()            .LeftJoin<Custom>    ((o, cus) => o.CustomId == cus.Id)            .LeftJoin<OrderItem> ((o, cus, oritem ) => o.Id == oritem.OrderId)            .Where(o => o.Id == 1)              .Select((o, cus) => new ViewOrder { Id = o.Id, CustomName = cus.Name })            .ToList();   
  • 生成 SQL
SELECT  [o].[Id] AS [Id],  [cus].[Name] AS [CustomName]FROM  [Order] o  Left JOIN [Custom] cus ON ([o].[CustomId] = [cus].[Id])  Left JOIN [OrderDetail] oritem ON ([o].[Id] = [oritem].[OrderId])WHERE  ([o].[Id] = @Id0)

10.1.5.2 分页查询

int pageIndex = 1; int pageSize = 20;int totalCount=0;var page = db.Queryable<Student>().ToPageList(pageIndex, pageSize, ref totalCount);

10.1.5.3 动态表达式

  • Linq/Lambda
var names= new string [] { "a","b"};Expressionable<Order> exp = new Expressionable<Order>();foreach (var item in names){    exp.Or(it => it.Name.Contains(item.ToString()));}var list= db.Queryable<Order>().Where(exp.ToExpression()).ToList();
  • 生成 SQL
SELECT [Id],[Name],[Price],[CreateTime],[CustomId]        FROM [Order]  WHERE (                      ([Name] like '%'+ CAST(@MethodConst0 AS NVARCHAR(MAX))+'%') OR                       ([Name] like '%'+ CAST(@MethodConst1 AS NVARCHAR(MAX))+'%')                     )

10.1.5.4 仓储方法

新建一个仓储类,如果想扩展方法写到仓储类中

public class Repository<T> : SimpleClient<T> where T : class, new(){    public Repository(ISqlSugarClient context = null) : base(context)//默认值等于null不能少    {        base.Context = App.GetService<ISqlSugarClient>();//用手动获取方式支持切换仓储    }}

继承仓储类就可以使用仓储API了

//查询var data1 = base.GetById(1);//根据id查询var data4 = base.GetSingle(it => it.Id == 1);//查询单条记录,结果集不能超过1,不然会提示错误var data = base.GetFirst(it => it.Id == 1);//查询第一条记录var data2 = base.GetList();//查询所有var data3 = base.GetList(it => it.Id == 1); //根据条件查询var p = new PageModel() { PageIndex = 1, PageSize = 2 };var data5 = base.GetPageList(it => it.Name == "xx", p);Console.Write(p.PageCount);var data6 = base.GetPageList(it => it.Name == "xx", p, it => it.Name, OrderByType.Asc);Console.Write(p.PageCount);List<IConditionalModel> conModels = new List<IConditionalModel>();conModels.Add(new ConditionalModel(){FieldName="id",ConditionalType=ConditionalType.Equal,FieldValue="1"});//id=1var data7 = base.GetPageList(conModels, p, it => it.Name, OrderByType.Asc);base.AsQueryable().Where(x => x.Id == 1).ToList(); //插入base.Insert(insertObj);base.InsertRange(InsertObjs);var id = base.InsertReturnIdentity(insertObj);base.AsInsertable(insertObj).ExecuteCommand(); //删除base.Delete(insertObj);base.DeleteById(1);base.DeleteByIds(new object [] { 1, 2 }); //数组带是 ids方法 ,封装传 object [] 类型base.Delete(it => it.Id == 1);base.AsDeleteable().Where(it => it.Id == 1).ExecuteCommand(); //更新base.Update(insertObj); base.UpdateRange(InsertObjs); base.Update(it => new Order() { Name = "a", }, it => it.Id == 1);base.AsUpdateable(insertObj).UpdateColumns(it=>new { it.Name }).ExecuteCommand(); //高级操作base.AsSugarClient // 获取完整的db对象base.AsTenant  // 获取多库相关操作 //切换仓储base.ChangeRepository<Repository<OrderItem>>() //支持多租户和扩展方法,使用SqlSugarScope单例(或者SqlSugarClient Scope注入)base.Change<OrderItem>()//只支持自带方法和单库

10.1.5.5 多库事务

SqlSugarClient db = new SqlSugarClient(new List<ConnectionConfig>(){    new ConnectionConfig(){ ConfigId="0", DbType=DbType.SqlServer,  ConnectionString=Config.ConnectionString, IsAutoCloseConnection=true },    new ConnectionConfig(){ ConfigId="1", DbType=DbType.MySql, ConnectionString=Config.ConnectionString4 ,IsAutoCloseConnection=true}});var mysqldb = db.GetConnection("1"); // mysql dbvar sqlServerdb = db.GetConnection("0"); // sqlserver db db.BeginTran();mysqldb.Insertable(new Order(){    CreateTime = DateTime.Now,    CustomId = 1,    Name = "a",    Price = 1}).ExecuteCommand();mysqldb.Queryable<Order>().ToList();sqlServerdb.Queryable<Order>().ToList();db.CommitTran();

10.1.5.6 单例模式

public static SqlSugarScope Db = new SqlSugarScope(new ConnectionConfig()    {        DbType = SqlSugar.DbType.SqlServer,        ConnectionString = Config.ConnectionString,        IsAutoCloseConnection = true     },    db=> {            db.Aop.OnLogExecuting = (s, p) =>            {                Console.WriteLine(s);            };    }); using (var tran = Db.UseTran()){    new Test2().Insert(XX);    new Test1().Insert(XX);    .....                     tran.CommitTran(); }

10.1.5.7 全局过滤器

db.QueryFilter.Add(new TableFilterItem<Order>(it => it.Name.Contains("a")));     db.Queryable<Order>().ToList();// SELECT [Id],[Name],[Price],[CreateTime],[CustomId] FROM [Order]  WHERE  ([Name] like '%'+@MethodConst0+'%')  db.Queryable<OrderItem, Order>((i, o) => i.OrderId == o.Id)        .Where(i => i.OrderId != 0)        .Select("i.*").ToList();// SELECT i.* FROM [OrderDetail] i  ,[Order]  o  WHERE ( [i].[OrderId] = [o].[Id] )  AND // ( [i].[OrderId] <> @OrderId0 )  AND  ([o].[Name] like '%'+@MethodConst1+'%')

10.1.5.8 添加或者更新

var x = Db.Storageable(list2).ToStorage();  x.AsInsertable.ExecuteCommand();  x.AsUpdateable.ExecuteCommand();  
var x = Db.Storageable(list).SplitInsert(it => !it.Any()).ToStorage()x.AsInsertable.ExecuteCommand(); 

10.1.5.9 自动分表

[SplitTable(SplitType.Year)] // Table by year (the table supports year, quarter, month, week and day)[SugarTable("SplitTestTable_{year}{month}{day}")] public class SplitTestTable{    [SugarColumn(IsPrimaryKey =true)]    public long Id { get; set; }    public string Name { get; set; }        //When the sub-table field is inserted, which table will be inserted according to this field.     //When it is updated and deleted, it can also be convenient to use this field to          //find out the related table     [SplitField]     public DateTime CreateTime { get; set; }}
var lis2t = db.Queryable<OrderSpliteTest>().SplitTable(DateTime.Now.Date.AddYears(-1), DateTime.Now).ToPageList(1,2); 

10.1.5.10 大数据插入,更新,插入或者更新

//Insert A million only takes a few secondsdb.Fastest<RealmAuctionDatum>().BulkCopy(GetList()); //update A million only takes a few secondsdb.Fastest<RealmAuctionDatum>().BulkUpdate(GetList());//A million only takes a few seconds完db.Fastest<RealmAuctionDatum>().BulkUpdate(GetList(),new string[]{"id"},new string[]{"name","time"})//no primary key //if exists update, else  insert var x= db.Storageable<Order>(data).ToStorage();     x.BulkCopy();     x.BulkUpdate();      //set table namedb.Fastest<RealmAuctionDatum>().AS("tableName").BulkCopy(GetList()) //set page db.Fastest<Order>().PageSize(300000).BulkCopy(insertObjs);

10.1.5.11 更多功能

可查阅 SqlSugar 官网

10.1.6 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 SqlSugar 知识可查阅 SqlSugar 官网

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/template/index.html b/handbook/build/docs/template/index.html index 57b6cf0c06..7730cf79ff 100644 --- a/handbook/build/docs/template/index.html +++ b/handbook/build/docs/template/index.html @@ -2,22 +2,21 @@ - - - + +2.2 官方脚手架 | Furion -2.2 官方脚手架 | Furion - - + + +
-

2.2 官方脚手架

特别说明

脚手架不是安装在项目中的! 而是通过 CMDPowerShell 安装到操作系统中的。

2.2.1 脚手架

Furion 官方提供了多种 Web 应用类型的脚手架,方便大家快速创建多层架构项目。目前支持以下应用脚手架:

2.2.1.1 Furion + EFCore

模板类型名称版本关键词描述
nugetFurion.Template.Mvcnuget👉 furionmvcMvc 模板
nugetFurion.Template.Apinuget👉 furionapiWebApi 模板
nugetFurion.Template.Appnuget👉 furionappMvc/WebApi 模板
nugetFurion.Template.Razornuget👉 furionrazorRazorPages 模板
nugetFurion.Template.RazorWithWebApinuget👉 furionrazorapiRazorPages/WebApi 模板
nugetFurion.Template.Blazornuget👉 furionblazorBlazor 模板
nugetFurion.Template.BlazorWithWebApinuget👉 furionblazorapiBlazor/WebApi 模板

2.2.1.2 Furion + SqlSugar

SqlSugar 优点

弥补 EF Core 上手难度:支持线程安全、支持多库事务、多库兼容、多库查询和多库切换。

模板类型名称版本关键词描述
nugetFurion.SqlSugar.Template.Mvcnuget👉 fsmvcMvc 模板
nugetFurion.SqlSugar.Template.Apinuget👉 fsapiWebApi 模板
nugetFurion.SqlSugar.Template.Appnuget👉 fsappMvc/WebApi 模板
nugetFurion.SqlSugar.Template.Razornuget👉 fsrazorRazorPages 模板
nugetFurion.SqlSugar.Template.RazorWithWebApinuget👉 fsrazorapiRazorPages/WebApi 模板
nugetFurion.SqlSugar.Template.Blazornuget👉 fsblazorBlazor 模板
nugetFurion.SqlSugar.Template.BlazorWithWebApinuget👉 fsblazorapiBlazor/WebApi 模板

2.2.2 安装脚手架

打开 CMDPowershell 执行模板安装命令(新版本 --install 可换成 install):

// EFCoredotnet new --install Furion.Template.Mvc::4.3.9// SqlSugardotnet new --install Furion.SqlSugar.Template.Mvc::4.3.9
SqlSugar 脚手架基本使用

SqlSugar 脚手架中,Core 层包含了一个 DbContext.cs 类,可通过 DbContext.Instance 就可以获取到 SqlSugarScope 对象。

数据库链接字符串在启动层 appsettings.json 文件的 ConnectionConfigs 节点中配置,对应的是 SqlSugar 中的 ConnectionConfig[] 对象。

2.2.3 使用脚手架

dotnet new furionmvc -n 项目名称

这样就可以生成项目代码了,生成之后推荐将所有的 nuget 包更新到最新版本。

关于项目名称

通过脚手架生成的项目名称不能包含 短横线 等特殊字符,如有该需求,可在生成之后通过 Visual Studio 进行手动修改。

特别提醒

furionmvc 对应的是上面列表的 关键字,我们也可以通过 dotnet new --list 查看。

想了解更多可以使用 dotnet new 关键字 --help 查看更多参数。

2.2.4 脚手架更新

只需要重新安装最新版替换即可,如:

dotnet new --install Furion.Template.Mvc::2.x.x

不带版本号总是安装最新的版本。

2.2.5 Visual Studio 集成

通过命令安装脚手架后,升级 Visual Studio 到最新版可使用可视化方式创建哦。

2.2.6 关于 MVC 添加区域出错问题

由于 Furion 底层依赖了 Microsoft.CodeAnalysis.CSharp 包,所以可能通过 Viusal Studio 的界面添加 Area 区域 时会出错,这时候只需要在 Web.Entry 层安装下面几个包即可:

  • Microsoft.CodeAnalysis.CSharp.Features
  • Microsoft.CodeAnalysis.CSharp.Scripting
  • Microsoft.CodeAnalysis.VisualBasic.Features
  • Microsoft.CodeAnalysis.Workspaces.MSBuild
  • Microsoft.VisualStudio.Web.CodeGeneration.Design

2.2.7 使用 .NET5 脚手架

目前 Furion 只提供了 .NET6+ 版本脚手架,如需使用 .NET 版本,可创建之后执行下面步骤:

  1. 替换 <TargetFramework>net6.0</TargetFramework><TargetFramework>net5.0</TargetFramework>

  2. 编辑所有层 .csproj 文件并添加 <LangVersion>10.0</LangVersion>,如:

<PropertyGroup>    <TargetFramework>net5.0</TargetFramework>    <LangVersion>10.0</LangVersion>    <!-- 其他配置 --></PropertyGroup>
  1. 如果使用的是 EFCore 版本则需要将启动层的 Microsoft.EntityFrameworkCore.Tools 版本改为 5.0.17 版本,如编辑启动层的 Web.Entry.csproj
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.7">    <PrivateAssets>all</PrivateAssets>    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets></PackageReference>

改为:

<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.17">    <PrivateAssets>all</PrivateAssets>    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets></PackageReference>
  1. 在启动层添加 Startup.cs 文件
namespace YourProject.Web.Entry;    // 你的项目命名空间public class Startup{    public Startup(IConfiguration configuration)    {        Configuration = configuration;    }    public IConfiguration Configuration { get; }    public void ConfigureServices(IServiceCollection services)    {    }    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    {    }}
  1. 修改 Program.cs 为:
using YourProject.Web.Entry;Serve.Run<Startup>(RunOptions.Default);

2.2.8 搭建脚手架

脚手架可以极大的提高我们搭建新项目的速度,推荐两篇文章给大家学习:

https://www.cnblogs.com/laozhang-is-phi/p/10205495.html

https://www.cnblogs.com/catcher1994/p/10061470.html

推荐直接拷贝 Furion 脚手架文件夹进行修改,可避免很多问题。

Furion 脚手架源码

2.2.9 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 模板知识 知识可查阅 dotnet-new 模板 章节。

演练场
- - +

2.2 官方脚手架

特别说明

脚手架不是安装在项目中的! 而是通过 CMDPowerShell 安装到操作系统中的。

2.2.1 脚手架

Furion 官方提供了多种 Web 应用类型的脚手架,方便大家快速创建多层架构项目。目前支持以下应用脚手架:

2.2.1.1 Furion + EFCore

模板类型名称版本关键词描述
nugetFurion.Template.Mvcnuget👉 furionmvcMvc 模板
nugetFurion.Template.Apinuget👉 furionapiWebApi 模板
nugetFurion.Template.Appnuget👉 furionappMvc/WebApi 模板
nugetFurion.Template.Razornuget👉 furionrazorRazorPages 模板
nugetFurion.Template.RazorWithWebApinuget👉 furionrazorapiRazorPages/WebApi 模板
nugetFurion.Template.Blazornuget👉 furionblazorBlazor 模板
nugetFurion.Template.BlazorWithWebApinuget👉 furionblazorapiBlazor/WebApi 模板

2.2.1.2 Furion + SqlSugar

SqlSugar 优点

弥补 EF Core 上手难度:支持线程安全、支持多库事务、多库兼容、多库查询和多库切换。

模板类型名称版本关键词描述
nugetFurion.SqlSugar.Template.Mvcnuget👉 fsmvcMvc 模板
nugetFurion.SqlSugar.Template.Apinuget👉 fsapiWebApi 模板
nugetFurion.SqlSugar.Template.Appnuget👉 fsappMvc/WebApi 模板
nugetFurion.SqlSugar.Template.Razornuget👉 fsrazorRazorPages 模板
nugetFurion.SqlSugar.Template.RazorWithWebApinuget👉 fsrazorapiRazorPages/WebApi 模板
nugetFurion.SqlSugar.Template.Blazornuget👉 fsblazorBlazor 模板
nugetFurion.SqlSugar.Template.BlazorWithWebApinuget👉 fsblazorapiBlazor/WebApi 模板

2.2.2 安装脚手架

打开 CMDPowershell 执行模板安装命令(新版本 --install 可换成 install):

// EFCoredotnet new --install Furion.Template.Mvc::4.4.0// SqlSugardotnet new --install Furion.SqlSugar.Template.Mvc::4.4.0
SqlSugar 脚手架基本使用

SqlSugar 脚手架中,Core 层包含了一个 DbContext.cs 类,可通过 DbContext.Instance 就可以获取到 SqlSugarScope 对象。

数据库链接字符串在启动层 appsettings.json 文件的 ConnectionConfigs 节点中配置,对应的是 SqlSugar 中的 ConnectionConfig[] 对象。

2.2.3 使用脚手架

dotnet new furionmvc -n 项目名称

这样就可以生成项目代码了,生成之后推荐将所有的 nuget 包更新到最新版本。

关于项目名称

通过脚手架生成的项目名称不能包含 短横线 等特殊字符,如有该需求,可在生成之后通过 Visual Studio 进行手动修改。

特别提醒

furionmvc 对应的是上面列表的 关键字,我们也可以通过 dotnet new --list 查看。

想了解更多可以使用 dotnet new 关键字 --help 查看更多参数。

2.2.4 脚手架更新

只需要重新安装最新版替换即可,如:

dotnet new --install Furion.Template.Mvc::2.x.x

不带版本号总是安装最新的版本。

2.2.5 Visual Studio 集成

通过命令安装脚手架后,升级 Visual Studio 到最新版可使用可视化方式创建哦。

2.2.6 关于 MVC 添加区域出错问题

由于 Furion 底层依赖了 Microsoft.CodeAnalysis.CSharp 包,所以可能通过 Viusal Studio 的界面添加 Area 区域 时会出错,这时候只需要在 Web.Entry 层安装下面几个包即可:

  • Microsoft.CodeAnalysis.CSharp.Features
  • Microsoft.CodeAnalysis.CSharp.Scripting
  • Microsoft.CodeAnalysis.VisualBasic.Features
  • Microsoft.CodeAnalysis.Workspaces.MSBuild
  • Microsoft.VisualStudio.Web.CodeGeneration.Design

2.2.7 使用 .NET5 脚手架

目前 Furion 只提供了 .NET6+ 版本脚手架,如需使用 .NET 版本,可创建之后执行下面步骤:

  1. 替换 <TargetFramework>net6.0</TargetFramework><TargetFramework>net5.0</TargetFramework>

  2. 编辑所有层 .csproj 文件并添加 <LangVersion>10.0</LangVersion>,如:

<PropertyGroup>    <TargetFramework>net5.0</TargetFramework>    <LangVersion>10.0</LangVersion>    <!-- 其他配置 --></PropertyGroup>
  1. 如果使用的是 EFCore 版本则需要将启动层的 Microsoft.EntityFrameworkCore.Tools 版本改为 5.0.17 版本,如编辑启动层的 Web.Entry.csproj
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.7">    <PrivateAssets>all</PrivateAssets>    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets></PackageReference>

改为:

<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.17">    <PrivateAssets>all</PrivateAssets>    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets></PackageReference>
  1. 在启动层添加 Startup.cs 文件
namespace YourProject.Web.Entry;    // 你的项目命名空间public class Startup{    public Startup(IConfiguration configuration)    {        Configuration = configuration;    }    public IConfiguration Configuration { get; }    public void ConfigureServices(IServiceCollection services)    {    }    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    {    }}
  1. 修改 Program.cs 为:
using YourProject.Web.Entry;Serve.Run<Startup>(RunOptions.Default);

2.2.8 搭建脚手架

脚手架可以极大的提高我们搭建新项目的速度,推荐两篇文章给大家学习:

https://www.cnblogs.com/laozhang-is-phi/p/10205495.html

https://www.cnblogs.com/catcher1994/p/10061470.html

推荐直接拷贝 Furion 脚手架文件夹进行修改,可避免很多问题。

Furion 脚手架源码

2.2.9 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 模板知识 知识可查阅 dotnet-new 模板 章节。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/tran/index.html b/handbook/build/docs/tran/index.html index a33bf36809..050505973b 100644 --- a/handbook/build/docs/tran/index.html +++ b/handbook/build/docs/tran/index.html @@ -2,22 +2,21 @@ - - - + +9.26 事务和工作单元 | Furion -9.26 事务和工作单元 | Furion - - + + +
-

9.26 事务和工作单元

9.26.1 事务

事务指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行

简单的说,事务就是并发控制的单位,是用户定义的一个操作序列。 而一个逻辑工作单元要成为事务,就必须满足 ACID 属性。

  • A:原子性(Atomicity):事务中的操作要么都不做,要么就全做
  • C:一致性(Consistency):事务执行的结果必须是从数据库从一个一致性状态转换到另一个一致性状态
  • I:隔离性(Isolation):一个事务的执行不能被其他事务干扰
  • D:持久性(Durability):一个事务一旦提交,它对数据库中数据的改变就应该是永久性的

9.26.2 工作单元

简单来说,就是为了保证一次完整的功能操作所产生的一些列提交数据的完整性,起着事务的作用。在计算机领域中,工作单元通常用 UnitOfWork 名称表示。

通常我们保证用户的每一次请求都是处于在一个功能单元中,也就是工作单元。

9.26.3 如何使用

9.26.3.1 [UnitOfWork] 自动管理

Furion 框架中,我们只需要在控制器 Action 中贴 [UnitOfWork] 特性即可开启工作单元模式,保证了每一次请求都是一个 工作单元,要么同时成功,要么同时失败。

  • 单库操作

下面方式支持所有关系型数据库类型

[UnitOfWork]    // 由于出现错误,所以所有数据库变更都会自动回滚public async Task 测试环境事务(int id){    // 各种奇葩数据库操作    await _personRepository.DeleteNowAsync(id);    // 其他数据库操作。。    // 故意出错    var d = await _personRepository.SqlQueriesAsync("select * from persion2 d");}
  • 多库操作

支持各种奇葩的 ORM,包括 ADO.NETEFCore 等第三方,支持所有关系型数据库类型但不支持 Sqlite

[UnitOfWork(UseAmbientTransaction = true)]    // 由于出现错误,所以所有数据库变更都会自动回滚public async Task 测试环境事务(int id){    // 各种奇葩数据库操作    await _personRepository.DeleteNowAsync(id);    // 其他数据库操作。。    // 故意出错    var d = await _personRepository.SqlQueriesAsync("select * from persion2 d");}
  • UnitOfWork 内置配置:
    • UseAmbientTransaction:是否开启分布式环境事务,bool 类型,默认 false不支持 Sqlite
    • TransactionScope:配置分布式环境事务范围,TransactionScopeOption 类型,当 UseAmbientTransactiontrue 有效
    • TransactionIsolationLevel:配置分布式环境事务隔离级别,IsolationLevel 类型,当 UseAmbientTransactiontrue 有效
    • TransactionTimeout:配置分布式环境事务执行超时时间,int 类型,当 UseAmbientTransactiontrue 有效
    • TransactionScopeAsyncFlow:配置分布式环境事务异步流支持,TransactionScopeAsyncFlowOption 类型,当 UseAmbientTransactiontrue 有效
    • EnsureTransaction:强制使字符串 sql 拓展事务有效,bool 类型,默认 false
版本说明

以下内容仅限 Furion 3.7.3 + 版本使用。

如使用非 EFCore ORM 框架,可实现 IUnitOfWork 接口之后调用 services.AddUnitOfWork<TUnitOfWork>() 注册即可,如示例代码:

using Microsoft.AspNetCore.Mvc.Filters;namespace Furion.DatabaseAccessor;/// <summary>/// SqlSugar 工作单元实现/// </summary>public sealed class SqlSugarUnitOfWork : IUnitOfWork{    /// <summary>    /// SqlSugar 对象    /// </summary>    private readonly ISqlSugarClient _sqlSugarClient;    /// <summary>    /// 构造函数    /// </summary>    /// <param name="sqlSugarClient"></param>    public SqlSugarUnitOfWork(ISqlSugarClient sqlSugarClient)    {        _sqlSugarClient = sqlSugarClient;    }    /// <summary>    /// 开启工作单元处理    /// </summary>    /// <param name="context"></param>    /// <param name="unitOfWork"></param>    /// <exception cref="NotImplementedException"></exception>    public void BeginTransaction(FilterContext context, UnitOfWorkAttribute unitOfWork)    {        _sqlSugarClient.AsTenant().BeginTran();    }    /// <summary>    /// 提交工作单元处理    /// </summary>    /// <param name="resultContext"></param>    /// <param name="unitOfWork"></param>    /// <exception cref="NotImplementedException"></exception>    public void CommitTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork)    {        _sqlSugarClient.AsTenant().CommitTran();    }    /// <summary>    /// 回滚工作单元处理    /// </summary>    /// <param name="resultContext"></param>    /// <param name="unitOfWork"></param>    /// <exception cref="NotImplementedException"></exception>    public void RollbackTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork)    {        _sqlSugarClient.AsTenant().RollbackTran();    }    /// <summary>    /// 执行完毕(无论成功失败)    /// </summary>    /// <param name="context"></param>    /// <param name="resultContext"></param>    /// <exception cref="NotImplementedException"></exception>    public void OnCompleted(FilterContext context, FilterContext resultContext)    {        _sqlSugarClient.Dispose();    }}

之后注册即可:

services.AddUnitOfWork<SqlSugarUnitOfWork>();
小知识-如何判断是否开启了分布式环境事务

有时候我们自定义了工作单元之后,个别 ORM 不支持分布式环境事务,那么就会出现执行错误,我们可以通过 System.Transactions.Transaction.Current != null 来判断是否启用了分布式环境事务,不等于 null 则为启用,否则未启用。

9.26.3.2 EnsureTransaction() 方法 ✨

有些时候我们通过静态类或者其他方式不小心创建了新的 DbContext 实例,这时候贴了 [UnitOfWork] 也不见起效,这时候可以通过以下方法来确认事务是否有效:

repository.EnsureTransaction();

如果不喜欢手动方式也可以通过 [UnitOfWork(true)] 开启此功能。

该方法会将当前仓储添加到数据库上下文池中,并确保事务可用。

9.26.3.2 手动管理

// 开启事务using (var transaction = _testRepository.Database.BeginTransaction()){    try    {        _testRepository.Insert(new Blog { Url = "http://blogs.msdn.com/dotnet" });        _testRepository.SaveNow();        _testRepository.Insert(new Blog { Url = "http://blogs.msdn.com/visualstudio" });        _testRepository.SaveNow();        var blogs = _testRepository.Entity                .OrderBy(b => b.Url)                .ToList();        // 提交事务        transaction.Commit();     }     catch (Exception)     {        // 回滚事务        // transaction.RollBack(); // 新版本自动回滚了     }}

9.26.4 工作单元特性说明

9.26.4.1 [UnitOfWork] 特性

[UnitOfWork] 特性只能用于控制器的 Action 中,一旦贴了 [UnitOfWork] 特性后,那么该请求自动启用工作单元模式,要么成功,要么失败。

9.26.4.2 [ManualCommit] 特性

默认情况下,Furion 框架会在一次成功请求之后自动调用 SaveChanges() 方法,如果选择手动调用 SaveChanges() 方法,可以在控制器 Action 中贴 [ManualCommit] 特性即可。

9.26.5 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 事务 知识可查阅 EF Core - 使用事务 章节。

演练场
- - +

9.26 事务和工作单元

9.26.1 事务

事务指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行

简单的说,事务就是并发控制的单位,是用户定义的一个操作序列。 而一个逻辑工作单元要成为事务,就必须满足 ACID 属性。

  • A:原子性(Atomicity):事务中的操作要么都不做,要么就全做
  • C:一致性(Consistency):事务执行的结果必须是从数据库从一个一致性状态转换到另一个一致性状态
  • I:隔离性(Isolation):一个事务的执行不能被其他事务干扰
  • D:持久性(Durability):一个事务一旦提交,它对数据库中数据的改变就应该是永久性的

9.26.2 工作单元

简单来说,就是为了保证一次完整的功能操作所产生的一些列提交数据的完整性,起着事务的作用。在计算机领域中,工作单元通常用 UnitOfWork 名称表示。

通常我们保证用户的每一次请求都是处于在一个功能单元中,也就是工作单元。

9.26.3 如何使用

9.26.3.1 [UnitOfWork] 自动管理

Furion 框架中,我们只需要在控制器 Action 中贴 [UnitOfWork] 特性即可开启工作单元模式,保证了每一次请求都是一个 工作单元,要么同时成功,要么同时失败。

  • 单库操作

下面方式支持所有关系型数据库类型

[UnitOfWork]    // 由于出现错误,所以所有数据库变更都会自动回滚public async Task 测试环境事务(int id){    // 各种奇葩数据库操作    await _personRepository.DeleteNowAsync(id);    // 其他数据库操作。。    // 故意出错    var d = await _personRepository.SqlQueriesAsync("select * from persion2 d");}
  • 多库操作

支持各种奇葩的 ORM,包括 ADO.NETEFCore 等第三方,支持所有关系型数据库类型但不支持 Sqlite

[UnitOfWork(UseAmbientTransaction = true)]    // 由于出现错误,所以所有数据库变更都会自动回滚public async Task 测试环境事务(int id){    // 各种奇葩数据库操作    await _personRepository.DeleteNowAsync(id);    // 其他数据库操作。。    // 故意出错    var d = await _personRepository.SqlQueriesAsync("select * from persion2 d");}
  • UnitOfWork 内置配置:
    • UseAmbientTransaction:是否开启分布式环境事务,bool 类型,默认 false不支持 Sqlite
    • TransactionScope:配置分布式环境事务范围,TransactionScopeOption 类型,当 UseAmbientTransactiontrue 有效
    • TransactionIsolationLevel:配置分布式环境事务隔离级别,IsolationLevel 类型,当 UseAmbientTransactiontrue 有效
    • TransactionTimeout:配置分布式环境事务执行超时时间,int 类型,当 UseAmbientTransactiontrue 有效
    • TransactionScopeAsyncFlow:配置分布式环境事务异步流支持,TransactionScopeAsyncFlowOption 类型,当 UseAmbientTransactiontrue 有效
    • EnsureTransaction:强制使字符串 sql 拓展事务有效,bool 类型,默认 false
版本说明

以下内容仅限 Furion 3.7.3 + 版本使用。

如使用非 EFCore ORM 框架,可实现 IUnitOfWork 接口之后调用 services.AddUnitOfWork<TUnitOfWork>() 注册即可,如示例代码:

using Microsoft.AspNetCore.Mvc.Filters;namespace Furion.DatabaseAccessor;/// <summary>/// SqlSugar 工作单元实现/// </summary>public sealed class SqlSugarUnitOfWork : IUnitOfWork{    /// <summary>    /// SqlSugar 对象    /// </summary>    private readonly ISqlSugarClient _sqlSugarClient;    /// <summary>    /// 构造函数    /// </summary>    /// <param name="sqlSugarClient"></param>    public SqlSugarUnitOfWork(ISqlSugarClient sqlSugarClient)    {        _sqlSugarClient = sqlSugarClient;    }    /// <summary>    /// 开启工作单元处理    /// </summary>    /// <param name="context"></param>    /// <param name="unitOfWork"></param>    /// <exception cref="NotImplementedException"></exception>    public void BeginTransaction(FilterContext context, UnitOfWorkAttribute unitOfWork)    {        _sqlSugarClient.AsTenant().BeginTran();    }    /// <summary>    /// 提交工作单元处理    /// </summary>    /// <param name="resultContext"></param>    /// <param name="unitOfWork"></param>    /// <exception cref="NotImplementedException"></exception>    public void CommitTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork)    {        _sqlSugarClient.AsTenant().CommitTran();    }    /// <summary>    /// 回滚工作单元处理    /// </summary>    /// <param name="resultContext"></param>    /// <param name="unitOfWork"></param>    /// <exception cref="NotImplementedException"></exception>    public void RollbackTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork)    {        _sqlSugarClient.AsTenant().RollbackTran();    }    /// <summary>    /// 执行完毕(无论成功失败)    /// </summary>    /// <param name="context"></param>    /// <param name="resultContext"></param>    /// <exception cref="NotImplementedException"></exception>    public void OnCompleted(FilterContext context, FilterContext resultContext)    {        _sqlSugarClient.Dispose();    }}

之后注册即可:

services.AddUnitOfWork<SqlSugarUnitOfWork>();
小知识-如何判断是否开启了分布式环境事务

有时候我们自定义了工作单元之后,个别 ORM 不支持分布式环境事务,那么就会出现执行错误,我们可以通过 System.Transactions.Transaction.Current != null 来判断是否启用了分布式环境事务,不等于 null 则为启用,否则未启用。

9.26.3.2 EnsureTransaction() 方法 ✨

有些时候我们通过静态类或者其他方式不小心创建了新的 DbContext 实例,这时候贴了 [UnitOfWork] 也不见起效,这时候可以通过以下方法来确认事务是否有效:

repository.EnsureTransaction();

如果不喜欢手动方式也可以通过 [UnitOfWork(true)] 开启此功能。

该方法会将当前仓储添加到数据库上下文池中,并确保事务可用。

9.26.3.2 手动管理

// 开启事务using (var transaction = _testRepository.Database.BeginTransaction()){    try    {        _testRepository.Insert(new Blog { Url = "http://blogs.msdn.com/dotnet" });        _testRepository.SaveNow();        _testRepository.Insert(new Blog { Url = "http://blogs.msdn.com/visualstudio" });        _testRepository.SaveNow();        var blogs = _testRepository.Entity                .OrderBy(b => b.Url)                .ToList();        // 提交事务        transaction.Commit();     }     catch (Exception)     {        // 回滚事务        // transaction.RollBack(); // 新版本自动回滚了     }}

9.26.4 工作单元特性说明

9.26.4.1 [UnitOfWork] 特性

[UnitOfWork] 特性只能用于控制器的 Action 中,一旦贴了 [UnitOfWork] 特性后,那么该请求自动启用工作单元模式,要么成功,要么失败。

9.26.4.2 [ManualCommit] 特性

默认情况下,Furion 框架会在一次成功请求之后自动调用 SaveChanges() 方法,如果选择手动调用 SaveChanges() 方法,可以在控制器 Action 中贴 [ManualCommit] 特性即可。

9.26.5 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 事务 知识可查阅 EF Core - 使用事务 章节。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/unittest/index.html b/handbook/build/docs/unittest/index.html index 01619548e7..c2e8ff5d65 100644 --- a/handbook/build/docs/unittest/index.html +++ b/handbook/build/docs/unittest/index.html @@ -2,22 +2,21 @@ - - - + +36.1 单元/集成测试 | Furion -36.1 单元/集成测试 | Furion - - + + +
-

36.1 单元/集成测试

36.1.1 关于单元测试

引用自百度百科:

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如 C 语言中单元指一个函数,Java 里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

36.1.2 单元测试好处

  • 消灭低级错误

基本的单元测试,可以在系统测试之前,把大部分比较低级的错误都消灭掉,减少系统测试过程中的问题,这样也就减少了系统测试中定位和解决问题的时间成本了。

  • 找出潜在的 bug

某些类型的 bug,靠系统测试是很难找到的。例如一些代码分支,平时 99%的场景基本上都走不到,但一旦走到了,如果没有提前测试好,那么可能就是一个灾难。

  • 上线前的保证

加了新代码,上线前跑一把单元测试,都通过,说明代码可能没有影响到之前的逻辑,这样上线也比较放心。如果之前的单元测试跑不过,那么很有可能新的代码有潜在的问题,赶紧修复去吧。

  • 重构代码的机会

写单元测试的过程中,你可能会顺手把一些 code 重构了,为什么?举例,一些长得非常像的代码,如果每次都要写一堆测试代码去测同样的 code,你会不会抓狂?不测吧,覆盖率又上不去,于是我就会想方设法把待测试的 code 改得尽量的精简,重复代码减少,这样覆盖率上去了,测试也好测了,代码也简洁了。如果没有单元测试和覆盖率的要求的话,坦白说可能一来自己不会发现这些重复的 code,另一方面即使发现了,可能也没有太大的动力去改进。

另外,由于单元测试中,你需要尝试去覆盖一些异常分支,这是系统测试常常走不到的地方,于是就会引起你的一些思考,例如这个异常分支是否真的需要?是否真的会发生?对于一些实际上绝对不会出错的函数,那么我觉得可能异常分支是没必要存在的。

  • 重新 review 代码的机会

写 UT 的过程中,我总是会好好看哪些代码执行到了,哪些代码没有执行到,这其实也是一个 review 自己代码的机会,有些时候,并不是 UT 本身帮我找到 bug,而是回头 review 自己代码的时候发现的。

36.1.3 单元测试类型

  • 基于 API 接口测试(白盒 + 浅度黑盒测试)
  • 基于项目代码测试(深度黑盒测试)

36.1.4 主流的单元测试库

  • xUnit最流行的库,推荐
  • NUnit
  • MSTest

在本章节,Furion 框架使用 xUnit 库进行单元测试。

36.1.5 第一个例子

36.1.5.1 创建 xUnit 单元测试项目

36.1.5.2 第一个测试方法

using Xunit;namespace TestProject1{    public class UnitTest1    {        [Fact]        public void Test1()        {            Assert.Equal(2, 1 + 1);        }    }}

单元测试实际上是通过普通的类的方法进行模块功能测试,具体测试则是标记了 [Fact] 特性的方法,在方法中使用 Assert 类提供的静态方法进行 断言断言 成功,则测试通过,否则测试不通过。

36.1.5.3 运行测试

在单元测试项目中 右键 选择 运行测试 并打开 测试资源管理器 即可查看测试结果。

36.1.5.4 多个测试方法测试

36.1.5.5 重复/回归测试

后续添加更多测试方法只需在 测试资源管理器 点击 在视图中运行所有测试 播放按钮即可,如下图

36.1.6 集成 Furion 强大功能

Furion 是跨平台、跨项目的开发框架,支持任意项目类型,包括单元测试项目。

36.1.6.1 安装 Furion.Xunit

Furion 纯净版

如果使用的是 Furion.Pure 则安装 Furion.Pure.Xunit 这个拓展包。

打开 Nuget 程序包控制台,安装 Furion.Xunit

特别注意

Furion.Xunit 已经包含 Furion 无需再次安装 Furion

36.1.6.2 添加初始配置类

在单元测试项目根目录下添加 TestProgram.cs 类,并写下以下代码:

TestProgram.cs
using Furion.Xunit;using Xunit.Abstractions;using Xunit.Sdk;// 配置启动类类型,第一个参数是 TestProgram 类完整限定名,第二个参数是当前项目程序集名称[assembly: TestFramework("TestProject1.TestProgram", "TestProject1")]namespace TestProject1;/// <summary>/// 单元测试启动类/// </summary>public class TestProgram : TestStartup{    public TestProgram(IMessageSink messageSink) : base(messageSink)    {        // 初始化 Furion        Serve.Run(silence: true);    }}
小提示

TestProgram.cs 名称可随意,只需要继承 TestStartup 类即可。

36.1.6.3 使用 Furion 完整功能

Furion 是跨平台、跨项目的开发框架,下面在单元测试中演示 远程请求 并请求 https://www.baidu.com 数据,并测试是否请求成功。

  • 在根目录下添加 Startup.cs 启动类,并继承 AppStartup:
Startup.cs
using Furion;using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;namespace TestProject1;public class Startup : AppStartup{    public void ConfigureServices(IServiceCollection services)    {        // 注册远程服务        services.AddRemoteRequest();    }    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    {    }}
  • 编写测试方法
[Fact]public async Task 测试请求百度(){    var rep = await "https://www.baidu.com".GetAsync();    Assert.True(rep.IsSuccessStatusCode);}
  • 查看测试结果

很神奇吧!Furion 支持任何项目类型,任何平台使用。

36.1.7 带参数的测试方法

上面例子中,测试方法都是没有参数的,有时候需要同一个方法输入多个不同的值进行测试,这时候就需要用到 [Theory][InlineData] 特性了。

如,下面测试两个数的和是 奇数,测试代码如下:

[Theory][InlineData(1, 2)][InlineData(3, 4)][InlineData(5, 7)]public void 带参数测试(int i, int j){    Assert.NotEqual(0, (i + j) % 2);}

测试结果:

36.1.8 如何进行依赖注入

有些时候,我们需要测试某接口,或者进行依赖注入方式解析服务并调用,Furion.Xunit 提供完整的构造函数注入。

36.1.8.1 编写一个 ICalcService 接口及实现类

using Furion.DependencyInjection;namespace TestProject1.Services;public interface ICalcService{    int Plus(int i, int j);}public class CalcService : ICalcService, ITransient // 支持任何生命周期{    public int Plus(int i, int j)    {        return i + j;    }}

36.1.8.2 在测试类中调用

using TestProject1.Services;using Xunit;namespace TestProject1;public class UnitTest1{    private readonly ICalcService _calcService;    public UnitTest1(ICalcService calcService)    {        _calcService = calcService;    }    [Fact]    public void 测试两个数的和()    {        Assert.Equal(3, _calcService.Plus(1, 2));    }}

36.1.8.3 输出日志

如果在单元测试中想输出日志,只需要在构造函数注入 ITestOutputHelper 即可,如:

using Xunit;using Xunit.Abstractions;namespace TestProject1{    public class UnitTest1    {        private readonly ITestOutputHelper Output;        public UnitTest1(ITestOutputHelper tempOutput)        {            Output = tempOutput;        }        [Fact]        public void Test_String_Equal()        {            Output.WriteLine("哈哈哈哈,我是 Furion");            Assert.NotEqual("Furion", "Fur");        }    }}

36.1.8.4 关于依赖注入作用域释放

Furion 会在创建单元测试实例时创建一个 IServiceScope 对象,等该实例所有测试案例执行完毕自动调用 Dispose,编写测试的开发者无需关注。

36.1.8.5 测试释放资源

有时候,我们需要测试成功后释放一些不能及时释放的对象,这时,只需要实现 IDisposable 接口即可:

using System;using Xunit;namespace TestProject1{    public class UnitTest1 : IDisposable    {        [Fact]        public void Test_String_Equal()        {            Assert.NotEqual("Furion", "Fur");        }        public void Dispose()        {            // 释放你的对象        }    }}

36.1.8.6 [AssemblyFixture] 特性

有时候我们可能不需要对类进行依赖注册,或者无法通过外部进行注册,这时候可以通过 [AssemblyFixture] 特性实现构造函数注入任何类,如:

有效范围说明

[AssemblyFixture] 方式对整个单元测试类构造函数都有效,如需个别单元测试类有效可使用 IClassFixture<>ICollectionFixture<> + [Collection] 组合方式。

  • 定义需要注入进单元测试构造函数中的类
public class MyAssemblyFixture : IDisposable{    public static int InstantiationCount;    public MyAssemblyFixture()    {        InstantiationCount++;    }    public void Dispose()    {        // 做一些释放工作    }}
  • TestProgram.cs 顶部全局注册
TestProgram.cs
using Furion.Xunit;using TestProject1;using Xunit;using Xunit.Abstractions;using Xunit.Sdk;// 配置启动类类型,第一个参数是 TestProgram 类完整限定名,第二个参数是当前项目程序集名称[assembly: TestFramework("TestProject1.TestProgram", "TestProject1")]// 支持多个[assembly: AssemblyFixture(typeof(MyAssemblyFixture))]// [assembly: AssemblyFixture(typeof(XXXXFixture))]namespace TestProject1;/// <summary>/// 单元测试启动类/// </summary>public class TestProgram : TestStartup{    public TestProgram(IMessageSink messageSink) : base(messageSink)    {        Serve.Run(silence: true);    }}
  • 在测试类构造函数注入
using TestProject1.Services;using Xunit;namespace TestProject1;public class UnitTest1{    private readonly ICalcService _calcService;    private readonly MyAssemblyFixture _fixture;    public UnitTest1(ICalcService calcService        , MyAssemblyFixture fixture)    {        _calcService = calcService;        _fixture = fixture;    }    [Fact]    public void 测试两个数的和()    {        Assert.Equal(3, _calcService.Plus(1, 2));    }    [Fact]    public void EnsureSingleton()    {        Assert.Equal(1, MyAssemblyFixture.InstantiationCount);    }}

36.1.8.7 IClassFixture<> 单个注入

通过上面 [AssemblyFixture] 方式我们知道此方式对全局的单元测试类都有效,但有时候我们只需要特定单元测试类有效,则可通过 IClassFixture<> 方式,如:

  • 定义需要注入进单元测试构造函数中的类
public class MyClassFixture : IDisposable{    public static int InstantiationCount;    public MyClassFixture()    {        InstantiationCount++;    }    public void Dispose()    {        // 做一些释放工作    }}
  • 在测试类构造函数注入
using TestProject1.Services;using Xunit;namespace TestProject1;public class UnitTest1 : IClassFixture<MyClassFixture>{    private readonly ICalcService _calcService;    private readonly MyAssemblyFixture _fixture;    private readonly MyClassFixture _classFixture;    public UnitTest1(ICalcService calcService        , MyAssemblyFixture fixture        , MyClassFixture classFixture)    {        _calcService = calcService;        _fixture = fixture;        _classFixture = classFixture;    }    [Fact]    public void 测试两个数的和()    {        Assert.Equal(3, _calcService.Plus(1, 2));    }    [Fact]    public void EnsureSingleton()    {        Assert.Equal(1, MyAssemblyFixture.InstantiationCount);    }    [Fact]    public void EnsureClassSingleton()    {        Assert.Equal(1, MyClassFixture.InstantiationCount);    }}

36.1.8.8 ICollectionFixture<> 多个注入

ICollectionFixture<> 方式和 IClassFixture<> 方式最大的不同就是后者只能配置为单个测试类使用,而 ICollectionFixture<> 则通过 [Collection] 方式配置多个测试类有效,如:

  • 定义需要注入进单元测试构造函数中的类
特别注意

这里区别于 IClassFixture<> 方式,需定义配置器并实现 ICollectionFixture<> 接口。

using Xunit;namespace TestProject1;public class MyCollectionFixture : IDisposable{    public static int InstantiationCount;    public MyCollectionFixture()    {        InstantiationCount++;    }    public void Dispose()    {        // 做一些释放工作    }}[CollectionDefinition("MyCollection")]public class MyCollection : ICollectionFixture<MyCollectionFixture>{}
  • 在测试类构造函数注入
using TestProject1.Services;using Xunit;namespace TestProject1;[Collection("MyCollection")]public class UnitTest1 : IClassFixture<MyClassFixture>{    private readonly ICalcService _calcService;    private readonly MyAssemblyFixture _fixture;    private readonly MyClassFixture _classFixture;    private readonly MyCollectionFixture _collectionFixture;    public UnitTest1(ICalcService calcService        , MyAssemblyFixture fixture        , MyClassFixture classFixture        , MyCollectionFixture collectionFixture)    {        _calcService = calcService;        _fixture = fixture;        _classFixture = classFixture;        _collectionFixture = collectionFixture;    }    [Fact]    public void 测试两个数的和()    {        Assert.Equal(3, _calcService.Plus(1, 2));    }    [Fact]    public void EnsureSingleton()    {        Assert.Equal(1, MyAssemblyFixture.InstantiationCount);    }    [Fact]    public void EnsureClassSingleton()    {        Assert.Equal(1, MyClassFixture.InstantiationCount);    }    [Fact]    public void EnsureCollectionSingleton()    {        Assert.Equal(1, MyCollectionFixture.InstantiationCount);    }}

36.1.9 Web 集成测试

Web 集成测试有三种方式,通过这三种方式可以对项目进行全方位的测试,保证部署上线是测试期盼效果。

36.1.9.1 对现有项目进行集成测试

这种方式比较简单,也是最常用的方式,无需部署到服务器直接在本地即可测试,如:

  1. 创建 Xunit 单元测试项目
  1. 添加 Microsoft.AspNetCore.Mvc.Testing 微软提供的集成测试拓展
  1. 添加测试项目或使用已有的测试项目引用
  1. 在需要测试的 Web 项目启动层添加 FakeStarup.cs
FakeStarup.cs
namespace WebApplication1;/// <summary>/// 供集成测试使用/// </summary>public class FakeStartup{}
  1. 编写测试 Web 项目接口测试案例
using Microsoft.AspNetCore.Mvc.Testing;using Xunit;namespace TestProject2;public class UnitTest1 : IClassFixture<WebApplicationFactory<WebApplication1.FakeStartup>>{    private readonly WebApplicationFactory<WebApplication1.FakeStartup> _factory;    public UnitTest1(WebApplicationFactory<WebApplication1.FakeStartup> factory)    {        _factory = factory;    }    [Theory]    [InlineData("/default")]    public async Task TestEnsureSuccessStatusCode(string url)    {        using var client = _factory.CreateClient();        using var response = await client.GetAsync(url);        response.EnsureSuccessStatusCode();    }}

/default 接口对应控制器定义如下:

using Microsoft.AspNetCore.Mvc;namespace WebApplication1.Controllers{    [ApiController]    [Route("[controller]")]    public class DefaultController : ControllerBase    {        [HttpGet]        public string Get()        {            return "Furion 集成测试";        }    }}
  1. 允许测试

36.1.9.2 独立主机方式测试

独立主机的方式就是利用单元测试的每一个测试案例构建主机进行测试。

  1. 创建 Xunit 单元测试项目
  1. 添加 Microsoft.AspNetCore.Mvc.Testing 微软提供的集成测试拓展
  1. 各种创建主机方式示例
using Microsoft.AspNetCore.Builder;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;using Xunit;namespace TestProject3;public class UnitTest1{    /// <summary>    /// 创建主机并注册服务    /// </summary>    /// <remarks>可用来判断服务是否注册</remarks>    [Fact]    public void Test1()    {        var builder = WebApplication.CreateBuilder();        // 注册服务        builder.Services.AddScoped<IYourService, YourService>();        using var app = builder.Build();        var services = app.Services;        services.GetRequiredService<IYourService>();    }    /// <summary>    /// 测试配置    /// </summary>    /// <remarks>比如添加 JSON 文件配置后读取</remarks>    [Fact]    public void Test2()    {        var builder = WebApplication.CreateBuilder();        var host = builder.Host;        host.ConfigureAppConfiguration(builder =>        {            builder.Sources.Clear();        });        var config = builder.Configuration["配置"];        // 判断不为空    }}

36.1.9.3 系统集成/环境/配置部署测试

有时候我们需要测试 Web 主机各种情况,比如端口是否有效,环境配置是否有效,系统集成情况等等,这时候只需要添加 Microsoft.AspNetCore.TestHost 拓展,然后在测试类顶部贴:

[assembly: HostingStartup(typeof(WebApplicationTests.TestHostingStartup))]

微软已经提供了非常详细的例子,这里直接放链接 https://github.com/dotnet/aspnetcore/tree/main/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests

WebApplicationTests.TestHostingStartup 为您要测试的 Web 项目启动类。

36.1.9.4 集成 Furion.Xunit 拓展

Web 集成测试支持完整的 Furion 特性,参考上面单元测试集成 Furion 章节。

Furion 纯净版

如果使用的是 Furion.Pure 则安装 Furion.Pure.Xunit 这个拓展包。

36.1.10 Assert 断言

Assert 是单元测试判定成功的依据,通常第一个参数为 期望值,第二个参数为 实际值,对比这两个值是否一致即可判断成功与否。详细的 Assert 静态方法可查阅官方库 Assert 方法

36.1.11 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 单元测试 知识可查阅 在 .NET 中测试 章节。

演练场
- - +

36.1 单元/集成测试

36.1.1 关于单元测试

引用自百度百科:

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如 C 语言中单元指一个函数,Java 里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

36.1.2 单元测试好处

  • 消灭低级错误

基本的单元测试,可以在系统测试之前,把大部分比较低级的错误都消灭掉,减少系统测试过程中的问题,这样也就减少了系统测试中定位和解决问题的时间成本了。

  • 找出潜在的 bug

某些类型的 bug,靠系统测试是很难找到的。例如一些代码分支,平时 99%的场景基本上都走不到,但一旦走到了,如果没有提前测试好,那么可能就是一个灾难。

  • 上线前的保证

加了新代码,上线前跑一把单元测试,都通过,说明代码可能没有影响到之前的逻辑,这样上线也比较放心。如果之前的单元测试跑不过,那么很有可能新的代码有潜在的问题,赶紧修复去吧。

  • 重构代码的机会

写单元测试的过程中,你可能会顺手把一些 code 重构了,为什么?举例,一些长得非常像的代码,如果每次都要写一堆测试代码去测同样的 code,你会不会抓狂?不测吧,覆盖率又上不去,于是我就会想方设法把待测试的 code 改得尽量的精简,重复代码减少,这样覆盖率上去了,测试也好测了,代码也简洁了。如果没有单元测试和覆盖率的要求的话,坦白说可能一来自己不会发现这些重复的 code,另一方面即使发现了,可能也没有太大的动力去改进。

另外,由于单元测试中,你需要尝试去覆盖一些异常分支,这是系统测试常常走不到的地方,于是就会引起你的一些思考,例如这个异常分支是否真的需要?是否真的会发生?对于一些实际上绝对不会出错的函数,那么我觉得可能异常分支是没必要存在的。

  • 重新 review 代码的机会

写 UT 的过程中,我总是会好好看哪些代码执行到了,哪些代码没有执行到,这其实也是一个 review 自己代码的机会,有些时候,并不是 UT 本身帮我找到 bug,而是回头 review 自己代码的时候发现的。

36.1.3 单元测试类型

  • 基于 API 接口测试(白盒 + 浅度黑盒测试)
  • 基于项目代码测试(深度黑盒测试)

36.1.4 主流的单元测试库

  • xUnit最流行的库,推荐
  • NUnit
  • MSTest

在本章节,Furion 框架使用 xUnit 库进行单元测试。

36.1.5 第一个例子

36.1.5.1 创建 xUnit 单元测试项目

36.1.5.2 第一个测试方法

using Xunit;namespace TestProject1{    public class UnitTest1    {        [Fact]        public void Test1()        {            Assert.Equal(2, 1 + 1);        }    }}

单元测试实际上是通过普通的类的方法进行模块功能测试,具体测试则是标记了 [Fact] 特性的方法,在方法中使用 Assert 类提供的静态方法进行 断言断言 成功,则测试通过,否则测试不通过。

36.1.5.3 运行测试

在单元测试项目中 右键 选择 运行测试 并打开 测试资源管理器 即可查看测试结果。

36.1.5.4 多个测试方法测试

36.1.5.5 重复/回归测试

后续添加更多测试方法只需在 测试资源管理器 点击 在视图中运行所有测试 播放按钮即可,如下图

36.1.6 集成 Furion 强大功能

Furion 是跨平台、跨项目的开发框架,支持任意项目类型,包括单元测试项目。

36.1.6.1 安装 Furion.Xunit

Furion 纯净版

如果使用的是 Furion.Pure 则安装 Furion.Pure.Xunit 这个拓展包。

打开 Nuget 程序包控制台,安装 Furion.Xunit

特别注意

Furion.Xunit 已经包含 Furion 无需再次安装 Furion

36.1.6.2 添加初始配置类

在单元测试项目根目录下添加 TestProgram.cs 类,并写下以下代码:

TestProgram.cs
using Furion.Xunit;using Xunit.Abstractions;using Xunit.Sdk;// 配置启动类类型,第一个参数是 TestProgram 类完整限定名,第二个参数是当前项目程序集名称[assembly: TestFramework("TestProject1.TestProgram", "TestProject1")]namespace TestProject1;/// <summary>/// 单元测试启动类/// </summary>public class TestProgram : TestStartup{    public TestProgram(IMessageSink messageSink) : base(messageSink)    {        // 初始化 Furion        Serve.Run(silence: true);    }}
小提示

TestProgram.cs 名称可随意,只需要继承 TestStartup 类即可。

36.1.6.3 使用 Furion 完整功能

Furion 是跨平台、跨项目的开发框架,下面在单元测试中演示 远程请求 并请求 https://www.baidu.com 数据,并测试是否请求成功。

  • 在根目录下添加 Startup.cs 启动类,并继承 AppStartup:
Startup.cs
using Furion;using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.DependencyInjection;namespace TestProject1;public class Startup : AppStartup{    public void ConfigureServices(IServiceCollection services)    {        // 注册远程服务        services.AddRemoteRequest();    }    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    {    }}
  • 编写测试方法
[Fact]public async Task 测试请求百度(){    var rep = await "https://www.baidu.com".GetAsync();    Assert.True(rep.IsSuccessStatusCode);}
  • 查看测试结果

很神奇吧!Furion 支持任何项目类型,任何平台使用。

36.1.7 带参数的测试方法

上面例子中,测试方法都是没有参数的,有时候需要同一个方法输入多个不同的值进行测试,这时候就需要用到 [Theory][InlineData] 特性了。

如,下面测试两个数的和是 奇数,测试代码如下:

[Theory][InlineData(1, 2)][InlineData(3, 4)][InlineData(5, 7)]public void 带参数测试(int i, int j){    Assert.NotEqual(0, (i + j) % 2);}

测试结果:

36.1.8 如何进行依赖注入

有些时候,我们需要测试某接口,或者进行依赖注入方式解析服务并调用,Furion.Xunit 提供完整的构造函数注入。

36.1.8.1 编写一个 ICalcService 接口及实现类

using Furion.DependencyInjection;namespace TestProject1.Services;public interface ICalcService{    int Plus(int i, int j);}public class CalcService : ICalcService, ITransient // 支持任何生命周期{    public int Plus(int i, int j)    {        return i + j;    }}

36.1.8.2 在测试类中调用

using TestProject1.Services;using Xunit;namespace TestProject1;public class UnitTest1{    private readonly ICalcService _calcService;    public UnitTest1(ICalcService calcService)    {        _calcService = calcService;    }    [Fact]    public void 测试两个数的和()    {        Assert.Equal(3, _calcService.Plus(1, 2));    }}

36.1.8.3 输出日志

如果在单元测试中想输出日志,只需要在构造函数注入 ITestOutputHelper 即可,如:

using Xunit;using Xunit.Abstractions;namespace TestProject1{    public class UnitTest1    {        private readonly ITestOutputHelper Output;        public UnitTest1(ITestOutputHelper tempOutput)        {            Output = tempOutput;        }        [Fact]        public void Test_String_Equal()        {            Output.WriteLine("哈哈哈哈,我是 Furion");            Assert.NotEqual("Furion", "Fur");        }    }}

36.1.8.4 关于依赖注入作用域释放

Furion 会在创建单元测试实例时创建一个 IServiceScope 对象,等该实例所有测试案例执行完毕自动调用 Dispose,编写测试的开发者无需关注。

36.1.8.5 测试释放资源

有时候,我们需要测试成功后释放一些不能及时释放的对象,这时,只需要实现 IDisposable 接口即可:

using System;using Xunit;namespace TestProject1{    public class UnitTest1 : IDisposable    {        [Fact]        public void Test_String_Equal()        {            Assert.NotEqual("Furion", "Fur");        }        public void Dispose()        {            // 释放你的对象        }    }}

36.1.8.6 [AssemblyFixture] 特性

有时候我们可能不需要对类进行依赖注册,或者无法通过外部进行注册,这时候可以通过 [AssemblyFixture] 特性实现构造函数注入任何类,如:

有效范围说明

[AssemblyFixture] 方式对整个单元测试类构造函数都有效,如需个别单元测试类有效可使用 IClassFixture<>ICollectionFixture<> + [Collection] 组合方式。

  • 定义需要注入进单元测试构造函数中的类
public class MyAssemblyFixture : IDisposable{    public static int InstantiationCount;    public MyAssemblyFixture()    {        InstantiationCount++;    }    public void Dispose()    {        // 做一些释放工作    }}
  • TestProgram.cs 顶部全局注册
TestProgram.cs
using Furion.Xunit;using TestProject1;using Xunit;using Xunit.Abstractions;using Xunit.Sdk;// 配置启动类类型,第一个参数是 TestProgram 类完整限定名,第二个参数是当前项目程序集名称[assembly: TestFramework("TestProject1.TestProgram", "TestProject1")]// 支持多个[assembly: AssemblyFixture(typeof(MyAssemblyFixture))]// [assembly: AssemblyFixture(typeof(XXXXFixture))]namespace TestProject1;/// <summary>/// 单元测试启动类/// </summary>public class TestProgram : TestStartup{    public TestProgram(IMessageSink messageSink) : base(messageSink)    {        Serve.Run(silence: true);    }}
  • 在测试类构造函数注入
using TestProject1.Services;using Xunit;namespace TestProject1;public class UnitTest1{    private readonly ICalcService _calcService;    private readonly MyAssemblyFixture _fixture;    public UnitTest1(ICalcService calcService        , MyAssemblyFixture fixture)    {        _calcService = calcService;        _fixture = fixture;    }    [Fact]    public void 测试两个数的和()    {        Assert.Equal(3, _calcService.Plus(1, 2));    }    [Fact]    public void EnsureSingleton()    {        Assert.Equal(1, MyAssemblyFixture.InstantiationCount);    }}

36.1.8.7 IClassFixture<> 单个注入

通过上面 [AssemblyFixture] 方式我们知道此方式对全局的单元测试类都有效,但有时候我们只需要特定单元测试类有效,则可通过 IClassFixture<> 方式,如:

  • 定义需要注入进单元测试构造函数中的类
public class MyClassFixture : IDisposable{    public static int InstantiationCount;    public MyClassFixture()    {        InstantiationCount++;    }    public void Dispose()    {        // 做一些释放工作    }}
  • 在测试类构造函数注入
using TestProject1.Services;using Xunit;namespace TestProject1;public class UnitTest1 : IClassFixture<MyClassFixture>{    private readonly ICalcService _calcService;    private readonly MyAssemblyFixture _fixture;    private readonly MyClassFixture _classFixture;    public UnitTest1(ICalcService calcService        , MyAssemblyFixture fixture        , MyClassFixture classFixture)    {        _calcService = calcService;        _fixture = fixture;        _classFixture = classFixture;    }    [Fact]    public void 测试两个数的和()    {        Assert.Equal(3, _calcService.Plus(1, 2));    }    [Fact]    public void EnsureSingleton()    {        Assert.Equal(1, MyAssemblyFixture.InstantiationCount);    }    [Fact]    public void EnsureClassSingleton()    {        Assert.Equal(1, MyClassFixture.InstantiationCount);    }}

36.1.8.8 ICollectionFixture<> 多个注入

ICollectionFixture<> 方式和 IClassFixture<> 方式最大的不同就是后者只能配置为单个测试类使用,而 ICollectionFixture<> 则通过 [Collection] 方式配置多个测试类有效,如:

  • 定义需要注入进单元测试构造函数中的类
特别注意

这里区别于 IClassFixture<> 方式,需定义配置器并实现 ICollectionFixture<> 接口。

using Xunit;namespace TestProject1;public class MyCollectionFixture : IDisposable{    public static int InstantiationCount;    public MyCollectionFixture()    {        InstantiationCount++;    }    public void Dispose()    {        // 做一些释放工作    }}[CollectionDefinition("MyCollection")]public class MyCollection : ICollectionFixture<MyCollectionFixture>{}
  • 在测试类构造函数注入
using TestProject1.Services;using Xunit;namespace TestProject1;[Collection("MyCollection")]public class UnitTest1 : IClassFixture<MyClassFixture>{    private readonly ICalcService _calcService;    private readonly MyAssemblyFixture _fixture;    private readonly MyClassFixture _classFixture;    private readonly MyCollectionFixture _collectionFixture;    public UnitTest1(ICalcService calcService        , MyAssemblyFixture fixture        , MyClassFixture classFixture        , MyCollectionFixture collectionFixture)    {        _calcService = calcService;        _fixture = fixture;        _classFixture = classFixture;        _collectionFixture = collectionFixture;    }    [Fact]    public void 测试两个数的和()    {        Assert.Equal(3, _calcService.Plus(1, 2));    }    [Fact]    public void EnsureSingleton()    {        Assert.Equal(1, MyAssemblyFixture.InstantiationCount);    }    [Fact]    public void EnsureClassSingleton()    {        Assert.Equal(1, MyClassFixture.InstantiationCount);    }    [Fact]    public void EnsureCollectionSingleton()    {        Assert.Equal(1, MyCollectionFixture.InstantiationCount);    }}

36.1.9 Web 集成测试

Web 集成测试有三种方式,通过这三种方式可以对项目进行全方位的测试,保证部署上线是测试期盼效果。

36.1.9.1 对现有项目进行集成测试

这种方式比较简单,也是最常用的方式,无需部署到服务器直接在本地即可测试,如:

  1. 创建 Xunit 单元测试项目
  1. 添加 Microsoft.AspNetCore.Mvc.Testing 微软提供的集成测试拓展
  1. 添加测试项目或使用已有的测试项目引用
  1. 在需要测试的 Web 项目启动层添加 FakeStarup.cs
FakeStarup.cs
namespace WebApplication1;/// <summary>/// 供集成测试使用/// </summary>public class FakeStartup{}
  1. 编写测试 Web 项目接口测试案例
using Microsoft.AspNetCore.Mvc.Testing;using Xunit;namespace TestProject2;public class UnitTest1 : IClassFixture<WebApplicationFactory<WebApplication1.FakeStartup>>{    private readonly WebApplicationFactory<WebApplication1.FakeStartup> _factory;    public UnitTest1(WebApplicationFactory<WebApplication1.FakeStartup> factory)    {        _factory = factory;    }    [Theory]    [InlineData("/default")]    public async Task TestEnsureSuccessStatusCode(string url)    {        using var client = _factory.CreateClient();        using var response = await client.GetAsync(url);        response.EnsureSuccessStatusCode();    }}

/default 接口对应控制器定义如下:

using Microsoft.AspNetCore.Mvc;namespace WebApplication1.Controllers{    [ApiController]    [Route("[controller]")]    public class DefaultController : ControllerBase    {        [HttpGet]        public string Get()        {            return "Furion 集成测试";        }    }}
  1. 允许测试

36.1.9.2 独立主机方式测试

独立主机的方式就是利用单元测试的每一个测试案例构建主机进行测试。

  1. 创建 Xunit 单元测试项目
  1. 添加 Microsoft.AspNetCore.Mvc.Testing 微软提供的集成测试拓展
  1. 各种创建主机方式示例
using Microsoft.AspNetCore.Builder;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;using Xunit;namespace TestProject3;public class UnitTest1{    /// <summary>    /// 创建主机并注册服务    /// </summary>    /// <remarks>可用来判断服务是否注册</remarks>    [Fact]    public void Test1()    {        var builder = WebApplication.CreateBuilder();        // 注册服务        builder.Services.AddScoped<IYourService, YourService>();        using var app = builder.Build();        var services = app.Services;        services.GetRequiredService<IYourService>();    }    /// <summary>    /// 测试配置    /// </summary>    /// <remarks>比如添加 JSON 文件配置后读取</remarks>    [Fact]    public void Test2()    {        var builder = WebApplication.CreateBuilder();        var host = builder.Host;        host.ConfigureAppConfiguration(builder =>        {            builder.Sources.Clear();        });        var config = builder.Configuration["配置"];        // 判断不为空    }}

36.1.9.3 系统集成/环境/配置部署测试

有时候我们需要测试 Web 主机各种情况,比如端口是否有效,环境配置是否有效,系统集成情况等等,这时候只需要添加 Microsoft.AspNetCore.TestHost 拓展,然后在测试类顶部贴:

[assembly: HostingStartup(typeof(WebApplicationTests.TestHostingStartup))]

微软已经提供了非常详细的例子,这里直接放链接 https://github.com/dotnet/aspnetcore/tree/main/src/DefaultBuilder/test/Microsoft.AspNetCore.Tests

WebApplicationTests.TestHostingStartup 为您要测试的 Web 项目启动类。

36.1.9.4 集成 Furion.Xunit 拓展

Web 集成测试支持完整的 Furion 特性,参考上面单元测试集成 Furion 章节。

Furion 纯净版

如果使用的是 Furion.Pure 则安装 Furion.Pure.Xunit 这个拓展包。

36.1.10 Assert 断言

Assert 是单元测试判定成功的依据,通常第一个参数为 期望值,第二个参数为 实际值,对比这两个值是否一致即可判断成功与否。详细的 Assert 静态方法可查阅官方库 Assert 方法

36.1.11 反馈与建议

与我们交流

给 Furion 提 Issue


了解更多

想了解更多 单元测试 知识可查阅 在 .NET 中测试 章节。

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/upgrade/index.html b/handbook/build/docs/upgrade/index.html index 478fc0aa75..bba1dc8173 100644 --- a/handbook/build/docs/upgrade/index.html +++ b/handbook/build/docs/upgrade/index.html @@ -2,23 +2,22 @@ - - - + +1.6 更新日志 | Furion -1.6 更新日志 | Furion - - + + +
-

1.6 更新日志

Furion 框架发版规则

版本号规则:主版本号.次版本号.修订版本号

  • 只要【确认】为框架 bug,则当天修复,当天发版,修订版本号 加 1
  • 只要 .NET SDK 版本更新,则当天升级,当天发版,修订版本号 加 1
  • 如果 .csproj 文件有变更,则当天发版,修订版本号 加 1
  • 如果新增 拓展包,为了版本号统一,则当天发版,修订版本号 加 1
  • 如果涉及到代码重构,则当天发版,次版本号 加 1,修订版本号 清 0
  • 如果 .NET SDK 主版本号升级,则当天发版,主版本号 加 1

如有意外不能当天发版,则会在 Issue 中说明具体发版时间,正常不会超过 3 天。

v4.3.9(当前版本)

  • 新特性

    • [新增] AppSettings 配置的 ExcludeAssemblies 属性,支持忽略指定程序集扫描 7b7747f
    • [新增] Oops.OhOops.Bah 支持设置额外数据 .WithData(data) #I5O38E
    • [新增] 定时任务 Crontab.GetSleepMilliseconds(baseTime) 获取下一个发生时间的时间差 d024fae
    • [新增] 友好异常默认打印异常日志,避免生产环境漏掉重要异常信息 6e3a5bd
    • [新增] 日志静态类 Log.CreateLoggerFactory() 静态方法 75c672a
    • [新增] 多语言 SharedResource 模式,避免硬编程 18e80c7
    • [新增] 事件总线 MessageCenter 静态类,解决从 Fur v1.x 版本升级问题 a29fc7c
    • [新增] 组件化 IWebComponent 模式,支持 .NET5+ 08a44c3
    • [新增] 远程请求设置自己的 HttpClient 功能 #I5PBR3 !545
    • [新增] LoggingMonitor 支持添加更多自定义配置 #I5PEPA
    • [新增] LoggingMonitor 可配置 WithReturnValueReturnValueThreshold #I5PFJ1 #I5PFOW
    • [新增] LoggingMonitor 可配置 MethodsSettings 更多信息 #I5PFJ1 #I5PFOW
Serve.Run(RunOptions.Default     .AddWebComponent<XXXWebComponent>());public class XXXWebComponent : IWebComponent{    public void Load(WebApplicationBuilder builder, ComponentContext componentContext)    {        // ....    }}
  • 突破性变化

    • [新增] Furion 程序集 PublicKeyToken 强签名 26b12c0
    • [调整] 事件总线 IEventBusFactory 事件工厂方法 AddSubscriber -> SubscribeRemoveSubscriber -> Unsubscribe a29fc7c
    • [调整] .AddInject().UseInject() 配置选项名称,移除 Configure 后缀 b6953cd
    • [调整] 远程请求 请求拦截响应拦截异常拦截 委托签名,新增 HttpClient 参数 #I5OWBO
[Interceptor(InterceptorTypes.Request)]static void OnRequest(HttpClient client, HttpRequestMessage req){}[Interceptor(InterceptorTypes.Response)]static void OnResponsing(HttpClien client, HttpResponseMessage res){}[Interceptor(InterceptorTypes.Exception)]static void OnException(HttpClient client, HttpResponseMessage res, string errors){}
  • 问题修复

    • [修复] 生成包含 中文JWT Token 解密后出现乱码问题 #I5O397
    • [修复] `HttpRequestMessage`` 拓展中追加查询参数时的空引用异常 #I5PENW !547
    • [修复] 日志模块配置多个 IDatabaseLoggingWriter 只有一个生效 #I5PFQ2 #I5PFJ1
  • 其他更改

    • [调整] 默认输出文件日志模板,使其更加美观 #1518cf3
    • [调整] 默认规范化结果验证处理也支持状态码设置 2eb9390
    • [更新] SqlSugarCore 拓展包和脚手架至 5.1.2.6 版本 #I5PCXK
    • [更新] JSON Schema 关于 LoggingMonitor 更多配置 #I5PFJ1
  • 文档

    • [新增] RabbitMQ 事件总线文档
    • [更新] AppSettings 配置文档、事件总线文档、多数据库配置文档、日志文档、定时任务文档、MessageCenter 文档、远程请求文档、组件化文档、入门指南、多语言文档。

v4.2.13(已发布)

  • 新特性

    • [新增] 事件总线工厂,支持运行时动态添加订阅程序和移除订阅程序 #I5NNQX
    • [新增] 事件总线 [EventSubscribe] 事件 Id 支持正则表达式匹配 #I5NNQX
    • [新增] 事件总线 [EventSubscribe] 支持局部失败重试配置 #I5NNQX
    • [新增] Log 全局静态类,方便随时随地记录日志 ba9b1f1
    • [新增] 事件总线 options.AddSubscriber(Type) 重载 42446078
    • [新增] ValidationMetadata 类型 FirstErrorPropertyFirstErrorMessage 属性 #I5MFJT
    • [新增] Serve.Run() 模式 WithArgs(args) 方法 #I5MOJB
    • [新增] [UnitOfWork] 分布式事务 TransactionScope 支持 #I5MRTY
    • [新增] 16 位 MD5 加密支持 #I5N8RC
  • 突破性变化

    • [调整] 异步创建作用域方法名称,避免一些情况下无法区分,同步方法不变 #I5N9XY

由:

// Scoped.CreateUow 一样await Scoped.Create(async (f, s) => {});

改为:

// Scoped.CreateUowAsync 一样await Scoped.CreateAsync(async (f, s) => {});
  • [支持] .NET 6.0.8.NET 7 Preview 7 842d4f7
  • [调整] [LoggingMonitor] 命名空间为 System,因为使用频率越来越高 b879861
  • [添加] 在非 Web 环境中不正确使用字符串拓展方法检测机制 6389cbd
  • [调整] 所有 .Default 静态属性为 .Default() 方法 6389cbd
  • [调整] 工作单元 IUnitOfWork 所有方法参数类型,由 ActionExecutingContextActionExecutedContext 改为 FilterContext #I5MHX5
public interface IUnitOfWork{    void BeginTransaction(FilterContext context, UnitOfWorkAttribute unitOfWork);    void CommitTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork);    void RollbackTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork);    void OnCompleted(FilterContext context, FilterContext resultContext);}
  • 问题修复

    • [修复] 日志上下文数据多次写入被清空问题以及数据库日志出现异常后停止写入 #I5LIWF
    • [修复] 个别情况下跨域默认配置的响应缓存导致嵌入式资源异常问题 7a57efe
    • [修复] 远程请求传入不合法的请求报文头数据触发校验失败问题 #I5LPFE
    • [修复] 多线程中使用静态日志写数据库日志导致连接池耗光问题 8d5cdd6
    • [修复] EFCore 6.0 之后 IModelCacheKeyFactory 接口方法改变导致分表分库异常问题 #I5MCZ6 EFCore#25154 EFCore!3305
    • [修复] ValidationMetadata 对象 Message 字符串类型出现 \"\" 问题 #I5MFJT
    • [修复] [IfException] 覆盖 Oops.Oh/Bah 错误消息问题 4bbd854
    • [修复] 数据库日志写入循环写入和频繁创建数据库连接池问题 9ce214c
    • [修复] Razor Pages 不支持全局异常拦截问题 #I5MHX5
    • [修复] Razor Pages 不支持全局数据验证问题 #I5MHX5
    • [修复] Razor Pages 不支持工作单元 [UnitOfWork] 问题 #I5MHX5
    • [修复] Razor Pages 不支持 EFCore 自动 SaveChanges 问题 #I5MHX5
    • [修复] Blazor Serverv4.2.2 版本更新导致的问题 #I5MNFN
    • [修复] [IfException] 不支持多语言配置问题 #I5MPN7
    • [修复] 通过 services.AddMvcFilter<LoggingMonitorAttribute>() 方式注册无效问题 8d1477d
    • [修复] 事件总线默认 Channel 管道初始化时机过晚问题,解决部分第三方依赖使用问题 #I5MM3O
    • [修复] 主机停止时写入日志异常问题 #I5N7S2
    • [修复] 数据库上下文手动释放导致 AutoSaveChange 特性出现释放异常问题 #I5NFWC
    • [修复] [LoggingMonitor] 循环引用序列化问题 #I5NRT9
    • [修复] 远程请求传入 null Body 参数抛出空异常问题 #I5NTUE
    • [修复] 事件总线默认开启模糊匹配(正则表达式)导致不必要的订阅 #I5NVOP
  • 其他更改

    • [调整] 事件总线默认 Channel 管道初始化时机,解决部分第三方依赖使用问题 #I5MM3O
    • [优化] 底层迭代改进优化
    • [公开] 规范化文档获取控制器、方法分组、标签信息 66d8d54
  • 文档

    • [新增] 全局日志静态类 Log 文档 ba9b1f1
    • [新增] Nuget 本地测试包文档
    • [更新] 日志文档、静态类文档、数据校验文档、Worker Service 文档、工作单元文档、依赖注入文档

v4.1.14(已发布)

  • 新特性

    • [新增] Furion.Xunit 拓展包,正式实现 Xunit 单元测试完整支持 Furion 063a034e
    • [新增] services.AddMonitorLogging() 日志监视器服务,支持非常灵活的日志操作 81df742
    • [新增] Serve.Run(silence: true) 等一系列强大的静默启动功能 #I5JBSQ #I5J98T 7cced4
    • [新增] SpecificationDocumentBuilder.GetOpenApiGroups() 方法获取底层的规范化接口分组信息 4ff03c5
    • [新增] logger.ScopeContext() 配置日志上下文功能 #I5JC0D
    • [新增] 跨域配置 CorsAccessorSettings.SignalRSupport 配置选项,支持配置 SignalR 跨域 #I5JREM
    • [新增] 事件总线 UseUtcTimestamp 选项配置,可选择使用 DateTime.UtcNow 还是 DateTime.Now,默认是 DateTime.Now #I5JSEU
    • [新增] 规范化文档 [OperationId] 配置,解决自定义 Swagger UI 不能正确显示路由问题 #I5K1IB
    • [新增] 远程请求 IHttpDispatchProxy 方式全局拦截支持多态(继承) #I5K8FS
  • 突破性变化

    • [新增] Furion.Xunit 拓展包,正式实现 Xunit 单元测试完整支持 Furion 063a034e
    • [移除] Furion.Extras.DatabaseAccessor.SqlSugar 拓展插件中的 [SqlSugarUnitOfWork] 工作单元特性,将使用通用工作单元替换,查看最新实现文档
    • [移除] Inject.Create() 方法,再也不需要了,框架提供了无敌强大的 Serve.Run() 静默启动方式 200848e
    • [调整] Serve.RunConfigureConfiguration 方法参数,由 configuration => {} 改为 (environment, configuration) => {} 83c97bb
// 由Serve.Run(RunOptions.Default.ConfigureConfiguration(configuration => {}));// 改为:Serve.Run(RunOptions.Default.ConfigureConfiguration((environment, configuration) => {}));
  • 问题修复

    • [修复] [LoggingMonitor] 异常消息日志级别为 Information 错误问题 ab46cdf
    • [修复] 新版本日志组件频繁提示文件占用问题,将文件独占锁改为共享锁 #I5J3S6
    • [修复] 配置数据库日志读写器为 EFCore 时控制台出现无限打印问题 #I5J474
    • [修复] [LoggingMonitor] 针对 byte[] 类型参数输出过大问题 5380f35
    • [修复] 友好异常和规范化结果丢失了原始 ErrorCode 问题 #I5IX2R
    • [修复] 新版本日志组件自定义数据库读写器注入 IRepository 仓储导致死循环问题 #I5IX2R
    • [修复] Mvc 默认手动验证和 Furion 全局验证冲突问题 2a06c39
    • [修复] Serve.Run() 模式不支持 SuperSocket 第三方包问题,原生是支持的。186ca0a
    • [修复] SignalR 跨域错误问题 #I5JREM
    • [修复] [LoggingMonitor]Oops.OhOops.Bah 记录到了错误日志中,默认应该是 Information 且提供可配置 #I5JZ1H
    • [修复] 自定义 Swagger UI 之后个别 UI 要求必须配置 operationId,否则出现 guid 序号 #I5K1IB
    • [修复] 主动抛出 NotFoundResultNotFoundObjectResult 无效问题 #I5KALZ
    • [修复] [LoggingMonitor] 解析方法参数但前端未传入时出现错误问题 #I5KC5P
    • [修复] [LoggingMonitor] 无法序列化 IQueryable 返回值问题 #I5KJD1
    • [修复] [LoggingMonitor] 不能记录全局验证错误问题 b44087d
    • [修复] [LoggingMonitor] 存在注册顺序差异问题 b44087d
  • 其他更改

    • [开放] 底层的规范化文档 SpecificationDocumentBuilder 部分方法,提供更加便捷的第三方 Swagger UI 集成 10f0f01
  • 文档

    • [更新] 单元测试文档、入门指南文档、Worker Services 文档
  • 本期亮点

  1. Serve.Run() 彻彻底底支持全平台,提供非常强大的静默模式

启用静默模式可以实现无阻塞方式执行程序,而且还能体验完整的 Furion 功能。

大革命

有了 Serve.Run() 静默模式后,Furion 彻彻底底支持全平台,不管你是 控制台、Web、桌面、移动、单元测试,集成测试,基准测试等等应用程序

Serve.Run(silence: true);// 不会阻塞执行哦,而且从这里开始可以使用 Furion 任何功能,比如 App.Configuration....Console.WriteLine("Hello, World!");Console.ReadKey();

还有更多静默模式。

// RunOptions 方式Serve.Run(RunOptions.DefaultSilence);// LegacyRunOptions 方式Serve.Run(LegacyRunOptions.DefaultSilence);// GenericRunOptions 方式Serve.Run(GenericRunOptions.DefaultSilence);
  1. 强大的 Furion.Xunit 单元测试、集成测试
大革命

单元测试和集成测试是保证一个系统能够持续维护和稳定运行的必备技能,但是目前现有的单元测试组件无法直接集成 Furion 的功能,最常用的就是如何在单元测试中读取配置,以及如何进行依赖注入

在过去,Furion 只能不断的去调整,以至于适配第三方单元测试写法,搞得不伦不类!

所以,这一次不再妥协,Furion 推出自己的单元测试工具,可以让现有的单元测试如 Xunit 100% 支持 Furion 所有功能,全部保证一致的写法。

单元测试中初始化 Furion

using Furion.Xunit;using Xunit.Abstractions;using Xunit.Sdk;// 配置启动类类型,第一个参数是 TestProgram 类完整限定名,第二个参数是当前项目程序集名称[assembly: TestFramework("TestProject1.TestProgram", "TestProject1")]namespace TestProject1;/// <summary>/// 单元测试启动类/// </summary>public class TestProgram : TestStartup{    public TestProgram(IMessageSink messageSink) : base(messageSink)    {        // 初始化 Furion        Serve.Run(silence: true);    }}

测试类支持完整依赖注入

using TestProject1.Services;using Xunit;namespace TestProject1;public class UnitTest1{    private readonly ICalcService _calcService;    public UnitTest1(ICalcService calcService)    {        _calcService = calcService;    }    [Fact]    public void 测试两个数的和()    {        Assert.Equal(3, _calcService.Plus(1, 2));    }}

查看新版本单元测试文档

  1. 开放底层规范化文档分组接口,使得集成第三方 Swagger UI 更加容易,如集成 IGeekFan.AspNetCore.Knife4jUI 拓展:
安装包

只需要在 YourPoject.Web.Core 层安装 IGeekFan.AspNetCore.Knife4jUI 即可。

3.1.1 Knife4jUI 独立版本配置

var routePrefix = "api";    // 定义 swagger 路由地址,如果是跟目录,设置 string.Empty 即可app.UseKnife4UI(options =>{    options.RoutePrefix = routePrefix;  // 配置 Knife4UI 路由地址    foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())    {        options.SwaggerEndpoint("/" + groupInfo.RouteTemplate, groupInfo.Title);    }});app.UseInject(routePrefix); // 配置 Furion 路由地址

3.1.2 Knife4jUISwagger 共存版本配置

app.UseKnife4UI(options =>{    options.RoutePrefix = "newapi";  // 配置 Knife4UI 路由地址,现在是 /newapi    foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())    {        options.SwaggerEndpoint("/" + groupInfo.RouteTemplate, groupInfo.Title);    }});app.UseInject();  // Furion 默认 api 地址为  /api

如需实现登录之后自动将 token 添加到头部可在登录接口 AfterScript 执行以下代码:

ke.global.setAllHeader(
"Authorization",
"Bearer " + ke.response.headers["access-token"]
);
  1. 提供强大的日志上下文功能
// 写法一_logger.ScopeContext(ctx => ctx.Set("Name", "Furion").Set("UserId", 10))       .LogInformation("我是一个日志 {id}", 20);// 写法二_logger.ScopeContext(new Dictionary<object, object> {    { "Name", "Furion" },    { "UserId", 10 }}).LogInformation("我是一个日志 {id}", 20);// 写法三_logger.ScopeContext(new LogContext {    // ....}).LogInformation("我是一个日志 {id}", 20)

v4.0.0(重新起航)

不忘初心,感恩遇见,感恩信任

2020 年 09 月 01 日,一个叫 Fur 的开源项目悄然诞生,她的出生仿佛带着某种使命,没有包袱,无限可能。

她缓缓的张开双眼,干净雪亮的眼睛似乎对这个世界充满了好奇,每一次思想碰撞在她看来都是非常宝贵的财富,她貌似有用不完的精力,一路汲取知识,升级打怪,不断奔跑,乐此不疲。

记得 2020 年 11 月 11 日的单身节,她迎来了“一岁(v1.0.0)”生日,自那以后,IT 这个大银幕上频繁出现她的身影,越来越多 .NET5 开发者转粉,像是告诉这个世界,她就是 IT 界大明星。

每一个明星都有一个好听的艺名,她当然也不例外,2020 年 11 月 20 日,经纪人百小僧为她起名为 Furion

2021 年 11 月 09 日,她进入了叛逆期,抛弃了曾经支持她的 .NET5 粉丝们,拥抱了新的 .NET6 拥趸者,自从过上了奢靡富足的生活。

但她过的不开心,时常在夜里想起 .NET5 的粉丝们,内心非常自责,但在双重工作压力下她依然选择了忽视他们的诉求,仿佛他们就是累赘。

时间真的是好东西,曾经认为是对的,经过岁月的蹉跎历磨,渐渐的明白:不忘初心,方能始终。

这一次,不落下一人(.NET5.NET6,...,.NET N),携手共进,重新起航,感恩遇见,感恩信任。

  • 新特性

    • v4.0.0 支持 .NET5.NET6,...,.NET N,所有的 Furion 项目都能够升级到该版本,重新起航,实现大统。

v3.9.2(已发布)

关于日志

日志模块是任何应用系统都必备的功能,可以说是最重要的模块!在 .NET 社区中有 Log4NETNLogSerilog 等日志组件,它们无一不是优秀的开源项目。

但由于这些日志组件历史悠久,内部兼容的 .NET 版本非常多,功能随着时间推移变得极其强大复杂,在实际项目使用中,发现每一个日志组件配置总是不那么友好,特别是在使用上不够简单

Furion 作为全栈开发框架,在过去版本并没有提供足以满足开发者需求的日志模块,转而推荐大家集成第三方组件,如 Serilog导致后续无法实现自定义功能和也增加了不少维护成本。

这一次,Furion 不再妥协,彻底重构了日志模块,实现日志功能/需求完全自主可控,提供给开发者几乎所有日志功能的需求!

Furion 的使用者们,是时候“更换”掉第三方日志组件,让我们一起迭代出更强更好的日志组件吧! 🍖

  • 新特性

    • [重构] 日志模块,内置写入控制台、文件、数据库功能,再也无需引入第三方日志了!日志源码
    • [新增] 强大的调试日志 [LoggingMonitor] 32dfc1
  • 突破性变化

    • [重构] 日志模块,内置写入控制台、文件、数据库功能,再也无需引入第三方日志了!日志源码
    • [调整] TP.Wrapper 规范化日志模板算法,由过去的 [属性] 改为 ##属性##,解决 JSON 内容冲突问题 394ecec
    • [公告] 未来 Furion.Extras.Logging.Serilog 拓展将不再继续维护,因为 Furion 有强大的日志组件了!
  • 问题修复

    • [修复] 修复脱敏模块模型绑定个别情况下空异常问题 #I5IM5C
  • 文档

    • [更新] 日志文档、静态类文档、数据校验文档
  • 本期亮点

  1. 极易使用且强大的日志模块
// 写入文件services.AddFileLogging("logs/application.log");// 写入数据库services.AddDatabaseLogging<DatabaseLoggingWriter>();

查看更多日志文档

  1. 强大的 [LoggingMonitor] 调试日志
using Furion.Logging;namespace Furion.Application;public class TestLoggerServices : IDynamicApiController{    [LoggingMonitor]    public PersonDto GetPerson(int id)    {        return new PersonDto        {            Id = id        };    }}

支持控制器、操作或全局注册拦截

输出日志为:

┏━━━━━━━━━━━  Logging Monitor ━━━━━━━━━━━┣ Furion.Application.TestLoggerServices.GetPerson (Furion.Application)┣ 控制器名称:              TestLoggerServices┣ 操作名称:                GetPerson┣ 路由信息:                [area]: ; [controller]: test-logger; [action]: person┣ 请求地址:                https://localhost:44316/api/test-logger/person/11┣ 来源地址:                https://localhost:44316/api/index.html┣ 浏览器标识:              Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62┣ 客户端 IP 地址:          0.0.0.1┣ 服务端 IP 地址:          0.0.0.1┣ 服务端运行环境:          Development┣ 执行耗时:                31ms┣ ━━━━━━━━━━━━━━━  授权信息 ━━━━━━━━━━━━━━━┣ JWT Token:               Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjEsIkFjY291bnQiOiJhZG1pbiIsImlhdCI6MTY1ODcxNjc5NywibmJmIjoxNjU4NzE2Nzk3LCJleHAiOjE2NTg3MTc5OTcsImlzcyI6ImRvdG5ldGNoaW5hIiwiYXVkIjoicG93ZXJieSBGdXJpb24ifQ.VYZkwwqCwlUy3aJjuL-og62I0rkxNQ96kSjEm3VgXtg┣ UserId (integer)1┣ Account (string):        admin┣ iat (integer)1658716797┣ nbf (integer)1658716797┣ exp (integer)1658717997┣ iss (string):            dotnetchina┣ aud (string):            powerby Furion┣ ━━━━━━━━━━━━━━━  参数列表 ━━━━━━━━━━━━━━━┣ Content-Type:id (Int32)11┣ ━━━━━━━━━━━━━━━  返回信息 ━━━━━━━━━━━━━━━┣ 类型:                    Furion.Application.Persons.PersonDto┣ 返回值:                  {"Id":11,"Name":null,"Age":0,"Address":null,"PhoneNumber":null,"QQ":null,"CreatedTime":"0001-01-01T00:00:00+00:00","Childrens":null,"Posts":null}┗━━━━━━━━━━━  Logging Monitor ━━━━━━━━━━━

v3.8.9(已发布)

  • 新特性

    • [新增] 规范化结果 ExceptionMetadataValidationMetadata 都可以获取 ErrorCode 属性 #I5GJ6D
    • [新增] ValidationMetadataStatusCode 属性 #I5HB5L
    • [新增] 远程请求对 Url 是否编码设置,[Get(WithEncodeUrl = false)]WithEncodeUrl(false) #I5GOBC
    • [新增] 更强大的 JWTEncryption.SecurityReadJwtToken('token') 读取解析 Token 静态方法 574eeb6
    • [新增] ValiationTypes.Html 验证 Html 标签 #I5HBKC
    • [新增] EFCore.NamingConventions 支持,可自定义生成表名,字段名风格,比如小驼峰,蛇形命名等 #I5HBEI
    • [新增] INamedServiceProvider 命名服务提供器,可解析接口多实现 #I5HF98
    • [新增] 脱敏处理模块方法参数单个值处理 a22ec3c
    • [新增] 脱敏词库支持 | 分割词语 3106b1d
  • 突破性变化

    • [升级] 所有 .NET 依赖包至 6.0.7 版本
    • [升级] Serilog.AspNetCore 包至 6.0.0 版本
    • [重构] JWT Token 刷新逻辑 #I5GXML 574eeb6
    • [调整] ExceptionMetadata 命名空间为 Furion.FriendlyException 3105d16
    • [调整] Retry.Invoke(Func<Task>...) 为:Retry.InvokeAsync(Func<Task>...) 3b78999
    • [重构] 脱敏处理模块,大大提高性能和准确率,同时支持方法参数单个值处理 a22ec3c
  • 问题修复

    • [修复] Rider 开发工具对同名脚手架 (EFCoreSqlSugar) 只显示一个问题 !518
    • [修复] UnitOfWork 工作单元在 EFCore 中失效问题 #I5H0T3
    • [修复] JWTToken 如果存在数组类型的值时,刷新 Token 后丢失了历史值 #I5GXML
    • [修复] 远程请求 WithEncodeUrl 无法在 [HttpMethod] 设置问题 574eeb6
    • [修复] Serve.Run() 模式下添加自定义配置导致 EFCore 无法获取自定义配置文件问题 #I5GZ0F
    • [修复] Oops.Bah 进入全局异常拦截器问题 #I5H47S
    • [修复] AddDbPool/AddDb 扩展未根据配置 Key 路径读取问题 #I5H6S4 !520
    • [修复] ValiationTypes.Url 正则表达式覆盖不全问题 #I5HBKC
    • [修复] v3.5.x 版本导致集成 EFCore.NamingConventions 失效问题 #I5HBEI
    • [修复] Swagger 长路由不支持问题以及 [Required] 配置 AllowEmptyStrings 无效问题 c014330
    • [修复] 远程请求上传文件时请求报文 boundaryContent-Disposition 设置不正确问题 #I5HEF0
    • [修复] 脱敏模块替换敏感词汇出现多替换问题 a22ec3c
  • 其他更改

    • [调整] 多语言默认处理逻辑,允许不配置任何语言,过去版本会报错 #I5GRD9 5077c5d
    • [改进] 规范化文档 Swagger 性能
    • [调整] 调整 MongoDB 仓储 TDocument 泛型约束 3f49055
  • 文档

    • [更新] 远程请求文档,日志记录文档、多数据库文档、PM2 部署文档、Visual Studio 高效率文档

v3.7.11(已发布)

  • 新特性

    • [新增] Minimal API 应用支持:.AddInjectMini() #I4KOQ5
    • [新增] 跨域 WithExposedHeaders 默认配置 access-tokenx-access-token 42ebdfd
    • [新增] 脚手架默认启用 app.UseHttpLogging() HTTP 日志 42ebdfd
    • [新增] FurionASP.NET Core 完整 json 配置的 JSON Schema 架构 JSON Schema
    • [新增] Sql 代理支持返回单个类类型参数 1d7fb5b
    • [新增] Sql 代理支持返回 ValueTuple 单个类类型参数 876a2f5
    • [新增] 组件化设计模块,支持比 AppStartup 更灵活便捷的设计 #components
    • [新增] 独立工作单元模块,支持任何第三方 ORM a02413d
    • [新增] 跨域 FixedClientToken 配置参数 bd01638
    • [新增] throw Oops.Bah 可以手动触发规范化验证失败处理 83f0036
    • [新增] FriendlyExceptionSettingsThrowBah 配置,可标记 Oops.Oh 不进入异常处理 76ffa7f
  • 突破性变化

    • [新增] Minimal API 应用支持:.AddInjectMini() #I4KOQ5
    • [新增] FurionASP.NET Core 完整 json 配置的 JSON Schema 架构 JSON Schema
    • [新增] 组件化设计模块,支持比 AppStartup 更灵活便捷的设计 #components
    • [新增] 独立工作单元单元模块,支持任何第三方 ORM a02413d
    • [重构] DataValidationFilterFriendlyExceptionFilter,解决不支持手动抛出业务异常问题 83f0036
    • [调整] .AddDb<>.AddDbPool<> 自定义委托参数签名,由 Action<DbContextOptionsBuilder> 改为:Action<IServiceProvider, DbContextOptionsBuilder>
// 由:options.AddDbPool<TDbContext>(DbProvider.MySql, opt => {});// 改为options.AddDbPool<TDbContext>(DbProvider.MySql, (services, opt)=> {})
  • 问题修复

    • [修复]v3.6.3 版本依赖,执行原生 Sql 添加了参数校验导致存储过程执行错误问题 #I5ERMQ
    • [修复] tools/cli.ps1 脚本工具出现数据库链接被占用问题
    • [修复] JWTSettings 算法配置 JSON Schema 错误问题,感谢 @gitwentao #I5G27B !516
    • [修复] 基于策略授权在不配置 Policy 的情况下出现空异常问题 #I5EVF2
    • [修复] 启用数据库实体跟踪时导致新增实体多次查询数据库问题 #I4J2LZ
    • [修复] 不启用规范化结果导致验证失效,异常失效问题 cdb3f57
    • [修复] 验证异常和友好异常冲突问题 83f0036
    • [修复] CentOS 7.9 系统部署无法指定命令 --urls 参数问题 8cc8ee
  • 其他更改

    • [调整] 脚手架所有 .json 文件,默认添加 JSON Schema 支持
  • 文档

    • [新增] 组件化启动文档
    • [新增] Vue/React/Angular 请求代理文档
    • [新增] JSON Schema 文档,支持配置智能提示和验证
    • [更新] 跨域文档、规范化文档、配置文档、日志文档、IIS 部署文档
  • 本期亮点

  1. 新增 JSON Schema 支持,所有 .json 文件支持智能提示和验证
{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json",  "Logging": {    "LogLevel": {      "Default": "Information",      "Microsoft": "Warning",      "Microsoft.Hosting.Lifetime": "Information",      "Microsoft.EntityFrameworkCore": "Information"    }  },  "AllowedHosts": "*"}

查看更多 JSON Schema 文档

  1. 根据 Swagger 生成 Vue/React/Angular 前端请求代码

查看文档

  1. Sql 代理支持返回单个类类型参数
public interface ISql : ISqlDispatchProxy{    // 集合类型    [SqlExecute("select * from person")]    List<Person> GetPersons();    // 自 v3.7.3+ 版本支持返回单个类类型参数    [SqlExecute("select * from person where id=@id")]    Person GetPerson(int id);}
  1. Sql 代理支持返回 ValueTuple 单个类类型参数
public interface ISql : ISqlDispatchProxy{    [SqlExecute(@"            select * from person where id =@id;            select * from person")]    (Person, List<Person>) GetData(int id); // 注意返回值是 `(Person, List<Person>)` 组合}
  1. 支持 Minimal API 应用

了解 Minimal API 应用

var builder = WebApplication.CreateBuilder(args).Inject();// 注册 Minimal 服务builder.Services.AddInjectMini();var app = builder.Build();app.UseHttpsRedirection();app.UseInject(string.Empty);app.MapGet("/hello", () =>{    return "Hello, Furion";});app.Run();

v3.6.9(已发布)

  • 新特性

    • [新增] Serve.Run() 极简主机模式,真正实现极速入门。95cac5b
    • [新增] TP.Wrapper(...) 拓展方法,主要用来生成规范化的日志模板 427999a
    • [支持] 项目类型为 <Project Sdk="Microsoft.NET.Sdk"> 的控制台项目 fb08a65
    • [新增] BadPageResult 错误页面类型 !494
    • [新增] [SchemaId] 特性,解决不同程序集相同的类名生成 SwaggerSchemaId 冲突问题 #I5D3CU
    • [新增] 远程请求 options.ApproveAllCerts() 忽略所有客户端证书拓展 eb7d18a
    • [新增] 判断是否是单文件环境部署静态属性 App.SingleFileEnvironment de556f0
    • [新增] WebApplicationBuilder.UseSerilogDefault() 拓展 e02524c
  • 突破性变化

    • [支持] 项目类型为 <Project Sdk="Microsoft.NET.Sdk"> 的控制台项目 fb08a65
    • [新增] Serve.Run() 极简主机模式,真正实现极速入门。95cac5b
    • [调整] 未启用规范化结果时,MVC 验证失败返回 BadPageResult() 页面类型 !494
  • 问题修复

    • [修复] 修复默认注册的 services.AddResponseCaching(); 服务导致 .axd 内嵌资源请求错误问题 !495
    • [修复] Oracle 数据库执行 sql 必须要求命令参数和 sql 语言参数数量一致 #I5D057
    • [修复] IHostService 类型不能自动注册问题,之前只扫描了 BackgroundService 派生类 968344
    • [修复] 国产芯片主机不能识别 dotnet run --urls 参数问题 6d4398
    • [修复] 远程请求上传文件不支持特定文件后缀问题,如 .pem 文件 ba42198
    • [修复] 一些程序集已破坏或程序集不完整导致主机无法启动问题 d2dc3e4
    • [修复] 远程请求传入 headers 时类型为 Dictionary<string, string> 导致转换异常问题 #I5DHL9
    • [修复] Serilog 单文件发布不生成日志文件 I5DQ2B
  • 其他更改

    • [调整] 远程请求默认客户端不检查 SSL 证书 eb7d18a
    • [调整] 开放验证服务选项 SuppressModelStateInvalidFilter 属性为可配置 !494
  • 文档

    • [新增] Serve.Run() 文档
    • [新增] HttpContext 文档
    • [新增] GlobalUsings 文档
    • [新增] TP 全局静态类文档
    • [新增] 中间件文档、筛选器文档、审计日志文档
    • [更新] 跨域文档、远程请求文档
  • 精彩贡献

    • !494 优秀 Pull Request 辩论典范
  • 本期亮点

  1. 极速入门
Program.cs
Serve.Run();[DynamicApiController]public class HelloService{    public string Say()    {        return "Hello, Furion";    }}

启动浏览器查看效果,惊呆了吗!

  1. 内置错误页
using Furion.FriendlyException;public IActionResult Add(Person person){    if(!ModelState.IsValid)    {        return new BadPageResult();    }}
  1. Swagger 支持 Markdown
/// <summary>/// 测试 Markdown/// </summary>/// <remarks>/// # 测试 `Markdown` 注释////// ![](https://localhost:44316/images/logo.png)////// ```cs/// Serve.Run();////// [DynamicApiController/// public class HelloService/// {///     public string Say()///     {///         return nameof(Furion);///     }/// }/// ```////// 功能还不错!!!////// | 商品         | 价格     | # 其他 |/// |--------------|-----------|------------|/// | Juicy Apples | 1.99      | *7*        |/// | Bananas      | **1.89**  | 5234       |/// | Bananas      | **1.89**  | 5234       |/// | Bananas      | **1.89**  | 5234       |////// -----////// # Furion 探索版////// > 在过去一年,实现 `Furion` 从无到有,编写文档已逾百万字,过程心酸开源人自知。/// >/// > 这一路日夜兼程,嘲讽批评常伴眼耳,即便辛苦无奈、想过放弃,但为了那微不足道的存在感依然努力着。/// >/// > 当然,也收获了不少...越来越多拥趸者,越发精湛技术能力,更高层次思维模式,还有许多跨界跨行朋友。/// >/// > 在 《[开源指北] (https://gitee.com/opensource-guide/comments/)》中,我曾说道:“开源如同人的脸,好坏一面便知,缺点可能会受到嘲讽批评,优点也会收获赞扬尊重。别担心,他们正在塑造更好的你。”/// >/// > 所以,这一次重新起航,重塑 `Furion` 重塑自己。也许未来在某个 IT 圈但凡有人谈起 `.NET` 还能瞟到 `Furion` 的身影。////// ---////// 🎉 探索 Furion 未来更多可能性,实现无第三方依赖的版本,所有模块功能按需安装,按需加载。////// - 作者:[百小僧] (https://gitee.com/monksoul)/// - 日期:2021 年 08 月 30 日////// ## 环境////// - IDE :[Microsoft Visual Studio Enterprise 2022 Preview(64 位) 版本 17.0.0 Preview 3.1] (https://visualstudio.microsoft.com/zh-hans/vs/preview/)/// - SDK :[.NET SDK 6] (https://dotnet.microsoft.com/download/dotnet/6.0)/// - 语言:[C# 10](https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-10)////// ## 包说明////// - `Furion.Core`:无第三方依赖,可在 `.NET 6` 所有项目类型中运行。/// - `Furion`:内部依赖 `Furion.Core` 且无第三方依赖,**聚焦 `Web` 应用**,采用共享框架 `<FrameworkReference Include="Microsoft.AspNetCore.App" />` 模式///  </remarks>public void MarkdownTest(){    // ....}

v3.5.7(已发布)

  • 新特性

    • [新增] Options 选项属性支持自定义 Key 名称,[MapSettings("key")] #I5B2HN
    • [新增] EventBus 模块事件 Id 支持枚举类型 2f328aa
    • [新增] EventBus 模块发布者 PublishAsyncPublishDelayAsync 重载 2f328aa
    • [新增] EventBus 模块拓展方法:Enum.ParseToString()String.ParseToEnum() 2f328aa
    • [新增] FurionSqlSugar 脚手架 🆕🆕🆕 8d9293d
    • [新增] Dapper 拓展全局配置委托 #I5AYFX
    • [新增] sql 转实体支持多种命名策略(纯大写,纯小写,带下划线分割等等),如 Oracle 数据库 a90e245
    • [新增] FS.InitalContentTypeProvider() 拓展方法,获取系统内所有支持的 Content-Type 文件提供器 6099900
  • 突破性变化

    • [解决] 彻底解决了 Furion 不能单文件发布的问题 7e8e0b7
  • 问题修复

    • [修复] 框架规范化文档 Swagger 不支持 Controller 派生类 api 路由问题,原生 ASP.NET 是支持的 29e47bc
    • [修复] 基于 Schema 多租户配置无效问题 6f820ce
    • [修复] 指定实体 [Table(schema:"dbo")] 特性后 Schema 无效问题 6f820ce
    • [修复] 数据库视图不支持 Schema 配置问题 6f820ce
    • [修复] 规范化结果极端情况下出现 空异常 问题 c9b0ef
  • 其他更改

    • [调整] axios-utils.tsangular-utils.ts ,新增请求拦截携带刷新 Token 的时机判断 82f89bd
    • [优化] 规范化文档 Swagger 加载继承注释 <inheritoc /> 性能小优化 5f06880
    • [调整] 脚手架模板,新增 GlobalUsings.cs 模式
    • [调整] 对象映射默认支持忽略大小写 !486
  • 文档

    • [新增] Furion 单文件发布文档
    • [新增] Furion + SqlSugar 脚手架文档
    • [更新] 事件总线文档、选项文档、即时通讯文档、.NET5 升级 .NET6 文档、依赖注入文档、跨域文档、数据加解密文档
  • 本期亮点

  1. 事件总线 Id 支持枚举类型
EventSubscribe("TO:DO")]  // 字符串类型public async Task EventHandler1(EventHandlerExecutingContext context){    // ....}[EventSubscribe(YourEnum.Some)] // 枚举类型public async Task EventHandler2(EventHandlerExecutingContext context){    var eventEnum = context.Source.EventId.ParseToEnum(); // 将事件 Id 转换成枚举对象    // ....}
  1. 事件总线发布支持更简单调用
// 旧版本await _eventPublisher.PublishAsync(new ChannelEventSource("ToDo:Create", name));// 新版本await _eventPublisher.PublishAsync("ToDo:Create", name);await _eventPublisher.PublishAsync(YourEnum.Some); // 也支持枚举
  1. 选项支持属性自定义配置 Key
"AppInfo": {    "Name": "Furion",    "Version": "1.0.0",    "Company_Name": "Baiqian" // 可以和属性不一样}
public class AppInfoOptions : IConfigurableOptions{    public string Name { get; set; }    public string Version { get; set; }    [MapSettings("Company_Name")] // 支持自定义    public string Company { get; set; }}
  1. 日志规范化模板
// 生成模板字符串var template = TP.Wrapper("Furion 框架", "让 .NET 开发更简单,更通用,更流行。",    "[作者] 百小僧",    "[当前版本] v3.5.3",    "[文档地址] https://furion.icu",    "[Copyright] 百小僧, Baiqian Co.,Ltd.");Console.WriteLine(template);

输出结果

┏━━━━━━━━━━━  Furion 框架 ━━━━━━━━━━━┣ 让 .NET 开发更简单,更通用,更流行。┣ 作者:        百小僧┣ 当前版本:     v3.5.3┣ 文档地址:     https://furion.icu┣ Copyright:   百小僧, Baiqian Co.,Ltd.┗━━━━━━━━━━━  Furion 框架 ━━━━━━━━━━━

v3.4.2(已发布)

  • 新特性

    • [新增] 规范化文件 EnableAllGroups 功能,可以将多个分组合并到一个分组中 9277b98
    • [新增] angular-utils 客户端工具库,专门处理 angular 项目接口代理问题 6c70584
    • [新增] Swagger 支持单个接口更多描述功能(支持 htmle5e1db0
    • [新增] Swagger 接口 [Obsolete] 过时支持功能 e5e1db0
    • [新增] 动态 API[ApiDescriptionSettings] 特性 和DynamicApiControllerSettings 配置 的 ForceWithRoutePrefix 参数,支持强制复写 [Route] 特性并添加 DefaultRoutePrefix #I59B74
  • 突破性变化

    • [内置] 默认内置 GBKWindows-1252, Shift-JIS, GB2312 等编码支持 c456ecb
    • [新增] FurionSqlSugar 脚手架
  • 问题修复

    • [修复] <inheritdoc /> 不能跨程序集问题 3b9d39c
    • [修复] <inheritdoc /> 不支持带参数,不支持隐式实现接口注释问题 #I59A6W#note_10699021
    • [修复] v3.3.1 版本导致 Swagger 不能显示问题 6763352
    • [修复] 远程请求、JSON以及 Web 页面不支持 GBKGB2312 等国标编码问题 c456ecb
    • [修复] 远程请求响应报文设置了 Content-Type:charset= 不能自动转换编码问题 c456ecb
  • 其他更改

    • [新增] axios-utils.tsangular-utils.ts 多客户端支持
  • 文档

    • [新增] GlobalUsings 文档 文档地址
    • [新增] 请求大小/上传大小限制文档 文档地址
    • [更新] 规范化文档,Worker Service 文档,动态 API 文档
  • 本期亮点

  1. 启用 All Groups 分组功能

有时候我们为了更好的对接口进行归类,配置了 Swagger 多个分组的功能,但这样也对生成客户端请求代码造成了困扰,所以添加了新的配置:

{  "SpecificationDocumentSettings": {    "EnableAllGroups": true  }}
  1. 接口过时控制

当我们某个接口已经过时,提示尽早调用最新接口,只需要在方法上面贴 [Obsolete] 即可,如:

[Obsolete("GetName() 已经过时,请调用 GetFrameworkName() 替代")]public string GetName(){  return nameof(Furion);}[Obsolete]public string Other(){  // ...}
  1. 单一接口更多描述

在该版本新增了 [ApiDescriptionSettings]Description 属性,支持定义更多描述,如:

[ApiDescriptionSettings(Description = "我是一段描述,显示更多内容 <button>我是按钮</button>")]public string add(){  //....}

v3.3.3(已发布)

  • 新特性

    • [新增] 远程请求文件上传自动识别 Content-TypeMime #I57ZMN
    • [新增] 远程请求方法支持设置 Content-TypeEncoding #I57ZMN
    • [新增] 根据文件名获取 Content-TypeMime 类型 #8f78184
    • [新增] 规范化文档支持授权访问 #32aa3b6
    • [新增] 代码注释,规范化文档注释 inheritdoc 语法支持 ❤️️️️ #159A6W
    • [新增] 新增 Vue2/3React 16.8+Angular 9+ 前端请求工具库,实现后端 API 代理 axios-utils
  • 突破性变化

    • [新增] 代码注释,规范化文档注释 inheritdoc 语法支持 ❤️️️️ #159A6W
    • [更新] .NET 所有依赖包至 v6.0.5 版本
  • 问题修复

    • [修复] 自定义全局异常 Exception 后导致获取错误行号,文件空异常问题 #I53EGM
    • [修复] 配置数据库上下文传递空委托导致空引用异常问题 #I519AW
    • [修复] 字符串模板模板 Render 拓展方法返回 void 问题,应该返回 string Github-#99
    • [修复] 远程请求文件上传出现空情况问题(原因是缺失 Content-TypeI57ZMN
  • 其他更改

    • [调整] 框架源码引入 GlobalUsings 机制,减少代码体积 #7e9cc1c
    • [调整] 跨域请求的预检设置,如果未设置,则默认为 24 小时,主要解决前端多次发送 204 预检问题 4a11e7c
    • [优化] 视图引擎反射性能
  • 文档

    • [新增] 粘土对象序列化 JSON 配置文档
    • [新增] 前端解密 JWT 文档
    • [新增]byte[]url 文档
    • [更新] 二级虚拟目录部署文档,远程请求文档,文件上传文档,安全授权文档、规范化文档
  • 本期亮点

    • ❤️️️️ 根据文件名获取 MIMEContent-Type 类型
var success = FS.TryGetContentType("image.png", out var contentType);  // image/png
  • ❤️️️️ 支持 Swagger 配置登录后才能访问
{  "SpecificationDocumentSettings": {    "LoginInfo": {      "Enabled": true,      "CheckUrl": "检查登录地址",      "SubmitUrl": "提交登录地址"    }  }}

查看详细文档

  • ❤️️️️ 支持代码注释继承,Swagger 文档注释也支持
/// <inheritdoc cref="ITestInheritdoc" />public class TestInheritdoc : ITestInheritdoc, IDynamicApiController{    /// <inheritdoc cref="ITestInheritdoc.GetName"/>    public string GetName()    {        return "Furion";    }    /// <inheritdoc />    public string GetVersion()    {        return "3.3.3";    }}/// <summary>/// 测试注释继承/// </summary>public interface ITestInheritdoc{    /// <summary>    /// 获取名称    /// </summary>    /// <returns></returns>    string GetName();    /// <summary>    /// 获取版本    /// </summary>    /// <returns></returns>    string GetVersion();}

查看详细文档


v3.2.0(已发布)

  • 新特性

    • [新增] IFormFile 拓展方法 ToByteArray() da69640
    • [新增] 规范化文档 ServeDir 虚拟目录配置功能,支持一键将一级目录切换至二级目录部署(IIS)8718392
  • 突破性变化

    • [更新] 所有依赖包至最新版
    • [重构] 依赖注入模块核心代码,移除注册服务采用反射机制,减少反射性能损耗 acdb315
  • 问题修复

    • [修复] Swaggerschema 类型如果是 C# Object 类型无法正确生成前端代码问题 Swagger 官方 Issue 1a25274
    • [修复] Worker Service 发布成 Windows Services 时日志绝对路径问题 感谢 @jacoat !467
    • [修复] NginxIIS 对二级虚拟目录配置不同导致 404 问题 8718392
    • [修复] 远程请求模块未初始化 OnRequestFailded 导致空异常问题 #I54PK7
    • [修复] 依赖注入反射出现 Not found Method bug #I546L1
  • 其他更改

    • [调整] 定时任务失败后异常处理逻辑,感谢 @程小胜 !463
  • 文档

    • [更新] 定时任务文档,日志文档
    • [新增] 文件上传/下载 文档,包含单文件/多文件/Base64/Byte[]

v3.1.0(已发布)

  • 新特性

    • [新增] 远程请求模块异常 Http 状态码 !462
    • [新增] 动态 WebAPI 支持小驼峰配置 #I4W1R4
    • [新增] 远程请求 SendAsByteArrayAsync 等一系列方法,支持返回 byte[] !452
    • [新增] 远程请求 GZip 压缩支持 #I506S5
  • 突破性变化

    • [升级] .NET6 依赖包全部升级至 Nuget 最新版 v6.0.3
  • 问题修复

    • [修复] .NET6 WebApplication 模式二级虚拟目录问题 #I4UZLM #I4PZ0C
    • [修复] 日期验证不支持 2022-03-01 0:00:00(现在支持小时域 000) 问题 #I4Y3NT
    • [修复] 环境配置和文件配置优先级问题
    • [修复] 脱敏模块替换敏感词汇只替换最后一个 bug #I4YFA0
    • [修复] 远程请求返回字符串个别情况出现中文乱码问题 #I50GBD
    • [修复] [DataValidate] 配置 AllowNullValueAllowEmptyString 无效问题 #I4ZZBE
  • 其他更改

    • [过时] 标记 Furion.Extras.Logging.Serilog 拓展包 IWebHost 拓展为过时状态
  • 文档

    • [文档] 优化文档体验,新增面包屑导航,重写文档缓存,提升文档访问速度
    • [文档] 更新动态 API 文档、配置文档、远程请求文档
    • [文档] 更新二级虚拟目录文档
  • 本期亮点

  1. 新增动态 WebApi 支持小驼峰路径,如 GetMyName -> getMyName
{  "DynamicApiControllerSettings": {    "LowercaseRoute": false,    "KeepName": true,    "AsLowerCamelCase": true  }}
  1. 支持 .NET6 WebApplication 模式二级虚拟目录配置:
Progame.cs
app.UseVirtualPath(app =>{    app.UseInject(String.Empty);  // 注意 String.Empty 只是例子,可以不填或填其他的,见一分钟入门    app.MapRouteControllers();});

v3.0.0(已发布)

v3+ 版本说明

Furion v3.x 版本采用 .NET6 构建。

  • 新特性

    • [新增] 远程请求支持 GET 请求自动转换 类类型 类型对象 #I4HR5Q
  • 突破性变化

    • [升级] 全面支持 .NET6 版本
  • 问题修复

    • [修复] 开启规范化结果并自定义全局异常导致异常经过 OnSucceeded 过滤器 bug #I4DTVL
    • [修复] .NET5.0.5+.NET6 微软底层修改了 [ApiController] 验证失败返回 IActionResult 类型 #I4ISOK
    • [修复] EFCore 6.0 适配 SqlServer 2005+ 出错 #I4ILA5
    • [修复] .NET6 获取配置对象如果不存在返回 null 问题,.NET5 则返回初始对象 94ae4d
    • [修复] Sql 命令参数传入 Clay 类型异常问题 #I4D21Q
    • [修复] Cron 定时任务特性方式 bug #I4OJQI
  • 其他更改

    • [移除] ToPagedList 泛型约束 d0244d
  • 文档

  • 特别鸣谢


v2.20(已发布)

v2.20+ 版本说明

Furion v2.20+ 版本后采用 Jaina 事件总线替换原有的 EventBus

  • 新特性

    • [新增] 远程请求支持 GET 请求自动转换 类类型 类型对象 #I4HR5Q
  • 突破性变化

    • [重构] EventBus 模块,采用 Jaina 方式
  • 问题修复

    • [修复] 开启规范化结果并自定义全局异常导致异常经过 OnSucceeded 过滤器 bug #I4DTVL
    • [修复] .NET5.0.5+ 微软底层修改了 [ApiController] 验证失败返回 IActionResult 类型 #I4ISOK
    • [修复] 远程请求上传文件异常 0c0752
    • [修复] 框架启动不支持环境变量 ASPNETCORE_HOSTINGSTARTUPASSEMBLIES 配置 !438
    • [修复] 定时任务内存和 CPU 占用及特殊情况下空异常问题 12c65de
    • [修复] 默认控制器启用规范化结果无效 bugc7a4a5e
    • [修正] 依赖注入 InjectionAttribute 特性的 ExceptInterfaces 单词拼写错误问题 !436
    • [修复] Sql 命令参数传入 Clay 类型异常问题 #I4D21Q
  • 其他更改

    • [优化] InjectionAttribute 代码 !435
    • [移除] ToPagedList 泛型约束 d0244d
  • 文档

    • [新增] 事件总线新文档

v2.19(已发布)

  • 新特性

    • [新增] 定时任务监听器 ISpareTimeListener #I468Q1
    • [新增] 执行 Sql 支持 JsonElement 参数 61985d6
    • [新增] Swagger 配置枚举及标签排序过滤器 #I46LON !404
    • [新增] 远程请求 application/octet-stream 类型默认支持 d9bad03
    • [新增] 远程请求代理模式请求报文头支持 IDictionary<string ,object> 类型。0204c0a
    • [新增] MongoDB 拓展类,添加更多常用操作方法 !423
    • [新增] DateTimeOffset? 转换 DateTime 拓展(包含互换) !432
  • 问题修复

    • [修复] Scoped.CreateEFCore 进行 Add-Migration 时候报空异常问题,原因是在 PM 环境中不存在根服务0853e74
    • [修复] 定时任务执行异常后异常一直驻留内存问题,修正为执行成功自动清空过去异常 197a62b
    • [修复] Jwt 拓展包不正确的代码导致 IOptions 失效#I46LUP
    • [修复] Swagger 枚举 Schema 过滤器不输出值问题 #I46LON !404
    • [修复] Swagger 处理非 int 类型枚举转换 bug #I46QJ9
    • [修复] 视图引擎编译模板生成 dll 后再次加载出现 IL 格式化错误问题 ff52d38
    • [修复] 管道 Channel 读取器无法释放 Handler 对象问题 10f4a90
    • [修复] Worker Services 下日志不输出问题 c482548
    • [修复] 远程请求 multipart/form-data 类型对接微信小程序上传文件 问题 d9bad03
    • [修复] 工作单元上下文在某些情况下共享事务失效问题 006d439
    • [修复] Swagger 枚举值在 GET 请求中 Schema 显示不正确问题 fb72fd7
    • [修复] 远程请求 404 不走异常过滤器问题 !426
    • [修复] 自定义事件总线并发情况下调用完成后无法正确处理队列数据 !429
    • [修复] v2.19+ 版本之后模块化开发加载外部程序集失效问题 !433
    • [修复] 定时任务 SpareTime 频繁检查导致 CPU 增高问题 aa0a2ee
  • 特别鸣谢


v2.18(已发布)

  • 新特性

    • [新增] Furion.Tools.CommandLine 拓展库 查看源码
    • [新增] 基于 AsyncLocal<T>CallContext 实现 9057a21
    • [新增] 远程请求可配置请求异常重试策略 656da87
    • [新增] 远程请求 OnRequestFailded 事件 4a3da4b
  • 突破性变化

    • [移除] Scoped 所有带返回值方法 656da87
    • [调整] ConfigureService 中调用 App.GetOptions<>() 获取配置逻辑 afa4ac3

在过去,很多开发者总是喜欢在 Startup.cs 配置服务的 ConfigureService 方法中解析服务,这样导致内存存在溢出风险,GC 无法回收。 -正确的方式是尽可能的避免 ConfigureService 中解析服务。如果需要在【启动时】获取 配置选项,请使用 App.GetConfig<TOptions>(路径, true) 代替 App.GetOptions<TOption>

  • 问题修复

    • [修复] v2.16+ 版本重构 AppDbContextBuilder 之后写错实体类型 #I45E6M
    • [修复] 远程请求单个值序列化错误处理方式 3282eba
    • [修复] v2.17.3+ 单元测试创建 TestServer bug #I45JR3
    • [修复] Retry.Invoke 正常方法死循环 bug !392
    • [修复] 刷新 Token 生成新 Token 存在数组/集合类型导致 Key 重复异常问题 aeea2b1
    • [修复] 远程请求序列化引用类型对象(不含 string)不正确的处理 93cf63a
    • [修复] AppDbContext 默认租户属性受工作单元影响问题 e51557f
  • 文档

    • [新增] 包管理工具文档
    • [更新] 模板引擎、Sql 操作,数据库上下文 等等文档

v2.17(已发布)

  • 新特性

    • [新增] IPC(Inter-Process Communication,进程间通信) 模块功能,目前提供进程内通信和共享内存进程外通讯 ProcessChannel
    • [新增] 远程请求 application/xmltext/xml 默认支持 4753a1a
    • [新增] 控制台全局异常拦截 4a4fe1f
    • [新增] 支持自定义 .json 配置文件扫描目录 3e2910a
    • [新增] 支持数据库实体接口显式实现接口配置 9610a0a
    • [新增] 控制台应用程序全局拦截 [IfException] 支持 4a4fe1f
    • [新增] 依赖注入模块接口可以限制实现类生存周期,实现类也支持复写生存周期 d2ce089
  • 突破性变化

    • [抽离] Oops.Retry() 重试策略功能至新类:Retry.Invoke() 6a7bbd0
    • [移除] IHttpContextAccessor.SigninToSwagger() 拓展,请使用 IHttpContextAccessor.HttpContext.SigninToSwagger(),退出也一样
    • [移除] 全局处理 Request Body 重复读处理 Request.EnableBuffering() d92c24b
  • 问题修复

    • [修复] 规范化状态码过滤逻辑错误问题 #I44JYS
    • [修复] 非关系型数据库(内存数据库)注册及操作异常 e167651
    • [修复] 远程请求默认序列化问题 a55603b
    • [修复] 定时任务零点/整点提前一秒触发问题 #I4321L
    • [修复] 友好异常在子类重写抽象类方法内部抛异常无法获取的问题 4a4fe1f
    • [修复] 修复非 Web 项目抛异常问题 4a4fe1f
    • [修复] 数据库实体模型贴 [NotMapper] 特性无效 #I44MNO
  • 其他更改

    • [调整] Swagger 生成泛型 SchemaIds 默认连接符,由 Of 改为 _ 81946b6

v2.16(已发布)

  • 新特性

    • [新增] MVC 控制器支持规范化处理 #I427Z2
    • [新增] throw Oops.Bah() 抛出业务异常(状态码 400
    • [新增] UnifyResultSettings 规范化 json 配置选项 #I42NY7
    • [新增] 多语言自定义配置资源文件名及自定义程序集 #I434YJ
  • 突破性变化

    • [调整] 规范化结果 IUnifyResultProvider 参数 (破坏性更改) #I427Z2
    • [调整] IJsonSerializerProvider 接口参数,去掉 inherit 参数 a55603b
新版本自定义规范化结果
using Furion.DataValidation;using Furion.DependencyInjection;using Furion.UnifyResult.Internal;using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.Filters;using System;using System.Threading.Tasks;namespace Furion.UnifyResult{    /// <summary>    /// RESTful 风格返回值    /// </summary>    [SuppressSniffer, UnifyModel(typeof(RESTfulResult<>))]    public class RESTfulResultProvider : IUnifyResultProvider    {        /// <summary>        /// 异常返回值        /// </summary>        /// <param name="context"></param>        /// <param name="metadata"></param>        /// <returns></returns>        public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata)        {            return new JsonResult(RESTfulResult(metadata.StatusCode, errors: metadata.Errors));        }        /// <summary>        /// 成功返回值        /// </summary>        /// <param name="context"></param>        /// <param name="data"></param>        /// <returns></returns>        public IActionResult OnSucceeded(ActionExecutedContext context, object data)        {            return new JsonResult(RESTfulResult(StatusCodes.Status200OK, true, data));        }        /// <summary>        /// 验证失败返回值        /// </summary>        /// <param name="context"></param>        /// <param name="metadata"></param>        /// <returns></returns>        public IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata)        {            return new JsonResult(RESTfulResult(StatusCodes.Status400BadRequest, errors: metadata.ValidationResult));        }        /// <summary>        /// 特定状态码返回值        /// </summary>        /// <param name="context"></param>        /// <param name="statusCode"></param>        /// <param name="unifyResultSettings"></param>        /// <returns></returns>        public async Task OnResponseStatusCodes(HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings)        {            // 设置响应状态码            UnifyContext.SetResponseStatusCodes(context, statusCode, unifyResultSettings);            switch (statusCode)            {                // 处理 401 状态码                case StatusCodes.Status401Unauthorized:                    await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "401 Unauthorized")                        , App.GetOptions<JsonOptions>()?.JsonSerializerOptions);                    break;                // 处理 403 状态码                case StatusCodes.Status403Forbidden:                    await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "403 Forbidden")                        , App.GetOptions<JsonOptions>()?.JsonSerializerOptions);                    break;                default: break;            }        }        /// <summary>        /// 返回 RESTful 风格结果集        /// </summary>        /// <param name="statusCode"></param>        /// <param name="succeeded"></param>        /// <param name="data"></param>        /// <param name="errors"></param>        /// <returns></returns>        private static RESTfulResult<object> RESTfulResult(int statusCode, bool succeeded = default, object data = default, object errors = default)        {            return new RESTfulResult<object>            {                StatusCode = statusCode,                Succeeded = succeeded,                Data = data,                Errors = errors,                Extras = UnifyContext.Take(),                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()            };        }    }}
  • 问题修复

    • [修复] MVC 控制器启用规范化处理后返回 new Json({}) 对象为 null 问题 #I4354S
  • 其他更改

    • [优化] 多语言底层设计,取消需要创建 Lang.cs 空类的要求 #I434YJ
    • [优化] MiniProfiler 性能,减少不必要的监听

v2.15(已发布)

  • 新特性

    • [新增] Db.GetDbRepository<定位器>() 静态方法 #I41MZP
    • [新增] 远程请求缺省序列化配置选项 #I41PBW
  • 问题修复

    • [修复] 自动扫描接口进行依赖注入获取首个接口错误 bug #I41D1M
    • [修复] IRepository<TEntity> 没有实现 IRepository<TEntity, TDbContextLocator> 问题 #I41MZP
    • [修复] 远程请求缺省序列化 bug #I41PBW
    • [修复] 修复 AppDbContext.Tenant 多租户空异常问题 #I421DA
    • [修复] Worker Service 多个 Worker 定时任务阻塞问题 82a79cc
    • [修复] Jwt 自动刷新机制时区处理问题,主要针对国外用户 #I41UB1 82a79cc
  • 其他更改

    • [优化] 系统启动性能,从 106M 减少到 84M
    • [优化] 大量底层代码,包大小从 391Kb 减少到 350Kb(不带注释版本仅 64Kb)

v2.13/v2.14(已发布)

  • 新特性

    • [新增] 简易字符串模板功能,支持远程请求、数据库模块、日志模块、事件总线模块、定时任务模块、异常模块、数据校验模块 #I402BL
    • [新增] 404 状态码规范化默认处理 #I408F5
    • [新增] 定时任务 ISpareTimeWorker 声明方式支持异步方法 #I40KWR
    • [新增] 自动配置二级虚拟目录 !354
  • 突破性变化

    • [升级] 框架依赖 SDK.NET 5.0.8 版本
    • [移除] Db.GetNewDbContext() 静态方法 #I400BK
    • [移除] 数据库模块时态表拓展支持 #I405HI
    • [调整] IJsonSerializerProvider 接口参数,新增 inherit 参数 #I3ZQU5
    • [调整] AppSettings 配置的 LogEntityFrameworkCoreSqlExecuteCommand 名称为 OutputOriginalSqlExecuteLog #I40VVE
  • 问题修复

    • [修复] Worker Services 定时任务边界值问题导致跳过单次任务 #I405NI
    • [修复] Worker Services 独立发布后程序集扫描失效 bug #I3ZH3X
    • [修复] 远程请求如果配置了 Client 客户端但传入了空 RequestUrl 地址导致异常问题 #I40BC6
    • [修复] 规范化结果篡改非短路端状态码出现异常 bug #I408F5
  • 其他更改

    • [优化] App.GetServiceProvider(type) 解析服务性能 #I40KXN
    • [调整] 视图引擎保存成文件流默认缓存区大小,从 4096 提升至 8192 #I40KH5

v2.10/2.11/2.12 (已发布)

该版本有多个破坏性更改,更新时请认真查看。

  • 新特性

    • [新增] App.Configuration.Reload() 拓展 #I3XYI8
    • [新增] ISubscribeHandler 支持异步方法定义 #I3XYHJ
    • [新增] app.UseUnifyResultStatusCodes() 可配置修改返回状态码 #I3VZQH
    • [新增] 远程请求添加默认 User-Agent#I3W17C
    • [新增] 支持 Sql 高级代理切换数据库上下文定位器 #I3XFP6 #I3XDCR
    • [新增] 定时任务 CronFormat 自动识别 #I3Y7GT
    • [新增] Sql 高级代理 拦截功能 #I3YHG4
    • [新增] 拦截远程请求所有异常处理 #I3YPDE
    • [新增] 远程请求配置 Timeout 超时时间 #I3YPPK
    • [新增] 新增 RSA 加密算法 #I3YZNU !345
    • [新增] DataTableDataSet 支持不指定强类型返回 #I3Z6RI
    • [新增] Sql 字符串拓展方法设置 Timeout 超时时间 #I3ZKWF
    • [新增] Sql 高级代理 [Timeout] 特性,设置超时时间 #I3ZKWF
  • 突破性变化

    • [移除] FakeDelete 假删除/软删除所有功能 #I3XKII
    • [移除] 移除 PBKDF2 加密算法 #I3Z0IO
    • [调整] 远程请求设置超时时间单位由 分钟 改为 #I3YPPK
    • [调整] IJsonSerializerProvider 接口参数,新增 inherit 参数 #I3ZQU5
    • [调整] [NonAutomatic] 特性名称为 [Manual] #I3XKKX
    • [调整] [NotChangedListener] 特性名称为 [SuppressChangedListener] #I3XKLZ
    • [调整] [ManualSaveChanges] 名称为 [ManualCommit] #I3XKNP
    • [调整] DbContext.TenantIdQueryFilterExpression 名称为 DbContext.BuildTenantQueryFilter #I3XKTB
    • [调整] [SkipScan] 名称为 [SuppressSniffer] #I3XN5N
    • [调整] [SkipProxy] 名称为 [SuppressProxy] #I3XN7O
    • [重构] Sql 执行,性能提升 20% #I3W33U
  • 问题修复

    • [修复] 动态 WebAPI 扫描控制器没有屏蔽没有注册的第三方控制器 #I3Y7TJ
    • [修复] AppDbContext 设置 TablePrefix 无效: #I3Y57Q
    • [修复] 修复定时任务使用异步委托导致程序终止 bug #I3XVZ0
    • [修复] 事件总线一个 消息id 对应多个 Handler 只触发第一个#I3XYP0
    • [修复] .ToPagedList() 分页方法传入小于或等于 0 的页码 #I3XNAN
    • [修复] JSON 序列化默认 DateTimeOffset 异常 #I3XMOL
    • [修复] 继承 Serilog 日志在 Worker Service 生成重复日志 bug #I3WA0L !331
    • [修复] 粘土对象 动态添加 Clay 类型 bug #I3W9LW
    • [修复] ValidationTypes.Numeric 校验数值类型正则表达式错误 #I3WADS
    • [修复] 数据库命令参数 DbParameterValueobject 类型的时候且不指定 #I3YKM6
    • [修复] Oracle 数据库存储过程 游标参数 报错问题 #I3ZBYE
    • [修复] Worker Services 采用独立发布后无法执行问题 #I3ZH3X
    • [修复] 修复远程请求如果无返回值序列化异常问题 !348
  • 其他更改

    • [增强] 支持 appsettings.json 等自定义配置文件中文命名 #I3YBFD
    • [改进] 远程请求配置命名客户端 BaseAddress 地址兼容处理 #I3YCRH
    • [移除] 框架无用代码、优化代码
    • [优化] Furion非 Web 环境下性能
  • 文档变化

    • [新增] 会话和状态管理 文档 #I3YI3G
    • [更新] 远程请求、日志、数据库上下文、远程请求、Sql 高级代理文档
    • [更新] 配置文件 #I3Y2EV
  • 问答答疑

    • [答疑] dapper 多个数据源如何继承 #I3WUOI
    • [答疑] 关于 SpareTime 多次执行问题#I3XEQU
    • [答疑] 选项更改通知(热更新):数据库里的数据更改了如何通知选项进行改变? #I3XYI8
    • [答疑] SaaS 多租户添加时无法获取租户Id #I3Y5CF
    • [答疑] 获取 _httpContextAccessor.HttpContext 为空#I3Y6BI
    • [答疑] Ubuntu 中使用 App.Configuration 方法读取不到值 #I3Y74H
    • [答疑] 数据库上下文作用域问题 #I3YHXP
    • [答疑] 使用 UnitofWork 提交事务,可以提交成功,但是系统会有错误 #I3YIWU
    • [答疑] 数据库读写分离--非默认主库的从库随机该如何配置? #I3YVR7
  • 不做实现

    • [废弃] SpareTIme 新增 Dashboard 控制台看板,同时可以对任务进行暂停、删除、查看#I3XELY

v2.9.0 (已发布)

  • 新特性

    • [新增] 应用全局未托管资源监听,并实现特定时机释放非托管资源 #I3VXAU
    • [新增] 不包含 EntityFramework.Core 版本的 Furion.Pure#I3VGW8
    • [新增] swagger 支持设置多语言方式,设置的语言自动添加到 api 地址后面 #I3VDTD
    • [新增] 动态 WebAPI 支持 [FromRoute] 非必填(选填)参数设置 #I3VFIM
    • [新增] 动态 WebAPI 参数支持配置路由约束 #I3VFIR
    • [新增] MD5DESC 加密支持 大写 输出 #326
  • 突破性变化

    • [新增] Furion 所有包生成 .snupkg 包,支持开发阶段直接调试 Furion 所有包源码 #I3VFIX
    • [调整] repository.BuildChange() 方法的返回值,多返回一个 IServiceScope 对象 #I3VX3D
    • [调整] JWT 刷新 Token 方法 AutoRefreshToken 参数 days 改为 minutes #I3VXNB
  • 问题修复

    • [修复] App.GetOptionsSnapshot<> 从根服务解析异常 bug #I3VS2X
    • [修复] 修复远程请求如果出现异常,返回 Stream 为 null 导致异常的问题 #I3VSTU
    • [修复] 如果实体被跟踪后,无法执行删除操作 #I3W08P
  • 其他更改

    • [优化] 运行时内存,实现请求结束自动释放未托管资源 #I3VXAU
  • 文档变化

    • [更新] App 静态类文档、远程请求文档、分表分库文档
  • 问答答疑

    • [答疑] 动态 WebAPI,自定义根据方法名生成 [HttpMethod] 规则报错 #I3VKQG
    • [答疑] InsertAsync 的时候提示 ID 为空 #I3VS7E
    • [答疑] FirstOrDefault 自动过滤了 TanantId 字段 #I3W0VH
    • [答疑] 对方接口返回 HttpConnectionResponseContent 远程请求拿不到返回值 #I3W17C
    • [答疑] 查询方法 FindOrDefault 报错 #I3W830
    • [答疑] SqlNonQueryUnitOfWork 循环执行#I3W8WW
    • [答疑]Swagger 配置问题,导致 Swagger 中不能自动携带 token 授权的问题 #I3W934
    • [答疑] 远程请求 SetBody 参数识别不了#I3WBM1
    • [答疑] Scoped.Create 里执行 sql.SqlNonQuery() 或者 obj.insert() 问题#I3WB5O
    • [答疑] 调用函数或存储过程,怎么出参数据自定义对象?如 Oracle数据库的数组或记录 #I3W71W
  • 不做实现

    • [无效] 数据库小写下划线字段,无法自动映射成小驼峰 #I3W021
    • [废弃] EfCore 5 直接多对多时进行 SeedData #I3WDRJ

v2.7.0/2.8.0 (已发布)

  • 新特性

    • [新增] throw Oops.On("异常消息") 应用多语言支持 #I3UYC2
    • [新增] Db.GetMSRepository() 获取主从库仓储静态方法 #I3UBSJ
    • [新增] 工作单元特性,支持静态类强制性开启共享事务 #I3S9N8
    • [新增] EFCore 执行 sql 模式打印日志 #I3SE8X
    • [新增] 远程请求支持默认 HttpClient 配置 #I3SI17
    • [新增] 新增 短 ID 生成功能 #I3T7JP
    • [新增] [SensitiveDetection] 支持配置替换敏感词汇 #I3THIA
    • [新增] SpecificationDocumentBuilder.DocumentGroupsSpecificationDocumentBuilder.CheckApiDescriptionInCurrentGroup(currentGroup, apiDescription) 公开方法#I3UDSY
  • 突破性变化

    • [重构] 自动扫描 .json.xml 文件并加载到配置中的代码和规则,同时移除默认 .xml 文件加载,只保留 .json 文件 #I3UJ3L
    • [重构] 分布式连续 GUID 代码 #I3UBK0
    • [调整] Scoped.CreateUnitOfWork 名称为 Scoped.CreateUow #I3SJPU
    • [调整] JWTEncryption.Validate 返回值,支持返回 TokenValidationResult #I3S2ND
  • 问题修复

    • [修复] [DataValidation][SensitiveDetection] 多语言应用失效 #I3UH6U
    • [修复] Scoped 系列方法异步出现 Task is cancel 情况 #I3SJF6
    • [修复] Mysql 数据库的 ToPagedList 方法返回的结果进行遍历出现 MySqlConnection is aleady use 问题 #I3SJQ3
    • [修复] tool/cli.psl 没有包含项目名称 #I3S1T6
    • [修复] 远程请求做上传文件时,没有传入 Body,程序直接跳过 #I3TKFH
    • [修复] 远程请求 multipart/form-data 内容分割符缺失 #I3TNO9
    • [修复] 远程请求代理拦截方式返回 HttpResponseMessage 问题 #I3V161
    • [修复] repository.Database.SetCommandTimeout(600) 无法生效#I3VAQS
  • 其他更改

    • [改进] 支持规范化结果中间件判断是否跳过规范化结果 #I3T2AA
    • [调整] 更新部分列 UpdateIncludeNowAsync 具有二义性 #I3RW9Q
    • [优化] 框架底层性能,大大减少内存占用和溢出情况,启动内存从之前 136M 下将到 86M
    • [其他] 删除无用代码,优化不规范命名等
  • 文档变化

    • [新增] Inject 说明文档 #I3TITA
    • [更新] 4.2.9 的示例代码文档,方法没有放在 class 中 #I3S9T5
    • [修正] 规范化结果 6.5.6 多分组排序图片引用错误 #I3UBOQ
    • [更新] 静态类 Scoped 文档
  • 问答答疑

    • [答疑] 默认 MasterDbContextLocator 不随自定义的参数生成 #I3SDBB
    • [答疑] 事件总线中订阅处理程序类获取不到用户信息,这个正常吗 #I3SS0U
    • [答疑] 在有多租户过滤器的情况下,是否有一种方式查询全量的数据 #I3T0VI
    • [答疑] mysql 使用 &"tools/cli.ps1" 页面化加载表结构失败 #I3T4F8
    • [答疑] 其他 Web 层的 Startup 优先执行 #I3T8IP
    • [答疑] 辅助角色服务实现建议 #I3T906
    • [答疑] 开启 easy connection 后同一内网地址浏览器可以正常访问,远程请求则无法访问#I3TA2U
    • [答疑] scope.ServiceProvider.GetService<IOtherService>不存在 #I3TQMV
    • [答疑] 能否在 WPF 项目中使用呢? #I3TMCC
    • [答疑] Dapper 多个数据源 #I3TM9B
    • [答疑] L.GetSelectCulture() 方法异常 #I3TQS4
    • [答疑] 循环中使用 IDGen.NextID() 得到的结果并不是连续的 #I3UAF6
    • [答疑] 模块化动态加载插件支持通配符匹配.dll #I3UDT8
    • [答疑] MVC 模式,在 Controller 里快捷方式创建 View 页面出错 #I3UFGB
    • [答疑] 数据库迁移没有种子数据 #I3UI7G
    • [答疑] SpareTimeAttribute 中 根据 Cron 表达式 自动匹配 Cron 表达式格式化方式 #I3UTKQ
    • [答疑] 使用 workService 集成 SqlSugar 报错 #I3V8HJ
    • [答疑] sqlserver 2008 分页报错如何解决呢 #I3VF96
  • 不做实现

    • [废弃] 添加令牌桶限流算法 #I3SCDV
    • [废弃] 定时任务立即执行需求 #I3SF4A
    • [废弃] 文档建议 关于 reids 和 es 、消息队列的 #I3T90I
    • [废弃] IP 高频率请求限制 #I3UHE1
    • [废弃] Url 转发大模块 #I3TZHO

v2.5.0/2.6.0 (已发布)

  • 新特性

    • [新增] 虚拟文件服务,支持物理文件和嵌入资源文件 #I3RBR9
    • [新增] 读写分离/主从复制仓储 IMSRepositoryIMSRepository<TMasterDbContextLocator> 仓储,可进行随机或自定义获取从库
    • [新增] 数据脱敏处理 #I3R5ZF
  • 突破性变化

    • [移除] InsertOrUpdate 一系列数据库操作方法 #I3RI9L
    • [移除] 所有包含 Exists 单词的数据库操作方法 #I3RJ0T
    • [调整] 分布式 GUID IDGenerater 静态类名称为 IDGen #I3RGUA
  • 问题修复

    • [修复] 远程调用方法错误,请求报文头 Headers 不能添加到 IHttpDispatchProxy 的子接口上 #I3RAF7
  • 其他更改

    • [优化] 应用启动性能,减少内存分配
  • 文档变化

    • [新增] 脱敏处理文档 #I3R6WZ
    • [新增] 文件系统文档、FS 静态类文档 #I3RCC4
    • [更新] 读写分离/主从复制、数据库仓储文档、Db 静态类 #I3R3B6
  • 问答答疑

    • [答疑] 关于 Furion 集群部署 #I3R3J4
    • [答疑] 升级最新框架以后, 数据库生成模型报错 #I3R7TP
    • [答疑] 数据库上下文事务执行中,SaveNow 执行后有警告 #I3RAJI
    • [答疑] Hangfire 使用事务出现错误 #I3ROQ5
    • [答疑] 如何实现 cli 不执行某些表的迁移,web 请求可以正常操作呢? #I3ROU5
    • [答疑] 在使用定时任务时候出现的问题:继承 ISpareTimeWorker #I3RRZS
    • [答疑] MySql 时间差 8 小时处理 #I3RSCO
    • [答疑] Db.GetRepository<> 方法结合 [UnitOfWork] 后不可用 #I3RUK5
    • [答疑] 事务开启失败问题 #I3RYJY
    • [答疑] 支持 DbProvider 可动态配置 #I3RYPE
    • [答疑] WorkService 依赖注入 ISingleton 问题 #I3RZ1L
    • [答疑] ISpareTimeWorker 运行期动态修改 #I3S33Q
  • 不做实现

    • [拒绝] 有序 Guid 精度是固定的毫秒级:1 毫秒内生成的多个 Guid 是无序的 #I3R59J
    • [拒绝] 建议:JWTEncryption.Validate 方法返回 JWT 的检查失败时的原因 #I3S1F2

v2.4.0 (已发布)

  • 新特性

    • [新增] 支持自动加载模块化/插件 .xml 注释文件 #I3Q7XY
    • [新增] AppDbContext.FailedAutoRollback 属性,可配置事务是否自动回滚 #I3QOUS
  • 突破性变化

    • [升级] .NET 5 SDK 为 5.0.6 版本
    • [新增] IJsonSerializerProvider.GetSerializerOptions() 接口方法 #I3QIJN
  • 问题修复

    • [修复] 通过 services.AddInject() 方式注册,模块化/插件不加载 #I3Q7XH
    • [修复] 种子数据返回 null 报空异常 #I3QCM5
    • [修复] 通过 Clay.Object 创建粘土对象后属性变小写问题 #I3QRV3
  • 其他更改

    • [优化] Furion 框架底层性能,减少内存占用,提高应用初始化速度 92f8cc1
  • 文档变化

    • [更新] JSON 序列化文档、规范化结果文档、数据库上下文文档
  • 问答答疑

    • [答疑] InsertOrUpdateNowAsync 报错 #I3QKO5
  • 不做实现

    • [废弃] 定时任务自定义 Failed 事件 #I3QCM2
    • [废弃] 模块化动态生成数据库表 #I3QH3G
    • [废弃] 建议事件总线新增 MQ 支持 #I3QWZ4
    • [废弃] 重构规范化整个模块代码 #I3NFT7

v2.3.0 (已发布)

  • 新特性

    • [新增] Furion.Extras.DatabaseAccessor.MongoDB 拓展包支持 #I3PKST
    • [新增] 动态粘土类型直接转 objectdynamic 类型 #I3OY27
    • [新增] 新增 Oops.Retry 方法,支持设置方法调用失败进行重试 #I3PJKQ
    • [新增] JWTSettings 配置节点 Algorithm,用于配置加密算法 #I3PQGV
    • [新增] repository.EnsureTransaction() 方法确保工作单元事务有效 #I3PVF1
  • 突破性变化

    • [支持] 支持 .NET 6.0.0 Preview 3 版本 #I3P2C7
  • 问题修复

    • [修复] 使用数据库生成模型 tools/cli.ps1,从数据库表生成的实体异常 #I3PL18
    • [修复] 贴了 [NonUntify] 特性后,SwaggerExample Value 没有匹配正确 #I3PK0L
    • [修复] SpareTimer.TallyCron 表达式中计数无效 #I3PWSE
  • 其他更改

    • [改进] 框架默认序列化应该从配置中读取,而非手动编写 #I3P1SJ
    • [改进] SqlSugar 拓展库,支持非泛型仓储获取上下文操作对象 #I3PK2N
    • [改进] 支持分布式内存缓存可配置化 #I3POKD
  • 文档变化

    • [文档] 添加 JWTSettings 配置独立文档 #I3PQGW
  • 问答答疑

    • [答疑] 软删除如果数据不存在,则报错 #I3PTVB
    • [答疑] 多个类集成测试会造成数据库定位器多次注册,无法运行所有测试,只能一个类一个类的运行 #I3PXGY
  • 不做实现


v2.2.0 (已发布)

  • 新特性

    • [新增] Clay 粘土类型,支持让 C# 创建一个弱类型对象并操作弱类型 #I3O2QQ
    • [新增] 新增 Scoped.Create 带返回值重载 #I3O47J
    • [新增] 支持 Scoped.Create() 一系列方法支持传入作用域工厂 #I3OAP5
    • [新增] 支持事件总线同步执行方式 #I3OAW2
    • [新增] [DataValidation] 跳过空字符串和空值验证 #I3OGEN
    • [新增] Worker Service 可配置是否自动注册 Worker #I3OLW4
  • 突破性变化

  • 问题修复

    • [修复] 定时任务设置 cancelInNoneNextTime: false 一次也不执行 #I3O3N0
    • [修复] SpareTime 自定义下次执行时间出现空异常 #I3O46X
    • [修复] MiniProfiler 设置为 false 时,数据库上下文提交拦截器未添加 #I3OAWX
    • [修复] [Consumes("application/x-www-form-urlencoded")]ModelQuery 配置同时配置导致空引用问题 #I3ODUR
    • [修复] 在 Grpc 中使用 jwt 授权出现空异常 #I3OW3I
  • 其他更改

    • [优化] 支持发布后代码精简配置,减少不必要的文件夹输出 #I3OAPF
    • [优化] 自动刷新 Token 机制,新增容错值处理,解决并发 Token 刷新失败问题 #I3OGYF
  • 文档变化

    • [新增] 粘土对象文档 #I3OG18
  • 问答答疑

    • [答疑] 动态 WebAPI 如何获取接收文件 #I3O29B
    • [答疑] 定时任务使用 Scope.CreateUow 引发的问题 #I3O2CD
    • [答疑] 单文件发布程序工作不正常 #I3O4D8
    • [答疑] 同时配置租户过滤器和软删除过滤器,最终的 sql 只生成了一种过滤条件 #I3OB0A
    • [答疑] HTTP 重定向 HTTPS 后跨域失效 #I3OB8R
    • [答疑] 在 PostgreSql 数据库使用 rep.FirstOrDefault(u => u.Id == UserId); 引起异常 #I3O5OF
    • [答疑] 定时任务有时能触发有时不能触发 #I3ORBE
  • 不做实现

    • [作废] 框架中的 swagger 是否有提供导出文档为 markdwon/word 的功能计划? #I3OL8O
    • [作废] 数据库实体父子继承,子类生成的 SQL 不一样 #I3NHU3
    • [作废] 支持第三方数据库 ORM #I3OXA3

v2.1.0 (已发布)

  • 新特性

    • [新增] 新增定时任务 ISpareTimeWorker 方式支持 [SpareTime("{配置路径}}] 方式 #I3NTUX
    • [新增] 定时任务支持异步委托 #I3NP96
    • [新增] 轻量级分布式连续 GUID 生成器 #I3NKLZ
    • [新增] ClayObject 模块,处理 ExpandoObjectIDictionary<string,object> 类型 #I3N3J4
    • [新增] Scoped.CreateUow(handler) 创建作用域并自动提交数据库更改方法 #I3NU3G
  • 突破性变化

    • [调整] 规范化结果接口 OnResponseStatusCodes 方法,新增 UnifyResultStatusCodesOptions 参数 #I3NDB9
    • [移除] 雪花 ID 实现代码 #I3NKLZ
  • 问题修复

    • [修复] Swagger 不能支持非 int 类型的枚举 #I3NQM8
    • [修复] 数据库线程池多线程并发问题 #I3NR4L
    • [修复] 自定义控制器路由后且为方法参数指定了 [ApiSeat] 后生成路由重复 #I3NRF6
  • 其他更改

    • [改进] 支持应用启动的时候迁移种子数据 #I3NH3M
  • 文档变化

    • [新增] 分布式 ID 生成文档 #I3B6CX
    • [新增] 新增模块化开发文档 #I3NSUS
    • [更新] 20.4 字符串拓展方式 > 错误ToAESDecrypt 写成了 ToToAESDecrypt #
  • 问答答疑

    • [答疑] 有关【定时任务/委托】的疑问 #I3N3EW
    • [答疑] 统一返回格式支持自定义 #I3NU1G
  • 不做实现

    • [作废] 期待 IEnumerableExtensions 扩展 OrderBy 函数来支持分页排序 #I3NOQ9

v2.0.0 (已发布)

  • 新特性

    • [新增] 控制台应用程序及 Worker Services 支持 #I3K4DG
    • [新增] 完整任务调度功能 #I3IRUX
    • [新增] Cron 表达式解析 #I3IQ9Y
    • [新增] 支持 Swagger 自定义配置 swagger.json 地址模板 #I3IHMX
    • [新增] 支持配置动态 WebApi 区域 #I3IJAZ
    • [新增] 远程请求新增支持传入服务提供器 IServiceProvider #I3IVBL
    • [新增] 全局配置选型 SupportPackageNamePrefixs 配置,支持配置包前缀 #I3K0SN
    • [新增] 应用启动时支持 referenceassembly 类型程序集扫描 #I3K0SN
    • [新增] 依赖注入 AOP 拦截获取方法真实特性 #I3LZBX
    • [新增] EFCore 手动 SaveChanges() 特性 #I3N01Y
    • [新增] 支持 Cors 跨域更多配置 #I3N2J0
  • 突破性变化

    • [重构] 完整任务调度功能 #I3IRUX
    • [重构] 日志模块功能 #I3J2K0
    • [重构] 模板引擎功能 #I3J46E
    • [重构] 底层 EFCoreRepository 仓储 #I3J6W5
    • [重构] sql 字符串拓展底层代码 #I3IVCE
    • [重构] 底层 SqlRepository 所有逻辑代码 #I3J6V6
    • [重构] 数据库实体拓展方法 #I3J609
    • [调整] 事件事件总线同步执行为异步方式执行 #I3J0WA
    • [移除] 框架底层 HttpContext.IsAjaxRequest() 拓展 #I3IVAA
    • [移除] ValidationTypes.Required 验证 #I3KR85
  • 问题修复

    • [修复] 关闭 InjectMiniProfiler 参数后内存缓存无效 #I3IHLR
    • [修复] 在多租户中调用 Tenant 属性出现偶然性数据库上下文被释放的情况 #I3IC70
    • [修复] Sql 代理中如果返回基元类型抛出不能将 object 转换成对应类型的异常 #I3IC84
    • [修复] 存储过程多返回值的时候,outputvalues 的 name 不是定义的 MSG 的 name,是 Msg 类型。 #I3IC7Y
    • [修复] PhoneNumber 手机号验证正则表达式错误 #I3ID10
    • [修复] 依赖注入 AOP 拦截无法捕获内部异常 #I3IGCC
    • [修复] 全局拦截标记异常已被处理后异常过滤器依然执行 #I3J463
    • [修复] 自定义全局异常拦截器不起作用 #I3K1SJ
    • [修复] 在 WorkerService 模式下,还是使用 WebHostEnvironment 来判断 Host 环境,会导致错误 #I3LCQY
    • [修复] 定时任务 DoOnce 抛空异常 bug #I3M0ZT
  • 其他更改

    • [改进] 启动时程序集扫描类型 #I3K0SN
    • [改进] App.GetConfig<>("key") 不支持获取单个值问题 #I3ILF1
    • [改进] UrlEncode 应该用 Uri.EscapeDataString() 而不是 HttpUtility.UrlEncode #I3ICTK
  • 文档变化

    • [新增] 定位任务、后台任务文档 #I3JHHG
    • [新增] 辅助角色服务文档 #I3K5GN
    • [更新] 动态 WebAPI、规范化文档、数据库上下文文档
  • 问答答疑

    • [答疑] 数据校验,自定义 ErrorMessage 无效问题 #I3ICL3
    • [答疑] 最新 issue 中新增的“新增常用的 JSON 序列化方法” 会导致 AOP 拦截异常 #I3I7VE
    • [答疑] Furion.DatabaseAccessor.PrivateEntityBase 中的 TenantId 数据类型设置为 object #I3IQV6
    • [答疑] 有关异常拦截和处理的疑问 #I3IUFZ
    • [答疑] DataValidation 在空值的情况下被忽略掉了#I3IWSM
    • [答疑] 日志文档没有更新 #I3J1DX
    • [答疑] 对于 webapi 简单类型参数,是否可以以 json 方式提交 #I3J18I
    • [答疑] IUnifyResultProvider 实现中如果 UnifyModel 的 type 不是范型会报错 #I3JBXF
    • [答疑] 如何模块化开发新功能? #I3J7ZZ
    • [答疑] 建议增加微服务中间件的集成 #I3JTZQ
    • [答疑] 二级虚拟目录部署的 swagger 的 MiniProfiler js 报错 #I3IWLR
  • 不做实现

    • [作废] 在请求审计日志中对贴有 DisableAuditing 特性的字段自动过滤 #I3DHAN

v1.19.0 (已发布)

  • 新特性

    • [新增] EFCore 5.0 支持 SqlServer 2005-2008 数据库 #I3HZZ6
    • [新增] Sql 高级代理支持模板替换了 #I3HHWU #I3HH2T
    • [新增] PBKDF2 加密 #I3HN7A
    • [新增] 常用的 JSON 操作方法 #I3HUYO
    • [新增] 所有解析服务的方法都支持传入 IServiceProvidier 参数 #I3HXEU
  • 突破性变化

    • [升级] .NET 5 SDK 至 5.0.5 版本
  • 问题修复

    • [修复] 远程请求 application/x-www-form-urlencoded 自动被转码了 #I3HDPC
    • [修复] ISqlDispatchProxy 调用带返回值的存储过程出错 #I3HISS
    • [修复] 多数据库工作单元异常无法回滚数据 #I3I2KN #I3HYN5
    • [修复] Serilog 日志生成太多文件 #I3I2PN
    • [修复] 1.18.0 版本数据库连接池存在连接泄漏问题 #I3I5KO
    • [修复] Sqlite 提示事务已完成异常 #I3I9F2
  • 其他更改

    • [改进] 视图模板功能,默认支持可枚举泛型类型 #I3GYEE
    • [改进] 开发阶段 MiniProfiler 打印数据库相关信息 #I3I8VQ
    • [改进] EFCore 5.0 未提供 Sqlite 数据库 DataAdapter 的支持 #I3I9FC
  • 文档变化

    • [更新] 数据库上下文、多租户、仓储、日志、序列化等文档。
  • 问答答疑

    • [答疑] 建议 MVC 模式下增加 Furion 的功能 #I3GY4R
    • [答疑] 数据库关联操作 #I3H5QP
    • [答疑] 1.17.5 版本 suagger 无法生成 swagger.json #I3HGPZ
    • [答疑] Serilog 扩展+dll 启动与 swagger 的 MiniProfiler 冲突 #I3HWJM
    • [答疑] Sql 高级代理返回 DataTable 时,结果为空取不到记录 #I3HUWG
    • [答疑] Task.Run 操作数据库问题 #I3HZ9D
  • 不做实现


v1.18.0 (已发布)

  • 新特性

    • [新增] Oracle 11 版本支持 #I3EVL5
    • [新增] Mysql 官方包 MySql.EntityFrameworkCore 支持 #I3E6J1
    • [新增] 全局配置 WebApi 参数 [FromQury]#I3EFYJ
    • [新增] 公开框架底层依赖注入扫描注册拓展 services.AddRisterTypes(types) #I3EIV3
    • [新增] SqlSugar 工作单元特性 #I3EJO5
  • 突破性变化

  • 问题修复

    • [修复] 数据库上下文池一旦有上下文操作失败还数据库上下文出现二次提交数据库的问题 #I3EIJJ
    • [修复] 不同数据库命令参数前缀都添加了 @ 处理 #I3EBJP
    • [修复] 尝试修复事件总线线程安全问题 #I3EGSB #PR236
    • [修复] HttpContextExtensionsSignoutToSwagger 方法无效 #I3EHNQ
    • [修复] 如果动态 WebApi 贴了 [ApiController] 特性后,导致路由参数重复生成 #I3EOQQ
    • [修复] 如果没有任何 webapi 控制器时,文档报错 #I3EVLB
    • [修复] 依赖注入泛型类型注册失败 #I3EX66
  • 其他更改

    • [调整] SqlSugar 拓展库仓储 Context 属性类型未 SqlSugarClient #I3EHXA
    • [改进] 刷新 Token 黑名单 Redis 中分组 #I3EQWO
    • [改进] 远程请求在请求拦截次发起二次请求导致异常问题 #I3ER71
    • [改进] 多租户默认缓存改为分布式缓存 #I3EXEU
  • 文档变化

    • [更新] 数据库操作文档 #I3E84X
  • 问答答疑

    • [答疑] 如何方便的获取 IDynamicApiController API 产生的 url 和 谓词 #I3ED17
    • [答疑] Code First -执行命令 Add-Migration 遇到了问题 #I3EHD0
    • [答疑] tools v1.16.0 无法生成实体,一直提示 Missing required argument <PROVIDER>. #I3ENZ8
    • [答疑] Authorize 的 Logout 按钮,无法实时请空 token#I3EOF9
  • 不做实现


v1.17.0 (已发布)

  • 新特性

    • [新增] 动态 WebAPI 支持继承基类配置特性 #I3D5PX
    • [新增] 远程请求支持 multipart/form-data 内容类型处理 #I3D7KG
    • [新增] 字符串加密拓展 #I3DHBW
    • [新增] 新增远程请求可直接下载返回值内容转为 string 类型 #I3DIGR
    • [新增] 远程请求地址支持模板引擎 #I3D5Y8
    • [新增] [DataValidation] 错误消息支持 string.Format 操作 #I3E08W
    • [新增] 远程请求 HttpRequestMessage 拓展方法 AppendQueries() 追加更多 query 参数拓展 #I3E3DI
  • 突破性变化

    • [调整] IRepository.AsAsyncEnumerable() 返回值 #I3DIQ1,调整为:rep.AsQueryable().ToListAsync()
  • 问题修复

    • [修复] 数据验证失败后也打印了成功的字段 #I3CVBS
    • [修复] 远程请求配置 contentTypeapplication/x-www-form-urlencoded 无效问题#I3CWBS
    • [修复] 远程请求无法打印完整的请求地址,比如配置了 HttpClient 之后 #I3CY42
    • [修复] 程序启动时排除默认配置文件算法不对,应该采用正则表达式匹配 #I3D9E7
    • [修复] 远程请求成功请求拦截不生效 #I3DOE4
    • [修复] Dapper 拓展数据库切换为 oracle 时,系统找不到指定的文件 Oracle.ManagedDataAccess.Core #I3DYM3
  • 其他更改

    • [改进] 获取 JWT token 信息支持配置 Token 前缀,如 Bearer #I3DJIV
    • [改进] 刷新 Token 黑名单存储方式,将内存缓存调整为分布式缓存 #I3DPBR
  • 文档变化

    • [调整] 远程请求文档 #I3CPJO
  • 问答答疑

    • [答疑] LinqExpression.And 没有 2 个参数的方法 #I3CXKZ
    • [答疑] 异常信息 如何记录到数据库中:) #I3DDGO
    • [答疑] 无键实体选用 IEntityNotKey #I3DWRF
    • [答疑] 根据主键删除一条记录不成功,无错误信息 #I3DWWF
    • [答疑] 如何自定义接口返回格式 #I3DZN6
    • [答疑] DynamicApiController 如何在运行时决定是否公开一个 Action #I3D5UL
    • [答疑] Furion.DatabaseAccessor.DbHelpers 方法:ConvertToDbParameters 是不是应该过滤掉贴 NotMapped 的特性 #I3E2XS
  • 不做实现

    • [废弃] 框架是否提供 ISoftDelete 类似接口 #I3CP93

v1.16.0 (已发布)

  • 新特性

    • [新增] IDGenerator 雪花 ID 算法,感谢 idgenerator 作者提交 PR #PR204 #I3B60S
    • [新增] DbContext 刷新多租户缓存拓展方法 #I39N5U
    • [新增] 自定义配置单个控制器名称规范,如小写路由 #I3A5XL
    • [新增] 获取当前选择区域语言方法 #I3BSDH
  • 突破性变化

    • [升级] .NET 5 SDK 至 5.0.4 版本 #I3ASTL
    • [重构] 远程请求所有功能 #I2LB7M
    • [重构] JSON 序列化功能,提供统一的抽象接口,方便自由替换 JSON#I39GT9
    • [重构] 验证失败返回消息模型及规范化接口验证参数 #I3AFQW
    • [优化] 插件式开发热插拔功能,实现动态加载卸载 #PR200, 感谢 @SamWangCoder
    • [移除] 移除 JsonSerializerUtility 静态类及移除属性大写序列化拓展配置 #I3AFRJ
  • 问题修复

    • [修复] MVC 模式下不支持验证自定义验证逻辑 #I39LM5
    • [修复] 验证数值类型正则表达式不支持负数 bug #I39YUV
    • [修复] 框架启动时无法加载未被引用的程序集 bug #I3A3Z4
    • [修复] EFCoreRepository.IsAttached() 方法判断错误 bug #I3A824
    • [修复] 动态API 驼峰显示配置无效 bug #I3AF32
    • [修复] cli.ps1 不支持新版本 EFCore bug #I3APO9
    • [修复] EFCore 实体配置 [Table] 特性无效 bug #I3BAYH
    • [修复] 动态 WebAPI CheckIsSplitCamelCase bug #I3BLKX
    • [修复] 修复动态 WebAPI 配置保留 Action 的 Async 后缀无效问题 #I3C3DA
    • [修复] JWT Token 刷新后旧的刷新 Token 依旧可用 bug #I3C8ZH
    • [修复] 多语言 Razor 视图变量多语言乱码问题 #I3CBMU
  • 其他更改

    • [优化] 默认序列化提供器 System.Text.Json 反序列化字符串时区分大小写问题 #I3BSXV
    • [优化] 优化 MessageCenter 性能问题 #I39PRR
    • [优化] 数据库上下文池小性能优化
  • 文档变化

    • [新增] Docker 环境下自动化部署 #PR209
    • [新增] JSON 序列化 文档 #I3B6D8
    • [更新] 跨域、安全授权、即时通信文档、多语言、规范化文档
  • 问答答疑

    • [答疑] Furion.Extras.DatabaseAccessor.SqlSugar 配置多个数据库打印 SQL 语句问题 #I39PDC
    • [答疑] ORACLE 数据库多租户模式下返回值为指定类型时系统卡死 #I39RNH
    • [答疑] 假删除指向异常 #I39XZA
    • [答疑] Furion 多语言配置节是放在 AppSettings 里面还是外面呢? #I3A4SB
    • [答疑] 没找到数据库上下文 #I3A5HS
    • [答疑]QQ 交流群吗? #I3AAM7
    • [答疑] Vue3 环境下配置 SignalR 跨域出错 #I3ALQ7
    • [答疑] 设置 Swagger 参数非必填 #I3AT02
    • [答疑] EFCore 调用 Insert 时报 Unknown column 'Discriminator' in 'field list' 异常 #I3B2LC
    • [答疑] 逆向 mysql 数据库时 cli 出现错误 #I3B64F
    • [答疑] Sql 高级代理使用过程中 DateTime 类型的参数序列化失败 #I3AZXK
    • [答疑] 使用 Mysql 执行 Add-Migration 报错 #I3B8EW
    • [答疑] Saas 多租户模式-独立 Database 模式下无法获取 Tenant, 导致无法自动切换的问题#I3AVXU
    • [答疑] 如何自定义 WebAPI 统一结果模型 #I3BBYW #I3BBYV
    • [答疑]Web.Entry 项目新建了一个 Controller,多了未知方法 #I3BKH5
    • [答疑] AOP 拦截如何解析服务 #I3BUM3
    • [答疑] 动态 WebAPI 返回参数被省略 #I3C2XR
    • [答疑] 如何设置某一个接口响应数据不自动转小写,按原始字段名返回 #I38L9B
    • [答疑] code first 如何配置自动迁移 #I3CCR0
    • [答疑] webapi 混合授权如何区分不同系统 #I3CJCY
    • [答疑] EFCore 不支持递归无限级遍历关系 #I3CET9
  • 不做实现

    • [废弃] 建议 EFCore 可配置外键关系导航问题 #I3994X
    • [废弃] 建议将 EFCore 剥离出来,作为插件的形式提供。这样可以选择自己喜欢的 ORM #I3ABNX
    • [废弃] 事件总线能否提供返回值 #I3AWL6
    • [废弃] Sql 模板能仿照 Mybatis 一样加各种标签吗?#I3ASRS
    • [废弃] EFCore 更新或排除更新指定列支持传入 DTO 模型 #I3AS5K
    • [废弃] 新增 UnitOfWork 事务完成事件 #I3BRMI

v1.15.0 (已发布)

  • 新特性

    • [新增] 跳过特定实体数据库操作监听特性 #I386LB
    • [新增] IEntityChangedListener 增加对 OldEntity 的支持 #I385X2
    • [新增] 实时通信自动配置集线器拓展及特性 #I387QX
    • [新增] Mapster 拓展支持 IMapper 依赖注入方式 #I38C7C
    • [新增] [AppDbContext] 特性默认构造函数 #I38J97
    • [新增] UnifyContext.GetExceptionMetadata(context) 返回错误码支持 #I38ONX
  • 突破性变化

  • 问题修复

    • [修复] 多次循环中调用 Db.GetNewDbContext() 还是获取到同一个对象 #I38NNP
    • [修复] Swagger 过滤掉 object 类型属性问题 #I38FHL
    • [修复] 同一类不支持多继承 IEntityChangedListener 问题 #I38UQJ
    • [修复] 自定义序列化属性名称导致验证失败属性不匹配问题 #I38W8Z
  • 其他更改

    • [优化] 代码不规范命名导致开发者阅读代码时产生歧义
  • 文档变化

    • [新增] FluentValidation 集成文档 #I38IOT
  • 问答答疑

    • [答疑] Furion 框架版本向下兼容问题 #I38WMZ
  • 不做实现

    • [废弃] 建议 SqlSugar 添加动态切换数据库功能 #I38G4M
    • [废弃] 建议 MessageCenter 采用 Channel 实现 #I38BP8
    • [废弃] 建议接口文档整合 Knife4jUI 或 Redoc #I38S70

v1.14.0(已发布)

  • 新特性

    • [新增] EFCore 5.0 的 Oracle 数据库支持 #I37Z8E
    • [新增] 控制是否在开发环境下显示数据库连接信息 #I37YQ2
    • [新增] [NonUnify] 支持在类中贴此特性 #I359Q6
    • [新增] 网络请求 字符串 HttpClient 拦截器 #I35F3E
    • [新增] HttpContextHttpRequest 获取远程地址拓展 #I3688Z
    • [新增] services.AddMvcFilter<> 添加 Mvc 过滤器拓展 #I368BH
  • 突破性变化

    • [升级] 框架依赖的 .NET 5 SDK 至最新版 5.0.3 #I37YQQ
    • [升级] Swashbuckle.AspNetCore 组件包到 6.0.x 版本 #I37EZK
    • [移除] Furion 框架 JWT 拓展类,只在 Furion.Extras.Authentication.JwtBearer 中保留 #I35D59
  • 问题修复

    • [修复] 传入错误 JWT Token 字符串导致自动刷新 Token 出现字符串边界值异常 bug #I34ZE5
    • [修复] 瞬时作用域数据库上下文也会自动加入工作单元导致写日志时连锁异常 bug #I37WTV
  • 其他更改

    • [优化] 获取系统环境参数的性能 #I36SR5
    • [优化] Furion 底层添加 Mvc 过滤器代码 #I36SKA
    • [优化] 添加默认 Json 序列化时间默认时间格式 #I36SL0
    • [升级] 升级 SqlSugar 拓展包到 5.0.2.6 版本 #I36SIG
  • 文档变化

    • [新增] 数据库入门文档 #I37Z8S
    • [新增] 更新日志文档 #I36PI0
    • [新增] 请求审计日志、执行 Sql 更新日志文档 #I36PIK
    • [新增] 前端使用 axios 跨域配置文档 #I36PIT
    • [新增] App 静态类获取应用、环境更多信息数据 #I36SOV
    • [新增] 英文版 README.md 介绍 #I37QHP
  • 问答答疑

  • 不做实现

    • [废弃] 多语言资源文件自动创建 #I35AA4
    • [废弃] 建议多语言加上维吾尔语支持 #I37X1L

v1.13.0(已发布)

  • 新特性

    • [新增] 多语言功能及拓展 #I2DOCL
    • [新增] 事件总线功能及消息中心 #I23BKN
    • [新增] Swagger 分组显示隐藏配置 #I2AHH8
    • [新增] Furion.Extras.Logging.Serilog 拓展插件 #I2AAN8
    • [新增] cli.ps 支持 -Namespace 命名空间指定 #I2A175
    • [新增] Swagger 规范化化文档授权失效后自动取消授权锁 #I2AIWC
    • [新增] Request.Body 支持重复读功能,主要解决微信 SDK 问题 #I2AMG0
    • [新增] 网络请求功能及文档 #I2APGJ
    • [新增] SqlSugar 拓展包支持打印 sqlMiniProfiler#I2ASLS
    • [新增] Furion.Extras.DatabaseAccesssor.Dapper 拓展插件 #I2ASYA
    • [新增] Furion.Extras.DatabaseAccessor.PetaPoco 拓展插件 #I2AUGA
    • [新增] 网络请求字符串拓展方法 #I2CPQ0
    • [新增] SqlSugar 拓展新增 PagedList 拓展 #I2CW99
    • [新增] 远程请求支持参数特性验证 #I2CX5L
    • [新增] App.User 获取当前授权用户信息便捷方法 #I2CZLO
    • [新增] 规范化文档可配置功能,支持 appsettings.json 配置 #I2D1K9
    • [新增] 远程请求拦截器添加方法和方法参数 #I2D2CM
    • [新增] 远程请求出错返回默认值支持 #I2D44M
    • [新增] 远程请求 body 参数序列化支持设置 PropertyNamingPolicy #I2D685
    • [新增] 远程服务接口客户端配置 #I2D7PS
    • [新增] AddInjectUseInject 允许自定义 SecurityDefinitionsSwaggerUI #I2DIMG
    • [新增] [SecurityDefine] 默认构造函数 #I2DNXT
    • [新增] AspectDispatchProxy 动态代理类 #I2DO6I
    • [新增] [QueryParameters] 特性,支持一键将 Action 参数添加 [FromQuery] 特性 #I2G8TF
    • [新增] 动态日志配置及拓展方法 #I2GDGD
    • [新增] WebApi 请求谓词默认规则配置功能 #I2M70X
  • 突破性变化

    • [升级] .NET 5 SDK 到 .NET 5.0.2 版本 #I2D0PZ
    • [调整] 框架内所有拓展类命名空间,全部迁移到 Furion.模块.Extensions#I2AH54
    • [调整] Swagger 记住授权存储方式,替换 Session 存储方式为 LocalStorage 方式 #I2AKUA
    • [调整] Furion 框架包描述文件,减少框架体积 #I2APAU
    • [调整] App.CanBeScanTypesApp.EffectiveTypes #I2B0ZR
    • [调整] App.ServiceProvider 属性并移除 App.GetDuplicateXXX 方法 #I2CYZE
    • [调整] Db.GetDuplicateDbContextDb.GetNewDbContext #I2CZ04
    • [调整] Db.GetSqlDispatchProxyDb.GetSqlProxy #I2DO9T
    • [重构] Aop 服务拦截器,支持异步、同步两种方式 #I2B9HQ
    • [重构] 网络请求所有功能 #I2BMR7
  • 问题修复

    • [修复] Swagger 规范化化结果不一致 bug #I2ACF3
    • [修复] 数据库新增或更新忽略空值操作方法报空异常 #I2AB6C
    • [修复] Startup.cs Aop 全局拦截无效 #I2A7T2
    • [修复] Token 过期后自动刷新 Token 无法获取最新的用户信息 bug #I2AWQI
    • [修复] [ApiDescriptionSettings(Tag="xx")] 导致 swagger.json 报错 bug #I2B47R
    • [修复] Mysql sql 数据库查询结果 tinyint 类型转换出错 bug #I2BEBM
    • [修复] 规范化结果多次包裹类型 bug #I2BHHZ
    • [修复] 动态 Api 基元类型数组问题 #I2BMS5
    • [修复] sql 查询枚举类型转换异常 bug #I2BS2Y
    • [修复] string.SqlQuerizeAsync<T1>() 拓展返回错误 bug #I2BSTS
    • [修复] 动态 Api 子类重写父类方法并取别名后 Swagger 异常 bug #I2C9VP
    • [修复] 网络请求 application/json 序列化大小写问题 #I2CRJC
    • [修复] 多数据库定位器实体嵌套关联 bug #I2CVN0
    • [修复] 跨域响应头设置无效 bug #I2CW5T
    • [修复] 远程网络请求代理打印到 MiniProfiler bug #I2CZBC
    • [修复] 远程请求响应拦截器 bug #I2D4DG
    • [修复] SqlSugar 框架 AsQueryable() 一直追加参数 #I2DH1D
    • [修复] 自动刷新 Token 空异常 bug #I2DO29
    • [修复] 生成 JWT Token 不传过期时间出现验证 401 bug #I2DO8L
    • [修复] AppStartup 排序无效 #I2DVD2
    • [修复] 未启用多语言服务时友好异常和验证出现空异常 #I2ECUJ
    • [修复] 数据校验字母和数字组合无法匹配 bug #I2EF2Q
    • [修复] 数据校验手机或固话无效 bug #I2M5IZ
    • [修复] Dapper 拓展解析 SqlConnection 异常 bug #I2M5P2
    • [修复] 开启多语言后,EF 迁移异常 bug #I2M7DT
    • [修复] IEntityTypeBuilder 不支持多重继承 bug #I2PAOD
    • [修复] JwtHandler 设置自动刷新后,匿名访问无法通过 bug #I2SDOX
    • [修复] Dapper 拓展中 SqlServer 数据库获取连接对象类型 bug #PR159
  • 其他更改

    • [优化] 移除 Sql 查询结果映射检查 [NotMapper] 特性机制 #I34XD0
    • [优化] 依赖注入时排除 IDynamicApiController 接口 #I2ECTG
    • [优化] MD5 加密性能 #PR158
  • 文档变化

    • [重构] 文档首页 #I34XBR
    • [新增] 网络请求文档 #I2APGJ
    • [新增] 多语言文档 #I2DOCL
    • [新增] 文档全文搜索引擎 #I34XAW
    • [新增] 全局静态类类型 #I34XB4
    • [新增] 框架可配置选项文档 #I34XB9
    • [新增] 事件总线文档 #I34XBI
    • [新增] 数据加解密文档 #I34XC0
    • [新增] 贡献指南文档 #I34XC8
    • [新增] HttpContext文件上传下载 博客文章 #I34XCB
    • [其他] 文档小调整,小优化
  • 问答答疑

    • [答疑] 跨域设置无效 #I2ASNJ
    • [答疑] MVC 视图无效,原因是 .cshtml 文件没有设置为 内容 #I2AXUU
    • [答疑] Sql 操作可以实现事务吗?#I2B0NX
    • [答疑] IRepository 操作数据库会打开多次数据库连接 #I2BB7B
    • [答疑] 如何进入自定义 AppAuthorizeHandler 断点 #I2BGXY
    • [答疑] SqlSugar 注入问题 #I2C2AQ
    • [答疑] 建议增加 API 签名验证,时效验证 #I2C6ET
    • [答疑] 多数据库多租户同时使用 Add-Migration 报错 #I2CEHS
    • [答疑] ISqlSugarRepository 没有 Getxxx 方法 #I2CJLZ
    • [答疑] cli.ps1 如何将 sql 里的表导出成 model#I2CSUL
    • [答疑] 手动修改 Swagger 终结点路径无效 #I2D608
    • [答疑] DefaultDbContext 不能识别 #I2DCZX
    • [答疑] 各分层项目 Startup.cs 支持 Configuration #I2DDUP
    • [答疑] Aop 无法拦截,无效 #I2DEY8
    • [答疑] mysql 执行 Add-Migration 报错 #I2DSB8\
    • [答疑] Entity 创建时间和是否删除添加默认值 #I2E04H
    • [答疑] swagger 中多个 servers 设置 #I2E0IF
    • [答疑] 全局筛选器 没有执行 #I2E5R4
    • [答疑] 多数据库定位器疑问 #I2E77T
    • [答疑] cli.ps 逆向工程 Mysql 数据库报错 #I2E7I5
    • [答疑] Swagger 开发环境 applicationsettings.json 中文乱码 #I2EAG1
    • [答疑] 增加指定路径程序集映射 #I2EEO2
    • [答疑] 动态编译 cs 脚本文件 #I2EH66
    • [答疑] 自定义中间件,返回的错误没有规范化结果 #I2NV8S
    • [答疑] Swagger 循环引用设置生成文档层级无效 #I2PLQQ
    • [答疑] 配置文件支持 yaml 文件吗? #I2TJ3N
    • [答疑] 修改数据库未 mysql 执行 Add-Migration 报错 #I2VR64
    • [答疑] 多数据库使用定位器时报错 #I2VR8F
    • [答疑] Migration To Oracle 异常 #I2WBYQ
    • [答疑] 开发时显示 Swagger,上线时关闭 Swagger,这需要怎么配置 #I2WOYV
    • [答疑] 兼容 Mvc 复杂验证没有试验成功 #I2X3GV
    • [答疑] Aop 能不能支持无接口的类 #I2X8AS
    • [答疑] 关于 JWT Token 自动刷新问题 #I2YD4K
    • [答疑] 能否增加一个拓展的 Entity,增加一些拓展的属性 #I2YDKT
    • [答疑] Furion 无法还原包,使用Nuget 下载和通过最新的的脚手架下载都提示这个问题 #I30446
    • [答疑] 复杂校验与特性验证不能并行 #I3046U
  • 不做实现

    • [废弃] 引入 Webhook 机制 #I2A3I0
    • [废弃] 增加 blog 存储服务 #I2AMBP
    • [废弃] Blazor Server 环境下 EF 的 DbContext 多线程问题 #I2AMD2
    • [废弃] 希望实现工作单元操作接口(IUnitOfWork)#I2AOR5
    • [废弃] 建议新增 string.ToPagedListAsync() 操作 #I2BZ3Z
    • [废弃] 建议新增 GraphQLOData 功能 #I2C9EH
    • [废弃] 迫切期望支持 CAP 分布式事务 #I2CBRF
    • [废弃] 如何让某个方法或实体变化后,不被 SavingChangesEvent 等拦截 #I2CEM9
    • [废弃] 建议日志封装增加更多拓展,比如:自定义保存日志文件 #I2CW8V
    • [废弃]SqlSugar 的支持,增加 Nuget 脚手架 #I2D91U
    • [废弃] 使用 Middleware 实现反向代理 #I2DKM1
    • [废弃] 支持配置多个 Aop 功能 #I2E6Z2
    • [废弃] 是否计划开发类似网关的功能 #I2PD1L
    • [废弃] waring CS8002: 引用程序集 Furion 没有强名称 #I2WDN2
    • [废弃] Oracle 数据库驱动集成 Devart.Data.Oracle.Entity.EFCore #I2XJIU

v1.7.0(已发布)

  • 新特性

    • [新增] Furion.Extras.ObjectMapper.Mapster 拓展包 #I29LSJ
    • [新增] Furion.Extras.Logging.Serilog 拓展包 #I2AAN8
    • [新增] Furion.Extras.Web.HttpContext 拓展包 #I29LSM
    • [新增] 内置 Token 刷新机制支持 #I29K57
    • [新增] 动态数据库上下文,支持运行时执行 OnModelCreating #I28UDT
    • [新增] 支持依赖注入排除指定接口 #I29693
    • [新增] 规范化结果返回时间戳字段 #I29697
    • [新增] 基础 CURD 父类操作例子 #I296SR
    • [新增] sql.Change("定位器完整类型名称") 支持 #I29LAB
    • [新增] UpdateIncludeUpdateExclude 忽略空参数支持 #I29VUG
    • [新增] 数据库上下文内置假删除查询过滤器支持 #I29Y2R
    • [新增] 忽略空值排除默认时间格式 #I29VUV
    • [升级] MiniProfiler 组件 #I297R9
  • 突破性变化

    • [调整] AppAuthorizeHandler 授权管道为异步处理 #I29MD9
    • [调整] Swagger 默认启用 JWT 授权支持 #I29LI4
    • [调整] HttpContextUtilities 名称改为 HttpContextLocal #I29KQE
    • [调整] UnifyResultContext 名称改为 UnifyContext #I29LLZ
    • [调整] 只有执行迁移命令才扫描种子数据 #I29E6P
    • [调整] 规范化结果 Successed 属性名为 Succeeded #I29NMV
    • [移除] Mapster 对象组件,采用提供拓展方式 #I29D2M
    • [移除] CacheManager 拓展类 #I29LU1
    • [重构] SaveChanges 拦截器 #I292LO
  • 问题修复

    • [修复] 未注册的数据库上下文也被引用全局查询拦截器 bug #I29ZXJ
    • [修复] 手动返回 BadObjectResultValidationProblemDetails 结果类型时规范化结果失效 bug #I29ZU9
    • [修复] 动态 WebApi KeepNameKeepVerbSplitCamelCase 无效 bug #I29X90
    • [修复] Sql代理 返回 元组 类型出错 bug #I29SMV
    • [修复] 401,403 状态码规范化返回值属性变大写 bug #I29M8Y
    • [修复] HttpContext 空异常 bug #I29LU4
    • [修复] 接口无返回值没有应用规范化结果 bug #I29GT7
    • [修复] 前端 Less 配置文件导致主机启动失败 bug #I29E7P
    • [修复] 执行 sql 结果转泛型后属性重复赋值 bug #I29BUO
    • [修复] Swagger 关闭 MiniProfiler 之后 组中组 失效 #I29789
    • [修复] 未启用规范化结果时异常返回 System.Object 字符 #I2969A
    • [修复] 正数数据验证 0 也验证通过 bug #I2955T
    • [修复] 非泛型类集成泛型接口依赖注入 bug #I294YT
    • [修复] Swagger 不支持 new 覆盖父类的 bug #I28Z1A
    • [修复] JsonSerializerUtility 没有公开 bug #I28WMI
    • [修复] SqlSugar 拓展查询泛型类型注册异常 bug #I28VMT
    • [修复] Furion Tools 不支持生成不同命名空间的实体 bug #I2A175
    • [修复] 全局拦截器无效 bug #I2A7T2
    • [修复] 新增或更新忽略空值空异常 bug #I2AB6C
  • 其他更改

    • [优化] Token 生成加密算法 #I29KIH
  • 文档变化

    • [新增] 日志文档 #I28Y9D
    • [调整] 数据库上下文、实体拦截器、配置、一分钟入门等等文档
  • 问答答疑

    • [问答] Swagger 如何实现授权访问 #I294F2
    • [问答] 如何实现多个数据库多对多实体配置 #I29G6S
    • [问答] 动态 WebApi 支持文件上传吗 #I29R5E
    • [疑问] 多个数据库上下文无法生成迁移代码 #I2A6II
  • 不做实现

    • [废弃] 实现 BuildChange 传入表名 #I292SN
    • [废弃] 执行数据库操作结果不支持属性忽略大小写赋值 #I29DRQ
    • [废弃] 引入 Webhook 机制 #I2A3I0

v1.4.0(已发布)

  • 新特性

    • [新增] Furion 支持二级虚拟目录部署功能 #I28B77
    • [新增] Furion.Template.RazorWithWebApi 脚手架 #I28QGI
    • [新增] Furion.Template.BlazorWithWebApi 脚手架 #I27Z3O
    • [新增] EFCore 时态查询拓展 #I28AJ
    • [新增] [AppDbContext(连接字符串,数据库类型)] 配置支持 #I28QTB
    • [新增] DateTimeOffsetDateTime 拓展方法 #I27MQA
    • [新增] ValidationTypes 验证正则表达式智能提示 #I2801V
    • [新增] ValiationTypes.WordWithNumber 验证 #I2805
    • [新增] 获取客户端和服务端 IP 地址 #I28QV9
  • 突破性变化

    • [升级] .NET 5.0 版本至 .NET 5.0.1 版本 #I28QU
    • [重构] 视图引擎功能,优化不规范命名和新增字符串模板编译 #I28G0S
    • [重构] 数据库实体查找算法,并优化性能 #I28QUQ
    • [优化] 应用启动初始化性能和数据库第一次自动配置 DbSet 性能
  • 问题修复

    • [修复] 多数据库上下文配置定位器后实体无法正确生成 bug #I2888L
    • [修复] 多租户数据库上下文实体生成 bug #I2891G
    • [修复] 对象验证失败提示消息没有应用 JSON 大小写配置 bug #I27UTX
    • [修复] 仓储 InsertUpdate 方法指定 ignoreNullValues 无效 bug #I27UN6
    • [修复] Controller 派生类如果贴了 [Route] 特性后出现在 Swagger 中 bug #I27TN7
    • [修复] SqlScalar 执行 sql 返回 Nullable 类型出现转换失败 bug #I27S2N
    • [修复] [UnitOfWork] 特性异常 bug #I27MLM
    • [修复] sql 静态执行方式和 sql 高级代理无法监听数据库连接状态 bug #I27M4F
    • [修复] 修复更换 Json 序列化库无效 bug,如替换为 Microsoft.AspNetCore.Mvc.NewtonsoftJson #I27M43
    • [修复] Furion Tools 工具生成模型 bug #I27XI5
    • [修复] 软删除没有生效 bug #I2804I
    • [修复] Furion Tools 识别带多个 \\ 的连接字符串识别 bug #I280TS#PR91
    • [修复] Furion Tools 无法取消生成 bug #I2816M
    • [修复] DateTimeOffset 转本地时间差 8 小时 bug #I28BA9
    • [修复] 启用 bundle js&css 压缩后启动异常 bug #I28KR
    • [修复] ValidationTypes.Required 无效 bug #PR98
    • [修复] 规范化结果OnValidateFailed 参数名拼写错误 bug #PR93#PR92
    • [修复] 授权管道验证失败还显示结果 bug #PR89
  • 其他更改

    • [更新] README.md 友情连接地址 #PR88
    • [更新] 模板脚手架源码,添加 EFCore Tools#PR87
    • [更新] README.md Nuget 图标 #PR85
    • [废弃]List<T>DateTable #PR97
  • 文档变化

    • [新增] 视图引擎模板文档 #I27ZVA
    • [新增] EFCore 时态查询文档 #I28AJ, DOC
    • [更新] 仓储文档书写纰漏 bug #PR90
    • [更新] 选项文档错误 bug #PR86
    • [更新] 实体数据监听器 文档书写错误 bug #PR83
    • [更新] 数据库上下文、多数据库、脚手架等文档
  • 问答答疑

    • [建议] 希望 api 返回的值自动将 null 转为 '' 或 [][#I286IJ](https://gitee.com/dotnetchina/Furion/issues/I286IJ),【已关闭】
    • [建议] 添加网关功能 #I27TP7,【已关闭】
    • [建议] 新增 SqlQuery<T> 获取单条记录方法 #I28M1V,【已关闭】
    • [建议] 希望可以提供集成 Serilog 例子 #I282J4,【已关闭】
    • [疑问] 如何通过特性配置唯一约束 #I2891L,【已关闭】
    • [疑问] 怎么读取 appsettings.json 数组 #I27WU,【已关闭】
    • [疑问] IRepository<TEntity> 出现空异常 #I281IE,【已关闭】
    • [疑问] 规范化接口问题问题 #I28NMZ,【已关闭】
    • [疑问] 统一返回值模型中 OnResponseStatusCodes 未执行 #I28NNL,【已关闭】

v1.2.0(已发布)

  • 新特性

    • [新增] 雪花算法 #I26OXG, #PR78
    • [新增] [AppDbContext] 配置数据库提供器支持 #I27G3T
    • [新增] 实体表数据更改监听接口 IEntityDataChangedListener #I278DD, #I278LQ
    • [新增] 全局服务接口 AOP 拦截功能 #I278CP
    • [新增] 定位器仓储 IDbRepository<TDbContextLocator> #I276Q3
    • [新增] 数据库操作 InsertOrUpdate 支持排除空字符串功能 #I272OG
    • [新增] 数据库操作 UpdateIncludeUpdateExclude 匿名对象支持 #I271X0
    • [新增] 数据验证传入空对象跳过验证支持 #I273R4
    • [新增] 应用启动时支持排除特定配置文件自动加载 #I26U0A
    • [新增] 单个实体表名前缀支持 #I26LX0
    • [新增] MySql 数据库自动配置默认版本号 #I26XQ6
    • [优化] 授权处理程序代码
  • 突破性变化

    • [新增] 实体表数据更改监听接口 IEntityDataChangedListener #I278DD, #I278LQ
    • [新增] 全局服务接口 AOP 拦截功能 #I278CP
    • [新增] 雪花算法 #I26OXG, #PR78
  • 问题修复

    • [修复] 视图引擎加载外部程序集出错 bug
    • [修复] 依赖注入代理接口报空对象异常 bug
    • [修复] EFCore 取消附加实体出错 bug
    • [修复] 数据库仓储在非 Web 请求下出现空异常 bug
    • [修复] 多个授权策略共存问题出现无效 bug
    • [修复] 友好异常 Oop.Oh 不支持普通方法 bug
    • [修复] 获取多租户对象时数据库上下文出现作用域验证失败 bug
    • [修复] 工作单元不支持 Sql代理 拦截 bug #I27GST
  • 其他更改

  • 文档变化


v1.1.0(已发布)

  • 新特性

    • [新增] Db.GetDbContext() 获取默认数据库上下文方法
    • [新增] HttpContextUtility.GetCurrentHttpContext() 获取全局 HttpContext 上下文
    • [新增] App.GetRequiredService<> 解析服务方法
    • [新增] object.GetService<> 对象拓展方法
    • [新增] 策略授权 PolicyPipeline 基类方法,支持多重判断授权
    • [新增] JWTEncryption.ValidateJwtBearerToken 手动验证静态方法
    • [新增] 全局数据库上下文 InsertOrUpdateIgnoreNullValuesEnabledEntityStateTracked 全局配置
    • [新增] Swagger Jwt授权 全局授权参数 #I26GLR
    • [新增] InsertOrUpdate 支持自定义判断条件功能 #I269Q1
    • [新增] 字符串字段小写命名支持 #I2695D
    • [新增] 字符串文本对比功能 #I268LE
    • [新增] 全局异常特性消息功能 #I2662O
    • [新增] InsertUpdate 数据库忽略空值功能 #I264Q4
  • 突破性变化

    • [调整] Fur 项目名为 Furion
    • [调整] Db.GetRequestDbContext<>() 命名为 Db.GetDbContext<>()
    • [调整] Db.GetDbContext<>() 命名为 Db.GetDuplicateDbContext<>()
    • [重构] App.GetService<> 解析服务的底层逻辑,大大提高了解析服务的性能
    • [重构] 授权核心代码,保持和微软一致的授权规范 #I26DCB
    • [移除] App.GetRequestService<> 方法
    • [移除] ValidateJwtBearer Jwt 授权方法,无需手动判断了
  • 问题修复

    • [修复] Furion 官方脚手架生成后编译异常 bug
    • [修复] Tenant 内置属性不是 virtual 修饰 bug
    • [修复] dockerfile 新命名构建失败 bug
    • [修复] 自定义角色授权和多个授权共存出现 403 bug #I26H1L
    • [修复] httpContext.GetEndpoint() 空异常 bug #PR73
    • [修复] Oops.Oh 空异常和不支持服务抛异常 bug #I26EFU#I26GM4
    • [修复] cli.ps 生成文件编码乱码 bug #I26DVT
    • [修复] Swagger 文件上传按钮不显示 #I26B6U
    • [修复] 规范化结果授权状态码序列化大小写不一致问题 #I26B26
    • [修复] 未启用规范化结果时中文乱码 bug #I268T5
    • [修复] MySql 异步异常捕获不到 bug #I265SO
    • [修复] cli.ps1 提示找不到数据库连接字符串 bug #I2647U
  • 其他更改

  • 文档变化

    • [更新] 一分钟入门、安全鉴权、数据库等文档

v1.0.3(已发布)

  • 新特性

    • [新增] Mvc 模板脚手架:Fur.Template.Mvc
    • [新增] WebApi 模板:Fur.Template.Api
    • [新增] Mvc/WebApi 模板:Fur.Template.App
    • [新增] Razar Pages 模板:Fur.Template.Razor
    • [新增] Blazor 模板:Fur.Template.Blazor
  • 突破性变化

    • [调整] PagedListSystem.Collections.Generic 命名空间下
    • [优化] 解析服务性能问题,底层代码大量优化
  • 问题修复

    • [修复] ApiSears.ControllerEnd不起作用 bug #I25KH6
    • [修复] RemoteRequest 请求完成结果序列化属性大小写问题 #I25I8R
    • [修复] HttpContext.GetEndpoinet() 空异常 bug #PR73
  • 其他更改

  • 文档变化

    • [更新] 入门文档、数据库上下文文档、多数据库操作文档

v1.0.2(已发布)

  • 新特性

    • [新增] Pomelo.EntityFrameworkCore.MySql 最新 .NET 5 包配置 #I24ZQK
    • [新增] .AddDateTimeJsonConverter(format) 时间格式序列化配置
    • [新增] DateTimeDateTimeOffset 类型序列化格式配置 #I253FI
  • 突破性变化

    • [更新] Mapster 包至 7.0.0
    • [调整] App.Services 名为 App.ServiceProvider
    • [移除] App.ApplicationServicesApp.GetRequestService<>()
    • [移除] 非 Web 主机注入拓展
  • 问题修复

    • [修复] services.AddFriendlyException() 缺少配置注入 bug
    • [修复] 数据库上下文池被释放和高并发下内存溢出 bug #I2524K#I24UMN
    • [修复] Sql代理 返回空数据时异常 bug #I24TCK
    • [修复] 工作单元 [UnitOfWork] 多数据库被释放 bug #I24Q6W
  • 其他更改

    • [调整] EntityBaseEntity 所有属性为 vitural 修饰
    • [优化] Jwt 读取和解析性能
    • [优化] 优化代码支持 C# 9.0 最新语法
    • [优化] MD5 加密性能 #PR71
    • [移除] 无用或未使用代码
  • 文档

    • [更新] 数据库上下文、多数据库、一分钟入门文档

v1.0.0(已发布)

  • 新特性

    • [新增] 网络请求 RemoteRequest 组件 #I1YYWD
    • [新增] .AddInjectBase() 注入,只包含基础服务注入
    • [新增] 所有服务都支持 IServiceCollectionIMvcBuilder 注入
    • [新增] 抛异常状态码设置功能 StatusCode
    • [新增] Swagger 序列化支持 Pascal 属性命名方式
  • 突破性变化

    • [更新] 所有的包为 .NET 5 正式版
  • 问题修复

    • [修复] SqlProxy 代理异步处理 bug
    • [修复] 数据库类型 DatetimeDateTimeOffset bug
    • [修复] 属性首字母大小写序列化不匹配出现 null bug
    • [修复] 对象序列化中文出现乱码 bug
    • [修复] 默认序列化配置无效 bug
    • [修复] 数据库非依赖注入方式提交无效 bug
    • [修复] 应用程序池提交所有 DbContext 空异常 bug
    • [修复] Saas 多租户 Tenant 类型字符串属性在 MySql 数据库下出现 longtext 类型 bug
    • [修复] Mvc 自动验证字符串空值 bug #I24M2T
    • [修复] 枚举注释被覆盖 bug #I24N6J
    • [修复] 忽略规范化结果无效 bug #I24B8P
    • [修复] Swagger 默认 ContentType 不是 applicaiton/json bug #I24F3U
    • [修复] 内置 System.Text.JsonNewtonsoft.Json 冲突 bug #I24F3U
  • 其他更改

    • [调整] Fur 框架域名为:https://furion.icu
    • [调整] 仓储 FromSqlRawFromSqlInterpolated 接口位置
    • [优化] 数据加解密性能,#PR70
  • 文档

    • [更新] README.md、框架介绍、数据库上下文、配置选项、多租户、跨域文档
演练场
- - +

1.6 更新日志

Furion 框架发版规则

版本号规则:主版本号.次版本号.修订版本号

  • 只要【确认】为框架 bug,则当天修复,当天发版,修订版本号 加 1
  • 只要 .NET SDK 版本更新,则当天升级,当天发版,修订版本号 加 1
  • 如果 .csproj 文件有变更,则当天发版,修订版本号 加 1
  • 如果新增 拓展包,为了版本号统一,则当天发版,修订版本号 加 1
  • 如果涉及到代码重构,则当天发版,次版本号 加 1,修订版本号 清 0
  • 如果 .NET SDK 主版本号升级,则当天发版,主版本号 加 1

如有意外不能当天发版,则会在 Issue 中说明具体发版时间,正常不会超过 3 天。

v4.4.0(当前版本)

版本细节
  • 新特性

    • [新增] 新增友好异常可控制是否输出错误日志配置 LogError: true #I5PKJH
  • 突破性变化

    • [调整] 远程请求 .SetBodyBytes.SetFiles #I5PMS5 #I5PIYI
    • [移除] 远程请求 [BodyBytes] 设计,采用 HttpFile 方式 #I5PMS5 #I5PIYI
public interface IHttp : IHttpDispatchProxy{    [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")]    Task<HttpResponseMessage> PostXXXAsync(HttpFile file);    // 支持多个文件    [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")]    Task<HttpResponseMessage> PostXXXAsync(HttpFile[] files);    // 支持多个文件    [Post("https://www.furion.icu/upload", ContentType = "multipart/form-data")]    Task<HttpResponseMessage> PostXXXAsync(IList<HttpFile> files);}
// bytes 可以通过 File.ReadAllBytes(文件路径) 获取var res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")                                               .SetFiles(HttpFile.Create("file", bytes, "image.png")).PostAsync();// 支持多个文件var res = await "https://www.furion.icu/upload".SetContentType("multipart/form-data")                                               .SetFiles(HttpFile.CreateMultiple("files", (bytes, "image1.png"), (bytes, "image2.png"))).PostAsync();
  • 其他更改

    • [调整] JWTEncryption 静态类,支持无需注册 services.AddJwt() 使用 #I5PPKE #I5POLZ
  • 文档

    • [更新] 友好异常文档、远程请求文档

v4.3.9(已发布)

  • 新特性

    • [新增] AppSettings 配置的 ExcludeAssemblies 属性,支持忽略指定程序集扫描 7b7747f
    • [新增] Oops.OhOops.Bah 支持设置额外数据 .WithData(data) #I5O38E
    • [新增] 定时任务 Crontab.GetSleepMilliseconds(baseTime) 获取下一个发生时间的时间差 d024fae
    • [新增] 友好异常默认打印异常日志,避免生产环境漏掉重要异常信息 6e3a5bd
    • [新增] 日志静态类 Log.CreateLoggerFactory() 静态方法 75c672a
    • [新增] 多语言 SharedResource 模式,避免硬编程 18e80c7
    • [新增] 事件总线 MessageCenter 静态类,解决从 Fur v1.x 版本升级问题 a29fc7c
    • [新增] 组件化 IWebComponent 模式,支持 .NET5+ 08a44c3
    • [新增] 远程请求设置自己的 HttpClient 功能 #I5PBR3 !545
    • [新增] LoggingMonitor 支持添加更多自定义配置 #I5PEPA
    • [新增] LoggingMonitor 可配置 WithReturnValueReturnValueThreshold #I5PFJ1 #I5PFOW
    • [新增] LoggingMonitor 可配置 MethodsSettings 更多信息 #I5PFJ1 #I5PFOW
Serve.Run(RunOptions.Default     .AddWebComponent<XXXWebComponent>());public class XXXWebComponent : IWebComponent{    public void Load(WebApplicationBuilder builder, ComponentContext componentContext)    {        // ....    }}
  • 突破性变化

    • [新增] Furion 程序集 PublicKeyToken 强签名 26b12c0
    • [调整] 事件总线 IEventBusFactory 事件工厂方法 AddSubscriber -> SubscribeRemoveSubscriber -> Unsubscribe a29fc7c
    • [调整] .AddInject().UseInject() 配置选项名称,移除 Configure 后缀 b6953cd
    • [调整] 远程请求 请求拦截响应拦截异常拦截 委托签名,新增 HttpClient 参数 #I5OWBO
[Interceptor(InterceptorTypes.Request)]static void OnRequest(HttpClient client, HttpRequestMessage req){}[Interceptor(InterceptorTypes.Response)]static void OnResponsing(HttpClien client, HttpResponseMessage res){}[Interceptor(InterceptorTypes.Exception)]static void OnException(HttpClient client, HttpResponseMessage res, string errors){}
  • 问题修复

    • [修复] 生成包含 中文JWT Token 解密后出现乱码问题 #I5O397
    • [修复] `HttpRequestMessage`` 拓展中追加查询参数时的空引用异常 #I5PENW !547
    • [修复] 日志模块配置多个 IDatabaseLoggingWriter 只有一个生效 #I5PFQ2 #I5PFJ1
  • 其他更改

    • [调整] 默认输出文件日志模板,使其更加美观 #1518cf3
    • [调整] 默认规范化结果验证处理也支持状态码设置 2eb9390
    • [更新] SqlSugarCore 拓展包和脚手架至 5.1.2.6 版本 #I5PCXK
    • [更新] JSON Schema 关于 LoggingMonitor 更多配置 #I5PFJ1
  • 文档

    • [新增] RabbitMQ 事件总线文档
    • [更新] AppSettings 配置文档、事件总线文档、多数据库配置文档、日志文档、定时任务文档、MessageCenter 文档、远程请求文档、组件化文档、入门指南、多语言文档。

v4.2.13(已发布)

  • 新特性

    • [新增] 事件总线工厂,支持运行时动态添加订阅程序和移除订阅程序 #I5NNQX
    • [新增] 事件总线 [EventSubscribe] 事件 Id 支持正则表达式匹配 #I5NNQX
    • [新增] 事件总线 [EventSubscribe] 支持局部失败重试配置 #I5NNQX
    • [新增] Log 全局静态类,方便随时随地记录日志 ba9b1f1
    • [新增] 事件总线 options.AddSubscriber(Type) 重载 42446078
    • [新增] ValidationMetadata 类型 FirstErrorPropertyFirstErrorMessage 属性 #I5MFJT
    • [新增] Serve.Run() 模式 WithArgs(args) 方法 #I5MOJB
    • [新增] [UnitOfWork] 分布式事务 TransactionScope 支持 #I5MRTY
    • [新增] 16 位 MD5 加密支持 #I5N8RC
  • 突破性变化

    • [调整] 异步创建作用域方法名称,避免一些情况下无法区分,同步方法不变 #I5N9XY

由:

// Scoped.CreateUow 一样await Scoped.Create(async (f, s) => {});

改为:

// Scoped.CreateUowAsync 一样await Scoped.CreateAsync(async (f, s) => {});
  • [支持] .NET 6.0.8.NET 7 Preview 7 842d4f7
  • [调整] [LoggingMonitor] 命名空间为 System,因为使用频率越来越高 b879861
  • [添加] 在非 Web 环境中不正确使用字符串拓展方法检测机制 6389cbd
  • [调整] 所有 .Default 静态属性为 .Default() 方法 6389cbd
  • [调整] 工作单元 IUnitOfWork 所有方法参数类型,由 ActionExecutingContextActionExecutedContext 改为 FilterContext #I5MHX5
public interface IUnitOfWork{    void BeginTransaction(FilterContext context, UnitOfWorkAttribute unitOfWork);    void CommitTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork);    void RollbackTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork);    void OnCompleted(FilterContext context, FilterContext resultContext);}
  • 问题修复

    • [修复] 日志上下文数据多次写入被清空问题以及数据库日志出现异常后停止写入 #I5LIWF
    • [修复] 个别情况下跨域默认配置的响应缓存导致嵌入式资源异常问题 7a57efe
    • [修复] 远程请求传入不合法的请求报文头数据触发校验失败问题 #I5LPFE
    • [修复] 多线程中使用静态日志写数据库日志导致连接池耗光问题 8d5cdd6
    • [修复] EFCore 6.0 之后 IModelCacheKeyFactory 接口方法改变导致分表分库异常问题 #I5MCZ6 EFCore#25154 EFCore!3305
    • [修复] ValidationMetadata 对象 Message 字符串类型出现 \"\" 问题 #I5MFJT
    • [修复] [IfException] 覆盖 Oops.Oh/Bah 错误消息问题 4bbd854
    • [修复] 数据库日志写入循环写入和频繁创建数据库连接池问题 9ce214c
    • [修复] Razor Pages 不支持全局异常拦截问题 #I5MHX5
    • [修复] Razor Pages 不支持全局数据验证问题 #I5MHX5
    • [修复] Razor Pages 不支持工作单元 [UnitOfWork] 问题 #I5MHX5
    • [修复] Razor Pages 不支持 EFCore 自动 SaveChanges 问题 #I5MHX5
    • [修复] Blazor Serverv4.2.2 版本更新导致的问题 #I5MNFN
    • [修复] [IfException] 不支持多语言配置问题 #I5MPN7
    • [修复] 通过 services.AddMvcFilter<LoggingMonitorAttribute>() 方式注册无效问题 8d1477d
    • [修复] 事件总线默认 Channel 管道初始化时机过晚问题,解决部分第三方依赖使用问题 #I5MM3O
    • [修复] 主机停止时写入日志异常问题 #I5N7S2
    • [修复] 数据库上下文手动释放导致 AutoSaveChange 特性出现释放异常问题 #I5NFWC
    • [修复] [LoggingMonitor] 循环引用序列化问题 #I5NRT9
    • [修复] 远程请求传入 null Body 参数抛出空异常问题 #I5NTUE
    • [修复] 事件总线默认开启模糊匹配(正则表达式)导致不必要的订阅 #I5NVOP
  • 其他更改

    • [调整] 事件总线默认 Channel 管道初始化时机,解决部分第三方依赖使用问题 #I5MM3O
    • [优化] 底层迭代改进优化
    • [公开] 规范化文档获取控制器、方法分组、标签信息 66d8d54
  • 文档

    • [新增] 全局日志静态类 Log 文档 ba9b1f1
    • [新增] Nuget 本地测试包文档
    • [更新] 日志文档、静态类文档、数据校验文档、Worker Service 文档、工作单元文档、依赖注入文档

v4.1.14(已发布)

  • 新特性

    • [新增] Furion.Xunit 拓展包,正式实现 Xunit 单元测试完整支持 Furion 063a034e
    • [新增] services.AddMonitorLogging() 日志监视器服务,支持非常灵活的日志操作 81df742
    • [新增] Serve.Run(silence: true) 等一系列强大的静默启动功能 #I5JBSQ #I5J98T 7cced4
    • [新增] SpecificationDocumentBuilder.GetOpenApiGroups() 方法获取底层的规范化接口分组信息 4ff03c5
    • [新增] logger.ScopeContext() 配置日志上下文功能 #I5JC0D
    • [新增] 跨域配置 CorsAccessorSettings.SignalRSupport 配置选项,支持配置 SignalR 跨域 #I5JREM
    • [新增] 事件总线 UseUtcTimestamp 选项配置,可选择使用 DateTime.UtcNow 还是 DateTime.Now,默认是 DateTime.Now #I5JSEU
    • [新增] 规范化文档 [OperationId] 配置,解决自定义 Swagger UI 不能正确显示路由问题 #I5K1IB
    • [新增] 远程请求 IHttpDispatchProxy 方式全局拦截支持多态(继承) #I5K8FS
  • 突破性变化

    • [新增] Furion.Xunit 拓展包,正式实现 Xunit 单元测试完整支持 Furion 063a034e
    • [移除] Furion.Extras.DatabaseAccessor.SqlSugar 拓展插件中的 [SqlSugarUnitOfWork] 工作单元特性,将使用通用工作单元替换,查看最新实现文档
    • [移除] Inject.Create() 方法,再也不需要了,框架提供了无敌强大的 Serve.Run() 静默启动方式 200848e
    • [调整] Serve.RunConfigureConfiguration 方法参数,由 configuration => {} 改为 (environment, configuration) => {} 83c97bb
// 由Serve.Run(RunOptions.Default.ConfigureConfiguration(configuration => {}));// 改为:Serve.Run(RunOptions.Default.ConfigureConfiguration((environment, configuration) => {}));
  • 问题修复

    • [修复] [LoggingMonitor] 异常消息日志级别为 Information 错误问题 ab46cdf
    • [修复] 新版本日志组件频繁提示文件占用问题,将文件独占锁改为共享锁 #I5J3S6
    • [修复] 配置数据库日志读写器为 EFCore 时控制台出现无限打印问题 #I5J474
    • [修复] [LoggingMonitor] 针对 byte[] 类型参数输出过大问题 5380f35
    • [修复] 友好异常和规范化结果丢失了原始 ErrorCode 问题 #I5IX2R
    • [修复] 新版本日志组件自定义数据库读写器注入 IRepository 仓储导致死循环问题 #I5IX2R
    • [修复] Mvc 默认手动验证和 Furion 全局验证冲突问题 2a06c39
    • [修复] Serve.Run() 模式不支持 SuperSocket 第三方包问题,原生是支持的。186ca0a
    • [修复] SignalR 跨域错误问题 #I5JREM
    • [修复] [LoggingMonitor]Oops.OhOops.Bah 记录到了错误日志中,默认应该是 Information 且提供可配置 #I5JZ1H
    • [修复] 自定义 Swagger UI 之后个别 UI 要求必须配置 operationId,否则出现 guid 序号 #I5K1IB
    • [修复] 主动抛出 NotFoundResultNotFoundObjectResult 无效问题 #I5KALZ
    • [修复] [LoggingMonitor] 解析方法参数但前端未传入时出现错误问题 #I5KC5P
    • [修复] [LoggingMonitor] 无法序列化 IQueryable 返回值问题 #I5KJD1
    • [修复] [LoggingMonitor] 不能记录全局验证错误问题 b44087d
    • [修复] [LoggingMonitor] 存在注册顺序差异问题 b44087d
  • 其他更改

    • [开放] 底层的规范化文档 SpecificationDocumentBuilder 部分方法,提供更加便捷的第三方 Swagger UI 集成 10f0f01
  • 文档

    • [更新] 单元测试文档、入门指南文档、Worker Services 文档
  • 本期亮点

  1. Serve.Run() 彻彻底底支持全平台,提供非常强大的静默模式

启用静默模式可以实现无阻塞方式执行程序,而且还能体验完整的 Furion 功能。

大革命

有了 Serve.Run() 静默模式后,Furion 彻彻底底支持全平台,不管你是 控制台、Web、桌面、移动、单元测试,集成测试,基准测试等等应用程序

Serve.Run(silence: true);// 不会阻塞执行哦,而且从这里开始可以使用 Furion 任何功能,比如 App.Configuration....Console.WriteLine("Hello, World!");Console.ReadKey();

还有更多静默模式。

// RunOptions 方式Serve.Run(RunOptions.DefaultSilence);// LegacyRunOptions 方式Serve.Run(LegacyRunOptions.DefaultSilence);// GenericRunOptions 方式Serve.Run(GenericRunOptions.DefaultSilence);
  1. 强大的 Furion.Xunit 单元测试、集成测试
大革命

单元测试和集成测试是保证一个系统能够持续维护和稳定运行的必备技能,但是目前现有的单元测试组件无法直接集成 Furion 的功能,最常用的就是如何在单元测试中读取配置,以及如何进行依赖注入

在过去,Furion 只能不断的去调整,以至于适配第三方单元测试写法,搞得不伦不类!

所以,这一次不再妥协,Furion 推出自己的单元测试工具,可以让现有的单元测试如 Xunit 100% 支持 Furion 所有功能,全部保证一致的写法。

单元测试中初始化 Furion

using Furion.Xunit;using Xunit.Abstractions;using Xunit.Sdk;// 配置启动类类型,第一个参数是 TestProgram 类完整限定名,第二个参数是当前项目程序集名称[assembly: TestFramework("TestProject1.TestProgram", "TestProject1")]namespace TestProject1;/// <summary>/// 单元测试启动类/// </summary>public class TestProgram : TestStartup{    public TestProgram(IMessageSink messageSink) : base(messageSink)    {        // 初始化 Furion        Serve.Run(silence: true);    }}

测试类支持完整依赖注入

using TestProject1.Services;using Xunit;namespace TestProject1;public class UnitTest1{    private readonly ICalcService _calcService;    public UnitTest1(ICalcService calcService)    {        _calcService = calcService;    }    [Fact]    public void 测试两个数的和()    {        Assert.Equal(3, _calcService.Plus(1, 2));    }}

查看新版本单元测试文档

  1. 开放底层规范化文档分组接口,使得集成第三方 Swagger UI 更加容易,如集成 IGeekFan.AspNetCore.Knife4jUI 拓展:
安装包

只需要在 YourPoject.Web.Core 层安装 IGeekFan.AspNetCore.Knife4jUI 即可。

3.1.1 Knife4jUI 独立版本配置

var routePrefix = "api";    // 定义 swagger 路由地址,如果是跟目录,设置 string.Empty 即可app.UseKnife4UI(options =>{    options.RoutePrefix = routePrefix;  // 配置 Knife4UI 路由地址    foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())    {        options.SwaggerEndpoint("/" + groupInfo.RouteTemplate, groupInfo.Title);    }});app.UseInject(routePrefix); // 配置 Furion 路由地址

3.1.2 Knife4jUISwagger 共存版本配置

app.UseKnife4UI(options =>{    options.RoutePrefix = "newapi";  // 配置 Knife4UI 路由地址,现在是 /newapi    foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())    {        options.SwaggerEndpoint("/" + groupInfo.RouteTemplate, groupInfo.Title);    }});app.UseInject();  // Furion 默认 api 地址为  /api

如需实现登录之后自动将 token 添加到头部可在登录接口 AfterScript 执行以下代码:

ke.global.setAllHeader(
"Authorization",
"Bearer " + ke.response.headers["access-token"]
);
  1. 提供强大的日志上下文功能
// 写法一_logger.ScopeContext(ctx => ctx.Set("Name", "Furion").Set("UserId", 10))       .LogInformation("我是一个日志 {id}", 20);// 写法二_logger.ScopeContext(new Dictionary<object, object> {    { "Name", "Furion" },    { "UserId", 10 }}).LogInformation("我是一个日志 {id}", 20);// 写法三_logger.ScopeContext(new LogContext {    // ....}).LogInformation("我是一个日志 {id}", 20)

v4.0.0(重新起航)

不忘初心,感恩遇见,感恩信任

2020 年 09 月 01 日,一个叫 Fur 的开源项目悄然诞生,她的出生仿佛带着某种使命,没有包袱,无限可能。

她缓缓的张开双眼,干净雪亮的眼睛似乎对这个世界充满了好奇,每一次思想碰撞在她看来都是非常宝贵的财富,她貌似有用不完的精力,一路汲取知识,升级打怪,不断奔跑,乐此不疲。

记得 2020 年 11 月 11 日的单身节,她迎来了“一岁(v1.0.0)”生日,自那以后,IT 这个大银幕上频繁出现她的身影,越来越多 .NET5 开发者转粉,像是告诉这个世界,她就是 IT 界大明星。

每一个明星都有一个好听的艺名,她当然也不例外,2020 年 11 月 20 日,经纪人百小僧为她起名为 Furion

2021 年 11 月 09 日,她进入了叛逆期,抛弃了曾经支持她的 .NET5 粉丝们,拥抱了新的 .NET6 拥趸者,自从过上了奢靡富足的生活。

但她过的不开心,时常在夜里想起 .NET5 的粉丝们,内心非常自责,但在双重工作压力下她依然选择了忽视他们的诉求,仿佛他们就是累赘。

时间真的是好东西,曾经认为是对的,经过岁月的蹉跎历磨,渐渐的明白:不忘初心,方能始终。

这一次,不落下一人(.NET5.NET6,...,.NET N),携手共进,重新起航,感恩遇见,感恩信任。

  • 新特性

    • v4.0.0 支持 .NET5.NET6,...,.NET N,所有的 Furion 项目都能够升级到该版本,重新起航,实现大统。

v3.9.2(已发布)

关于日志

日志模块是任何应用系统都必备的功能,可以说是最重要的模块!在 .NET 社区中有 Log4NETNLogSerilog 等日志组件,它们无一不是优秀的开源项目。

但由于这些日志组件历史悠久,内部兼容的 .NET 版本非常多,功能随着时间推移变得极其强大复杂,在实际项目使用中,发现每一个日志组件配置总是不那么友好,特别是在使用上不够简单

Furion 作为全栈开发框架,在过去版本并没有提供足以满足开发者需求的日志模块,转而推荐大家集成第三方组件,如 Serilog导致后续无法实现自定义功能和也增加了不少维护成本。

这一次,Furion 不再妥协,彻底重构了日志模块,实现日志功能/需求完全自主可控,提供给开发者几乎所有日志功能的需求!

Furion 的使用者们,是时候“更换”掉第三方日志组件,让我们一起迭代出更强更好的日志组件吧! 🍖

  • 新特性

    • [重构] 日志模块,内置写入控制台、文件、数据库功能,再也无需引入第三方日志了!日志源码
    • [新增] 强大的调试日志 [LoggingMonitor] 32dfc1
  • 突破性变化

    • [重构] 日志模块,内置写入控制台、文件、数据库功能,再也无需引入第三方日志了!日志源码
    • [调整] TP.Wrapper 规范化日志模板算法,由过去的 [属性] 改为 ##属性##,解决 JSON 内容冲突问题 394ecec
    • [公告] 未来 Furion.Extras.Logging.Serilog 拓展将不再继续维护,因为 Furion 有强大的日志组件了!
  • 问题修复

    • [修复] 修复脱敏模块模型绑定个别情况下空异常问题 #I5IM5C
  • 文档

    • [更新] 日志文档、静态类文档、数据校验文档
  • 本期亮点

  1. 极易使用且强大的日志模块
// 写入文件services.AddFileLogging("logs/application.log");// 写入数据库services.AddDatabaseLogging<DatabaseLoggingWriter>();

查看更多日志文档

  1. 强大的 [LoggingMonitor] 调试日志
using Furion.Logging;namespace Furion.Application;public class TestLoggerServices : IDynamicApiController{    [LoggingMonitor]    public PersonDto GetPerson(int id)    {        return new PersonDto        {            Id = id        };    }}

支持控制器、操作或全局注册拦截

输出日志为:

┏━━━━━━━━━━━  Logging Monitor ━━━━━━━━━━━┣ Furion.Application.TestLoggerServices.GetPerson (Furion.Application)┣ 控制器名称:              TestLoggerServices┣ 操作名称:                GetPerson┣ 路由信息:                [area]: ; [controller]: test-logger; [action]: person┣ 请求地址:                https://localhost:44316/api/test-logger/person/11┣ 来源地址:                https://localhost:44316/api/index.html┣ 浏览器标识:              Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62┣ 客户端 IP 地址:          0.0.0.1┣ 服务端 IP 地址:          0.0.0.1┣ 服务端运行环境:          Development┣ 执行耗时:                31ms┣ ━━━━━━━━━━━━━━━  授权信息 ━━━━━━━━━━━━━━━┣ JWT Token:               Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOjEsIkFjY291bnQiOiJhZG1pbiIsImlhdCI6MTY1ODcxNjc5NywibmJmIjoxNjU4NzE2Nzk3LCJleHAiOjE2NTg3MTc5OTcsImlzcyI6ImRvdG5ldGNoaW5hIiwiYXVkIjoicG93ZXJieSBGdXJpb24ifQ.VYZkwwqCwlUy3aJjuL-og62I0rkxNQ96kSjEm3VgXtg┣ UserId (integer)1┣ Account (string):        admin┣ iat (integer)1658716797┣ nbf (integer)1658716797┣ exp (integer)1658717997┣ iss (string):            dotnetchina┣ aud (string):            powerby Furion┣ ━━━━━━━━━━━━━━━  参数列表 ━━━━━━━━━━━━━━━┣ Content-Type:id (Int32)11┣ ━━━━━━━━━━━━━━━  返回信息 ━━━━━━━━━━━━━━━┣ 类型:                    Furion.Application.Persons.PersonDto┣ 返回值:                  {"Id":11,"Name":null,"Age":0,"Address":null,"PhoneNumber":null,"QQ":null,"CreatedTime":"0001-01-01T00:00:00+00:00","Childrens":null,"Posts":null}┗━━━━━━━━━━━  Logging Monitor ━━━━━━━━━━━

v3.8.9(已发布)

  • 新特性

    • [新增] 规范化结果 ExceptionMetadataValidationMetadata 都可以获取 ErrorCode 属性 #I5GJ6D
    • [新增] ValidationMetadataStatusCode 属性 #I5HB5L
    • [新增] 远程请求对 Url 是否编码设置,[Get(WithEncodeUrl = false)]WithEncodeUrl(false) #I5GOBC
    • [新增] 更强大的 JWTEncryption.SecurityReadJwtToken('token') 读取解析 Token 静态方法 574eeb6
    • [新增] ValiationTypes.Html 验证 Html 标签 #I5HBKC
    • [新增] EFCore.NamingConventions 支持,可自定义生成表名,字段名风格,比如小驼峰,蛇形命名等 #I5HBEI
    • [新增] INamedServiceProvider 命名服务提供器,可解析接口多实现 #I5HF98
    • [新增] 脱敏处理模块方法参数单个值处理 a22ec3c
    • [新增] 脱敏词库支持 | 分割词语 3106b1d
  • 突破性变化

    • [升级] 所有 .NET 依赖包至 6.0.7 版本
    • [升级] Serilog.AspNetCore 包至 6.0.0 版本
    • [重构] JWT Token 刷新逻辑 #I5GXML 574eeb6
    • [调整] ExceptionMetadata 命名空间为 Furion.FriendlyException 3105d16
    • [调整] Retry.Invoke(Func<Task>...) 为:Retry.InvokeAsync(Func<Task>...) 3b78999
    • [重构] 脱敏处理模块,大大提高性能和准确率,同时支持方法参数单个值处理 a22ec3c
  • 问题修复

    • [修复] Rider 开发工具对同名脚手架 (EFCoreSqlSugar) 只显示一个问题 !518
    • [修复] UnitOfWork 工作单元在 EFCore 中失效问题 #I5H0T3
    • [修复] JWTToken 如果存在数组类型的值时,刷新 Token 后丢失了历史值 #I5GXML
    • [修复] 远程请求 WithEncodeUrl 无法在 [HttpMethod] 设置问题 574eeb6
    • [修复] Serve.Run() 模式下添加自定义配置导致 EFCore 无法获取自定义配置文件问题 #I5GZ0F
    • [修复] Oops.Bah 进入全局异常拦截器问题 #I5H47S
    • [修复] AddDbPool/AddDb 扩展未根据配置 Key 路径读取问题 #I5H6S4 !520
    • [修复] ValiationTypes.Url 正则表达式覆盖不全问题 #I5HBKC
    • [修复] v3.5.x 版本导致集成 EFCore.NamingConventions 失效问题 #I5HBEI
    • [修复] Swagger 长路由不支持问题以及 [Required] 配置 AllowEmptyStrings 无效问题 c014330
    • [修复] 远程请求上传文件时请求报文 boundaryContent-Disposition 设置不正确问题 #I5HEF0
    • [修复] 脱敏模块替换敏感词汇出现多替换问题 a22ec3c
  • 其他更改

    • [调整] 多语言默认处理逻辑,允许不配置任何语言,过去版本会报错 #I5GRD9 5077c5d
    • [改进] 规范化文档 Swagger 性能
    • [调整] 调整 MongoDB 仓储 TDocument 泛型约束 3f49055
  • 文档

    • [更新] 远程请求文档,日志记录文档、多数据库文档、PM2 部署文档、Visual Studio 高效率文档

v3.7.11(已发布)

  • 新特性

    • [新增] Minimal API 应用支持:.AddInjectMini() #I4KOQ5
    • [新增] 跨域 WithExposedHeaders 默认配置 access-tokenx-access-token 42ebdfd
    • [新增] 脚手架默认启用 app.UseHttpLogging() HTTP 日志 42ebdfd
    • [新增] FurionASP.NET Core 完整 json 配置的 JSON Schema 架构 JSON Schema
    • [新增] Sql 代理支持返回单个类类型参数 1d7fb5b
    • [新增] Sql 代理支持返回 ValueTuple 单个类类型参数 876a2f5
    • [新增] 组件化设计模块,支持比 AppStartup 更灵活便捷的设计 #components
    • [新增] 独立工作单元模块,支持任何第三方 ORM a02413d
    • [新增] 跨域 FixedClientToken 配置参数 bd01638
    • [新增] throw Oops.Bah 可以手动触发规范化验证失败处理 83f0036
    • [新增] FriendlyExceptionSettingsThrowBah 配置,可标记 Oops.Oh 不进入异常处理 76ffa7f
  • 突破性变化

    • [新增] Minimal API 应用支持:.AddInjectMini() #I4KOQ5
    • [新增] FurionASP.NET Core 完整 json 配置的 JSON Schema 架构 JSON Schema
    • [新增] 组件化设计模块,支持比 AppStartup 更灵活便捷的设计 #components
    • [新增] 独立工作单元单元模块,支持任何第三方 ORM a02413d
    • [重构] DataValidationFilterFriendlyExceptionFilter,解决不支持手动抛出业务异常问题 83f0036
    • [调整] .AddDb<>.AddDbPool<> 自定义委托参数签名,由 Action<DbContextOptionsBuilder> 改为:Action<IServiceProvider, DbContextOptionsBuilder>
// 由:options.AddDbPool<TDbContext>(DbProvider.MySql, opt => {});// 改为options.AddDbPool<TDbContext>(DbProvider.MySql, (services, opt)=> {})
  • 问题修复

    • [修复]v3.6.3 版本依赖,执行原生 Sql 添加了参数校验导致存储过程执行错误问题 #I5ERMQ
    • [修复] tools/cli.ps1 脚本工具出现数据库链接被占用问题
    • [修复] JWTSettings 算法配置 JSON Schema 错误问题,感谢 @gitwentao #I5G27B !516
    • [修复] 基于策略授权在不配置 Policy 的情况下出现空异常问题 #I5EVF2
    • [修复] 启用数据库实体跟踪时导致新增实体多次查询数据库问题 #I4J2LZ
    • [修复] 不启用规范化结果导致验证失效,异常失效问题 cdb3f57
    • [修复] 验证异常和友好异常冲突问题 83f0036
    • [修复] CentOS 7.9 系统部署无法指定命令 --urls 参数问题 8cc8ee
  • 其他更改

    • [调整] 脚手架所有 .json 文件,默认添加 JSON Schema 支持
  • 文档

    • [新增] 组件化启动文档
    • [新增] Vue/React/Angular 请求代理文档
    • [新增] JSON Schema 文档,支持配置智能提示和验证
    • [更新] 跨域文档、规范化文档、配置文档、日志文档、IIS 部署文档
  • 本期亮点

  1. 新增 JSON Schema 支持,所有 .json 文件支持智能提示和验证
{  "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json",  "Logging": {    "LogLevel": {      "Default": "Information",      "Microsoft": "Warning",      "Microsoft.Hosting.Lifetime": "Information",      "Microsoft.EntityFrameworkCore": "Information"    }  },  "AllowedHosts": "*"}

查看更多 JSON Schema 文档

  1. 根据 Swagger 生成 Vue/React/Angular 前端请求代码

查看文档

  1. Sql 代理支持返回单个类类型参数
public interface ISql : ISqlDispatchProxy{    // 集合类型    [SqlExecute("select * from person")]    List<Person> GetPersons();    // 自 v3.7.3+ 版本支持返回单个类类型参数    [SqlExecute("select * from person where id=@id")]    Person GetPerson(int id);}
  1. Sql 代理支持返回 ValueTuple 单个类类型参数
public interface ISql : ISqlDispatchProxy{    [SqlExecute(@"            select * from person where id =@id;            select * from person")]    (Person, List<Person>) GetData(int id); // 注意返回值是 `(Person, List<Person>)` 组合}
  1. 支持 Minimal API 应用

了解 Minimal API 应用

var builder = WebApplication.CreateBuilder(args).Inject();// 注册 Minimal 服务builder.Services.AddInjectMini();var app = builder.Build();app.UseHttpsRedirection();app.UseInject(string.Empty);app.MapGet("/hello", () =>{    return "Hello, Furion";});app.Run();

v3.6.9(已发布)

  • 新特性

    • [新增] Serve.Run() 极简主机模式,真正实现极速入门。95cac5b
    • [新增] TP.Wrapper(...) 拓展方法,主要用来生成规范化的日志模板 427999a
    • [支持] 项目类型为 <Project Sdk="Microsoft.NET.Sdk"> 的控制台项目 fb08a65
    • [新增] BadPageResult 错误页面类型 !494
    • [新增] [SchemaId] 特性,解决不同程序集相同的类名生成 SwaggerSchemaId 冲突问题 #I5D3CU
    • [新增] 远程请求 options.ApproveAllCerts() 忽略所有客户端证书拓展 eb7d18a
    • [新增] 判断是否是单文件环境部署静态属性 App.SingleFileEnvironment de556f0
    • [新增] WebApplicationBuilder.UseSerilogDefault() 拓展 e02524c
  • 突破性变化

    • [支持] 项目类型为 <Project Sdk="Microsoft.NET.Sdk"> 的控制台项目 fb08a65
    • [新增] Serve.Run() 极简主机模式,真正实现极速入门。95cac5b
    • [调整] 未启用规范化结果时,MVC 验证失败返回 BadPageResult() 页面类型 !494
  • 问题修复

    • [修复] 修复默认注册的 services.AddResponseCaching(); 服务导致 .axd 内嵌资源请求错误问题 !495
    • [修复] Oracle 数据库执行 sql 必须要求命令参数和 sql 语言参数数量一致 #I5D057
    • [修复] IHostService 类型不能自动注册问题,之前只扫描了 BackgroundService 派生类 968344
    • [修复] 国产芯片主机不能识别 dotnet run --urls 参数问题 6d4398
    • [修复] 远程请求上传文件不支持特定文件后缀问题,如 .pem 文件 ba42198
    • [修复] 一些程序集已破坏或程序集不完整导致主机无法启动问题 d2dc3e4
    • [修复] 远程请求传入 headers 时类型为 Dictionary<string, string> 导致转换异常问题 #I5DHL9
    • [修复] Serilog 单文件发布不生成日志文件 I5DQ2B
  • 其他更改

    • [调整] 远程请求默认客户端不检查 SSL 证书 eb7d18a
    • [调整] 开放验证服务选项 SuppressModelStateInvalidFilter 属性为可配置 !494
  • 文档

    • [新增] Serve.Run() 文档
    • [新增] HttpContext 文档
    • [新增] GlobalUsings 文档
    • [新增] TP 全局静态类文档
    • [新增] 中间件文档、筛选器文档、审计日志文档
    • [更新] 跨域文档、远程请求文档
  • 精彩贡献

    • !494 优秀 Pull Request 辩论典范
  • 本期亮点

  1. 极速入门
Program.cs
Serve.Run();[DynamicApiController]public class HelloService{    public string Say()    {        return "Hello, Furion";    }}

启动浏览器查看效果,惊呆了吗!

  1. 内置错误页
using Furion.FriendlyException;public IActionResult Add(Person person){    if(!ModelState.IsValid)    {        return new BadPageResult();    }}
  1. Swagger 支持 Markdown
/// <summary>/// 测试 Markdown/// </summary>/// <remarks>/// # 测试 `Markdown` 注释////// ![](https://localhost:44316/images/logo.png)////// ```cs/// Serve.Run();////// [DynamicApiController/// public class HelloService/// {///     public string Say()///     {///         return nameof(Furion);///     }/// }/// ```////// 功能还不错!!!////// | 商品         | 价格     | # 其他 |/// |--------------|-----------|------------|/// | Juicy Apples | 1.99      | *7*        |/// | Bananas      | **1.89**  | 5234       |/// | Bananas      | **1.89**  | 5234       |/// | Bananas      | **1.89**  | 5234       |////// -----////// # Furion 探索版////// > 在过去一年,实现 `Furion` 从无到有,编写文档已逾百万字,过程心酸开源人自知。/// >/// > 这一路日夜兼程,嘲讽批评常伴眼耳,即便辛苦无奈、想过放弃,但为了那微不足道的存在感依然努力着。/// >/// > 当然,也收获了不少...越来越多拥趸者,越发精湛技术能力,更高层次思维模式,还有许多跨界跨行朋友。/// >/// > 在 《[开源指北] (https://gitee.com/opensource-guide/comments/)》中,我曾说道:“开源如同人的脸,好坏一面便知,缺点可能会受到嘲讽批评,优点也会收获赞扬尊重。别担心,他们正在塑造更好的你。”/// >/// > 所以,这一次重新起航,重塑 `Furion` 重塑自己。也许未来在某个 IT 圈但凡有人谈起 `.NET` 还能瞟到 `Furion` 的身影。////// ---////// 🎉 探索 Furion 未来更多可能性,实现无第三方依赖的版本,所有模块功能按需安装,按需加载。////// - 作者:[百小僧] (https://gitee.com/monksoul)/// - 日期:2021 年 08 月 30 日////// ## 环境////// - IDE :[Microsoft Visual Studio Enterprise 2022 Preview(64 位) 版本 17.0.0 Preview 3.1] (https://visualstudio.microsoft.com/zh-hans/vs/preview/)/// - SDK :[.NET SDK 6] (https://dotnet.microsoft.com/download/dotnet/6.0)/// - 语言:[C# 10](https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-10)////// ## 包说明////// - `Furion.Core`:无第三方依赖,可在 `.NET 6` 所有项目类型中运行。/// - `Furion`:内部依赖 `Furion.Core` 且无第三方依赖,**聚焦 `Web` 应用**,采用共享框架 `<FrameworkReference Include="Microsoft.AspNetCore.App" />` 模式///  </remarks>public void MarkdownTest(){    // ....}

v3.5.7(已发布)

  • 新特性

    • [新增] Options 选项属性支持自定义 Key 名称,[MapSettings("key")] #I5B2HN
    • [新增] EventBus 模块事件 Id 支持枚举类型 2f328aa
    • [新增] EventBus 模块发布者 PublishAsyncPublishDelayAsync 重载 2f328aa
    • [新增] EventBus 模块拓展方法:Enum.ParseToString()String.ParseToEnum() 2f328aa
    • [新增] FurionSqlSugar 脚手架 🆕🆕🆕 8d9293d
    • [新增] Dapper 拓展全局配置委托 #I5AYFX
    • [新增] sql 转实体支持多种命名策略(纯大写,纯小写,带下划线分割等等),如 Oracle 数据库 a90e245
    • [新增] FS.InitalContentTypeProvider() 拓展方法,获取系统内所有支持的 Content-Type 文件提供器 6099900
  • 突破性变化

    • [解决] 彻底解决了 Furion 不能单文件发布的问题 7e8e0b7
  • 问题修复

    • [修复] 框架规范化文档 Swagger 不支持 Controller 派生类 api 路由问题,原生 ASP.NET 是支持的 29e47bc
    • [修复] 基于 Schema 多租户配置无效问题 6f820ce
    • [修复] 指定实体 [Table(schema:"dbo")] 特性后 Schema 无效问题 6f820ce
    • [修复] 数据库视图不支持 Schema 配置问题 6f820ce
    • [修复] 规范化结果极端情况下出现 空异常 问题 c9b0ef
  • 其他更改

    • [调整] axios-utils.tsangular-utils.ts ,新增请求拦截携带刷新 Token 的时机判断 82f89bd
    • [优化] 规范化文档 Swagger 加载继承注释 <inheritoc /> 性能小优化 5f06880
    • [调整] 脚手架模板,新增 GlobalUsings.cs 模式
    • [调整] 对象映射默认支持忽略大小写 !486
  • 文档

    • [新增] Furion 单文件发布文档
    • [新增] Furion + SqlSugar 脚手架文档
    • [更新] 事件总线文档、选项文档、即时通讯文档、.NET5 升级 .NET6 文档、依赖注入文档、跨域文档、数据加解密文档
  • 本期亮点

  1. 事件总线 Id 支持枚举类型
EventSubscribe("TO:DO")]  // 字符串类型public async Task EventHandler1(EventHandlerExecutingContext context){    // ....}[EventSubscribe(YourEnum.Some)] // 枚举类型public async Task EventHandler2(EventHandlerExecutingContext context){    var eventEnum = context.Source.EventId.ParseToEnum(); // 将事件 Id 转换成枚举对象    // ....}
  1. 事件总线发布支持更简单调用
// 旧版本await _eventPublisher.PublishAsync(new ChannelEventSource("ToDo:Create", name));// 新版本await _eventPublisher.PublishAsync("ToDo:Create", name);await _eventPublisher.PublishAsync(YourEnum.Some); // 也支持枚举
  1. 选项支持属性自定义配置 Key
"AppInfo": {    "Name": "Furion",    "Version": "1.0.0",    "Company_Name": "Baiqian" // 可以和属性不一样}
public class AppInfoOptions : IConfigurableOptions{    public string Name { get; set; }    public string Version { get; set; }    [MapSettings("Company_Name")] // 支持自定义    public string Company { get; set; }}
  1. 日志规范化模板
// 生成模板字符串var template = TP.Wrapper("Furion 框架", "让 .NET 开发更简单,更通用,更流行。",    "[作者] 百小僧",    "[当前版本] v3.5.3",    "[文档地址] https://furion.icu",    "[Copyright] 百小僧, Baiqian Co.,Ltd.");Console.WriteLine(template);

输出结果

┏━━━━━━━━━━━  Furion 框架 ━━━━━━━━━━━┣ 让 .NET 开发更简单,更通用,更流行。┣ 作者:        百小僧┣ 当前版本:     v3.5.3┣ 文档地址:     https://furion.icu┣ Copyright:   百小僧, Baiqian Co.,Ltd.┗━━━━━━━━━━━  Furion 框架 ━━━━━━━━━━━

v3.4.2(已发布)

  • 新特性

    • [新增] 规范化文件 EnableAllGroups 功能,可以将多个分组合并到一个分组中 9277b98
    • [新增] angular-utils 客户端工具库,专门处理 angular 项目接口代理问题 6c70584
    • [新增] Swagger 支持单个接口更多描述功能(支持 htmle5e1db0
    • [新增] Swagger 接口 [Obsolete] 过时支持功能 e5e1db0
    • [新增] 动态 API[ApiDescriptionSettings] 特性 和DynamicApiControllerSettings 配置 的 ForceWithRoutePrefix 参数,支持强制复写 [Route] 特性并添加 DefaultRoutePrefix #I59B74
  • 突破性变化

    • [内置] 默认内置 GBKWindows-1252, Shift-JIS, GB2312 等编码支持 c456ecb
    • [新增] FurionSqlSugar 脚手架
  • 问题修复

    • [修复] <inheritdoc /> 不能跨程序集问题 3b9d39c
    • [修复] <inheritdoc /> 不支持带参数,不支持隐式实现接口注释问题 #I59A6W#note_10699021
    • [修复] v3.3.1 版本导致 Swagger 不能显示问题 6763352
    • [修复] 远程请求、JSON以及 Web 页面不支持 GBKGB2312 等国标编码问题 c456ecb
    • [修复] 远程请求响应报文设置了 Content-Type:charset= 不能自动转换编码问题 c456ecb
  • 其他更改

    • [新增] axios-utils.tsangular-utils.ts 多客户端支持
  • 文档

    • [新增] GlobalUsings 文档 文档地址
    • [新增] 请求大小/上传大小限制文档 文档地址
    • [更新] 规范化文档,Worker Service 文档,动态 API 文档
  • 本期亮点

  1. 启用 All Groups 分组功能

有时候我们为了更好的对接口进行归类,配置了 Swagger 多个分组的功能,但这样也对生成客户端请求代码造成了困扰,所以添加了新的配置:

{  "SpecificationDocumentSettings": {    "EnableAllGroups": true  }}
  1. 接口过时控制

当我们某个接口已经过时,提示尽早调用最新接口,只需要在方法上面贴 [Obsolete] 即可,如:

[Obsolete("GetName() 已经过时,请调用 GetFrameworkName() 替代")]public string GetName(){  return nameof(Furion);}[Obsolete]public string Other(){  // ...}
  1. 单一接口更多描述

在该版本新增了 [ApiDescriptionSettings]Description 属性,支持定义更多描述,如:

[ApiDescriptionSettings(Description = "我是一段描述,显示更多内容 <button>我是按钮</button>")]public string add(){  //....}

v3.3.3(已发布)

  • 新特性

    • [新增] 远程请求文件上传自动识别 Content-TypeMime #I57ZMN
    • [新增] 远程请求方法支持设置 Content-TypeEncoding #I57ZMN
    • [新增] 根据文件名获取 Content-TypeMime 类型 #8f78184
    • [新增] 规范化文档支持授权访问 #32aa3b6
    • [新增] 代码注释,规范化文档注释 inheritdoc 语法支持 ❤️️️️ #159A6W
    • [新增] 新增 Vue2/3React 16.8+Angular 9+ 前端请求工具库,实现后端 API 代理 axios-utils
  • 突破性变化

    • [新增] 代码注释,规范化文档注释 inheritdoc 语法支持 ❤️️️️ #159A6W
    • [更新] .NET 所有依赖包至 v6.0.5 版本
  • 问题修复

    • [修复] 自定义全局异常 Exception 后导致获取错误行号,文件空异常问题 #I53EGM
    • [修复] 配置数据库上下文传递空委托导致空引用异常问题 #I519AW
    • [修复] 字符串模板模板 Render 拓展方法返回 void 问题,应该返回 string Github-#99
    • [修复] 远程请求文件上传出现空情况问题(原因是缺失 Content-TypeI57ZMN
  • 其他更改

    • [调整] 框架源码引入 GlobalUsings 机制,减少代码体积 #7e9cc1c
    • [调整] 跨域请求的预检设置,如果未设置,则默认为 24 小时,主要解决前端多次发送 204 预检问题 4a11e7c
    • [优化] 视图引擎反射性能
  • 文档

    • [新增] 粘土对象序列化 JSON 配置文档
    • [新增] 前端解密 JWT 文档
    • [新增]byte[]url 文档
    • [更新] 二级虚拟目录部署文档,远程请求文档,文件上传文档,安全授权文档、规范化文档
  • 本期亮点

    • ❤️️️️ 根据文件名获取 MIMEContent-Type 类型
var success = FS.TryGetContentType("image.png", out var contentType);  // image/png
  • ❤️️️️ 支持 Swagger 配置登录后才能访问
{  "SpecificationDocumentSettings": {    "LoginInfo": {      "Enabled": true,      "CheckUrl": "检查登录地址",      "SubmitUrl": "提交登录地址"    }  }}

查看详细文档

  • ❤️️️️ 支持代码注释继承,Swagger 文档注释也支持
/// <inheritdoc cref="ITestInheritdoc" />public class TestInheritdoc : ITestInheritdoc, IDynamicApiController{    /// <inheritdoc cref="ITestInheritdoc.GetName"/>    public string GetName()    {        return "Furion";    }    /// <inheritdoc />    public string GetVersion()    {        return "3.3.3";    }}/// <summary>/// 测试注释继承/// </summary>public interface ITestInheritdoc{    /// <summary>    /// 获取名称    /// </summary>    /// <returns></returns>    string GetName();    /// <summary>    /// 获取版本    /// </summary>    /// <returns></returns>    string GetVersion();}

查看详细文档


v3.2.0(已发布)

  • 新特性

    • [新增] IFormFile 拓展方法 ToByteArray() da69640
    • [新增] 规范化文档 ServeDir 虚拟目录配置功能,支持一键将一级目录切换至二级目录部署(IIS)8718392
  • 突破性变化

    • [更新] 所有依赖包至最新版
    • [重构] 依赖注入模块核心代码,移除注册服务采用反射机制,减少反射性能损耗 acdb315
  • 问题修复

    • [修复] Swaggerschema 类型如果是 C# Object 类型无法正确生成前端代码问题 Swagger 官方 Issue 1a25274
    • [修复] Worker Service 发布成 Windows Services 时日志绝对路径问题 感谢 @jacoat !467
    • [修复] NginxIIS 对二级虚拟目录配置不同导致 404 问题 8718392
    • [修复] 远程请求模块未初始化 OnRequestFailded 导致空异常问题 #I54PK7
    • [修复] 依赖注入反射出现 Not found Method bug #I546L1
  • 其他更改

    • [调整] 定时任务失败后异常处理逻辑,感谢 @程小胜 !463
  • 文档

    • [更新] 定时任务文档,日志文档
    • [新增] 文件上传/下载 文档,包含单文件/多文件/Base64/Byte[]

v3.1.0(已发布)

  • 新特性

    • [新增] 远程请求模块异常 Http 状态码 !462
    • [新增] 动态 WebAPI 支持小驼峰配置 #I4W1R4
    • [新增] 远程请求 SendAsByteArrayAsync 等一系列方法,支持返回 byte[] !452
    • [新增] 远程请求 GZip 压缩支持 #I506S5
  • 突破性变化

    • [升级] .NET6 依赖包全部升级至 Nuget 最新版 v6.0.3
  • 问题修复

    • [修复] .NET6 WebApplication 模式二级虚拟目录问题 #I4UZLM #I4PZ0C
    • [修复] 日期验证不支持 2022-03-01 0:00:00(现在支持小时域 000) 问题 #I4Y3NT
    • [修复] 环境配置和文件配置优先级问题
    • [修复] 脱敏模块替换敏感词汇只替换最后一个 bug #I4YFA0
    • [修复] 远程请求返回字符串个别情况出现中文乱码问题 #I50GBD
    • [修复] [DataValidate] 配置 AllowNullValueAllowEmptyString 无效问题 #I4ZZBE
  • 其他更改

    • [过时] 标记 Furion.Extras.Logging.Serilog 拓展包 IWebHost 拓展为过时状态
  • 文档

    • [文档] 优化文档体验,新增面包屑导航,重写文档缓存,提升文档访问速度
    • [文档] 更新动态 API 文档、配置文档、远程请求文档
    • [文档] 更新二级虚拟目录文档
  • 本期亮点

  1. 新增动态 WebApi 支持小驼峰路径,如 GetMyName -> getMyName
{  "DynamicApiControllerSettings": {    "LowercaseRoute": false,    "KeepName": true,    "AsLowerCamelCase": true  }}
  1. 支持 .NET6 WebApplication 模式二级虚拟目录配置:
Progame.cs
app.UseVirtualPath(app =>{    app.UseInject(String.Empty);  // 注意 String.Empty 只是例子,可以不填或填其他的,见一分钟入门    app.MapRouteControllers();});

v3.0.0(已发布)

v3+ 版本说明

Furion v3.x 版本采用 .NET6 构建。

  • 新特性

    • [新增] 远程请求支持 GET 请求自动转换 类类型 类型对象 #I4HR5Q
  • 突破性变化

    • [升级] 全面支持 .NET6 版本
  • 问题修复

    • [修复] 开启规范化结果并自定义全局异常导致异常经过 OnSucceeded 过滤器 bug #I4DTVL
    • [修复] .NET5.0.5+.NET6 微软底层修改了 [ApiController] 验证失败返回 IActionResult 类型 #I4ISOK
    • [修复] EFCore 6.0 适配 SqlServer 2005+ 出错 #I4ILA5
    • [修复] .NET6 获取配置对象如果不存在返回 null 问题,.NET5 则返回初始对象 94ae4d
    • [修复] Sql 命令参数传入 Clay 类型异常问题 #I4D21Q
    • [修复] Cron 定时任务特性方式 bug #I4OJQI
  • 其他更改

    • [移除] ToPagedList 泛型约束 d0244d
  • 文档

  • 特别鸣谢


v2.20(已发布)

v2.20+ 版本说明

Furion v2.20+ 版本后采用 Jaina 事件总线替换原有的 EventBus

  • 新特性

    • [新增] 远程请求支持 GET 请求自动转换 类类型 类型对象 #I4HR5Q
  • 突破性变化

    • [重构] EventBus 模块,采用 Jaina 方式
  • 问题修复

    • [修复] 开启规范化结果并自定义全局异常导致异常经过 OnSucceeded 过滤器 bug #I4DTVL
    • [修复] .NET5.0.5+ 微软底层修改了 [ApiController] 验证失败返回 IActionResult 类型 #I4ISOK
    • [修复] 远程请求上传文件异常 0c0752
    • [修复] 框架启动不支持环境变量 ASPNETCORE_HOSTINGSTARTUPASSEMBLIES 配置 !438
    • [修复] 定时任务内存和 CPU 占用及特殊情况下空异常问题 12c65de
    • [修复] 默认控制器启用规范化结果无效 bugc7a4a5e
    • [修正] 依赖注入 InjectionAttribute 特性的 ExceptInterfaces 单词拼写错误问题 !436
    • [修复] Sql 命令参数传入 Clay 类型异常问题 #I4D21Q
  • 其他更改

    • [优化] InjectionAttribute 代码 !435
    • [移除] ToPagedList 泛型约束 d0244d
  • 文档

    • [新增] 事件总线新文档

v2.19(已发布)

  • 新特性

    • [新增] 定时任务监听器 ISpareTimeListener #I468Q1
    • [新增] 执行 Sql 支持 JsonElement 参数 61985d6
    • [新增] Swagger 配置枚举及标签排序过滤器 #I46LON !404
    • [新增] 远程请求 application/octet-stream 类型默认支持 d9bad03
    • [新增] 远程请求代理模式请求报文头支持 IDictionary<string ,object> 类型。0204c0a
    • [新增] MongoDB 拓展类,添加更多常用操作方法 !423
    • [新增] DateTimeOffset? 转换 DateTime 拓展(包含互换) !432
  • 问题修复

    • [修复] Scoped.CreateEFCore 进行 Add-Migration 时候报空异常问题,原因是在 PM 环境中不存在根服务0853e74
    • [修复] 定时任务执行异常后异常一直驻留内存问题,修正为执行成功自动清空过去异常 197a62b
    • [修复] Jwt 拓展包不正确的代码导致 IOptions 失效#I46LUP
    • [修复] Swagger 枚举 Schema 过滤器不输出值问题 #I46LON !404
    • [修复] Swagger 处理非 int 类型枚举转换 bug #I46QJ9
    • [修复] 视图引擎编译模板生成 dll 后再次加载出现 IL 格式化错误问题 ff52d38
    • [修复] 管道 Channel 读取器无法释放 Handler 对象问题 10f4a90
    • [修复] Worker Services 下日志不输出问题 c482548
    • [修复] 远程请求 multipart/form-data 类型对接微信小程序上传文件 问题 d9bad03
    • [修复] 工作单元上下文在某些情况下共享事务失效问题 006d439
    • [修复] Swagger 枚举值在 GET 请求中 Schema 显示不正确问题 fb72fd7
    • [修复] 远程请求 404 不走异常过滤器问题 !426
    • [修复] 自定义事件总线并发情况下调用完成后无法正确处理队列数据 !429
    • [修复] v2.19+ 版本之后模块化开发加载外部程序集失效问题 !433
    • [修复] 定时任务 SpareTime 频繁检查导致 CPU 增高问题 aa0a2ee
  • 特别鸣谢


v2.18(已发布)

  • 新特性

    • [新增] Furion.Tools.CommandLine 拓展库 查看源码
    • [新增] 基于 AsyncLocal<T>CallContext 实现 9057a21
    • [新增] 远程请求可配置请求异常重试策略 656da87
    • [新增] 远程请求 OnRequestFailded 事件 4a3da4b
  • 突破性变化

    • [移除] Scoped 所有带返回值方法 656da87
    • [调整] ConfigureService 中调用 App.GetOptions<>() 获取配置逻辑 afa4ac3

在过去,很多开发者总是喜欢在 Startup.cs 配置服务的 ConfigureService 方法中解析服务,这样导致内存存在溢出风险,GC 无法回收。 +正确的方式是尽可能的避免 ConfigureService 中解析服务。如果需要在【启动时】获取 配置选项,请使用 App.GetConfig<TOptions>(路径, true) 代替 App.GetOptions<TOption>

  • 问题修复

    • [修复] v2.16+ 版本重构 AppDbContextBuilder 之后写错实体类型 #I45E6M
    • [修复] 远程请求单个值序列化错误处理方式 3282eba
    • [修复] v2.17.3+ 单元测试创建 TestServer bug #I45JR3
    • [修复] Retry.Invoke 正常方法死循环 bug !392
    • [修复] 刷新 Token 生成新 Token 存在数组/集合类型导致 Key 重复异常问题 aeea2b1
    • [修复] 远程请求序列化引用类型对象(不含 string)不正确的处理 93cf63a
    • [修复] AppDbContext 默认租户属性受工作单元影响问题 e51557f
  • 文档

    • [新增] 包管理工具文档
    • [更新] 模板引擎、Sql 操作,数据库上下文 等等文档

v2.17(已发布)

  • 新特性

    • [新增] IPC(Inter-Process Communication,进程间通信) 模块功能,目前提供进程内通信和共享内存进程外通讯 ProcessChannel
    • [新增] 远程请求 application/xmltext/xml 默认支持 4753a1a
    • [新增] 控制台全局异常拦截 4a4fe1f
    • [新增] 支持自定义 .json 配置文件扫描目录 3e2910a
    • [新增] 支持数据库实体接口显式实现接口配置 9610a0a
    • [新增] 控制台应用程序全局拦截 [IfException] 支持 4a4fe1f
    • [新增] 依赖注入模块接口可以限制实现类生存周期,实现类也支持复写生存周期 d2ce089
  • 突破性变化

    • [抽离] Oops.Retry() 重试策略功能至新类:Retry.Invoke() 6a7bbd0
    • [移除] IHttpContextAccessor.SigninToSwagger() 拓展,请使用 IHttpContextAccessor.HttpContext.SigninToSwagger(),退出也一样
    • [移除] 全局处理 Request Body 重复读处理 Request.EnableBuffering() d92c24b
  • 问题修复

    • [修复] 规范化状态码过滤逻辑错误问题 #I44JYS
    • [修复] 非关系型数据库(内存数据库)注册及操作异常 e167651
    • [修复] 远程请求默认序列化问题 a55603b
    • [修复] 定时任务零点/整点提前一秒触发问题 #I4321L
    • [修复] 友好异常在子类重写抽象类方法内部抛异常无法获取的问题 4a4fe1f
    • [修复] 修复非 Web 项目抛异常问题 4a4fe1f
    • [修复] 数据库实体模型贴 [NotMapper] 特性无效 #I44MNO
  • 其他更改

    • [调整] Swagger 生成泛型 SchemaIds 默认连接符,由 Of 改为 _ 81946b6

v2.16(已发布)

  • 新特性

    • [新增] MVC 控制器支持规范化处理 #I427Z2
    • [新增] throw Oops.Bah() 抛出业务异常(状态码 400
    • [新增] UnifyResultSettings 规范化 json 配置选项 #I42NY7
    • [新增] 多语言自定义配置资源文件名及自定义程序集 #I434YJ
  • 突破性变化

    • [调整] 规范化结果 IUnifyResultProvider 参数 (破坏性更改) #I427Z2
    • [调整] IJsonSerializerProvider 接口参数,去掉 inherit 参数 a55603b
新版本自定义规范化结果
using Furion.DataValidation;using Furion.DependencyInjection;using Furion.UnifyResult.Internal;using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.Filters;using System;using System.Threading.Tasks;namespace Furion.UnifyResult{    /// <summary>    /// RESTful 风格返回值    /// </summary>    [SuppressSniffer, UnifyModel(typeof(RESTfulResult<>))]    public class RESTfulResultProvider : IUnifyResultProvider    {        /// <summary>        /// 异常返回值        /// </summary>        /// <param name="context"></param>        /// <param name="metadata"></param>        /// <returns></returns>        public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata)        {            return new JsonResult(RESTfulResult(metadata.StatusCode, errors: metadata.Errors));        }        /// <summary>        /// 成功返回值        /// </summary>        /// <param name="context"></param>        /// <param name="data"></param>        /// <returns></returns>        public IActionResult OnSucceeded(ActionExecutedContext context, object data)        {            return new JsonResult(RESTfulResult(StatusCodes.Status200OK, true, data));        }        /// <summary>        /// 验证失败返回值        /// </summary>        /// <param name="context"></param>        /// <param name="metadata"></param>        /// <returns></returns>        public IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata)        {            return new JsonResult(RESTfulResult(StatusCodes.Status400BadRequest, errors: metadata.ValidationResult));        }        /// <summary>        /// 特定状态码返回值        /// </summary>        /// <param name="context"></param>        /// <param name="statusCode"></param>        /// <param name="unifyResultSettings"></param>        /// <returns></returns>        public async Task OnResponseStatusCodes(HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings)        {            // 设置响应状态码            UnifyContext.SetResponseStatusCodes(context, statusCode, unifyResultSettings);            switch (statusCode)            {                // 处理 401 状态码                case StatusCodes.Status401Unauthorized:                    await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "401 Unauthorized")                        , App.GetOptions<JsonOptions>()?.JsonSerializerOptions);                    break;                // 处理 403 状态码                case StatusCodes.Status403Forbidden:                    await context.Response.WriteAsJsonAsync(RESTfulResult(statusCode, errors: "403 Forbidden")                        , App.GetOptions<JsonOptions>()?.JsonSerializerOptions);                    break;                default: break;            }        }        /// <summary>        /// 返回 RESTful 风格结果集        /// </summary>        /// <param name="statusCode"></param>        /// <param name="succeeded"></param>        /// <param name="data"></param>        /// <param name="errors"></param>        /// <returns></returns>        private static RESTfulResult<object> RESTfulResult(int statusCode, bool succeeded = default, object data = default, object errors = default)        {            return new RESTfulResult<object>            {                StatusCode = statusCode,                Succeeded = succeeded,                Data = data,                Errors = errors,                Extras = UnifyContext.Take(),                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()            };        }    }}
  • 问题修复

    • [修复] MVC 控制器启用规范化处理后返回 new Json({}) 对象为 null 问题 #I4354S
  • 其他更改

    • [优化] 多语言底层设计,取消需要创建 Lang.cs 空类的要求 #I434YJ
    • [优化] MiniProfiler 性能,减少不必要的监听

v2.15(已发布)

  • 新特性

    • [新增] Db.GetDbRepository<定位器>() 静态方法 #I41MZP
    • [新增] 远程请求缺省序列化配置选项 #I41PBW
  • 问题修复

    • [修复] 自动扫描接口进行依赖注入获取首个接口错误 bug #I41D1M
    • [修复] IRepository<TEntity> 没有实现 IRepository<TEntity, TDbContextLocator> 问题 #I41MZP
    • [修复] 远程请求缺省序列化 bug #I41PBW
    • [修复] 修复 AppDbContext.Tenant 多租户空异常问题 #I421DA
    • [修复] Worker Service 多个 Worker 定时任务阻塞问题 82a79cc
    • [修复] Jwt 自动刷新机制时区处理问题,主要针对国外用户 #I41UB1 82a79cc
  • 其他更改

    • [优化] 系统启动性能,从 106M 减少到 84M
    • [优化] 大量底层代码,包大小从 391Kb 减少到 350Kb(不带注释版本仅 64Kb)

v2.13/v2.14(已发布)

  • 新特性

    • [新增] 简易字符串模板功能,支持远程请求、数据库模块、日志模块、事件总线模块、定时任务模块、异常模块、数据校验模块 #I402BL
    • [新增] 404 状态码规范化默认处理 #I408F5
    • [新增] 定时任务 ISpareTimeWorker 声明方式支持异步方法 #I40KWR
    • [新增] 自动配置二级虚拟目录 !354
  • 突破性变化

    • [升级] 框架依赖 SDK.NET 5.0.8 版本
    • [移除] Db.GetNewDbContext() 静态方法 #I400BK
    • [移除] 数据库模块时态表拓展支持 #I405HI
    • [调整] IJsonSerializerProvider 接口参数,新增 inherit 参数 #I3ZQU5
    • [调整] AppSettings 配置的 LogEntityFrameworkCoreSqlExecuteCommand 名称为 OutputOriginalSqlExecuteLog #I40VVE
  • 问题修复

    • [修复] Worker Services 定时任务边界值问题导致跳过单次任务 #I405NI
    • [修复] Worker Services 独立发布后程序集扫描失效 bug #I3ZH3X
    • [修复] 远程请求如果配置了 Client 客户端但传入了空 RequestUrl 地址导致异常问题 #I40BC6
    • [修复] 规范化结果篡改非短路端状态码出现异常 bug #I408F5
  • 其他更改

    • [优化] App.GetServiceProvider(type) 解析服务性能 #I40KXN
    • [调整] 视图引擎保存成文件流默认缓存区大小,从 4096 提升至 8192 #I40KH5

v2.10/2.11/2.12 (已发布)

该版本有多个破坏性更改,更新时请认真查看。

  • 新特性

    • [新增] App.Configuration.Reload() 拓展 #I3XYI8
    • [新增] ISubscribeHandler 支持异步方法定义 #I3XYHJ
    • [新增] app.UseUnifyResultStatusCodes() 可配置修改返回状态码 #I3VZQH
    • [新增] 远程请求添加默认 User-Agent#I3W17C
    • [新增] 支持 Sql 高级代理切换数据库上下文定位器 #I3XFP6 #I3XDCR
    • [新增] 定时任务 CronFormat 自动识别 #I3Y7GT
    • [新增] Sql 高级代理 拦截功能 #I3YHG4
    • [新增] 拦截远程请求所有异常处理 #I3YPDE
    • [新增] 远程请求配置 Timeout 超时时间 #I3YPPK
    • [新增] 新增 RSA 加密算法 #I3YZNU !345
    • [新增] DataTableDataSet 支持不指定强类型返回 #I3Z6RI
    • [新增] Sql 字符串拓展方法设置 Timeout 超时时间 #I3ZKWF
    • [新增] Sql 高级代理 [Timeout] 特性,设置超时时间 #I3ZKWF
  • 突破性变化

    • [移除] FakeDelete 假删除/软删除所有功能 #I3XKII
    • [移除] 移除 PBKDF2 加密算法 #I3Z0IO
    • [调整] 远程请求设置超时时间单位由 分钟 改为 #I3YPPK
    • [调整] IJsonSerializerProvider 接口参数,新增 inherit 参数 #I3ZQU5
    • [调整] [NonAutomatic] 特性名称为 [Manual] #I3XKKX
    • [调整] [NotChangedListener] 特性名称为 [SuppressChangedListener] #I3XKLZ
    • [调整] [ManualSaveChanges] 名称为 [ManualCommit] #I3XKNP
    • [调整] DbContext.TenantIdQueryFilterExpression 名称为 DbContext.BuildTenantQueryFilter #I3XKTB
    • [调整] [SkipScan] 名称为 [SuppressSniffer] #I3XN5N
    • [调整] [SkipProxy] 名称为 [SuppressProxy] #I3XN7O
    • [重构] Sql 执行,性能提升 20% #I3W33U
  • 问题修复

    • [修复] 动态 WebAPI 扫描控制器没有屏蔽没有注册的第三方控制器 #I3Y7TJ
    • [修复] AppDbContext 设置 TablePrefix 无效: #I3Y57Q
    • [修复] 修复定时任务使用异步委托导致程序终止 bug #I3XVZ0
    • [修复] 事件总线一个 消息id 对应多个 Handler 只触发第一个#I3XYP0
    • [修复] .ToPagedList() 分页方法传入小于或等于 0 的页码 #I3XNAN
    • [修复] JSON 序列化默认 DateTimeOffset 异常 #I3XMOL
    • [修复] 继承 Serilog 日志在 Worker Service 生成重复日志 bug #I3WA0L !331
    • [修复] 粘土对象 动态添加 Clay 类型 bug #I3W9LW
    • [修复] ValidationTypes.Numeric 校验数值类型正则表达式错误 #I3WADS
    • [修复] 数据库命令参数 DbParameterValueobject 类型的时候且不指定 #I3YKM6
    • [修复] Oracle 数据库存储过程 游标参数 报错问题 #I3ZBYE
    • [修复] Worker Services 采用独立发布后无法执行问题 #I3ZH3X
    • [修复] 修复远程请求如果无返回值序列化异常问题 !348
  • 其他更改

    • [增强] 支持 appsettings.json 等自定义配置文件中文命名 #I3YBFD
    • [改进] 远程请求配置命名客户端 BaseAddress 地址兼容处理 #I3YCRH
    • [移除] 框架无用代码、优化代码
    • [优化] Furion非 Web 环境下性能
  • 文档变化

    • [新增] 会话和状态管理 文档 #I3YI3G
    • [更新] 远程请求、日志、数据库上下文、远程请求、Sql 高级代理文档
    • [更新] 配置文件 #I3Y2EV
  • 问答答疑

    • [答疑] dapper 多个数据源如何继承 #I3WUOI
    • [答疑] 关于 SpareTime 多次执行问题#I3XEQU
    • [答疑] 选项更改通知(热更新):数据库里的数据更改了如何通知选项进行改变? #I3XYI8
    • [答疑] SaaS 多租户添加时无法获取租户Id #I3Y5CF
    • [答疑] 获取 _httpContextAccessor.HttpContext 为空#I3Y6BI
    • [答疑] Ubuntu 中使用 App.Configuration 方法读取不到值 #I3Y74H
    • [答疑] 数据库上下文作用域问题 #I3YHXP
    • [答疑] 使用 UnitofWork 提交事务,可以提交成功,但是系统会有错误 #I3YIWU
    • [答疑] 数据库读写分离--非默认主库的从库随机该如何配置? #I3YVR7
  • 不做实现

    • [废弃] SpareTIme 新增 Dashboard 控制台看板,同时可以对任务进行暂停、删除、查看#I3XELY

v2.9.0 (已发布)

  • 新特性

    • [新增] 应用全局未托管资源监听,并实现特定时机释放非托管资源 #I3VXAU
    • [新增] 不包含 EntityFramework.Core 版本的 Furion.Pure#I3VGW8
    • [新增] swagger 支持设置多语言方式,设置的语言自动添加到 api 地址后面 #I3VDTD
    • [新增] 动态 WebAPI 支持 [FromRoute] 非必填(选填)参数设置 #I3VFIM
    • [新增] 动态 WebAPI 参数支持配置路由约束 #I3VFIR
    • [新增] MD5DESC 加密支持 大写 输出 #326
  • 突破性变化

    • [新增] Furion 所有包生成 .snupkg 包,支持开发阶段直接调试 Furion 所有包源码 #I3VFIX
    • [调整] repository.BuildChange() 方法的返回值,多返回一个 IServiceScope 对象 #I3VX3D
    • [调整] JWT 刷新 Token 方法 AutoRefreshToken 参数 days 改为 minutes #I3VXNB
  • 问题修复

    • [修复] App.GetOptionsSnapshot<> 从根服务解析异常 bug #I3VS2X
    • [修复] 修复远程请求如果出现异常,返回 Stream 为 null 导致异常的问题 #I3VSTU
    • [修复] 如果实体被跟踪后,无法执行删除操作 #I3W08P
  • 其他更改

    • [优化] 运行时内存,实现请求结束自动释放未托管资源 #I3VXAU
  • 文档变化

    • [更新] App 静态类文档、远程请求文档、分表分库文档
  • 问答答疑

    • [答疑] 动态 WebAPI,自定义根据方法名生成 [HttpMethod] 规则报错 #I3VKQG
    • [答疑] InsertAsync 的时候提示 ID 为空 #I3VS7E
    • [答疑] FirstOrDefault 自动过滤了 TanantId 字段 #I3W0VH
    • [答疑] 对方接口返回 HttpConnectionResponseContent 远程请求拿不到返回值 #I3W17C
    • [答疑] 查询方法 FindOrDefault 报错 #I3W830
    • [答疑] SqlNonQueryUnitOfWork 循环执行#I3W8WW
    • [答疑]Swagger 配置问题,导致 Swagger 中不能自动携带 token 授权的问题 #I3W934
    • [答疑] 远程请求 SetBody 参数识别不了#I3WBM1
    • [答疑] Scoped.Create 里执行 sql.SqlNonQuery() 或者 obj.insert() 问题#I3WB5O
    • [答疑] 调用函数或存储过程,怎么出参数据自定义对象?如 Oracle数据库的数组或记录 #I3W71W
  • 不做实现

    • [无效] 数据库小写下划线字段,无法自动映射成小驼峰 #I3W021
    • [废弃] EfCore 5 直接多对多时进行 SeedData #I3WDRJ

v2.7.0/2.8.0 (已发布)

  • 新特性

    • [新增] throw Oops.On("异常消息") 应用多语言支持 #I3UYC2
    • [新增] Db.GetMSRepository() 获取主从库仓储静态方法 #I3UBSJ
    • [新增] 工作单元特性,支持静态类强制性开启共享事务 #I3S9N8
    • [新增] EFCore 执行 sql 模式打印日志 #I3SE8X
    • [新增] 远程请求支持默认 HttpClient 配置 #I3SI17
    • [新增] 新增 短 ID 生成功能 #I3T7JP
    • [新增] [SensitiveDetection] 支持配置替换敏感词汇 #I3THIA
    • [新增] SpecificationDocumentBuilder.DocumentGroupsSpecificationDocumentBuilder.CheckApiDescriptionInCurrentGroup(currentGroup, apiDescription) 公开方法#I3UDSY
  • 突破性变化

    • [重构] 自动扫描 .json.xml 文件并加载到配置中的代码和规则,同时移除默认 .xml 文件加载,只保留 .json 文件 #I3UJ3L
    • [重构] 分布式连续 GUID 代码 #I3UBK0
    • [调整] Scoped.CreateUnitOfWork 名称为 Scoped.CreateUow #I3SJPU
    • [调整] JWTEncryption.Validate 返回值,支持返回 TokenValidationResult #I3S2ND
  • 问题修复

    • [修复] [DataValidation][SensitiveDetection] 多语言应用失效 #I3UH6U
    • [修复] Scoped 系列方法异步出现 Task is cancel 情况 #I3SJF6
    • [修复] Mysql 数据库的 ToPagedList 方法返回的结果进行遍历出现 MySqlConnection is aleady use 问题 #I3SJQ3
    • [修复] tool/cli.psl 没有包含项目名称 #I3S1T6
    • [修复] 远程请求做上传文件时,没有传入 Body,程序直接跳过 #I3TKFH
    • [修复] 远程请求 multipart/form-data 内容分割符缺失 #I3TNO9
    • [修复] 远程请求代理拦截方式返回 HttpResponseMessage 问题 #I3V161
    • [修复] repository.Database.SetCommandTimeout(600) 无法生效#I3VAQS
  • 其他更改

    • [改进] 支持规范化结果中间件判断是否跳过规范化结果 #I3T2AA
    • [调整] 更新部分列 UpdateIncludeNowAsync 具有二义性 #I3RW9Q
    • [优化] 框架底层性能,大大减少内存占用和溢出情况,启动内存从之前 136M 下将到 86M
    • [其他] 删除无用代码,优化不规范命名等
  • 文档变化

    • [新增] Inject 说明文档 #I3TITA
    • [更新] 4.2.9 的示例代码文档,方法没有放在 class 中 #I3S9T5
    • [修正] 规范化结果 6.5.6 多分组排序图片引用错误 #I3UBOQ
    • [更新] 静态类 Scoped 文档
  • 问答答疑

    • [答疑] 默认 MasterDbContextLocator 不随自定义的参数生成 #I3SDBB
    • [答疑] 事件总线中订阅处理程序类获取不到用户信息,这个正常吗 #I3SS0U
    • [答疑] 在有多租户过滤器的情况下,是否有一种方式查询全量的数据 #I3T0VI
    • [答疑] mysql 使用 &"tools/cli.ps1" 页面化加载表结构失败 #I3T4F8
    • [答疑] 其他 Web 层的 Startup 优先执行 #I3T8IP
    • [答疑] 辅助角色服务实现建议 #I3T906
    • [答疑] 开启 easy connection 后同一内网地址浏览器可以正常访问,远程请求则无法访问#I3TA2U
    • [答疑] scope.ServiceProvider.GetService<IOtherService>不存在 #I3TQMV
    • [答疑] 能否在 WPF 项目中使用呢? #I3TMCC
    • [答疑] Dapper 多个数据源 #I3TM9B
    • [答疑] L.GetSelectCulture() 方法异常 #I3TQS4
    • [答疑] 循环中使用 IDGen.NextID() 得到的结果并不是连续的 #I3UAF6
    • [答疑] 模块化动态加载插件支持通配符匹配.dll #I3UDT8
    • [答疑] MVC 模式,在 Controller 里快捷方式创建 View 页面出错 #I3UFGB
    • [答疑] 数据库迁移没有种子数据 #I3UI7G
    • [答疑] SpareTimeAttribute 中 根据 Cron 表达式 自动匹配 Cron 表达式格式化方式 #I3UTKQ
    • [答疑] 使用 workService 集成 SqlSugar 报错 #I3V8HJ
    • [答疑] sqlserver 2008 分页报错如何解决呢 #I3VF96
  • 不做实现

    • [废弃] 添加令牌桶限流算法 #I3SCDV
    • [废弃] 定时任务立即执行需求 #I3SF4A
    • [废弃] 文档建议 关于 reids 和 es 、消息队列的 #I3T90I
    • [废弃] IP 高频率请求限制 #I3UHE1
    • [废弃] Url 转发大模块 #I3TZHO

v2.5.0/2.6.0 (已发布)

  • 新特性

    • [新增] 虚拟文件服务,支持物理文件和嵌入资源文件 #I3RBR9
    • [新增] 读写分离/主从复制仓储 IMSRepositoryIMSRepository<TMasterDbContextLocator> 仓储,可进行随机或自定义获取从库
    • [新增] 数据脱敏处理 #I3R5ZF
  • 突破性变化

    • [移除] InsertOrUpdate 一系列数据库操作方法 #I3RI9L
    • [移除] 所有包含 Exists 单词的数据库操作方法 #I3RJ0T
    • [调整] 分布式 GUID IDGenerater 静态类名称为 IDGen #I3RGUA
  • 问题修复

    • [修复] 远程调用方法错误,请求报文头 Headers 不能添加到 IHttpDispatchProxy 的子接口上 #I3RAF7
  • 其他更改

    • [优化] 应用启动性能,减少内存分配
  • 文档变化

    • [新增] 脱敏处理文档 #I3R6WZ
    • [新增] 文件系统文档、FS 静态类文档 #I3RCC4
    • [更新] 读写分离/主从复制、数据库仓储文档、Db 静态类 #I3R3B6
  • 问答答疑

    • [答疑] 关于 Furion 集群部署 #I3R3J4
    • [答疑] 升级最新框架以后, 数据库生成模型报错 #I3R7TP
    • [答疑] 数据库上下文事务执行中,SaveNow 执行后有警告 #I3RAJI
    • [答疑] Hangfire 使用事务出现错误 #I3ROQ5
    • [答疑] 如何实现 cli 不执行某些表的迁移,web 请求可以正常操作呢? #I3ROU5
    • [答疑] 在使用定时任务时候出现的问题:继承 ISpareTimeWorker #I3RRZS
    • [答疑] MySql 时间差 8 小时处理 #I3RSCO
    • [答疑] Db.GetRepository<> 方法结合 [UnitOfWork] 后不可用 #I3RUK5
    • [答疑] 事务开启失败问题 #I3RYJY
    • [答疑] 支持 DbProvider 可动态配置 #I3RYPE
    • [答疑] WorkService 依赖注入 ISingleton 问题 #I3RZ1L
    • [答疑] ISpareTimeWorker 运行期动态修改 #I3S33Q
  • 不做实现

    • [拒绝] 有序 Guid 精度是固定的毫秒级:1 毫秒内生成的多个 Guid 是无序的 #I3R59J
    • [拒绝] 建议:JWTEncryption.Validate 方法返回 JWT 的检查失败时的原因 #I3S1F2

v2.4.0 (已发布)

  • 新特性

    • [新增] 支持自动加载模块化/插件 .xml 注释文件 #I3Q7XY
    • [新增] AppDbContext.FailedAutoRollback 属性,可配置事务是否自动回滚 #I3QOUS
  • 突破性变化

    • [升级] .NET 5 SDK 为 5.0.6 版本
    • [新增] IJsonSerializerProvider.GetSerializerOptions() 接口方法 #I3QIJN
  • 问题修复

    • [修复] 通过 services.AddInject() 方式注册,模块化/插件不加载 #I3Q7XH
    • [修复] 种子数据返回 null 报空异常 #I3QCM5
    • [修复] 通过 Clay.Object 创建粘土对象后属性变小写问题 #I3QRV3
  • 其他更改

    • [优化] Furion 框架底层性能,减少内存占用,提高应用初始化速度 92f8cc1
  • 文档变化

    • [更新] JSON 序列化文档、规范化结果文档、数据库上下文文档
  • 问答答疑

    • [答疑] InsertOrUpdateNowAsync 报错 #I3QKO5
  • 不做实现

    • [废弃] 定时任务自定义 Failed 事件 #I3QCM2
    • [废弃] 模块化动态生成数据库表 #I3QH3G
    • [废弃] 建议事件总线新增 MQ 支持 #I3QWZ4
    • [废弃] 重构规范化整个模块代码 #I3NFT7

v2.3.0 (已发布)

  • 新特性

    • [新增] Furion.Extras.DatabaseAccessor.MongoDB 拓展包支持 #I3PKST
    • [新增] 动态粘土类型直接转 objectdynamic 类型 #I3OY27
    • [新增] 新增 Oops.Retry 方法,支持设置方法调用失败进行重试 #I3PJKQ
    • [新增] JWTSettings 配置节点 Algorithm,用于配置加密算法 #I3PQGV
    • [新增] repository.EnsureTransaction() 方法确保工作单元事务有效 #I3PVF1
  • 突破性变化

    • [支持] 支持 .NET 6.0.0 Preview 3 版本 #I3P2C7
  • 问题修复

    • [修复] 使用数据库生成模型 tools/cli.ps1,从数据库表生成的实体异常 #I3PL18
    • [修复] 贴了 [NonUntify] 特性后,SwaggerExample Value 没有匹配正确 #I3PK0L
    • [修复] SpareTimer.TallyCron 表达式中计数无效 #I3PWSE
  • 其他更改

    • [改进] 框架默认序列化应该从配置中读取,而非手动编写 #I3P1SJ
    • [改进] SqlSugar 拓展库,支持非泛型仓储获取上下文操作对象 #I3PK2N
    • [改进] 支持分布式内存缓存可配置化 #I3POKD
  • 文档变化

    • [文档] 添加 JWTSettings 配置独立文档 #I3PQGW
  • 问答答疑

    • [答疑] 软删除如果数据不存在,则报错 #I3PTVB
    • [答疑] 多个类集成测试会造成数据库定位器多次注册,无法运行所有测试,只能一个类一个类的运行 #I3PXGY
  • 不做实现


v2.2.0 (已发布)

  • 新特性

    • [新增] Clay 粘土类型,支持让 C# 创建一个弱类型对象并操作弱类型 #I3O2QQ
    • [新增] 新增 Scoped.Create 带返回值重载 #I3O47J
    • [新增] 支持 Scoped.Create() 一系列方法支持传入作用域工厂 #I3OAP5
    • [新增] 支持事件总线同步执行方式 #I3OAW2
    • [新增] [DataValidation] 跳过空字符串和空值验证 #I3OGEN
    • [新增] Worker Service 可配置是否自动注册 Worker #I3OLW4
  • 突破性变化

  • 问题修复

    • [修复] 定时任务设置 cancelInNoneNextTime: false 一次也不执行 #I3O3N0
    • [修复] SpareTime 自定义下次执行时间出现空异常 #I3O46X
    • [修复] MiniProfiler 设置为 false 时,数据库上下文提交拦截器未添加 #I3OAWX
    • [修复] [Consumes("application/x-www-form-urlencoded")]ModelQuery 配置同时配置导致空引用问题 #I3ODUR
    • [修复] 在 Grpc 中使用 jwt 授权出现空异常 #I3OW3I
  • 其他更改

    • [优化] 支持发布后代码精简配置,减少不必要的文件夹输出 #I3OAPF
    • [优化] 自动刷新 Token 机制,新增容错值处理,解决并发 Token 刷新失败问题 #I3OGYF
  • 文档变化

    • [新增] 粘土对象文档 #I3OG18
  • 问答答疑

    • [答疑] 动态 WebAPI 如何获取接收文件 #I3O29B
    • [答疑] 定时任务使用 Scope.CreateUow 引发的问题 #I3O2CD
    • [答疑] 单文件发布程序工作不正常 #I3O4D8
    • [答疑] 同时配置租户过滤器和软删除过滤器,最终的 sql 只生成了一种过滤条件 #I3OB0A
    • [答疑] HTTP 重定向 HTTPS 后跨域失效 #I3OB8R
    • [答疑] 在 PostgreSql 数据库使用 rep.FirstOrDefault(u => u.Id == UserId); 引起异常 #I3O5OF
    • [答疑] 定时任务有时能触发有时不能触发 #I3ORBE
  • 不做实现

    • [作废] 框架中的 swagger 是否有提供导出文档为 markdwon/word 的功能计划? #I3OL8O
    • [作废] 数据库实体父子继承,子类生成的 SQL 不一样 #I3NHU3
    • [作废] 支持第三方数据库 ORM #I3OXA3

v2.1.0 (已发布)

  • 新特性

    • [新增] 新增定时任务 ISpareTimeWorker 方式支持 [SpareTime("{配置路径}}] 方式 #I3NTUX
    • [新增] 定时任务支持异步委托 #I3NP96
    • [新增] 轻量级分布式连续 GUID 生成器 #I3NKLZ
    • [新增] ClayObject 模块,处理 ExpandoObjectIDictionary<string,object> 类型 #I3N3J4
    • [新增] Scoped.CreateUow(handler) 创建作用域并自动提交数据库更改方法 #I3NU3G
  • 突破性变化

    • [调整] 规范化结果接口 OnResponseStatusCodes 方法,新增 UnifyResultStatusCodesOptions 参数 #I3NDB9
    • [移除] 雪花 ID 实现代码 #I3NKLZ
  • 问题修复

    • [修复] Swagger 不能支持非 int 类型的枚举 #I3NQM8
    • [修复] 数据库线程池多线程并发问题 #I3NR4L
    • [修复] 自定义控制器路由后且为方法参数指定了 [ApiSeat] 后生成路由重复 #I3NRF6
  • 其他更改

    • [改进] 支持应用启动的时候迁移种子数据 #I3NH3M
  • 文档变化

    • [新增] 分布式 ID 生成文档 #I3B6CX
    • [新增] 新增模块化开发文档 #I3NSUS
    • [更新] 20.4 字符串拓展方式 > 错误ToAESDecrypt 写成了 ToToAESDecrypt #
  • 问答答疑

    • [答疑] 有关【定时任务/委托】的疑问 #I3N3EW
    • [答疑] 统一返回格式支持自定义 #I3NU1G
  • 不做实现

    • [作废] 期待 IEnumerableExtensions 扩展 OrderBy 函数来支持分页排序 #I3NOQ9

v2.0.0 (已发布)

  • 新特性

    • [新增] 控制台应用程序及 Worker Services 支持 #I3K4DG
    • [新增] 完整任务调度功能 #I3IRUX
    • [新增] Cron 表达式解析 #I3IQ9Y
    • [新增] 支持 Swagger 自定义配置 swagger.json 地址模板 #I3IHMX
    • [新增] 支持配置动态 WebApi 区域 #I3IJAZ
    • [新增] 远程请求新增支持传入服务提供器 IServiceProvider #I3IVBL
    • [新增] 全局配置选型 SupportPackageNamePrefixs 配置,支持配置包前缀 #I3K0SN
    • [新增] 应用启动时支持 referenceassembly 类型程序集扫描 #I3K0SN
    • [新增] 依赖注入 AOP 拦截获取方法真实特性 #I3LZBX
    • [新增] EFCore 手动 SaveChanges() 特性 #I3N01Y
    • [新增] 支持 Cors 跨域更多配置 #I3N2J0
  • 突破性变化

    • [重构] 完整任务调度功能 #I3IRUX
    • [重构] 日志模块功能 #I3J2K0
    • [重构] 模板引擎功能 #I3J46E
    • [重构] 底层 EFCoreRepository 仓储 #I3J6W5
    • [重构] sql 字符串拓展底层代码 #I3IVCE
    • [重构] 底层 SqlRepository 所有逻辑代码 #I3J6V6
    • [重构] 数据库实体拓展方法 #I3J609
    • [调整] 事件事件总线同步执行为异步方式执行 #I3J0WA
    • [移除] 框架底层 HttpContext.IsAjaxRequest() 拓展 #I3IVAA
    • [移除] ValidationTypes.Required 验证 #I3KR85
  • 问题修复

    • [修复] 关闭 InjectMiniProfiler 参数后内存缓存无效 #I3IHLR
    • [修复] 在多租户中调用 Tenant 属性出现偶然性数据库上下文被释放的情况 #I3IC70
    • [修复] Sql 代理中如果返回基元类型抛出不能将 object 转换成对应类型的异常 #I3IC84
    • [修复] 存储过程多返回值的时候,outputvalues 的 name 不是定义的 MSG 的 name,是 Msg 类型。 #I3IC7Y
    • [修复] PhoneNumber 手机号验证正则表达式错误 #I3ID10
    • [修复] 依赖注入 AOP 拦截无法捕获内部异常 #I3IGCC
    • [修复] 全局拦截标记异常已被处理后异常过滤器依然执行 #I3J463
    • [修复] 自定义全局异常拦截器不起作用 #I3K1SJ
    • [修复] 在 WorkerService 模式下,还是使用 WebHostEnvironment 来判断 Host 环境,会导致错误 #I3LCQY
    • [修复] 定时任务 DoOnce 抛空异常 bug #I3M0ZT
  • 其他更改

    • [改进] 启动时程序集扫描类型 #I3K0SN
    • [改进] App.GetConfig<>("key") 不支持获取单个值问题 #I3ILF1
    • [改进] UrlEncode 应该用 Uri.EscapeDataString() 而不是 HttpUtility.UrlEncode #I3ICTK
  • 文档变化

    • [新增] 定位任务、后台任务文档 #I3JHHG
    • [新增] 辅助角色服务文档 #I3K5GN
    • [更新] 动态 WebAPI、规范化文档、数据库上下文文档
  • 问答答疑

    • [答疑] 数据校验,自定义 ErrorMessage 无效问题 #I3ICL3
    • [答疑] 最新 issue 中新增的“新增常用的 JSON 序列化方法” 会导致 AOP 拦截异常 #I3I7VE
    • [答疑] Furion.DatabaseAccessor.PrivateEntityBase 中的 TenantId 数据类型设置为 object #I3IQV6
    • [答疑] 有关异常拦截和处理的疑问 #I3IUFZ
    • [答疑] DataValidation 在空值的情况下被忽略掉了#I3IWSM
    • [答疑] 日志文档没有更新 #I3J1DX
    • [答疑] 对于 webapi 简单类型参数,是否可以以 json 方式提交 #I3J18I
    • [答疑] IUnifyResultProvider 实现中如果 UnifyModel 的 type 不是范型会报错 #I3JBXF
    • [答疑] 如何模块化开发新功能? #I3J7ZZ
    • [答疑] 建议增加微服务中间件的集成 #I3JTZQ
    • [答疑] 二级虚拟目录部署的 swagger 的 MiniProfiler js 报错 #I3IWLR
  • 不做实现

    • [作废] 在请求审计日志中对贴有 DisableAuditing 特性的字段自动过滤 #I3DHAN

v1.19.0 (已发布)

  • 新特性

    • [新增] EFCore 5.0 支持 SqlServer 2005-2008 数据库 #I3HZZ6
    • [新增] Sql 高级代理支持模板替换了 #I3HHWU #I3HH2T
    • [新增] PBKDF2 加密 #I3HN7A
    • [新增] 常用的 JSON 操作方法 #I3HUYO
    • [新增] 所有解析服务的方法都支持传入 IServiceProvidier 参数 #I3HXEU
  • 突破性变化

    • [升级] .NET 5 SDK 至 5.0.5 版本
  • 问题修复

    • [修复] 远程请求 application/x-www-form-urlencoded 自动被转码了 #I3HDPC
    • [修复] ISqlDispatchProxy 调用带返回值的存储过程出错 #I3HISS
    • [修复] 多数据库工作单元异常无法回滚数据 #I3I2KN #I3HYN5
    • [修复] Serilog 日志生成太多文件 #I3I2PN
    • [修复] 1.18.0 版本数据库连接池存在连接泄漏问题 #I3I5KO
    • [修复] Sqlite 提示事务已完成异常 #I3I9F2
  • 其他更改

    • [改进] 视图模板功能,默认支持可枚举泛型类型 #I3GYEE
    • [改进] 开发阶段 MiniProfiler 打印数据库相关信息 #I3I8VQ
    • [改进] EFCore 5.0 未提供 Sqlite 数据库 DataAdapter 的支持 #I3I9FC
  • 文档变化

    • [更新] 数据库上下文、多租户、仓储、日志、序列化等文档。
  • 问答答疑

    • [答疑] 建议 MVC 模式下增加 Furion 的功能 #I3GY4R
    • [答疑] 数据库关联操作 #I3H5QP
    • [答疑] 1.17.5 版本 suagger 无法生成 swagger.json #I3HGPZ
    • [答疑] Serilog 扩展+dll 启动与 swagger 的 MiniProfiler 冲突 #I3HWJM
    • [答疑] Sql 高级代理返回 DataTable 时,结果为空取不到记录 #I3HUWG
    • [答疑] Task.Run 操作数据库问题 #I3HZ9D
  • 不做实现


v1.18.0 (已发布)

  • 新特性

    • [新增] Oracle 11 版本支持 #I3EVL5
    • [新增] Mysql 官方包 MySql.EntityFrameworkCore 支持 #I3E6J1
    • [新增] 全局配置 WebApi 参数 [FromQury]#I3EFYJ
    • [新增] 公开框架底层依赖注入扫描注册拓展 services.AddRisterTypes(types) #I3EIV3
    • [新增] SqlSugar 工作单元特性 #I3EJO5
  • 突破性变化

  • 问题修复

    • [修复] 数据库上下文池一旦有上下文操作失败还数据库上下文出现二次提交数据库的问题 #I3EIJJ
    • [修复] 不同数据库命令参数前缀都添加了 @ 处理 #I3EBJP
    • [修复] 尝试修复事件总线线程安全问题 #I3EGSB #PR236
    • [修复] HttpContextExtensionsSignoutToSwagger 方法无效 #I3EHNQ
    • [修复] 如果动态 WebApi 贴了 [ApiController] 特性后,导致路由参数重复生成 #I3EOQQ
    • [修复] 如果没有任何 webapi 控制器时,文档报错 #I3EVLB
    • [修复] 依赖注入泛型类型注册失败 #I3EX66
  • 其他更改

    • [调整] SqlSugar 拓展库仓储 Context 属性类型未 SqlSugarClient #I3EHXA
    • [改进] 刷新 Token 黑名单 Redis 中分组 #I3EQWO
    • [改进] 远程请求在请求拦截次发起二次请求导致异常问题 #I3ER71
    • [改进] 多租户默认缓存改为分布式缓存 #I3EXEU
  • 文档变化

    • [更新] 数据库操作文档 #I3E84X
  • 问答答疑

    • [答疑] 如何方便的获取 IDynamicApiController API 产生的 url 和 谓词 #I3ED17
    • [答疑] Code First -执行命令 Add-Migration 遇到了问题 #I3EHD0
    • [答疑] tools v1.16.0 无法生成实体,一直提示 Missing required argument <PROVIDER>. #I3ENZ8
    • [答疑] Authorize 的 Logout 按钮,无法实时请空 token#I3EOF9
  • 不做实现


v1.17.0 (已发布)

  • 新特性

    • [新增] 动态 WebAPI 支持继承基类配置特性 #I3D5PX
    • [新增] 远程请求支持 multipart/form-data 内容类型处理 #I3D7KG
    • [新增] 字符串加密拓展 #I3DHBW
    • [新增] 新增远程请求可直接下载返回值内容转为 string 类型 #I3DIGR
    • [新增] 远程请求地址支持模板引擎 #I3D5Y8
    • [新增] [DataValidation] 错误消息支持 string.Format 操作 #I3E08W
    • [新增] 远程请求 HttpRequestMessage 拓展方法 AppendQueries() 追加更多 query 参数拓展 #I3E3DI
  • 突破性变化

    • [调整] IRepository.AsAsyncEnumerable() 返回值 #I3DIQ1,调整为:rep.AsQueryable().ToListAsync()
  • 问题修复

    • [修复] 数据验证失败后也打印了成功的字段 #I3CVBS
    • [修复] 远程请求配置 contentTypeapplication/x-www-form-urlencoded 无效问题#I3CWBS
    • [修复] 远程请求无法打印完整的请求地址,比如配置了 HttpClient 之后 #I3CY42
    • [修复] 程序启动时排除默认配置文件算法不对,应该采用正则表达式匹配 #I3D9E7
    • [修复] 远程请求成功请求拦截不生效 #I3DOE4
    • [修复] Dapper 拓展数据库切换为 oracle 时,系统找不到指定的文件 Oracle.ManagedDataAccess.Core #I3DYM3
  • 其他更改

    • [改进] 获取 JWT token 信息支持配置 Token 前缀,如 Bearer #I3DJIV
    • [改进] 刷新 Token 黑名单存储方式,将内存缓存调整为分布式缓存 #I3DPBR
  • 文档变化

    • [调整] 远程请求文档 #I3CPJO
  • 问答答疑

    • [答疑] LinqExpression.And 没有 2 个参数的方法 #I3CXKZ
    • [答疑] 异常信息 如何记录到数据库中:) #I3DDGO
    • [答疑] 无键实体选用 IEntityNotKey #I3DWRF
    • [答疑] 根据主键删除一条记录不成功,无错误信息 #I3DWWF
    • [答疑] 如何自定义接口返回格式 #I3DZN6
    • [答疑] DynamicApiController 如何在运行时决定是否公开一个 Action #I3D5UL
    • [答疑] Furion.DatabaseAccessor.DbHelpers 方法:ConvertToDbParameters 是不是应该过滤掉贴 NotMapped 的特性 #I3E2XS
  • 不做实现

    • [废弃] 框架是否提供 ISoftDelete 类似接口 #I3CP93

v1.16.0 (已发布)

  • 新特性

    • [新增] IDGenerator 雪花 ID 算法,感谢 idgenerator 作者提交 PR #PR204 #I3B60S
    • [新增] DbContext 刷新多租户缓存拓展方法 #I39N5U
    • [新增] 自定义配置单个控制器名称规范,如小写路由 #I3A5XL
    • [新增] 获取当前选择区域语言方法 #I3BSDH
  • 突破性变化

    • [升级] .NET 5 SDK 至 5.0.4 版本 #I3ASTL
    • [重构] 远程请求所有功能 #I2LB7M
    • [重构] JSON 序列化功能,提供统一的抽象接口,方便自由替换 JSON#I39GT9
    • [重构] 验证失败返回消息模型及规范化接口验证参数 #I3AFQW
    • [优化] 插件式开发热插拔功能,实现动态加载卸载 #PR200, 感谢 @SamWangCoder
    • [移除] 移除 JsonSerializerUtility 静态类及移除属性大写序列化拓展配置 #I3AFRJ
  • 问题修复

    • [修复] MVC 模式下不支持验证自定义验证逻辑 #I39LM5
    • [修复] 验证数值类型正则表达式不支持负数 bug #I39YUV
    • [修复] 框架启动时无法加载未被引用的程序集 bug #I3A3Z4
    • [修复] EFCoreRepository.IsAttached() 方法判断错误 bug #I3A824
    • [修复] 动态API 驼峰显示配置无效 bug #I3AF32
    • [修复] cli.ps1 不支持新版本 EFCore bug #I3APO9
    • [修复] EFCore 实体配置 [Table] 特性无效 bug #I3BAYH
    • [修复] 动态 WebAPI CheckIsSplitCamelCase bug #I3BLKX
    • [修复] 修复动态 WebAPI 配置保留 Action 的 Async 后缀无效问题 #I3C3DA
    • [修复] JWT Token 刷新后旧的刷新 Token 依旧可用 bug #I3C8ZH
    • [修复] 多语言 Razor 视图变量多语言乱码问题 #I3CBMU
  • 其他更改

    • [优化] 默认序列化提供器 System.Text.Json 反序列化字符串时区分大小写问题 #I3BSXV
    • [优化] 优化 MessageCenter 性能问题 #I39PRR
    • [优化] 数据库上下文池小性能优化
  • 文档变化

    • [新增] Docker 环境下自动化部署 #PR209
    • [新增] JSON 序列化 文档 #I3B6D8
    • [更新] 跨域、安全授权、即时通信文档、多语言、规范化文档
  • 问答答疑

    • [答疑] Furion.Extras.DatabaseAccessor.SqlSugar 配置多个数据库打印 SQL 语句问题 #I39PDC
    • [答疑] ORACLE 数据库多租户模式下返回值为指定类型时系统卡死 #I39RNH
    • [答疑] 假删除指向异常 #I39XZA
    • [答疑] Furion 多语言配置节是放在 AppSettings 里面还是外面呢? #I3A4SB
    • [答疑] 没找到数据库上下文 #I3A5HS
    • [答疑]QQ 交流群吗? #I3AAM7
    • [答疑] Vue3 环境下配置 SignalR 跨域出错 #I3ALQ7
    • [答疑] 设置 Swagger 参数非必填 #I3AT02
    • [答疑] EFCore 调用 Insert 时报 Unknown column 'Discriminator' in 'field list' 异常 #I3B2LC
    • [答疑] 逆向 mysql 数据库时 cli 出现错误 #I3B64F
    • [答疑] Sql 高级代理使用过程中 DateTime 类型的参数序列化失败 #I3AZXK
    • [答疑] 使用 Mysql 执行 Add-Migration 报错 #I3B8EW
    • [答疑] Saas 多租户模式-独立 Database 模式下无法获取 Tenant, 导致无法自动切换的问题#I3AVXU
    • [答疑] 如何自定义 WebAPI 统一结果模型 #I3BBYW #I3BBYV
    • [答疑]Web.Entry 项目新建了一个 Controller,多了未知方法 #I3BKH5
    • [答疑] AOP 拦截如何解析服务 #I3BUM3
    • [答疑] 动态 WebAPI 返回参数被省略 #I3C2XR
    • [答疑] 如何设置某一个接口响应数据不自动转小写,按原始字段名返回 #I38L9B
    • [答疑] code first 如何配置自动迁移 #I3CCR0
    • [答疑] webapi 混合授权如何区分不同系统 #I3CJCY
    • [答疑] EFCore 不支持递归无限级遍历关系 #I3CET9
  • 不做实现

    • [废弃] 建议 EFCore 可配置外键关系导航问题 #I3994X
    • [废弃] 建议将 EFCore 剥离出来,作为插件的形式提供。这样可以选择自己喜欢的 ORM #I3ABNX
    • [废弃] 事件总线能否提供返回值 #I3AWL6
    • [废弃] Sql 模板能仿照 Mybatis 一样加各种标签吗?#I3ASRS
    • [废弃] EFCore 更新或排除更新指定列支持传入 DTO 模型 #I3AS5K
    • [废弃] 新增 UnitOfWork 事务完成事件 #I3BRMI

v1.15.0 (已发布)

  • 新特性

    • [新增] 跳过特定实体数据库操作监听特性 #I386LB
    • [新增] IEntityChangedListener 增加对 OldEntity 的支持 #I385X2
    • [新增] 实时通信自动配置集线器拓展及特性 #I387QX
    • [新增] Mapster 拓展支持 IMapper 依赖注入方式 #I38C7C
    • [新增] [AppDbContext] 特性默认构造函数 #I38J97
    • [新增] UnifyContext.GetExceptionMetadata(context) 返回错误码支持 #I38ONX
  • 突破性变化

  • 问题修复

    • [修复] 多次循环中调用 Db.GetNewDbContext() 还是获取到同一个对象 #I38NNP
    • [修复] Swagger 过滤掉 object 类型属性问题 #I38FHL
    • [修复] 同一类不支持多继承 IEntityChangedListener 问题 #I38UQJ
    • [修复] 自定义序列化属性名称导致验证失败属性不匹配问题 #I38W8Z
  • 其他更改

    • [优化] 代码不规范命名导致开发者阅读代码时产生歧义
  • 文档变化

    • [新增] FluentValidation 集成文档 #I38IOT
  • 问答答疑

    • [答疑] Furion 框架版本向下兼容问题 #I38WMZ
  • 不做实现

    • [废弃] 建议 SqlSugar 添加动态切换数据库功能 #I38G4M
    • [废弃] 建议 MessageCenter 采用 Channel 实现 #I38BP8
    • [废弃] 建议接口文档整合 Knife4jUI 或 Redoc #I38S70

v1.14.0(已发布)

  • 新特性

    • [新增] EFCore 5.0 的 Oracle 数据库支持 #I37Z8E
    • [新增] 控制是否在开发环境下显示数据库连接信息 #I37YQ2
    • [新增] [NonUnify] 支持在类中贴此特性 #I359Q6
    • [新增] 网络请求 字符串 HttpClient 拦截器 #I35F3E
    • [新增] HttpContextHttpRequest 获取远程地址拓展 #I3688Z
    • [新增] services.AddMvcFilter<> 添加 Mvc 过滤器拓展 #I368BH
  • 突破性变化

    • [升级] 框架依赖的 .NET 5 SDK 至最新版 5.0.3 #I37YQQ
    • [升级] Swashbuckle.AspNetCore 组件包到 6.0.x 版本 #I37EZK
    • [移除] Furion 框架 JWT 拓展类,只在 Furion.Extras.Authentication.JwtBearer 中保留 #I35D59
  • 问题修复

    • [修复] 传入错误 JWT Token 字符串导致自动刷新 Token 出现字符串边界值异常 bug #I34ZE5
    • [修复] 瞬时作用域数据库上下文也会自动加入工作单元导致写日志时连锁异常 bug #I37WTV
  • 其他更改

    • [优化] 获取系统环境参数的性能 #I36SR5
    • [优化] Furion 底层添加 Mvc 过滤器代码 #I36SKA
    • [优化] 添加默认 Json 序列化时间默认时间格式 #I36SL0
    • [升级] 升级 SqlSugar 拓展包到 5.0.2.6 版本 #I36SIG
  • 文档变化

    • [新增] 数据库入门文档 #I37Z8S
    • [新增] 更新日志文档 #I36PI0
    • [新增] 请求审计日志、执行 Sql 更新日志文档 #I36PIK
    • [新增] 前端使用 axios 跨域配置文档 #I36PIT
    • [新增] App 静态类获取应用、环境更多信息数据 #I36SOV
    • [新增] 英文版 README.md 介绍 #I37QHP
  • 问答答疑

  • 不做实现

    • [废弃] 多语言资源文件自动创建 #I35AA4
    • [废弃] 建议多语言加上维吾尔语支持 #I37X1L

v1.13.0(已发布)

  • 新特性

    • [新增] 多语言功能及拓展 #I2DOCL
    • [新增] 事件总线功能及消息中心 #I23BKN
    • [新增] Swagger 分组显示隐藏配置 #I2AHH8
    • [新增] Furion.Extras.Logging.Serilog 拓展插件 #I2AAN8
    • [新增] cli.ps 支持 -Namespace 命名空间指定 #I2A175
    • [新增] Swagger 规范化化文档授权失效后自动取消授权锁 #I2AIWC
    • [新增] Request.Body 支持重复读功能,主要解决微信 SDK 问题 #I2AMG0
    • [新增] 网络请求功能及文档 #I2APGJ
    • [新增] SqlSugar 拓展包支持打印 sqlMiniProfiler#I2ASLS
    • [新增] Furion.Extras.DatabaseAccesssor.Dapper 拓展插件 #I2ASYA
    • [新增] Furion.Extras.DatabaseAccessor.PetaPoco 拓展插件 #I2AUGA
    • [新增] 网络请求字符串拓展方法 #I2CPQ0
    • [新增] SqlSugar 拓展新增 PagedList 拓展 #I2CW99
    • [新增] 远程请求支持参数特性验证 #I2CX5L
    • [新增] App.User 获取当前授权用户信息便捷方法 #I2CZLO
    • [新增] 规范化文档可配置功能,支持 appsettings.json 配置 #I2D1K9
    • [新增] 远程请求拦截器添加方法和方法参数 #I2D2CM
    • [新增] 远程请求出错返回默认值支持 #I2D44M
    • [新增] 远程请求 body 参数序列化支持设置 PropertyNamingPolicy #I2D685
    • [新增] 远程服务接口客户端配置 #I2D7PS
    • [新增] AddInjectUseInject 允许自定义 SecurityDefinitionsSwaggerUI #I2DIMG
    • [新增] [SecurityDefine] 默认构造函数 #I2DNXT
    • [新增] AspectDispatchProxy 动态代理类 #I2DO6I
    • [新增] [QueryParameters] 特性,支持一键将 Action 参数添加 [FromQuery] 特性 #I2G8TF
    • [新增] 动态日志配置及拓展方法 #I2GDGD
    • [新增] WebApi 请求谓词默认规则配置功能 #I2M70X
  • 突破性变化

    • [升级] .NET 5 SDK 到 .NET 5.0.2 版本 #I2D0PZ
    • [调整] 框架内所有拓展类命名空间,全部迁移到 Furion.模块.Extensions#I2AH54
    • [调整] Swagger 记住授权存储方式,替换 Session 存储方式为 LocalStorage 方式 #I2AKUA
    • [调整] Furion 框架包描述文件,减少框架体积 #I2APAU
    • [调整] App.CanBeScanTypesApp.EffectiveTypes #I2B0ZR
    • [调整] App.ServiceProvider 属性并移除 App.GetDuplicateXXX 方法 #I2CYZE
    • [调整] Db.GetDuplicateDbContextDb.GetNewDbContext #I2CZ04
    • [调整] Db.GetSqlDispatchProxyDb.GetSqlProxy #I2DO9T
    • [重构] Aop 服务拦截器,支持异步、同步两种方式 #I2B9HQ
    • [重构] 网络请求所有功能 #I2BMR7
  • 问题修复

    • [修复] Swagger 规范化化结果不一致 bug #I2ACF3
    • [修复] 数据库新增或更新忽略空值操作方法报空异常 #I2AB6C
    • [修复] Startup.cs Aop 全局拦截无效 #I2A7T2
    • [修复] Token 过期后自动刷新 Token 无法获取最新的用户信息 bug #I2AWQI
    • [修复] [ApiDescriptionSettings(Tag="xx")] 导致 swagger.json 报错 bug #I2B47R
    • [修复] Mysql sql 数据库查询结果 tinyint 类型转换出错 bug #I2BEBM
    • [修复] 规范化结果多次包裹类型 bug #I2BHHZ
    • [修复] 动态 Api 基元类型数组问题 #I2BMS5
    • [修复] sql 查询枚举类型转换异常 bug #I2BS2Y
    • [修复] string.SqlQuerizeAsync<T1>() 拓展返回错误 bug #I2BSTS
    • [修复] 动态 Api 子类重写父类方法并取别名后 Swagger 异常 bug #I2C9VP
    • [修复] 网络请求 application/json 序列化大小写问题 #I2CRJC
    • [修复] 多数据库定位器实体嵌套关联 bug #I2CVN0
    • [修复] 跨域响应头设置无效 bug #I2CW5T
    • [修复] 远程网络请求代理打印到 MiniProfiler bug #I2CZBC
    • [修复] 远程请求响应拦截器 bug #I2D4DG
    • [修复] SqlSugar 框架 AsQueryable() 一直追加参数 #I2DH1D
    • [修复] 自动刷新 Token 空异常 bug #I2DO29
    • [修复] 生成 JWT Token 不传过期时间出现验证 401 bug #I2DO8L
    • [修复] AppStartup 排序无效 #I2DVD2
    • [修复] 未启用多语言服务时友好异常和验证出现空异常 #I2ECUJ
    • [修复] 数据校验字母和数字组合无法匹配 bug #I2EF2Q
    • [修复] 数据校验手机或固话无效 bug #I2M5IZ
    • [修复] Dapper 拓展解析 SqlConnection 异常 bug #I2M5P2
    • [修复] 开启多语言后,EF 迁移异常 bug #I2M7DT
    • [修复] IEntityTypeBuilder 不支持多重继承 bug #I2PAOD
    • [修复] JwtHandler 设置自动刷新后,匿名访问无法通过 bug #I2SDOX
    • [修复] Dapper 拓展中 SqlServer 数据库获取连接对象类型 bug #PR159
  • 其他更改

    • [优化] 移除 Sql 查询结果映射检查 [NotMapper] 特性机制 #I34XD0
    • [优化] 依赖注入时排除 IDynamicApiController 接口 #I2ECTG
    • [优化] MD5 加密性能 #PR158
  • 文档变化

    • [重构] 文档首页 #I34XBR
    • [新增] 网络请求文档 #I2APGJ
    • [新增] 多语言文档 #I2DOCL
    • [新增] 文档全文搜索引擎 #I34XAW
    • [新增] 全局静态类类型 #I34XB4
    • [新增] 框架可配置选项文档 #I34XB9
    • [新增] 事件总线文档 #I34XBI
    • [新增] 数据加解密文档 #I34XC0
    • [新增] 贡献指南文档 #I34XC8
    • [新增] HttpContext文件上传下载 博客文章 #I34XCB
    • [其他] 文档小调整,小优化
  • 问答答疑

    • [答疑] 跨域设置无效 #I2ASNJ
    • [答疑] MVC 视图无效,原因是 .cshtml 文件没有设置为 内容 #I2AXUU
    • [答疑] Sql 操作可以实现事务吗?#I2B0NX
    • [答疑] IRepository 操作数据库会打开多次数据库连接 #I2BB7B
    • [答疑] 如何进入自定义 AppAuthorizeHandler 断点 #I2BGXY
    • [答疑] SqlSugar 注入问题 #I2C2AQ
    • [答疑] 建议增加 API 签名验证,时效验证 #I2C6ET
    • [答疑] 多数据库多租户同时使用 Add-Migration 报错 #I2CEHS
    • [答疑] ISqlSugarRepository 没有 Getxxx 方法 #I2CJLZ
    • [答疑] cli.ps1 如何将 sql 里的表导出成 model#I2CSUL
    • [答疑] 手动修改 Swagger 终结点路径无效 #I2D608
    • [答疑] DefaultDbContext 不能识别 #I2DCZX
    • [答疑] 各分层项目 Startup.cs 支持 Configuration #I2DDUP
    • [答疑] Aop 无法拦截,无效 #I2DEY8
    • [答疑] mysql 执行 Add-Migration 报错 #I2DSB8\
    • [答疑] Entity 创建时间和是否删除添加默认值 #I2E04H
    • [答疑] swagger 中多个 servers 设置 #I2E0IF
    • [答疑] 全局筛选器 没有执行 #I2E5R4
    • [答疑] 多数据库定位器疑问 #I2E77T
    • [答疑] cli.ps 逆向工程 Mysql 数据库报错 #I2E7I5
    • [答疑] Swagger 开发环境 applicationsettings.json 中文乱码 #I2EAG1
    • [答疑] 增加指定路径程序集映射 #I2EEO2
    • [答疑] 动态编译 cs 脚本文件 #I2EH66
    • [答疑] 自定义中间件,返回的错误没有规范化结果 #I2NV8S
    • [答疑] Swagger 循环引用设置生成文档层级无效 #I2PLQQ
    • [答疑] 配置文件支持 yaml 文件吗? #I2TJ3N
    • [答疑] 修改数据库未 mysql 执行 Add-Migration 报错 #I2VR64
    • [答疑] 多数据库使用定位器时报错 #I2VR8F
    • [答疑] Migration To Oracle 异常 #I2WBYQ
    • [答疑] 开发时显示 Swagger,上线时关闭 Swagger,这需要怎么配置 #I2WOYV
    • [答疑] 兼容 Mvc 复杂验证没有试验成功 #I2X3GV
    • [答疑] Aop 能不能支持无接口的类 #I2X8AS
    • [答疑] 关于 JWT Token 自动刷新问题 #I2YD4K
    • [答疑] 能否增加一个拓展的 Entity,增加一些拓展的属性 #I2YDKT
    • [答疑] Furion 无法还原包,使用Nuget 下载和通过最新的的脚手架下载都提示这个问题 #I30446
    • [答疑] 复杂校验与特性验证不能并行 #I3046U
  • 不做实现

    • [废弃] 引入 Webhook 机制 #I2A3I0
    • [废弃] 增加 blog 存储服务 #I2AMBP
    • [废弃] Blazor Server 环境下 EF 的 DbContext 多线程问题 #I2AMD2
    • [废弃] 希望实现工作单元操作接口(IUnitOfWork)#I2AOR5
    • [废弃] 建议新增 string.ToPagedListAsync() 操作 #I2BZ3Z
    • [废弃] 建议新增 GraphQLOData 功能 #I2C9EH
    • [废弃] 迫切期望支持 CAP 分布式事务 #I2CBRF
    • [废弃] 如何让某个方法或实体变化后,不被 SavingChangesEvent 等拦截 #I2CEM9
    • [废弃] 建议日志封装增加更多拓展,比如:自定义保存日志文件 #I2CW8V
    • [废弃]SqlSugar 的支持,增加 Nuget 脚手架 #I2D91U
    • [废弃] 使用 Middleware 实现反向代理 #I2DKM1
    • [废弃] 支持配置多个 Aop 功能 #I2E6Z2
    • [废弃] 是否计划开发类似网关的功能 #I2PD1L
    • [废弃] waring CS8002: 引用程序集 Furion 没有强名称 #I2WDN2
    • [废弃] Oracle 数据库驱动集成 Devart.Data.Oracle.Entity.EFCore #I2XJIU

v1.7.0(已发布)

  • 新特性

    • [新增] Furion.Extras.ObjectMapper.Mapster 拓展包 #I29LSJ
    • [新增] Furion.Extras.Logging.Serilog 拓展包 #I2AAN8
    • [新增] Furion.Extras.Web.HttpContext 拓展包 #I29LSM
    • [新增] 内置 Token 刷新机制支持 #I29K57
    • [新增] 动态数据库上下文,支持运行时执行 OnModelCreating #I28UDT
    • [新增] 支持依赖注入排除指定接口 #I29693
    • [新增] 规范化结果返回时间戳字段 #I29697
    • [新增] 基础 CURD 父类操作例子 #I296SR
    • [新增] sql.Change("定位器完整类型名称") 支持 #I29LAB
    • [新增] UpdateIncludeUpdateExclude 忽略空参数支持 #I29VUG
    • [新增] 数据库上下文内置假删除查询过滤器支持 #I29Y2R
    • [新增] 忽略空值排除默认时间格式 #I29VUV
    • [升级] MiniProfiler 组件 #I297R9
  • 突破性变化

    • [调整] AppAuthorizeHandler 授权管道为异步处理 #I29MD9
    • [调整] Swagger 默认启用 JWT 授权支持 #I29LI4
    • [调整] HttpContextUtilities 名称改为 HttpContextLocal #I29KQE
    • [调整] UnifyResultContext 名称改为 UnifyContext #I29LLZ
    • [调整] 只有执行迁移命令才扫描种子数据 #I29E6P
    • [调整] 规范化结果 Successed 属性名为 Succeeded #I29NMV
    • [移除] Mapster 对象组件,采用提供拓展方式 #I29D2M
    • [移除] CacheManager 拓展类 #I29LU1
    • [重构] SaveChanges 拦截器 #I292LO
  • 问题修复

    • [修复] 未注册的数据库上下文也被引用全局查询拦截器 bug #I29ZXJ
    • [修复] 手动返回 BadObjectResultValidationProblemDetails 结果类型时规范化结果失效 bug #I29ZU9
    • [修复] 动态 WebApi KeepNameKeepVerbSplitCamelCase 无效 bug #I29X90
    • [修复] Sql代理 返回 元组 类型出错 bug #I29SMV
    • [修复] 401,403 状态码规范化返回值属性变大写 bug #I29M8Y
    • [修复] HttpContext 空异常 bug #I29LU4
    • [修复] 接口无返回值没有应用规范化结果 bug #I29GT7
    • [修复] 前端 Less 配置文件导致主机启动失败 bug #I29E7P
    • [修复] 执行 sql 结果转泛型后属性重复赋值 bug #I29BUO
    • [修复] Swagger 关闭 MiniProfiler 之后 组中组 失效 #I29789
    • [修复] 未启用规范化结果时异常返回 System.Object 字符 #I2969A
    • [修复] 正数数据验证 0 也验证通过 bug #I2955T
    • [修复] 非泛型类集成泛型接口依赖注入 bug #I294YT
    • [修复] Swagger 不支持 new 覆盖父类的 bug #I28Z1A
    • [修复] JsonSerializerUtility 没有公开 bug #I28WMI
    • [修复] SqlSugar 拓展查询泛型类型注册异常 bug #I28VMT
    • [修复] Furion Tools 不支持生成不同命名空间的实体 bug #I2A175
    • [修复] 全局拦截器无效 bug #I2A7T2
    • [修复] 新增或更新忽略空值空异常 bug #I2AB6C
  • 其他更改

    • [优化] Token 生成加密算法 #I29KIH
  • 文档变化

    • [新增] 日志文档 #I28Y9D
    • [调整] 数据库上下文、实体拦截器、配置、一分钟入门等等文档
  • 问答答疑

    • [问答] Swagger 如何实现授权访问 #I294F2
    • [问答] 如何实现多个数据库多对多实体配置 #I29G6S
    • [问答] 动态 WebApi 支持文件上传吗 #I29R5E
    • [疑问] 多个数据库上下文无法生成迁移代码 #I2A6II
  • 不做实现

    • [废弃] 实现 BuildChange 传入表名 #I292SN
    • [废弃] 执行数据库操作结果不支持属性忽略大小写赋值 #I29DRQ
    • [废弃] 引入 Webhook 机制 #I2A3I0

v1.4.0(已发布)

  • 新特性

    • [新增] Furion 支持二级虚拟目录部署功能 #I28B77
    • [新增] Furion.Template.RazorWithWebApi 脚手架 #I28QGI
    • [新增] Furion.Template.BlazorWithWebApi 脚手架 #I27Z3O
    • [新增] EFCore 时态查询拓展 #I28AJ
    • [新增] [AppDbContext(连接字符串,数据库类型)] 配置支持 #I28QTB
    • [新增] DateTimeOffsetDateTime 拓展方法 #I27MQA
    • [新增] ValidationTypes 验证正则表达式智能提示 #I2801V
    • [新增] ValiationTypes.WordWithNumber 验证 #I2805
    • [新增] 获取客户端和服务端 IP 地址 #I28QV9
  • 突破性变化

    • [升级] .NET 5.0 版本至 .NET 5.0.1 版本 #I28QU
    • [重构] 视图引擎功能,优化不规范命名和新增字符串模板编译 #I28G0S
    • [重构] 数据库实体查找算法,并优化性能 #I28QUQ
    • [优化] 应用启动初始化性能和数据库第一次自动配置 DbSet 性能
  • 问题修复

    • [修复] 多数据库上下文配置定位器后实体无法正确生成 bug #I2888L
    • [修复] 多租户数据库上下文实体生成 bug #I2891G
    • [修复] 对象验证失败提示消息没有应用 JSON 大小写配置 bug #I27UTX
    • [修复] 仓储 InsertUpdate 方法指定 ignoreNullValues 无效 bug #I27UN6
    • [修复] Controller 派生类如果贴了 [Route] 特性后出现在 Swagger 中 bug #I27TN7
    • [修复] SqlScalar 执行 sql 返回 Nullable 类型出现转换失败 bug #I27S2N
    • [修复] [UnitOfWork] 特性异常 bug #I27MLM
    • [修复] sql 静态执行方式和 sql 高级代理无法监听数据库连接状态 bug #I27M4F
    • [修复] 修复更换 Json 序列化库无效 bug,如替换为 Microsoft.AspNetCore.Mvc.NewtonsoftJson #I27M43
    • [修复] Furion Tools 工具生成模型 bug #I27XI5
    • [修复] 软删除没有生效 bug #I2804I
    • [修复] Furion Tools 识别带多个 \\ 的连接字符串识别 bug #I280TS#PR91
    • [修复] Furion Tools 无法取消生成 bug #I2816M
    • [修复] DateTimeOffset 转本地时间差 8 小时 bug #I28BA9
    • [修复] 启用 bundle js&css 压缩后启动异常 bug #I28KR
    • [修复] ValidationTypes.Required 无效 bug #PR98
    • [修复] 规范化结果OnValidateFailed 参数名拼写错误 bug #PR93#PR92
    • [修复] 授权管道验证失败还显示结果 bug #PR89
  • 其他更改

    • [更新] README.md 友情连接地址 #PR88
    • [更新] 模板脚手架源码,添加 EFCore Tools#PR87
    • [更新] README.md Nuget 图标 #PR85
    • [废弃]List<T>DateTable #PR97
  • 文档变化

    • [新增] 视图引擎模板文档 #I27ZVA
    • [新增] EFCore 时态查询文档 #I28AJ, DOC
    • [更新] 仓储文档书写纰漏 bug #PR90
    • [更新] 选项文档错误 bug #PR86
    • [更新] 实体数据监听器 文档书写错误 bug #PR83
    • [更新] 数据库上下文、多数据库、脚手架等文档
  • 问答答疑

    • [建议] 希望 api 返回的值自动将 null 转为 '' 或 [][#I286IJ](https://gitee.com/dotnetchina/Furion/issues/I286IJ),【已关闭】
    • [建议] 添加网关功能 #I27TP7,【已关闭】
    • [建议] 新增 SqlQuery<T> 获取单条记录方法 #I28M1V,【已关闭】
    • [建议] 希望可以提供集成 Serilog 例子 #I282J4,【已关闭】
    • [疑问] 如何通过特性配置唯一约束 #I2891L,【已关闭】
    • [疑问] 怎么读取 appsettings.json 数组 #I27WU,【已关闭】
    • [疑问] IRepository<TEntity> 出现空异常 #I281IE,【已关闭】
    • [疑问] 规范化接口问题问题 #I28NMZ,【已关闭】
    • [疑问] 统一返回值模型中 OnResponseStatusCodes 未执行 #I28NNL,【已关闭】

v1.2.0(已发布)

  • 新特性

    • [新增] 雪花算法 #I26OXG, #PR78
    • [新增] [AppDbContext] 配置数据库提供器支持 #I27G3T
    • [新增] 实体表数据更改监听接口 IEntityDataChangedListener #I278DD, #I278LQ
    • [新增] 全局服务接口 AOP 拦截功能 #I278CP
    • [新增] 定位器仓储 IDbRepository<TDbContextLocator> #I276Q3
    • [新增] 数据库操作 InsertOrUpdate 支持排除空字符串功能 #I272OG
    • [新增] 数据库操作 UpdateIncludeUpdateExclude 匿名对象支持 #I271X0
    • [新增] 数据验证传入空对象跳过验证支持 #I273R4
    • [新增] 应用启动时支持排除特定配置文件自动加载 #I26U0A
    • [新增] 单个实体表名前缀支持 #I26LX0
    • [新增] MySql 数据库自动配置默认版本号 #I26XQ6
    • [优化] 授权处理程序代码
  • 突破性变化

    • [新增] 实体表数据更改监听接口 IEntityDataChangedListener #I278DD, #I278LQ
    • [新增] 全局服务接口 AOP 拦截功能 #I278CP
    • [新增] 雪花算法 #I26OXG, #PR78
  • 问题修复

    • [修复] 视图引擎加载外部程序集出错 bug
    • [修复] 依赖注入代理接口报空对象异常 bug
    • [修复] EFCore 取消附加实体出错 bug
    • [修复] 数据库仓储在非 Web 请求下出现空异常 bug
    • [修复] 多个授权策略共存问题出现无效 bug
    • [修复] 友好异常 Oop.Oh 不支持普通方法 bug
    • [修复] 获取多租户对象时数据库上下文出现作用域验证失败 bug
    • [修复] 工作单元不支持 Sql代理 拦截 bug #I27GST
  • 其他更改

  • 文档变化


v1.1.0(已发布)

  • 新特性

    • [新增] Db.GetDbContext() 获取默认数据库上下文方法
    • [新增] HttpContextUtility.GetCurrentHttpContext() 获取全局 HttpContext 上下文
    • [新增] App.GetRequiredService<> 解析服务方法
    • [新增] object.GetService<> 对象拓展方法
    • [新增] 策略授权 PolicyPipeline 基类方法,支持多重判断授权
    • [新增] JWTEncryption.ValidateJwtBearerToken 手动验证静态方法
    • [新增] 全局数据库上下文 InsertOrUpdateIgnoreNullValuesEnabledEntityStateTracked 全局配置
    • [新增] Swagger Jwt授权 全局授权参数 #I26GLR
    • [新增] InsertOrUpdate 支持自定义判断条件功能 #I269Q1
    • [新增] 字符串字段小写命名支持 #I2695D
    • [新增] 字符串文本对比功能 #I268LE
    • [新增] 全局异常特性消息功能 #I2662O
    • [新增] InsertUpdate 数据库忽略空值功能 #I264Q4
  • 突破性变化

    • [调整] Fur 项目名为 Furion
    • [调整] Db.GetRequestDbContext<>() 命名为 Db.GetDbContext<>()
    • [调整] Db.GetDbContext<>() 命名为 Db.GetDuplicateDbContext<>()
    • [重构] App.GetService<> 解析服务的底层逻辑,大大提高了解析服务的性能
    • [重构] 授权核心代码,保持和微软一致的授权规范 #I26DCB
    • [移除] App.GetRequestService<> 方法
    • [移除] ValidateJwtBearer Jwt 授权方法,无需手动判断了
  • 问题修复

    • [修复] Furion 官方脚手架生成后编译异常 bug
    • [修复] Tenant 内置属性不是 virtual 修饰 bug
    • [修复] dockerfile 新命名构建失败 bug
    • [修复] 自定义角色授权和多个授权共存出现 403 bug #I26H1L
    • [修复] httpContext.GetEndpoint() 空异常 bug #PR73
    • [修复] Oops.Oh 空异常和不支持服务抛异常 bug #I26EFU#I26GM4
    • [修复] cli.ps 生成文件编码乱码 bug #I26DVT
    • [修复] Swagger 文件上传按钮不显示 #I26B6U
    • [修复] 规范化结果授权状态码序列化大小写不一致问题 #I26B26
    • [修复] 未启用规范化结果时中文乱码 bug #I268T5
    • [修复] MySql 异步异常捕获不到 bug #I265SO
    • [修复] cli.ps1 提示找不到数据库连接字符串 bug #I2647U
  • 其他更改

  • 文档变化

    • [更新] 一分钟入门、安全鉴权、数据库等文档

v1.0.3(已发布)

  • 新特性

    • [新增] Mvc 模板脚手架:Fur.Template.Mvc
    • [新增] WebApi 模板:Fur.Template.Api
    • [新增] Mvc/WebApi 模板:Fur.Template.App
    • [新增] Razar Pages 模板:Fur.Template.Razor
    • [新增] Blazor 模板:Fur.Template.Blazor
  • 突破性变化

    • [调整] PagedListSystem.Collections.Generic 命名空间下
    • [优化] 解析服务性能问题,底层代码大量优化
  • 问题修复

    • [修复] ApiSears.ControllerEnd不起作用 bug #I25KH6
    • [修复] RemoteRequest 请求完成结果序列化属性大小写问题 #I25I8R
    • [修复] HttpContext.GetEndpoinet() 空异常 bug #PR73
  • 其他更改

  • 文档变化

    • [更新] 入门文档、数据库上下文文档、多数据库操作文档

v1.0.2(已发布)

  • 新特性

    • [新增] Pomelo.EntityFrameworkCore.MySql 最新 .NET 5 包配置 #I24ZQK
    • [新增] .AddDateTimeJsonConverter(format) 时间格式序列化配置
    • [新增] DateTimeDateTimeOffset 类型序列化格式配置 #I253FI
  • 突破性变化

    • [更新] Mapster 包至 7.0.0
    • [调整] App.Services 名为 App.ServiceProvider
    • [移除] App.ApplicationServicesApp.GetRequestService<>()
    • [移除] 非 Web 主机注入拓展
  • 问题修复

    • [修复] services.AddFriendlyException() 缺少配置注入 bug
    • [修复] 数据库上下文池被释放和高并发下内存溢出 bug #I2524K#I24UMN
    • [修复] Sql代理 返回空数据时异常 bug #I24TCK
    • [修复] 工作单元 [UnitOfWork] 多数据库被释放 bug #I24Q6W
  • 其他更改

    • [调整] EntityBaseEntity 所有属性为 vitural 修饰
    • [优化] Jwt 读取和解析性能
    • [优化] 优化代码支持 C# 9.0 最新语法
    • [优化] MD5 加密性能 #PR71
    • [移除] 无用或未使用代码
  • 文档

    • [更新] 数据库上下文、多数据库、一分钟入门文档

v1.0.0(已发布)

  • 新特性

    • [新增] 网络请求 RemoteRequest 组件 #I1YYWD
    • [新增] .AddInjectBase() 注入,只包含基础服务注入
    • [新增] 所有服务都支持 IServiceCollectionIMvcBuilder 注入
    • [新增] 抛异常状态码设置功能 StatusCode
    • [新增] Swagger 序列化支持 Pascal 属性命名方式
  • 突破性变化

    • [更新] 所有的包为 .NET 5 正式版
  • 问题修复

    • [修复] SqlProxy 代理异步处理 bug
    • [修复] 数据库类型 DatetimeDateTimeOffset bug
    • [修复] 属性首字母大小写序列化不匹配出现 null bug
    • [修复] 对象序列化中文出现乱码 bug
    • [修复] 默认序列化配置无效 bug
    • [修复] 数据库非依赖注入方式提交无效 bug
    • [修复] 应用程序池提交所有 DbContext 空异常 bug
    • [修复] Saas 多租户 Tenant 类型字符串属性在 MySql 数据库下出现 longtext 类型 bug
    • [修复] Mvc 自动验证字符串空值 bug #I24M2T
    • [修复] 枚举注释被覆盖 bug #I24N6J
    • [修复] 忽略规范化结果无效 bug #I24B8P
    • [修复] Swagger 默认 ContentType 不是 applicaiton/json bug #I24F3U
    • [修复] 内置 System.Text.JsonNewtonsoft.Json 冲突 bug #I24F3U
  • 其他更改

    • [调整] Fur 框架域名为:https://furion.icu
    • [调整] 仓储 FromSqlRawFromSqlInterpolated 接口位置
    • [优化] 数据加解密性能,#PR70
  • 文档

    • [更新] README.md、框架介绍、数据库上下文、配置选项、多租户、跨域文档
演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/view-engine/index.html b/handbook/build/docs/view-engine/index.html index e848aa9481..6fabdb1725 100644 --- a/handbook/build/docs/view-engine/index.html +++ b/handbook/build/docs/view-engine/index.html @@ -2,22 +2,21 @@ - - - + +17. 视图引擎 | Furion -17. 视图引擎 | Furion - - + + +
-

17. 视图引擎

17.1 关于视图引擎

视图引擎负责根据视图模板创建 HTML。视图通常是 HTML 和编程语言的某种混合。支持变量定义、方法调用及逻辑编写。

Furion 框架中,底层集成了微软提供的 Razor 视图引擎组件并提供更加灵活方便的语法糖。

17.2 视图引擎作用

  • 支持 ASP.NET Core 完整的 Razor 语法
  • 根据不同的数据编译模板产生不同的输出
  • 实现强大的插件化机制
  • 实现全站页面静态化
  • 可以用作邮件模板、短信模板、优惠券信息模板等

17.3 基础使用

17.3.1 注册服务

使用之前需在 Startup.cs 中注册 视图引擎服务

public void ConfigureServices(IServiceCollection services){    services.AddViewEngine();}

17.3.2 使用方式

  • 构造函数注入 IViewEngine
using Furion.DynamicApiController;using Furion.ViewEngine;namespace Furion.Application{    public class ViewEngineService : IDynamicApiController    {        private readonly IViewEngine _viewEngine;        public ViewEngineService(IViewEngine viewEngine)        {            _viewEngine = viewEngine;            var result = _viewEngine.RunCompile("Hello @Model.Name", new { Name = "Furion" });        }    }}
  • 字符串方式
var result = "Hello @Model.Name".RunCompile(new { Name = "Furion" });

17.3.3 弱类型模板

var result = _viewEngine.RunCompile("Hello @Model.Name", new { Name = "Furion" });

结果:

Hello Furion

支持异步 RunCompileAsync

17.3.4 强类型模板

var result = _viewEngine.RunCompile(@"Hello @Model.Name@foreach(var item in Model.Items){    <p>@item</p>}", new TestModel{    Name = "Furion",    Items = new[] { 3, 1, 2 }});

结果:

Hello Furion<p>3</p><p>1</p><p>2</p>

支持异步 RunCompileAsync

17.3.5 高性能模板缓存 🥇

由于模板编译需要消耗大量的性能,所以建议使用带 FromCached 结尾的 RunCompileFromCached 替代。调用该方法后会自动将模板编译成 .dll 以便下次使用。减少第二次之后使用模板的性能损耗。

如,强类型模板:

var result = _viewEngine.RunCompileFromCached(@"Hello @Model.Name@foreach(var item in Model.Items){    <p>@item</p>}", new TestModel{    Name = "Furion",    Items = new[] { 3, 1, 2 }});

结果:

Hello Furion<p>3</p><p>1</p><p>2</p>

调用 RunCompileFromCached 方法之后将会使用 MD5 加密模板并生成 MD5字符串的 .dll 存放在网站根目录下的 templates 目录中。只要模板内容不变,数据发生改变也不会重新编译模板。这样大大的提高了首次之后的性能。

如,传入新的数据:

var result = _viewEngine.RunCompileFromCached(@"Hello @Model.Name@foreach(var item in Model.Items){    <p>@item</p>}", new TestModel{    Name = "Furion",    Items = new[] { 5,6,7,8 }});

结果:

Hello Furion<p>5</p><p>6</p><p>7</p><p>8</p>

模板不再重新编译,只是重新替换数据。

17.4 高级用法

高级用法支持将特定程序集、特定命名空间、特定类型引入到模板中使用。

17.4.1 添加程序集

比如这里添加 System.IO 程序集:

var result = _viewEngine.RunCompileFromCached(@"<div>@System.IO.Path.Combine(""Furion"", ""ViewEngine"")</div>", builderAction: builder =>            {                builder.AddAssemblyReferenceByName("System.IO");            });

结果:

<div>Furion\\ViewEngine</div>

另外,Furion 提供多种方式加载程序集:

builder.AddAssemblyReferenceByName("System.Security"); // 通过名称builder.AddAssemblyReference(typeof(System.IO.File)); // 通过类型builder.AddAssemblyReference(Assembly.Load("source")); // 通过元数据引用

17.4.2 添加命名空间

var result = _viewEngine.RunCompileFromCached(@"<div>@Path.Combine(""Furion"", ""ViewEngine"")</div>", builderAction: builder =>            {                builder.AddUsing("System.IO");                builder.AddAssemblyReferenceByName("System.IO");            });

结果:

<div>Furion\\ViewEngine</div>

也支持加入多个 using

builder.AddUsing("System.IO");
builder.AddUsing("Furion");

17.4.3 定义模板方法

var result = _viewEngine.RunCompileFromCached(@"<area>    @{ RecursionTest(3); }</area>@{  void RecursionTest(int level)  {    if (level <= 0)    {        return;    }    <div>LEVEL: @level</div>    @{ RecursionTest(level - 1); }  }}");

结果:

<area><div>LEVEL: 3</div><div>LEVEL: 2</div><div>LEVEL: 1</div></area>

17.4.4 调用类方法

定义 CustomModel 类并继承 ViewEngineModel 基类

public class CustomModel : ViewEngineModel{    public int A { get; set; }    public string B { get; set; }    public string Decorator(object value)    {        return "-=" + value + "=-";    }}

在模板中调用 Decorator(value) 方法:

var content = @"Hello @A, @B, @Decorator(123)";var template = _viewEngine.Compile<CustomModel>(content);var result = template.Run(instance =>{    instance.A = 10;    instance.B = "Alex";});

结果:

Hello 10, Alex, -=123=-

17.5 IViewEngine 接口

IViewEngine 提供了简单方便的 RunCompile 方法,也提供了最原始化的 CompileRun 方法。

通过原始的 CompileRun 方法可以实现很多复杂的逻辑和自定义指令集。

/// <summary>/// 编译模板/// </summary>/// <param name="content"></param>/// <param name="builderAction"></param>/// <returns></returns>IViewEngineTemplate Compile(string content, Action<IViewEngineOptionsBuilder> builderAction = null);/// <summary>/// 编译模板/// </summary>/// <param name="content"></param>/// <param name="builderAction"></param>/// <returns></returns>Task<IViewEngineTemplate> CompileAsync(string content, Action<IViewEngineOptionsBuilder> builderAction = null);/// <summary>/// 编译模板/// </summary>/// <typeparam name="T"></typeparam>/// <param name="content"></param>/// <param name="builderAction"></param>/// <returns></returns>IViewEngineTemplate<T> Compile<T>(string content, Action<IViewEngineOptionsBuilder> builderAction = null)    where T : IViewEngineModel;/// <summary>/// 编译模板/// </summary>/// <typeparam name="T"></typeparam>/// <param name="content"></param>/// <param name="builderAction"></param>/// <returns></returns>Task<IViewEngineTemplate<T>> CompileAsync<T>(string content, Action<IViewEngineOptionsBuilder> builderAction = null)    where T : IViewEngineModel;

17.6 字符串模板替换引擎

Furion 除了内置视图引擎之外,还支持以下几种模板替换,如:

// 提供数据模板方式var str = "我叫{name}".Render(new Dictionary{ {"name", "Furion"} });var str = "我叫{Name}".Render(new { Name = "Furion" });var str = "我叫{Detail.Name}".Render(new { Detail = new { Name = "Furoin" } });// 从配置读取方式var str = "我叫#(Furion:Address)".Render();
{  "Furion": {    "Address": "https://www.furion.icu"  }}

17.7 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

17. 视图引擎

17.1 关于视图引擎

视图引擎负责根据视图模板创建 HTML。视图通常是 HTML 和编程语言的某种混合。支持变量定义、方法调用及逻辑编写。

Furion 框架中,底层集成了微软提供的 Razor 视图引擎组件并提供更加灵活方便的语法糖。

17.2 视图引擎作用

  • 支持 ASP.NET Core 完整的 Razor 语法
  • 根据不同的数据编译模板产生不同的输出
  • 实现强大的插件化机制
  • 实现全站页面静态化
  • 可以用作邮件模板、短信模板、优惠券信息模板等

17.3 基础使用

17.3.1 注册服务

使用之前需在 Startup.cs 中注册 视图引擎服务

public void ConfigureServices(IServiceCollection services){    services.AddViewEngine();}

17.3.2 使用方式

  • 构造函数注入 IViewEngine
using Furion.DynamicApiController;using Furion.ViewEngine;namespace Furion.Application{    public class ViewEngineService : IDynamicApiController    {        private readonly IViewEngine _viewEngine;        public ViewEngineService(IViewEngine viewEngine)        {            _viewEngine = viewEngine;            var result = _viewEngine.RunCompile("Hello @Model.Name", new { Name = "Furion" });        }    }}
  • 字符串方式
var result = "Hello @Model.Name".RunCompile(new { Name = "Furion" });

17.3.3 弱类型模板

var result = _viewEngine.RunCompile("Hello @Model.Name", new { Name = "Furion" });

结果:

Hello Furion

支持异步 RunCompileAsync

17.3.4 强类型模板

var result = _viewEngine.RunCompile(@"Hello @Model.Name@foreach(var item in Model.Items){    <p>@item</p>}", new TestModel{    Name = "Furion",    Items = new[] { 3, 1, 2 }});

结果:

Hello Furion<p>3</p><p>1</p><p>2</p>

支持异步 RunCompileAsync

17.3.5 高性能模板缓存 🥇

由于模板编译需要消耗大量的性能,所以建议使用带 FromCached 结尾的 RunCompileFromCached 替代。调用该方法后会自动将模板编译成 .dll 以便下次使用。减少第二次之后使用模板的性能损耗。

如,强类型模板:

var result = _viewEngine.RunCompileFromCached(@"Hello @Model.Name@foreach(var item in Model.Items){    <p>@item</p>}", new TestModel{    Name = "Furion",    Items = new[] { 3, 1, 2 }});

结果:

Hello Furion<p>3</p><p>1</p><p>2</p>

调用 RunCompileFromCached 方法之后将会使用 MD5 加密模板并生成 MD5字符串的 .dll 存放在网站根目录下的 templates 目录中。只要模板内容不变,数据发生改变也不会重新编译模板。这样大大的提高了首次之后的性能。

如,传入新的数据:

var result = _viewEngine.RunCompileFromCached(@"Hello @Model.Name@foreach(var item in Model.Items){    <p>@item</p>}", new TestModel{    Name = "Furion",    Items = new[] { 5,6,7,8 }});

结果:

Hello Furion<p>5</p><p>6</p><p>7</p><p>8</p>

模板不再重新编译,只是重新替换数据。

17.4 高级用法

高级用法支持将特定程序集、特定命名空间、特定类型引入到模板中使用。

17.4.1 添加程序集

比如这里添加 System.IO 程序集:

var result = _viewEngine.RunCompileFromCached(@"<div>@System.IO.Path.Combine(""Furion"", ""ViewEngine"")</div>", builderAction: builder =>            {                builder.AddAssemblyReferenceByName("System.IO");            });

结果:

<div>Furion\\ViewEngine</div>

另外,Furion 提供多种方式加载程序集:

builder.AddAssemblyReferenceByName("System.Security"); // 通过名称builder.AddAssemblyReference(typeof(System.IO.File)); // 通过类型builder.AddAssemblyReference(Assembly.Load("source")); // 通过元数据引用

17.4.2 添加命名空间

var result = _viewEngine.RunCompileFromCached(@"<div>@Path.Combine(""Furion"", ""ViewEngine"")</div>", builderAction: builder =>            {                builder.AddUsing("System.IO");                builder.AddAssemblyReferenceByName("System.IO");            });

结果:

<div>Furion\\ViewEngine</div>

也支持加入多个 using

builder.AddUsing("System.IO");
builder.AddUsing("Furion");

17.4.3 定义模板方法

var result = _viewEngine.RunCompileFromCached(@"<area>    @{ RecursionTest(3); }</area>@{  void RecursionTest(int level)  {    if (level <= 0)    {        return;    }    <div>LEVEL: @level</div>    @{ RecursionTest(level - 1); }  }}");

结果:

<area><div>LEVEL: 3</div><div>LEVEL: 2</div><div>LEVEL: 1</div></area>

17.4.4 调用类方法

定义 CustomModel 类并继承 ViewEngineModel 基类

public class CustomModel : ViewEngineModel{    public int A { get; set; }    public string B { get; set; }    public string Decorator(object value)    {        return "-=" + value + "=-";    }}

在模板中调用 Decorator(value) 方法:

var content = @"Hello @A, @B, @Decorator(123)";var template = _viewEngine.Compile<CustomModel>(content);var result = template.Run(instance =>{    instance.A = 10;    instance.B = "Alex";});

结果:

Hello 10, Alex, -=123=-

17.5 IViewEngine 接口

IViewEngine 提供了简单方便的 RunCompile 方法,也提供了最原始化的 CompileRun 方法。

通过原始的 CompileRun 方法可以实现很多复杂的逻辑和自定义指令集。

/// <summary>/// 编译模板/// </summary>/// <param name="content"></param>/// <param name="builderAction"></param>/// <returns></returns>IViewEngineTemplate Compile(string content, Action<IViewEngineOptionsBuilder> builderAction = null);/// <summary>/// 编译模板/// </summary>/// <param name="content"></param>/// <param name="builderAction"></param>/// <returns></returns>Task<IViewEngineTemplate> CompileAsync(string content, Action<IViewEngineOptionsBuilder> builderAction = null);/// <summary>/// 编译模板/// </summary>/// <typeparam name="T"></typeparam>/// <param name="content"></param>/// <param name="builderAction"></param>/// <returns></returns>IViewEngineTemplate<T> Compile<T>(string content, Action<IViewEngineOptionsBuilder> builderAction = null)    where T : IViewEngineModel;/// <summary>/// 编译模板/// </summary>/// <typeparam name="T"></typeparam>/// <param name="content"></param>/// <param name="builderAction"></param>/// <returns></returns>Task<IViewEngineTemplate<T>> CompileAsync<T>(string content, Action<IViewEngineOptionsBuilder> builderAction = null)    where T : IViewEngineModel;

17.6 字符串模板替换引擎

Furion 除了内置视图引擎之外,还支持以下几种模板替换,如:

// 提供数据模板方式var str = "我叫{name}".Render(new Dictionary{ {"name", "Furion"} });var str = "我叫{Name}".Render(new { Name = "Furion" });var str = "我叫{Detail.Name}".Render(new { Detail = new { Name = "Furoin" } });// 从配置读取方式var str = "我叫#(Furion:Address)".Render();
{  "Furion": {    "Address": "https://www.furion.icu"  }}

17.7 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/virtual-deploy/index.html b/handbook/build/docs/virtual-deploy/index.html index 2051f0fb4c..547ba67b9c 100644 --- a/handbook/build/docs/virtual-deploy/index.html +++ b/handbook/build/docs/virtual-deploy/index.html @@ -2,22 +2,21 @@ - - - + +34.4 二级虚拟目录部署 | Furion -34.4 二级虚拟目录部署 | Furion - - + + +
-

34.4 二级虚拟目录部署

34.4.1 关于二级虚拟目录

通常我们的站点都是部署在网站的根目录下的,但是有些时候,我们可能将网站根目录下的目录作为二级站点或子站点,这个时候,就会出现 404 错误了。

这个时候就需要进行一些特殊配置了。

34.4.2 针对在 IIS 网站下添加 Application 情况

版本说明

以下内容仅限 Furion 3.2.0 + 版本使用。

如果网站是在 Site 下面添加 Application 下部署,则遵循以下步骤:

  1. 添加 Application Pool 应用程序池,并设置为非托管模式
  1. 添加 Application 并选择刚刚创建的应用程序池


  1. 添加应用配置:
{  "SpecificationDocumentSettings": {    "ServerDir": "IIS中应用程序名(Applicaiton)"  }}

该配置主要是解决 Swagger 出现 404 问题。

个别情况

如果配置之后还 Swagger 还出现不能加载 swagger.json 文件问题,那么需修改启动注册代码:

app.UseInject(string.Empty);  // 确保参数是 strng.Empty

34.4.3 针对非 IIS 下部署情况

注意事项

这里是针对 非 IIS 部署使用的!!!

34.4.3.1 配置 AppSettings

我们只需要配置 AppSettings 即可:

{  "AppSettings": {    "VirtualPath": "/虚拟目录"  }}

34.4.3.2 .NET6 WebApplication 模式下虚拟目录配置

版本说明

以下内容仅限 Furion 3.2.0 + 版本使用。

由于在 .NET6WebApplication 模式下微软底层发生了改变,所以需要使用 app.UseVirtualPath() 包裹 app.UseInject()app.MapRouteControllers()

app.UseVirtualPath(app =>{    app.UseInject(String.Empty);  // 注意 String.Empty 只是例子,可以不填或填其他的,见一分钟入门    app.MapRouteControllers();});

注意,app.MapRouteControllers() 是替换 app.MapControllers() 的!

34.4.4 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

34.4 二级虚拟目录部署

34.4.1 关于二级虚拟目录

通常我们的站点都是部署在网站的根目录下的,但是有些时候,我们可能将网站根目录下的目录作为二级站点或子站点,这个时候,就会出现 404 错误了。

这个时候就需要进行一些特殊配置了。

34.4.2 针对在 IIS 网站下添加 Application 情况

版本说明

以下内容仅限 Furion 3.2.0 + 版本使用。

如果网站是在 Site 下面添加 Application 下部署,则遵循以下步骤:

  1. 添加 Application Pool 应用程序池,并设置为非托管模式
  1. 添加 Application 并选择刚刚创建的应用程序池


  1. 添加应用配置:
{  "SpecificationDocumentSettings": {    "ServerDir": "IIS中应用程序名(Applicaiton)"  }}

该配置主要是解决 Swagger 出现 404 问题。

个别情况

如果配置之后还 Swagger 还出现不能加载 swagger.json 文件问题,那么需修改启动注册代码:

app.UseInject(string.Empty);  // 确保参数是 strng.Empty

34.4.3 针对非 IIS 下部署情况

注意事项

这里是针对 非 IIS 部署使用的!!!

34.4.3.1 配置 AppSettings

我们只需要配置 AppSettings 即可:

{  "AppSettings": {    "VirtualPath": "/虚拟目录"  }}

34.4.3.2 .NET6 WebApplication 模式下虚拟目录配置

版本说明

以下内容仅限 Furion 3.2.0 + 版本使用。

由于在 .NET6WebApplication 模式下微软底层发生了改变,所以需要使用 app.UseVirtualPath() 包裹 app.UseInject()app.MapRouteControllers()

app.UseVirtualPath(app =>{    app.UseInject(String.Empty);  // 注意 String.Empty 只是例子,可以不填或填其他的,见一分钟入门    app.MapRouteControllers();});

注意,app.MapRouteControllers() 是替换 app.MapControllers() 的!

34.4.4 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/docs/vsfast/index.html b/handbook/build/docs/vsfast/index.html index 305a719d8d..b20497e8c0 100644 --- a/handbook/build/docs/vsfast/index.html +++ b/handbook/build/docs/vsfast/index.html @@ -2,22 +2,21 @@ - - - + +2.8 Visual Studio 高效率 | Furion -2.8 Visual Studio 高效率 | Furion - - + + +
-

2.8 Visual Studio 高效率

工欲善其事必先利其器!

Visual Studio 提供了非常多代码辅助功能,启用这些功能将大大提高开发效率,这里列举一些常见的配置,后续不断完善。

2.8.1 开启内联参数提示

2.8.2 开启全局智能提示

2.8.3 实时显示诊断错误

在过去,我们需要写完代码编译才能知道具体的错误,最新版的 Visual Studio 支持 内联诊断错误,开启如下:

2.8.4 中文智能提示

打开网站 https://dotnet.microsoft.com/zh-cn/download/intellisense 下载对应的语言版本。

配置教程

如果配置了不能显示中文,可以查看此篇教程 https://blog.csdn.net/sD7O95O/article/details/103776077

关于 NET6 的中文智能提示

因为官方不再提供本地化包了,详情可查看相关 Issue https://github.com/dotnet/docs/issues/27283

可以使用博客园网友 @internalnet 制作的本地化包 https://www.cnblogs.com/internalnet/p/16185298.html

2.8.5 代码搜索

Visual Studio 2022 提供了非常强大的 代码搜索和功能搜索,只需要快捷键 Ctrl + T 呼出,如:

退出搜索只需快捷键 ESC 即可。

2.8.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
- - +

2.8 Visual Studio 高效率

工欲善其事必先利其器!

Visual Studio 提供了非常多代码辅助功能,启用这些功能将大大提高开发效率,这里列举一些常见的配置,后续不断完善。

2.8.1 开启内联参数提示

2.8.2 开启全局智能提示

2.8.3 实时显示诊断错误

在过去,我们需要写完代码编译才能知道具体的错误,最新版的 Visual Studio 支持 内联诊断错误,开启如下:

2.8.4 中文智能提示

打开网站 https://dotnet.microsoft.com/zh-cn/download/intellisense 下载对应的语言版本。

配置教程

如果配置了不能显示中文,可以查看此篇教程 https://blog.csdn.net/sD7O95O/article/details/103776077

关于 NET6 的中文智能提示

因为官方不再提供本地化包了,详情可查看相关 Issue https://github.com/dotnet/docs/issues/27283

可以使用博客园网友 @internalnet 制作的本地化包 https://www.cnblogs.com/internalnet/p/16185298.html

2.8.5 代码搜索

Visual Studio 2022 提供了非常强大的 代码搜索和功能搜索,只需要快捷键 Ctrl + T 呼出,如:

退出搜索只需快捷键 ESC 即可。

2.8.6 反馈与建议

与我们交流

给 Furion 提 Issue

演练场
+ + \ No newline at end of file diff --git a/handbook/build/index.html b/handbook/build/index.html index 32ceec3677..56d7949839 100644 --- a/handbook/build/index.html +++ b/handbook/build/index.html @@ -2,22 +2,21 @@ - - - + +让 .NET 开发更简单,更通用,更流行。 Furion | Furion -让 .NET 开发更简单,更通用,更流行。 Furion | Furion - - + + +
-
Furion [fu:rɪən]
您的痛点,Furion 已阅已历;Furion 的惊喜,您且慢慢享受。
让 .NET 开发更简单,更通用,更流行。
  • MIT 开源协议,商业无需授权
  • 支持 .NET5+ 平台,没有历史包袱
  • 极少依赖,只依赖两个第三方包
  • 极速上手,一个 Inject() 完成配置
  • 代码无侵入性,100% 兼容原生写法
受支持平台:
Serve.Run();

public class FurionAppService : IDynamicApiController
{
private readonly IRepository<User> _userRepository;
public AppService(IRepository<User> userRepository)
{
_userRepository = userRepository;
}

[IfException(1000, ErrorMessage = "用户ID: {0} 不存在")]
public async Task<UserDto> GetUser([Range(1, int.MaxValue)] int userId)
{
var user = await _userRepository.FindOrDefaultAsync(userId);
_ = user ?? throw Oops.Oh(1000, userId);
return user.Adapt<UserDto>();
}

public async Task<RemoteData> GetRemote(string id)
{
var data = await $"https://www.furion.icu/data?id={id}".GetAsAsync<RemoteData>();
return data;
}
}

开源免费/商业无需授权

⭐️ MIT 开源协议,代码在 Gitee/Github 平台托管 ⭐️

10000 +
Stars
3700 +
Forks
3,109,291
Downloads

他们都在用

Furion 已在全球超过 300万 个项目中使用。从小型企业到企业的解决方案及知名企业。他们在简单软件和复杂管理系统的开发方面都信任我们。

立即添加您的公司
演练场
- - +
Furion [fu:rɪən]
您的痛点,Furion 已阅已历;Furion 的惊喜,您且慢慢享受。
让 .NET 开发更简单,更通用,更流行。
  • MIT 开源协议,商业无需授权
  • 支持 .NET5+ 平台,没有历史包袱
  • 极少依赖,只依赖两个第三方包
  • 极速上手,一个 Inject() 完成配置
  • 代码无侵入性,100% 兼容原生写法
受支持平台:
Serve.Run();

public class FurionAppService : IDynamicApiController
{
private readonly IRepository<User> _userRepository;
public AppService(IRepository<User> userRepository)
{
_userRepository = userRepository;
}

[IfException(1000, ErrorMessage = "用户ID: {0} 不存在")]
public async Task<UserDto> GetUser([Range(1, int.MaxValue)] int userId)
{
var user = await _userRepository.FindOrDefaultAsync(userId);
_ = user ?? throw Oops.Oh(1000, userId);
return user.Adapt<UserDto>();
}

public async Task<RemoteData> GetRemote(string id)
{
var data = await $"https://www.furion.icu/data?id={id}".GetAsAsync<RemoteData>();
return data;
}
}

开源免费/商业无需授权

⭐️ MIT 开源协议,代码在 Gitee/Github 平台托管 ⭐️

10000 +
Stars
3700 +
Forks
3,122,542
Downloads

他们都在用

Furion 已在全球超过 300万 个项目中使用。从小型企业到企业的解决方案及知名企业。他们在简单软件和复杂管理系统的开发方面都信任我们。

立即添加您的公司
演练场
+ + \ No newline at end of file diff --git a/handbook/build/search/index.html b/handbook/build/search/index.html index 2e1179c8c8..03bd0f6746 100644 --- a/handbook/build/search/index.html +++ b/handbook/build/search/index.html @@ -2,22 +2,21 @@ - - - + +Search the documentation | Furion -Search the documentation | Furion - - + + +
-

Search the documentation

演练场
- - +

Search the documentation

演练场
+ + \ No newline at end of file diff --git a/handbook/docs/net5-to-net6.mdx b/handbook/docs/net5-to-net6.mdx index b35a7041e2..8419681d42 100644 --- a/handbook/docs/net5-to-net6.mdx +++ b/handbook/docs/net5-to-net6.mdx @@ -26,7 +26,7 @@ import useBaseUrl from "@docusaurus/useBaseUrl"; ### 2.5.1.3 升级 `Nuget` 包 -将 `Furion` 所有包升级至 `v4.3.9` 版本,同时 `Microsoft` 所有包升级至 `v6.0.8` 版本,如: +将 `Furion` 所有包升级至 `v4.4.0` 版本,同时 `Microsoft` 所有包升级至 `v6.0.8` 版本,如: diff --git a/handbook/docs/template.mdx b/handbook/docs/template.mdx index be86a2ffeb..22bd408d4b 100644 --- a/handbook/docs/template.mdx +++ b/handbook/docs/template.mdx @@ -52,9 +52,9 @@ import useBaseUrl from "@docusaurus/useBaseUrl"; ```bash showLineNumbers // EFCore -dotnet new --install Furion.Template.Mvc::4.3.9 +dotnet new --install Furion.Template.Mvc::4.4.0 // SqlSugar -dotnet new --install Furion.SqlSugar.Template.Mvc::4.3.9 +dotnet new --install Furion.SqlSugar.Template.Mvc::4.4.0 ``` :::tip `SqlSugar` 脚手架基本使用 diff --git a/handbook/docs/upgrade.mdx b/handbook/docs/upgrade.mdx index 27c1a70adc..6236d85c1b 100644 --- a/handbook/docs/upgrade.mdx +++ b/handbook/docs/upgrade.mdx @@ -21,7 +21,13 @@ import useBaseUrl from "@docusaurus/useBaseUrl"; ::: -## v4.4.0(未发布) +## v4.4.0(当前版本) + +:::important 版本细节 + +- `v4.4.0` 版本细节:[https://gitee.com/dotnetchina/Furion/issues/I5PQHR](https://gitee.com/dotnetchina/Furion/issues/I5PQHR) + +::: - **新特性** @@ -58,8 +64,6 @@ var res = await "https://www.furion.icu/upload".SetContentType("multipart/form-d .SetFiles(HttpFile.CreateMultiple("files", (bytes, "image1.png"), (bytes, "image2.png"))).PostAsync(); ``` -- **问题修复** - - **其他更改** - [调整] `JWTEncryption` 静态类,支持无需注册 `services.AddJwt()` 使用 [#I5PPKE](https://gitee.com/dotnetchina/Furion/issues/I5PPKE) [#I5POLZ](https://gitee.com/dotnetchina/Furion/issues/I5POLZ) @@ -70,7 +74,7 @@ var res = await "https://www.furion.icu/upload".SetContentType("multipart/form-d --- -## v4.3.9(当前版本) +## v4.3.9(已发布) :::important 版本细节 diff --git a/handbook/package.json b/handbook/package.json index bedeb90695..1fcc68092c 100644 --- a/handbook/package.json +++ b/handbook/package.json @@ -1,6 +1,6 @@ { "name": "furion", - "version": "v4.3.9", + "version": "v4.4.0", "private": true, "scripts": { "docusaurus": "docusaurus", diff --git a/handbook/src/pages/index.js b/handbook/src/pages/index.js index 8dccb3592e..d029d951be 100644 --- a/handbook/src/pages/index.js +++ b/handbook/src/pages/index.js @@ -84,7 +84,7 @@ function Banner() {
入门指南 - v4.3.9 + v4.4.0
-
3,109,291
+
3,122,542
Downloads
diff --git a/samples/Furion.Core/Furion.Core.csproj b/samples/Furion.Core/Furion.Core.csproj index 188def79a7..f28488d475 100644 --- a/samples/Furion.Core/Furion.Core.csproj +++ b/samples/Furion.Core/Furion.Core.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/templates/FurionApiTemplate/Furion.Template.Api.nuspec b/templates/FurionApiTemplate/Furion.Template.Api.nuspec index 427618ea43..1efde036bc 100644 --- a/templates/FurionApiTemplate/Furion.Template.Api.nuspec +++ b/templates/FurionApiTemplate/Furion.Template.Api.nuspec @@ -2,7 +2,7 @@ Furion.Template.Api - 4.3.9 + 4.4.0 基于 Furion 框架快速搭建 Api 多层架构模板。 百小僧 diff --git a/templates/FurionApiTemplate/src/FurionApi.Core/FurionApi.Core.csproj b/templates/FurionApiTemplate/src/FurionApi.Core/FurionApi.Core.csproj index 60c145ce2c..1ee0f8cef9 100644 --- a/templates/FurionApiTemplate/src/FurionApi.Core/FurionApi.Core.csproj +++ b/templates/FurionApiTemplate/src/FurionApi.Core/FurionApi.Core.csproj @@ -11,9 +11,9 @@ - - - + + + diff --git a/templates/FurionAppTemplate/Furion.Template.App.nuspec b/templates/FurionAppTemplate/Furion.Template.App.nuspec index bdafac811b..d9c8f0b887 100644 --- a/templates/FurionAppTemplate/Furion.Template.App.nuspec +++ b/templates/FurionAppTemplate/Furion.Template.App.nuspec @@ -2,7 +2,7 @@ Furion.Template.App - 4.3.9 + 4.4.0 基于 Furion 框架快速搭建 Mvc/Api 多层架构模板。 百小僧 diff --git a/templates/FurionAppTemplate/src/FurionApp.Core/FurionApp.Core.csproj b/templates/FurionAppTemplate/src/FurionApp.Core/FurionApp.Core.csproj index dd02d73943..7b02cc6a1f 100644 --- a/templates/FurionAppTemplate/src/FurionApp.Core/FurionApp.Core.csproj +++ b/templates/FurionAppTemplate/src/FurionApp.Core/FurionApp.Core.csproj @@ -11,9 +11,9 @@ - - - + + + diff --git a/templates/FurionBlazorTemplate/Furion.Template.Blazor.nuspec b/templates/FurionBlazorTemplate/Furion.Template.Blazor.nuspec index 78c87c8405..dd86b2f238 100644 --- a/templates/FurionBlazorTemplate/Furion.Template.Blazor.nuspec +++ b/templates/FurionBlazorTemplate/Furion.Template.Blazor.nuspec @@ -2,7 +2,7 @@ Furion.Template.Blazor - 4.3.9 + 4.4.0 基于 Furion 框架快速搭建 Blazor 多层架构模板。 百小僧 diff --git a/templates/FurionBlazorTemplate/src/FurionBlazor.Core/FurionBlazor.Core.csproj b/templates/FurionBlazorTemplate/src/FurionBlazor.Core/FurionBlazor.Core.csproj index d5a7090721..676c97b680 100644 --- a/templates/FurionBlazorTemplate/src/FurionBlazor.Core/FurionBlazor.Core.csproj +++ b/templates/FurionBlazorTemplate/src/FurionBlazor.Core/FurionBlazor.Core.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/templates/FurionBlazorWithWebApiTemplate/Furion.Template.BlazorWithWebApi.nuspec b/templates/FurionBlazorWithWebApiTemplate/Furion.Template.BlazorWithWebApi.nuspec index 00abdad4c6..fc797ba6c4 100644 --- a/templates/FurionBlazorWithWebApiTemplate/Furion.Template.BlazorWithWebApi.nuspec +++ b/templates/FurionBlazorWithWebApiTemplate/Furion.Template.BlazorWithWebApi.nuspec @@ -2,7 +2,7 @@ Furion.Template.BlazorWithWebApi - 4.3.9 + 4.4.0 基于 Furion 框架快速搭建 Blazor和WebApi 多层架构模板。 百小僧 diff --git a/templates/FurionBlazorWithWebApiTemplate/src/FurionBlazorApi.Core/FurionBlazorApi.Core.csproj b/templates/FurionBlazorWithWebApiTemplate/src/FurionBlazorApi.Core/FurionBlazorApi.Core.csproj index 56d3a3059c..5d5ca65c3e 100644 --- a/templates/FurionBlazorWithWebApiTemplate/src/FurionBlazorApi.Core/FurionBlazorApi.Core.csproj +++ b/templates/FurionBlazorWithWebApiTemplate/src/FurionBlazorApi.Core/FurionBlazorApi.Core.csproj @@ -11,9 +11,9 @@ - - - + + + diff --git a/templates/FurionMvcTemplate/Furion.Template.Mvc.nuspec b/templates/FurionMvcTemplate/Furion.Template.Mvc.nuspec index e3d03d8049..f921b8fef1 100644 --- a/templates/FurionMvcTemplate/Furion.Template.Mvc.nuspec +++ b/templates/FurionMvcTemplate/Furion.Template.Mvc.nuspec @@ -2,7 +2,7 @@ Furion.Template.Mvc - 4.3.9 + 4.4.0 基于 Furion 框架快速搭建 Mvc 多层架构模板。 百小僧 diff --git a/templates/FurionMvcTemplate/src/FurionMvc.Core/FurionMvc.Core.csproj b/templates/FurionMvcTemplate/src/FurionMvc.Core/FurionMvc.Core.csproj index b32d719818..3da80ddd76 100644 --- a/templates/FurionMvcTemplate/src/FurionMvc.Core/FurionMvc.Core.csproj +++ b/templates/FurionMvcTemplate/src/FurionMvc.Core/FurionMvc.Core.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/templates/FurionRazorTemplate/Furion.Template.Razor.nuspec b/templates/FurionRazorTemplate/Furion.Template.Razor.nuspec index 0ecce99cf1..bb569ba460 100644 --- a/templates/FurionRazorTemplate/Furion.Template.Razor.nuspec +++ b/templates/FurionRazorTemplate/Furion.Template.Razor.nuspec @@ -2,7 +2,7 @@ Furion.Template.Razor - 4.3.9 + 4.4.0 基于 Furion 框架快速搭建 Razor Pages 多层架构模板。 百小僧 diff --git a/templates/FurionRazorTemplate/src/FurionRazor.Core/FurionRazor.Core.csproj b/templates/FurionRazorTemplate/src/FurionRazor.Core/FurionRazor.Core.csproj index 0c92461794..efa04c8da5 100644 --- a/templates/FurionRazorTemplate/src/FurionRazor.Core/FurionRazor.Core.csproj +++ b/templates/FurionRazorTemplate/src/FurionRazor.Core/FurionRazor.Core.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/templates/FurionRazorWithWebApiTemplate/Furion.Template.RazorWithWebApi.nuspec b/templates/FurionRazorWithWebApiTemplate/Furion.Template.RazorWithWebApi.nuspec index ddd27e0bc2..85acadf42e 100644 --- a/templates/FurionRazorWithWebApiTemplate/Furion.Template.RazorWithWebApi.nuspec +++ b/templates/FurionRazorWithWebApiTemplate/Furion.Template.RazorWithWebApi.nuspec @@ -2,7 +2,7 @@ Furion.Template.RazorWithWebApi - 4.3.9 + 4.4.0 基于 Furion 框架快速搭建 RazorPages和WebApi 多层架构模板。 百小僧 diff --git a/templates/FurionRazorWithWebApiTemplate/src/FurionRazorApi.Core/FurionRazorApi.Core.csproj b/templates/FurionRazorWithWebApiTemplate/src/FurionRazorApi.Core/FurionRazorApi.Core.csproj index deac6a3c72..45c4a5fc5b 100644 --- a/templates/FurionRazorWithWebApiTemplate/src/FurionRazorApi.Core/FurionRazorApi.Core.csproj +++ b/templates/FurionRazorWithWebApiTemplate/src/FurionRazorApi.Core/FurionRazorApi.Core.csproj @@ -11,9 +11,9 @@ - - - + + + diff --git a/templates/SqlSugarTemplates/FurionApiTemplate/Furion.Template.Api.nuspec b/templates/SqlSugarTemplates/FurionApiTemplate/Furion.Template.Api.nuspec index c27adb317f..6b4c6537a5 100644 --- a/templates/SqlSugarTemplates/FurionApiTemplate/Furion.Template.Api.nuspec +++ b/templates/SqlSugarTemplates/FurionApiTemplate/Furion.Template.Api.nuspec @@ -2,7 +2,7 @@ Furion.SqlSugar.Template.Api - 4.3.9 + 4.4.0 基于 Furion 和 SqlSugar 框架快速搭建 Api 多层架构模板。 百小僧 diff --git a/templates/SqlSugarTemplates/FurionApiTemplate/src/FurionApi.Core/FurionApi.Core.csproj b/templates/SqlSugarTemplates/FurionApiTemplate/src/FurionApi.Core/FurionApi.Core.csproj index b3734cfaf0..2b813dcf39 100644 --- a/templates/SqlSugarTemplates/FurionApiTemplate/src/FurionApi.Core/FurionApi.Core.csproj +++ b/templates/SqlSugarTemplates/FurionApiTemplate/src/FurionApi.Core/FurionApi.Core.csproj @@ -11,9 +11,9 @@ - - - + + + diff --git a/templates/SqlSugarTemplates/FurionAppTemplate/Furion.Template.App.nuspec b/templates/SqlSugarTemplates/FurionAppTemplate/Furion.Template.App.nuspec index 87f362c17d..84f8cc969f 100644 --- a/templates/SqlSugarTemplates/FurionAppTemplate/Furion.Template.App.nuspec +++ b/templates/SqlSugarTemplates/FurionAppTemplate/Furion.Template.App.nuspec @@ -2,7 +2,7 @@ Furion.SqlSugar.Template.App - 4.3.9 + 4.4.0 基于 Furion 和 SqlSugar 框架快速搭建 Mvc/Api 多层架构模板。 百小僧 diff --git a/templates/SqlSugarTemplates/FurionAppTemplate/src/FurionApp.Core/FurionApp.Core.csproj b/templates/SqlSugarTemplates/FurionAppTemplate/src/FurionApp.Core/FurionApp.Core.csproj index f09a70966d..128f0eeeac 100644 --- a/templates/SqlSugarTemplates/FurionAppTemplate/src/FurionApp.Core/FurionApp.Core.csproj +++ b/templates/SqlSugarTemplates/FurionAppTemplate/src/FurionApp.Core/FurionApp.Core.csproj @@ -11,9 +11,9 @@ - - - + + + diff --git a/templates/SqlSugarTemplates/FurionBlazorTemplate/Furion.Template.Blazor.nuspec b/templates/SqlSugarTemplates/FurionBlazorTemplate/Furion.Template.Blazor.nuspec index 4e88444e48..686dfc2825 100644 --- a/templates/SqlSugarTemplates/FurionBlazorTemplate/Furion.Template.Blazor.nuspec +++ b/templates/SqlSugarTemplates/FurionBlazorTemplate/Furion.Template.Blazor.nuspec @@ -2,7 +2,7 @@ Furion.SqlSugar.Template.Blazor - 4.3.9 + 4.4.0 基于 Furion 和 SqlSugar 框架快速搭建 Blazor 多层架构模板。 百小僧 diff --git a/templates/SqlSugarTemplates/FurionBlazorTemplate/src/FurionBlazor.Core/FurionBlazor.Core.csproj b/templates/SqlSugarTemplates/FurionBlazorTemplate/src/FurionBlazor.Core/FurionBlazor.Core.csproj index 31eec9c884..3c35cc3553 100644 --- a/templates/SqlSugarTemplates/FurionBlazorTemplate/src/FurionBlazor.Core/FurionBlazor.Core.csproj +++ b/templates/SqlSugarTemplates/FurionBlazorTemplate/src/FurionBlazor.Core/FurionBlazor.Core.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/templates/SqlSugarTemplates/FurionBlazorWithWebApiTemplate/Furion.Template.BlazorWithWebApi.nuspec b/templates/SqlSugarTemplates/FurionBlazorWithWebApiTemplate/Furion.Template.BlazorWithWebApi.nuspec index a65ecd6e94..fe94dd7bb7 100644 --- a/templates/SqlSugarTemplates/FurionBlazorWithWebApiTemplate/Furion.Template.BlazorWithWebApi.nuspec +++ b/templates/SqlSugarTemplates/FurionBlazorWithWebApiTemplate/Furion.Template.BlazorWithWebApi.nuspec @@ -2,7 +2,7 @@ Furion.SqlSugar.Template.BlazorWithWebApi - 4.3.9 + 4.4.0 基于 Furion 和 SqlSugar 框架快速搭建 Blazor和WebApi 多层架构模板。 百小僧 diff --git a/templates/SqlSugarTemplates/FurionBlazorWithWebApiTemplate/src/FurionBlazorApi.Core/FurionBlazorApi.Core.csproj b/templates/SqlSugarTemplates/FurionBlazorWithWebApiTemplate/src/FurionBlazorApi.Core/FurionBlazorApi.Core.csproj index 8e6510029d..c58e296282 100644 --- a/templates/SqlSugarTemplates/FurionBlazorWithWebApiTemplate/src/FurionBlazorApi.Core/FurionBlazorApi.Core.csproj +++ b/templates/SqlSugarTemplates/FurionBlazorWithWebApiTemplate/src/FurionBlazorApi.Core/FurionBlazorApi.Core.csproj @@ -11,9 +11,9 @@ - - - + + + diff --git a/templates/SqlSugarTemplates/FurionMvcTemplate/Furion.Template.Mvc.nuspec b/templates/SqlSugarTemplates/FurionMvcTemplate/Furion.Template.Mvc.nuspec index 1814eefd54..39f90f3223 100644 --- a/templates/SqlSugarTemplates/FurionMvcTemplate/Furion.Template.Mvc.nuspec +++ b/templates/SqlSugarTemplates/FurionMvcTemplate/Furion.Template.Mvc.nuspec @@ -2,7 +2,7 @@ Furion.SqlSugar.Template.Mvc - 4.3.9 + 4.4.0 基于 Furion 和 SqlSugar 框架快速搭建 Mvc 多层架构模板。 百小僧 diff --git a/templates/SqlSugarTemplates/FurionMvcTemplate/src/FurionMvc.Core/FurionMvc.Core.csproj b/templates/SqlSugarTemplates/FurionMvcTemplate/src/FurionMvc.Core/FurionMvc.Core.csproj index d50c91ee07..15120a2cf1 100644 --- a/templates/SqlSugarTemplates/FurionMvcTemplate/src/FurionMvc.Core/FurionMvc.Core.csproj +++ b/templates/SqlSugarTemplates/FurionMvcTemplate/src/FurionMvc.Core/FurionMvc.Core.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/templates/SqlSugarTemplates/FurionRazorTemplate/Furion.Template.Razor.nuspec b/templates/SqlSugarTemplates/FurionRazorTemplate/Furion.Template.Razor.nuspec index bf91bfe13b..33449eedc3 100644 --- a/templates/SqlSugarTemplates/FurionRazorTemplate/Furion.Template.Razor.nuspec +++ b/templates/SqlSugarTemplates/FurionRazorTemplate/Furion.Template.Razor.nuspec @@ -2,7 +2,7 @@ Furion.SqlSugar.Template.Razor - 4.3.9 + 4.4.0 基于 Furion 和 SqlSugar 框架快速搭建 Razor Pages 多层架构模板。 百小僧 diff --git a/templates/SqlSugarTemplates/FurionRazorTemplate/src/FurionRazor.Core/FurionRazor.Core.csproj b/templates/SqlSugarTemplates/FurionRazorTemplate/src/FurionRazor.Core/FurionRazor.Core.csproj index 448e6ff31a..4f4a91294e 100644 --- a/templates/SqlSugarTemplates/FurionRazorTemplate/src/FurionRazor.Core/FurionRazor.Core.csproj +++ b/templates/SqlSugarTemplates/FurionRazorTemplate/src/FurionRazor.Core/FurionRazor.Core.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/templates/SqlSugarTemplates/FurionRazorWithWebApiTemplate/Furion.Template.RazorWithWebApi.nuspec b/templates/SqlSugarTemplates/FurionRazorWithWebApiTemplate/Furion.Template.RazorWithWebApi.nuspec index 53bdcdc2f1..20e87521e9 100644 --- a/templates/SqlSugarTemplates/FurionRazorWithWebApiTemplate/Furion.Template.RazorWithWebApi.nuspec +++ b/templates/SqlSugarTemplates/FurionRazorWithWebApiTemplate/Furion.Template.RazorWithWebApi.nuspec @@ -2,7 +2,7 @@ Furion.SqlSugar.Template.RazorWithWebApi - 4.3.9 + 4.4.0 基于 Furion 和 SqlSugar 框架快速搭建 RazorPages和WebApi 多层架构模板。 百小僧 diff --git a/templates/SqlSugarTemplates/FurionRazorWithWebApiTemplate/src/FurionRazorApi.Core/FurionRazorApi.Core.csproj b/templates/SqlSugarTemplates/FurionRazorWithWebApiTemplate/src/FurionRazorApi.Core/FurionRazorApi.Core.csproj index f5f062d110..2c900a9ec5 100644 --- a/templates/SqlSugarTemplates/FurionRazorWithWebApiTemplate/src/FurionRazorApi.Core/FurionRazorApi.Core.csproj +++ b/templates/SqlSugarTemplates/FurionRazorWithWebApiTemplate/src/FurionRazorApi.Core/FurionRazorApi.Core.csproj @@ -11,9 +11,9 @@ - - - + + + diff --git a/tools/Furion.Tools/Furion.Tools.CommandLine/Furion.Tools.CommandLine.csproj b/tools/Furion.Tools/Furion.Tools.CommandLine/Furion.Tools.CommandLine.csproj index 5f9156cf63..b1d05fb007 100644 --- a/tools/Furion.Tools/Furion.Tools.CommandLine/Furion.Tools.CommandLine.csproj +++ b/tools/Furion.Tools/Furion.Tools.CommandLine/Furion.Tools.CommandLine.csproj @@ -2,7 +2,7 @@ net5.0;net6.0;net7.0 - 4.3.9 + 4.4.0 false Furion 包管理工具开发库 diff --git a/tools/Furion.Tools/Furion.Tools/Furion.Tools.csproj b/tools/Furion.Tools/Furion.Tools/Furion.Tools.csproj index 5ae62c7b3c..63f7317a64 100644 --- a/tools/Furion.Tools/Furion.Tools/Furion.Tools.csproj +++ b/tools/Furion.Tools/Furion.Tools/Furion.Tools.csproj @@ -3,13 +3,13 @@ net5.0;net6.0;net7.0 Exe - 4.3.9 + 4.4.0 furion Furion 工具链 - + diff --git a/tools/cli.ps1 b/tools/cli.ps1 index 9641de1857..d4d7360b1a 100644 --- a/tools/cli.ps1 +++ b/tools/cli.ps1 @@ -24,7 +24,7 @@ Param( #[string]$UseDatabaseNames ) -$FurTools = "Furion Tools v4.3.9"; +$FurTools = "Furion Tools v4.4.0"; # 输出信息 $copyright = @" -- Gitee